Ticket #62: i18n_feedback_password.4.patch

File i18n_feedback_password.4.patch, 444.6 KB (added by mauser, 4 years ago)
  • lang/en.php

     
    11<?php 
     2 
     3// sets locale for dates, always use UTF-8! 
     4setlocale(LC_TIME, 'en_US.UTF-8'); 
     5 
    26$translations = array( 
    37        'General_Unknown' => 'Unknown', 
    48        'General_Required' => '%s required', 
    5  
    6         'Login_LoginPasswordNotCorrect' => 'Username & Password not correct', 
    7         'Login_Login' => 'Username', 
    8         'Login_Password' => 'Password', 
    9         'Login_LogIn' => 'Log in', 
     9        'General_Error' => 'Error', 
     10        'General_Warning' => 'Warning', 
     11        'General_BackToHomepage' => 'Back to Piwik homepage', 
     12        'General_Yes' => 'Yes', 
     13        'General_No' => 'No', 
     14        'General_Delete' => 'Delete', 
     15        'General_Edit' => 'Edit', 
     16        'General_Ok' => 'Ok', 
     17        'General_Close' => 'Close', 
     18        'General_Logout' => 'Logout', 
     19        'General_Done' => 'Done', 
     20        'General_LoadingData' => 'Loading data...', 
     21        'General_ErrorRequest' => 'Oops&hellip; problem during the request, please try again.', 
     22        'General_Next' => 'Next', 
     23        'General_Previous' => 'Previous', 
     24        'General_Table' => 'Table', 
     25        'General_Piechart' => 'Piechart', 
     26        'General_TagCloud' => 'Tag Cloud', 
     27        'General_VBarGraph' => 'Vertial bar graph', 
     28        'General_GraphData' => 'Graph data', 
     29        'General_Refresh' => 'Refresh the page', 
    1030         
    11 ); 
    12  brakuje znaku końca linii na końcu pliku  
     31        'General_ColumnNbUniqVisitors' => 'Unique visitors', 
     32        'General_ColumnNbVisits' => 'Visits', 
     33        'General_ColumnLabel' => 'Label', 
     34); 
  • lang/fr.php

     
    22$translations = array( 
    33        'General_Unknown' => 'Inconnu', 
    44        'General_Required' => '%s requis', 
    5  
    6         'Login_LoginPasswordNotCorrect' => 'Utilisateur & Mot de passe not correct', 
    7         'Login_Login' => 'Utilisateur', 
    8         'Login_Password' => 'Mot de passe', 
    9         'Login_LogIn' => 'Log in', 
    10          
    115); 
  • plugins/VisitFrequency/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'VisitFrequency_Evolution' => 'Evolution over the period', 
     4        'VisitFrequency_ReturnVisits' => '%s returning visits', 
     5        'VisitFrequency_ReturnActions' => '%s actions by the returning visits', 
     6        'VisitFrequency_ReturnMaxActions' => '%s maximum actions by a returning visit', 
     7        'VisitFrequency_ReturnTotalTime' => '%s total time spent by returning visits', 
     8        'VisitFrequency_ReturnBounces' => '%s times that a returning visit has bounced (left the site after one page)', 
     9 
     10        'VisitFrequency_WidgetOverview' => 'Frequency overview', 
     11        'VisitFrequency_WidgetGraphReturning' => 'Graph returning visits', 
     12 
     13        'VisitFrequency_SubmenuFrequency' => 'Frequency', 
     14); 
     15 
  • plugins/VisitFrequency/index.tpl

     
    22<script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 
    33 
    44<a name="evolutionGraph" graphId="VisitFrequencygetLastVisitsReturningGraph"></a> 
    5 <h2>Evolution over the period</h2> 
     5<h2>{'VisitFrequency_Evolution'|translate}</h2> 
    66{$graphEvolutionVisitFrequency} 
    77 
    88{include file=VisitFrequency/sparklines.tpl} 
    99         
    10 {postEvent name="template_footerVisitsFrequency"} 
    11  brakuje znaku końca linii na końcu pliku  
     10{postEvent name="template_footerVisitsFrequency"} 
  • plugins/VisitFrequency/VisitFrequency.php

     
    1818        public function getInformation() 
    1919        { 
    2020                $info = array( 
    21                         'name' => 'VisitorFrequency', 
     21                        'name' => 'VisitFrequency', 
    2222                        'description' => 'VisitorFrequency', 
    2323                        'author' => 'Piwik', 
    2424                        'homepage' => 'http://piwik.org/', 
    2525                        'version' => '0.1', 
     26                        'translationAvailable' => true 
    2627                ); 
    2728                 
    2829                return $info; 
    2930        } 
    3031         
     32        function postLoad() 
     33        { 
     34                Piwik_AddWidget( 'VisitFrequency', 'getSparklines', Piwik_Translate('VisitFrequency_WidgetOverview')); 
     35                Piwik_AddWidget( 'VisitFrequency', 'getLastVisitsReturningGraph', Piwik_Translate('VisitFrequency_WidgetGraphReturning')); 
     36 
     37                Piwik_AddMenu('Visitors', Piwik_Translate('VisitFrequency_SubmenuFrequency'), array('module' => 'VisitFrequency')); 
     38        } 
     39         
    3140        function getListHooksRegistered() 
    3241        { 
    3342                $hooks = array( 
     
    8796        } 
    8897} 
    8998 
    90  
    91 Piwik_AddWidget( 'VisitFrequency', 'getSparklines', 'Frequency overview'); 
    92 Piwik_AddWidget( 'VisitFrequency', 'getLastVisitsReturningGraph', 'Graph returning visits'); 
    93  
    94 Piwik_AddMenu('Visitors', 'Frequency', array('module' => 'VisitFrequency')); 
    95  
    96  
    97  
  • plugins/VisitFrequency/sparklines.tpl

     
    11 
    2         <p><img class="sparkline" src="{$urlSparklineNbVisitsReturning}" /> <span><strong>{$nbVisitsReturning} </strong> returning visits</span></p> 
    3         <p><img class="sparkline" src="{$urlSparklineNbActionsReturning}" /> <span><strong>{$nbActionsReturning} </strong> actions by the returning visits</span></p> 
    4         <p><img class="sparkline" src="{$urlSparklineMaxActionsReturning}" /> <span><strong>{$maxActionsReturning} </strong> maximum actions by a returning visit</span></p> 
    5         <p><img class="sparkline" src="{$urlSparklineSumVisitLengthReturning}" /> <span><strong>{$sumVisitLengthReturning|sumtime} </strong> total time spent by returning visits</span></p> 
    6         <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> 
     2        <p><img class="sparkline" src="{$urlSparklineNbVisitsReturning}" /> <span> 
     3        {'VisitFrequency_ReturnVisits'|translate:"<strong>$nbVisitsReturning</strong>"}</span></p> 
     4        <p><img class="sparkline" src="{$urlSparklineNbActionsReturning}" /> <span> 
     5        {'VisitFrequency_ReturnActions'|translate:"<strong>$nbActionsReturning</strong>"}</span></p> 
     6        <p><img class="sparkline" src="{$urlSparklineMaxActionsReturning}" /> <span> 
     7         {'VisitFrequency_ReturnMaxActions'|translate:"<strong>$maxActionsReturning</strong>"}</span></p> 
     8        <p><img class="sparkline" src="{$urlSparklineSumVisitLengthReturning}" /> <span> 
     9         {assign var=sumtimeVisitLengthReturning value=$sumVisitLengthReturning|sumtime} 
     10         {'VisitFrequency_ReturnTotalTime'|translate:"<strong>$sumtimeVisitLengthReturning</strong>"}</span></p> 
     11        <p><img class="sparkline" src="{$urlSparklineBounceCountReturning}" /> <span> 
     12         {'VisitFrequency_ReturnBounces'|translate:"<strong>$bounceCountReturning</strong>"} </span></p> 
  • plugins/SitesManager/API.php

     
    270270 
    271271                if($nbSites == 1) 
    272272                { 
    273                         throw new Exception("It is not possible to delete this website as it is the only registered website.  
    274                         Add a new website first, then delete this one."); 
     273                        throw new Exception(Piwik_TranslateException("SitesManager_ExceptionDeleteSite")); 
    275274                } 
    276275                 
    277276                $db = Zend_Registry::get('db'); 
     
    300299                if(!is_array($urls) 
    301300                        || count($urls) == 0) 
    302301                { 
    303                         throw new Exception("You must specify at least one URL for the site."); 
     302                        throw new Exception(Piwik_TranslateException("SitesManager_ExceptionNoUrl")); 
    304303                } 
    305304        } 
    306305 
     
    477476        { 
    478477                if(empty($siteName)) 
    479478                { 
    480                         throw new Exception("The site name can't be empty."); 
     479                        throw new Exception(Piwik_TranslateException("SitesManager_ExceptionEmptyName")); 
    481480                } 
    482481        } 
    483482 
     
    493492                {                        
    494493                        if(!self::isValidUrl($url)) 
    495494                        { 
    496                                 throw new Exception("The url '$url' is not a valid URL."); 
     495                                throw new Exception(sprintf(Piwik_TranslateException("SitesManager_ExceptionInvalidUrl"),$url)); 
    497496                        } 
    498497                } 
    499498        } 
  • plugins/SitesManager/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'SitesManager_Sites' => 'Sites', 
     4        'SitesManager_JsCode' => 'Javascript code', 
     5        'SitesManager_JsCodeHelp' => 'Here is the javascript code to include on all your pages', 
     6        'SitesManager_ShowJsCode' => 'show code', 
     7        'SitesManager_NoWebsites' => 'You don\'t have any website to administrate.', 
     8        'SitesManager_AddSite' => 'Add a new Site', 
     9        'SitesManager_Id' => 'Id', 
     10        'SitesManager_Name' => 'Name', 
     11        'SitesManager_Urls' => 'URLs', 
     12 
     13        'SitesManager_MenuSites' => 'Sites', 
     14 
     15        'SitesManager_DeleteConfirm_js' => 'Are you sure you want to delete the website %s?', 
     16         
     17        '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.', 
     18        'SitesManager_ExceptionNoUrl' => 'You must specify at least one URL for the site.', 
     19        'SitesManager_ExceptionEmptyName' => 'The site name can\'t be empty.', 
     20        'SitesManager_ExceptionInvalidUrl' => 'The url \'%s\' is not a valid URL.', 
     21); 
  • plugins/SitesManager/SitesManager.php

     
    2424                        'author' => 'Piwik', 
    2525                        'homepage' => 'http://piwik.org/', 
    2626                        'version' => '0.1', 
    27                         'translationAvailable' => false, 
     27                        'translationAvailable' => true, 
    2828                ); 
    2929                 
    3030                return $info; 
    3131        } 
    3232         
     33        function postLoad() 
     34        { 
     35                Piwik_AddAdminMenu(Piwik_Translate('SitesManager_MenuSites'), array('module' => 'SitesManager'));                
     36        } 
    3337} 
    3438 
    35 Piwik_AddAdminMenu('Sites', array('module' => 'SitesManager')); 
    36  
  • plugins/SitesManager/Controller.php

     
    3939                 
    4040                echo $view->render(); 
    4141        } 
    42 } 
    43  brakuje znaku końca linii na końcu pliku  
     42} 
  • plugins/SitesManager/templates/SitesManager.tpl

     
     1{loadJavascriptTranslations modules='SitesManager'} 
     2 
    13<script type="text/javascript" src="plugins/SitesManager/templates/SitesManager.js"></script> 
    24 
    3 <h2>Sites</h2> 
     5<h2>{'SitesManager_Sites'|translate}</h2> 
    46<div id="ajaxError" style="display:none"></div> 
    5 <div id="ajaxLoading" style="display:none">Loading... <img src="themes/default/loading.gif"></div> 
     7<div id="ajaxLoading" style="display:none">{'General_LoadingData'|translate} <img src="themes/default/loading.gif"></div> 
    68 
    79{if $sites|@count == 0} 
    8         You don't have any website to administrate. 
     10        {'SitesManager_NoWebsites'|translate} 
    911{else} 
    1012        <table id="editSites" border=1 cellpadding="10"> 
    1113                <thead> 
    1214                        <tr> 
    13                         <th>Id</th> 
    14                         <th>Name</th> 
    15                         <th>URLs</th> 
     15                        <th>{'SitesManager_Id'|translate}</th> 
     16                        <th>{'SitesManager_Name'|translate}</th> 
     17                        <th>{'SitesManager_Urls'|translate}</th> 
    1618                        <th> </th> 
    1719                        <th> </th> 
    18                         <th> Javascript code </th> 
     20                        <th> {'SitesManager_JsCode'|translate} </th> 
    1921                        </tr> 
    2022                </thead> 
    2123                <tbody> 
     
    2527                                <td id="siteName" class="editableSite">{$site.name}</td> 
    2628                                <td id="urls" class="editableSite">{foreach from=$site.alias_urls item=url}{$url}<br>{/foreach}</td>        
    2729                                <td><img src='plugins/UsersManager/images/edit.png' class="editSite" id="row{$i}" href='#'></td> 
    28                                 <td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" value="Delete"></td> 
    29                                 <td><a href='{url actionToLoad=displayJavascriptCode idsite=$site.idsite}'>Show Code</a></td> 
     30                                <td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" value="{'General_Delete'|translate}"></td> 
     31                                <td><a href='{url actionToLoad=displayJavascriptCode idsite=$site.idsite}'>{'SitesManager_ShowJsCode'|translate}</a></td> 
    3032                        </tr> 
    3133                        {/foreach} 
    3234                         
    3335                </tbody> 
    3436        </table> 
    35         <div id="addRowSite"><img src='plugins/UsersManager/images/add.png'> <a href="#">Add a new Site</a></div> 
     37        <div id="addRowSite"><img src='plugins/UsersManager/images/add.png'> <a href="#">{'SitesManager_AddSite'|translate}</a></div> 
    3638{/if} 
    3739 
  • plugins/SitesManager/templates/DisplayJavascriptCode.tpl

     
    1 <p>Here is the javascript code to include on all your pages:</p> 
     1<p>{'SitesManager_JsCodeHelp'|translate}:</p> 
    22 
    33<code> 
    44{$jsTag} 
  • plugins/SitesManager/templates/SitesManager.js

     
    108108                        var idRow = $(this).attr('id'); 
    109109                        var nameToDelete = $(this).parent().parent().find('#siteName').html(); 
    110110                        var idsiteToDelete = $(this).parent().parent().find('#idSite').html(); 
    111                         if(confirm('Are you sure you want to delete the website "'+nameToDelete+'" (idSite = '+idsiteToDelete+')?')) 
     111                        if(confirm(sprintf(_pk_translate('SitesManager_DeleteConfirm','Are you sure you want to delete the website %s'),'"'+nameToDelete+'" (idSite = '+idsiteToDelete+')')) ) 
    112112                        { 
    113113                                $.ajax( getDeleteSiteAJAX( idsiteToDelete ) ); 
    114114                        } 
  • plugins/Feedback/lang/en.php

     
     1<?php 
     2 
     3// not translated - feedback should be sent in English!!! 
     4 
     5$translations = array( 
     6); 
     7 
  • plugins/Feedback/index.tpl

     
     1<form method="post" action="?module=Feedback&action=sendFeedback"> 
     2 
     3<p><strong>Your name:</strong> 
     4<br /><input type="text" name="name" size="50" /></p> 
     5 
     6<p><strong>Your e-mail:</strong> 
     7<br /><input type="text" name="email" size="50" /></p> 
     8 
     9<p><strong>Choose category:</strong> 
     10<br /><select name="category"> 
     11        <option value="bug">Bug report</option> 
     12        <option value="feature">Feature missing</option> 
     13</select> 
     14</p> 
     15 
     16<p><strong>Topic:</strong> 
     17<br /><input type="text" name="topic" size="50" /></p> 
     18 
     19<p><strong>Body:</strong> 
     20<br /><textarea name="body" cols="50" rows="15"></textarea></p> 
     21 
     22<p><input type="submit" value="Send feedback" /> 
     23 
     24</form> 
  • plugins/Feedback/sent.tpl

     
     1<p>A mail was sent to Piwik developers</p> 
     2 
     3<p><strong>Thank you for your feedback.</strong><br /> - Piwik Team</p> 
  • plugins/Feedback/Controller.php

     
     1<?php 
     2/** 
     3 * Piwik - Open source web analytics 
     4 *  
     5 * @link http://piwik.org 
     6 * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later 
     7 * @version $Id: Controller.php 169 2008-01-14 05:41:15Z matt $ 
     8 *  
     9 * @package Piwik_Feedback 
     10 */ 
     11 
     12 
     13 
     14/** 
     15 * 
     16 * @package Piwik_Feedback  
     17 */ 
     18class Piwik_Feedback_Controller extends Piwik_Controller 
     19{        
     20        function index() 
     21        {                
     22                $view = new Piwik_View('Feedback/index.tpl'); 
     23                                 
     24                echo $view->render(); 
     25        } 
     26 
     27        /** 
     28         * send email to Piwik team and display nice thanks 
     29         */ 
     30        function sendFeedback() 
     31        { 
     32                // TODO: require user login or captcha if anonymous              
     33                 
     34                $name = Piwik_Common::getRequestVar('name', '', 'string'); 
     35                $topic = Piwik_Common::getRequestVar('topic', '', 'string'); 
     36                $body = Piwik_Common::getRequestVar('body', '', 'string'); 
     37                $email = Piwik_Common::getRequestVar('email', '', 'string'); 
     38                $category = Piwik_Common::getRequestVar('category', '', 'string'); 
     39                 
     40                $mail = new Piwik_Mail(); 
     41                $mail->setFrom($email, $name); 
     42                $mail->addTo('hello@piwik.org','Piwik Team'); 
     43                $mail->setSubject('[feedback:'.$category.'] '.$topic); 
     44                $mail->setBodyText($body); 
     45                $mail->send(); 
     46                 
     47                $view = new Piwik_View('Feedback/sent.tpl');                     
     48                echo $view->render(); 
     49        } 
     50} 
  • plugins/Feedback/Feedback.php

     
     1<?php 
     2/** 
     3 * Piwik - Open source web analytics 
     4 *  
     5 * @link http://piwik.org 
     6 * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later 
     7 * @version $Id: ExamplePlugin.php 169 2008-01-14 05:41:15Z matt $ 
     8 *  
     9 * @package Piwik_Feedback 
     10 */ 
     11 
     12class Piwik_Feedback extends Piwik_Plugin 
     13{ 
     14        public function getInformation() 
     15        { 
     16                return array( 
     17                        'name' => 'Feedback', 
     18                        'description' => '', 
     19                        'author' => 'Piwik', 
     20                        'homepage' => 'http://piwik.org/', 
     21                        'version' => '0.1', 
     22                        'translationAvailable' => true, 
     23                ); 
     24        } 
     25} 
  • plugins/Dashboard/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'Dashboard_AddWidget' => 'Add a widget...', 
     4        'Dashboard_DeleteWidgetConfirm' => 'Are you sure you want to delete this widget from the dashboard?', 
     5        'Dashboard_SelectWidget' => 'Select the widget to add in the dashboard', 
     6        'Dashboard_AddPreviewedWidget' => 'Add previewed widget to the dashboard', 
     7        'Dashboard_WidgetPreview' => 'Widget preview',   
     8 
     9        'Dashboard_TitleWidgetInDashboard_js' => 'Widget already in dashboard', 
     10        'Dashboard_TitleClickToAdd_js' => 'Click to add to dashboard', 
     11        'Dashboard_LoadingPreview_js' => 'Loading preview, please wait...', 
     12        'Dashboard_LoadingWidget_js' => 'Loading widget, please wait...', 
     13        'Dashboard_WidgetNotFound_js' => 'Widget not found', 
     14); 
  • plugins/Dashboard/Dashboard.php

     
    2020                        'author' => 'Piwik', 
    2121                        'homepage' => 'http://piwik.org/', 
    2222                        'version' => '0.1', 
     23                        'translationAvailable' => true, 
    2324                ); 
    2425        } 
    2526 
  • plugins/Dashboard/templates/Dashboard.js

     
    1  
    2  
    3 //label and string used in the javascript 
    4 //overide this object for dataTable_translation 
    5 if(typeof dashboard_translation == "undefined") 
    6 { 
    7         var dashboard_translation = { 
    8                 titleWidgetInDashboard:         'Widget already in dashboard', 
    9                 titleClickToAdd:                        'Click to add to dashboard', 
    10                 loadingPreview:                         'Loading preview, please wait...', 
    11                 loadingWidget:                          'Loading widget, please wait...', 
    12                 widgetNotFound:                         'Widget not found' 
    13         }; 
    14 } 
    15  
    161//there is a problem with loop for-in when we extends javascript Array 
    172//so I prefer using a separate function to do this 
    183function contains(array, searchElem) { 
     
    158143                                                //format the div for upcomming ajax loading and set a temporary content 
    159144                                                $(this) .attr('plugin', plugin) 
    160145                                                                .attr('id', action) 
    161                                                                 .html('<div id="previewLoading"><img src="themes/default/loading.gif" />'+ dashboard_translation.loadingPreview +'</div>').show(); 
     146                                                                .html('<div id="previewLoading"><img src="themes/default/loading.gif" />'+ _pk_translate('Dashboard_LoadingPreview','Loading preview, please wait...') +'</div>').show(); 
    162147                                                self.dashboard.ajaxLoading(plugin, action); 
    163148                                        } 
    164149                                }); 
     
    208193                        if(contains(widgets, plugin+'.'+action)) 
    209194                        { 
    210195                                $(this).addClass('menuDisabled'); 
    211                                 $(this).attr('title', dashboard_translation.titleWidgetInDashboard); 
     196                                $(this).attr('title', _pk_translate('Dashboard_TitleWidgetInDashboard','Widget already in dashboard')); 
    212197                        } 
    213198                        else 
    214199                        { 
    215200                                $(this).removeClass('menuDisabled'); 
    216                                 $(this).attr('title', dashboard_translation.titleClickToAdd); 
     201                                $(this).attr('title', _pk_translate('Dashboard_TitleClickToAdd','Click to add to dashboard')); 
    217202                        } 
    218203                }); 
    219204        }, 
     
    343328                if(typeof onTop == "undefined") 
    344329                        onTop = false; 
    345330                 
    346                 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>'; 
     331                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>'; 
    347332         
    348333                if(onTop) 
    349334                { 
     
    390375        { 
    391376                var self = this; 
    392377                 
    393                 var title = dashboard_translation.widgetNotFound; 
     378                var title = _pk_translate('Dashboard_WidgetNotFound','Widget not found'); 
    394379                var widgets = piwik.availableWidgets[plugin]; 
    395380                for(var i in widgets) 
    396381                { 
  • plugins/Dashboard/templates/index.tpl

     
     1{loadJavascriptTranslations modules='Home Dashboard'} 
     2 
    13<script type="text/javascript"> 
    24        {* define some global constants for the following javascript includes *} 
    35        var piwik = new Object; 
     
    2224  
    2325        <div class="dialog" id="confirm">  
    2426                <img src="themes/default/images/delete.png" style="padding: 10px; position: relative; margin-top: 10%; float: left;"/> 
    25                 <p>Are you sure you want to delete this widget from the dashboard ?</p> 
    26                         <input id="yes" type="button" value="Yes"/> 
    27                         <input id="no" type="button" value="No"/> 
     27                <p>{'Dashboard_DeleteWidgetConfirm'|translate}</p> 
     28                        <input id="yes" type="button" value="{'General_Yes'|translate}"/> 
     29                        <input id="no" type="button" value="{'General_No'|translate}"/> 
    2830        </div>  
    2931 
    3032        <div class="button" id="addWidget"> 
    31                 Add a widget... 
     33                {'Dashboard_AddWidget'|translate} 
    3234        </div> 
    3335         
    3436        <div class="menu" id="widgetChooser"> 
    35                 <div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="Close this menu"/></div> 
    36                 <div id="menuTitleBar">Select the widget to add in the dashboard</div> 
     37                <div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="{'General_Close'|translate}"/></div> 
     38                <div id="menuTitleBar">{'Dashboard_SelectWidget'|translate}</div> 
    3739                <div class="subMenu" id="sub1"> 
    3840                </div> 
    3941                 
     
    4244                 
    4345                <div class="subMenu" id="sub3"> 
    4446                        <div class="widget"> 
    45                                 <div class="handle" title="Add previewed widget to the dashboard"> 
     47                                <div class="handle" title="{'Dashboard_AddPreviewedWidget'|translate}"> 
    4648                                        <div class="button" id="close"> 
    47                                                 <img src="themes/default/images/close.png" /> 
     49                                                <img src="themes/default/images/close.png" title="{'General_Close'|translate}"/> 
    4850                                        </div> 
    49                                         <div class="widgetTitle">Widget preview</div> 
     51                                        <div class="widgetTitle">{'Dashboard_WidgetPreview'|translate}</div> 
    5052                                </div> 
    5153                                <div class="widgetDiv previewDiv"></div> 
    5254                        </div> 
  • plugins/Dashboard/templates/header.tpl

     
    11{* This header is for loading the dashboard in stand alone mode*} 
    22<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> 
    33 
     4{loadJavascriptTranslations modules='Home Dashboard'} 
     5 
    46<script type="text/javascript" src="libs/jquery/jquery.js"></script> 
    57 
    68<script type="text/javascript" src="themes/default/common.js"></script> 
     
    2022<script type="text/javascript" src="libs/jquery/ui.sortable_modif.js"></script> 
    2123 
    2224<link rel="stylesheet" href="plugins/Home/templates/datatable.css"> 
    23 <link rel="stylesheet" href="plugins/Dashboard/templates/dashboard.css"> 
    24  brakuje znaku końca linii na końcu pliku  
     25<link rel="stylesheet" href="plugins/Dashboard/templates/dashboard.css"> 
  • plugins/Home/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'Home_NoPrivileges' => "You are logged in as '%s' but it seems you don't have any permission set in Piwik.". 
     4                "<br />Ask your Piwik administrator to give you 'view' access to a website.", 
     5        'Home_JavascriptDisabled' => "JavaScript must be enabled in order for you to use Piwik in standard view.<br>". 
     6                "However, it seems JavaScript is either disabled or not supported by your browser.<br>". 
     7                "To use standard view, enable JavaScript by changing your browser options, then %1stry again%2s.<br>", 
     8        'Home_TableNoData' => 'No data for this table.', 
     9        'Home_CategoryNoData' => 'No data in this category. Try to "Include all population".', 
     10        'Home_ShowJSCode' => 'Show the javascript code to insert', 
     11         
     12        'Home_IncludeAllPopulation_js' => 'Include all population', 
     13        'Home_ExcludeLowPopulation_js' => 'Exclude low population', 
     14        'Home_PageOf_js' => '%s of %s', 
     15        'Home_Loading_js' => 'Loading...', 
     16 
     17        'Home_LocalizedDateFormat' => '%A %e %B %Y', 
     18        'Home_PeriodDay' => 'Day', 
     19        'Home_PeriodWeek' => 'Week', 
     20        'Home_PeriodMonth' => 'Month', 
     21        'Home_PeriodYear' => 'Year', 
     22         
     23        'Home_DaySu_js' => 'Su', 
     24        'Home_DayMo_js' => 'Mo', 
     25        'Home_DayTu_js' => 'Tu', 
     26        'Home_DayWe_js' => 'We', 
     27        'Home_DayTh_js' => 'Th', 
     28        'Home_DayFr_js' => 'Fr', 
     29        'Home_DaySa_js' => 'Sa', 
     30         
     31        'Home_MonthJanuary_js' => 'January', 
     32        'Home_MonthFebruary_js' => 'February', 
     33        'Home_MonthMarch_js' => 'March', 
     34        'Home_MonthApril_js' => 'April', 
     35        'Home_MonthMay_js' => 'May', 
     36        'Home_MonthJune_js' => 'June', 
     37        'Home_MonthJuly_js' => 'July', 
     38        'Home_MonthAugust_js' => 'August', 
     39        'Home_MonthSeptember_js' => 'September', 
     40        'Home_MonthOctober_js' => 'October', 
     41        'Home_MonthNovember_js' => 'November', 
     42        'Home_MonthDecemeber_js' => 'Decemeber', 
     43); 
  • plugins/Home/Controller.php

     
    3737                { 
    3838                        if(($currentLogin = Piwik::getCurrentUserLogin()) != 'anonymous') 
    3939                        { 
    40                                 Piwik_ExitWithMessage( "You are logged in as '$currentLogin' but it seems you don't have any permission set in Piwik. 
    41                                 <br />Ask your Piwik administrator to give you 'view' access to a website. 
    42                                 <br /><br />&nbsp;&nbsp;&nbsp;<b><a href='?module=Login&action=logout'>&rsaquo; Logout from Piwik</a></b><br />"); 
     40                                Piwik_ExitWithMessage( sprintf(Piwik_Translate('Home_NoPrivileges'),$currentLogin). 
     41                                "<br /><br />&nbsp;&nbsp;&nbsp;<b><a href='?module=Login&action=logout'>&rsaquo; ".Piwik_Translate('General_Logout')."</a></b><br />"); 
    4342                        } 
    4443                        else 
    4544                        { 
     
    5453                // date 
    5554                $view->date = $this->strDate; 
    5655                $oDate = new Piwik_Date($this->strDate); 
    57                 $view->prettyDate = $oDate->get("l j\<\s\u\p\>S\<\/\s\u\p\> F Y"); 
     56                $view->prettyDate = $oDate->getLocalized(Piwik_Translate('Home_LocalizedDateFormat')); 
    5857                 
    5958                // period 
    6059                $currentPeriod = Piwik_Common::getRequestVar('period'); 
    61                 $otherPeriodsAvailable = array('day','week','month','year'); 
     60                $otherPeriodsAvailable = array('day', 'week', 'month', 'year'); 
     61 
     62                $otherPeriodsNames = array( 
     63                        'day' => Piwik_Translate('Home_PeriodDay'), 
     64                        'week' => Piwik_Translate('Home_PeriodWeek'), 
     65                        'month' => Piwik_Translate('Home_PeriodMonth'), 
     66                        'year' => Piwik_Translate('Home_PeriodYear') 
     67                        ); 
    6268                 
    6369                $found = array_search($currentPeriod,$otherPeriodsAvailable); 
    6470                if($found !== false) 
     
    6874                 
    6975                $view->period = $currentPeriod; 
    7076                $view->otherPeriods = $otherPeriodsAvailable; 
     77                $view->periodsNames = $otherPeriodsNames; 
    7178                 
    7279                // other 
    7380                $view->idSite = Piwik_Common::getRequestVar('idSite'); 
     
    117124 
    118125         
    119126 
    120 } 
    121  brakuje znaku końca linii na końcu pliku  
     127} 
  • plugins/Home/templates/datatable.tpl

     
    33                {$arrayDataTable.message}  
    44        {else} 
    55                {if count($arrayDataTable) == 0} 
    6                 <div id="emptyDatatable">No data for this table.</div> 
     6                <div id="emptyDatatable">{'Home_TableNoData'|translate}</div> 
    77                {else} 
    88                        <a name="{$id}"></a> 
    99                        <table cellspacing="0" class="dataTable">  
    1010                        <thead> 
    1111                        <tr> 
    1212                        {foreach from=$dataTableColumns item=column} 
    13                                 <th class="sortable" id="{$column.id}"><div id="thDIV">{$column.name}</div></th> 
     13                                <th class="sortable" id="{$column.id}"><div id="thDIV">{$column.displayName}</div></th> 
    1414                        {/foreach} 
    1515                        </tr> 
    1616                        </thead> 
  • plugins/Home/templates/period_select.tpl

     
    11<div id="periodString"> 
    22        <span id="date"><img src='plugins/Home/templates/images/more_date.gif' style="vertical-align:middle"> {$prettyDate}</span> -&nbsp; 
    33        <span id="periods">  
    4                 <span id="currentPeriod">{$period|ucfirst}</span>  
     4                <span id="currentPeriod">{$periodsNames.$period}</span>  
    55                <span id="otherPeriods"> 
    66                        {foreach from=$otherPeriods item=thisPeriod} 
    7                         | <a href='{url period=$thisPeriod}'>{$thisPeriod|ucfirst}</a> 
     7                        | <a href='{url period=$thisPeriod}'>{$periodsNames.$thisPeriod}</a> 
    88                        {/foreach} 
    99                </span> 
    1010        </span> 
    1111        <span id="calendar"></span> 
    1212</div> 
    1313 
    14 <div style="clear:both"></div> 
    15  brakuje znaku końca linii na końcu pliku  
     14<div style="clear:both"></div> 
  • plugins/Home/templates/links_misc_modules.tpl

     
     1<script type="text/javascript" src="libs/jquery/thickbox.js"></script> 
     2<link rel="stylesheet" href="libs/jquery/thickbox.css"> 
    13<span id="miscLinks"> 
    2 <a href='?module=AdminHome'>Admin</a></li> | 
    3 <a href='?module=API&action=listAllAPI'><b>API </b></a> |  
    4 <a href='?module=Widgetize'>Widgets</li></a> 
    5 </span> 
    6  brakuje znaku końca linii na końcu pliku  
     4        <ul> 
     5                <li><a href='?module=API&action=listAllAPI'><b>API</b> examples</a></li> 
     6                <li><a href='?module=AdminHome'>Administration</a></li> 
     7                <li><a href='?module=Widgetize'>Embed</a> Piwik widgets everywhere</li> 
     8                <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> 
     9        </ul> 
     10</span> 
  • plugins/Home/templates/calendar.js

     
    144144                        prevText: "", 
    145145                        nextText: "", 
    146146                        currentText: "", 
    147                         customDate: isDateSelected 
     147                        customDate: isDateSelected, 
     148                        dayNames: [ 
     149                                _pk_translate('Home_DaySu'), 
     150                                _pk_translate('Home_DayMo'), 
     151                                _pk_translate('Home_DayTu'), 
     152                                _pk_translate('Home_DayWe'), 
     153                                _pk_translate('Home_DayTh'), 
     154                                _pk_translate('Home_DayFr'), 
     155                                _pk_translate('Home_DaySa')], 
     156                        monthNames: [ 
     157                                _pk_translate('Home_MonthJanuary'), 
     158                                _pk_translate('Home_MonthFebruary'), 
     159                                _pk_translate('Home_MonthMarch'), 
     160                                _pk_translate('Home_MonthApril'), 
     161                                _pk_translate('Home_MonthMay'), 
     162                                _pk_translate('Home_MonthJune'), 
     163                                _pk_translate('Home_MonthJuly'), 
     164                                _pk_translate('Home_MonthAugust'), 
     165                                _pk_translate('Home_MonthSeptember'), 
     166                                _pk_translate('Home_MonthOctober'), 
     167                                _pk_translate('Home_MonthNovember'), 
     168                                _pk_translate('Home_MonthDecemeber')], 
    148169                        }, 
    149170                        currentDate); 
    150171        } 
  • plugins/Home/templates/datatable_actions_subdatable.tpl

     
    33        {$arrayDataTable.message}  
    44{else} 
    55        {if count($arrayDataTable) == 0} 
    6         <tr><td colspan="{$nbColumns}">No data in this category. Try to "Include all population".</td></tr> 
     6        <tr><td colspan="{$nbColumns}">{'Home_CategoryNoData'|translate}</td></tr> 
    77        {else} 
    88                {foreach from=$arrayDataTable item=row} 
    99                <tr {if $row.idsubdatatable}class="subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable"{/if}> 
     
    1616                </tr> 
    1717                {/foreach} 
    1818        {/if}            
    19 {/if} 
    20  brakuje znaku końca linii na końcu pliku  
     19{/if} 
  • plugins/Home/templates/datatable_actions_recursive.tpl

     
    33        {$arrayDataTable.message}  
    44{else} 
    55        {if count($arrayDataTable) == 0} 
    6                 <div id="emptyDatatable">No data for this table.</div> 
     6                <div id="emptyDatatable">{'Home_TableNoData'|translate}</div> 
    77        {else} 
    88                <table cellspacing="0" class="dataTable dataTableActions">  
    99                <thead> 
    1010                <tr> 
    1111                {foreach from=$dataTableColumns item=column} 
    12                         <th class="sortable" id="{$column.id}">{$column.name}</td> 
     12                        <th class="sortable" id="{$column.id}">{$column.displayName}</td> 
    1313                {/foreach} 
    1414                </tr> 
    1515                </thead> 
     
    4141        {include file="Home/templates/datatable_actions_js.tpl"} 
    4242         
    4343        {/if} 
    44 </div> 
    45  brakuje znaku końca linii na końcu pliku  
     44</div> 
  • plugins/Home/templates/menu.css

     
    2424        border-left: 1px solid #fff; 
    2525        float: left; 
    2626        list-style: none; 
    27         z-index: 999; 
     27        z-index: 49; 
    2828} 
    2929 
    3030.nav li.current ul { 
    31         z-index: 999; 
     31        z-index: 49; 
    3232} 
    3333 
    3434.nav li.sfHover ul,ul.nav li:hover ul { 
    35         z-index: 1000; 
     35        z-index: 50; 
    3636} 
    3737 
    3838/* LEVEL2 NORMAL */ 
     
    108108when and how it appears*/ 
    109109.superfish li:hover ul,.superfish li li:hover ul { 
    110110        top: -999em; 
    111 } 
    112  brakuje znaku końca linii na końcu pliku  
     111} 
  • plugins/Home/templates/datatable.js

     
    1  
    2 //label and string used in the javascript 
    3 //overide this object for dataTable_translation 
    4 if(typeof dataTable_translation == "undefined") 
    5 { 
    6         var dataTable_translation = { 
    7                 includeLowPop:          'Include all population', 
    8                 excludeLowPop:          'Exclude low population', 
    9                 pageOf:                         ' of ',                                         //like in 1-10 _of_ 42 
    10                 loading:                        'Loading...' 
    11         }; 
    12 } 
    13  
    141//----------------------------------------------------------------------------- 
    152//                                                              Data Table 
    163//----------------------------------------------------------------------------- 
     
    281268                                        { 
    282269                                                if(Number(self.param.filter_excludelowpop) != 0) 
    283270                                                { 
    284                                                         string = dataTable_translation.includeLowPop; 
     271                                                        string = _pk_translate('Home_IncludeAllPopulation','Include all population'); 
    285272                                                } 
    286273                                                else 
    287274                                                { 
    288                                                         string = dataTable_translation.excludeLowPop; 
     275                                                        string = _pk_translate('Home_ExcludeLowPopulation','Exclude low population'); 
    289276                                                } 
    290277                                                $(this).html(string); 
    291278                                        }  
     
    423410                                        // only show this string if there is some rows in the datatable 
    424411                                        if(totalRows != 0) 
    425412                                        { 
    426                                                 var str = offset + '-' + offsetEndDisp + dataTable_translation.pageOf + totalRows; 
     413                                                var str = sprintf(_pk_translate('Home_PageOf','%s of %s'),offset + '-' + offsetEndDisp,totalRows); 
    427414                                                $(this).text(str); 
    428415                                        } 
    429416                                } 
     
    631618                                        <tr>\ 
    632619                                                <td colspan="'+numberOfColumns+'" class="cellSubDataTable">\ 
    633620                                                        <div id="'+divIdToReplaceWithSubTable+'">\ 
    634                                                                 <span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ dataTable_translation.loading +'</span>\ 
     621                                                                <span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ _pk_translate('Home_Loading','Loading...') +'</span>\ 
    635622                                                        </div>\ 
    636623                                                </td>\ 
    637624                                        </tr>\ 
     
    999986        $('img',domElem).attr('src', 'themes/default/images/plus.png'); 
    1000987} 
    1001988 
    1002          
    1003  brakuje znaku końca linii na końcu pliku  
     989         
  • plugins/Home/templates/datatable_footer.tpl

     
    77        </span> 
    88         
    99        <span id="dataTablePages"></span> 
    10         <span id="dataTablePrevious">&lt; Previous</span> 
    11         <span id="dataTableNext">Next &gt;</span> 
     10        <span id="dataTablePrevious">&lt; {'General_Previous'|translate}</span> 
     11        <span id="dataTableNext">{'General_Next'|translate} &gt;</span> 
    1212        <div> 
    1313                <span id="exportDataTable"> 
    1414                        <span id="exportToFormat" style="display:none"> 
     
    1919                                        <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="JSON" filter_limit="100">Json</a> | 
    2020                                        <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="PHP" filter_limit="100">Php</a> 
    2121                                </span> 
    22                                 <a class="viewDataTable" format="table"><img width="16" height="16" src="themes/default/images/table.png" title="Table" /></a> 
    23                                 <a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="Tag Cloud" /></a> 
    24                                 <a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="themes/default/images/chart_bar.png" title="Vertical bar graph" /></a> 
    25                                 <a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="Pie chart" /></a> 
     22                                <a class="viewDataTable" format="table"><img width="16" height="16" src="themes/default/images/table.png" title="{'General_Table'|translate}" /></a> 
     23                                <a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a> 
     24                                <a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a> 
     25                                <a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a> 
    2626                        </span> 
    2727                        <span id="exportDataTableShow" style="display:none"> 
    2828                                <img src="plugins/Home/templates/images/more.png" /> 
    2929                        </span> 
    3030                </span> 
    3131 
    32                 <span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> Loading...</span> 
     32                <span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> {'General_LoadingData'|translate}</span> 
    3333        </div> 
    3434</div> 
    3535 
  • plugins/Home/templates/datatable_actions.tpl

     
    33        {$arrayDataTable.message}  
    44{else} 
    55        {if count($arrayDataTable) == 0} 
    6                 <div id="emptyDatatable">No data for this table.</div> 
     6                <div id="emptyDatatable">{'Home_TableNoData'|translate}</div> 
    77        {else} 
    88                <table cellspacing="0" class="dataTable dataTableActions">  
    99                <thead> 
  • plugins/Home/templates/graph.tpl

     
    66        <form class="formEmbedCode" id="{$formId}"> 
    77        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"> 
    88         
    9         | <a target="_blank" href="{$urlData}">Graph data</a> 
     9        | <a target="_blank" href="{$urlData}">{'General_GraphData'|translate}</a> 
    1010        </form> 
    1111         
    1212        {include file="Home/templates/datatable_footer.tpl"} 
  • plugins/Home/templates/index.tpl

     
    44</head> 
    55<body> 
    66 
     7{loadJavascriptTranslations modules='Home'} 
    78 
    89<script type="text/javascript"> 
    910var period = "{$period}"; 
     
    174175/* style for the date picking */ 
    175176#periodString { 
    176177        margin-left:350px; 
    177         margin-top:10px; 
    178178} 
    179179 
    180180#periodString #date, #periodString #periods,  
     
    265265        font-weight:bold; 
    266266        color:#F88D22; 
    267267} 
    268  
    269  
    270  
    271 #downloadButton .download-button { 
    272         display: block; 
    273         text-align: center; 
    274         line-height: 1.4em; 
    275         padding: 10px; 
    276 } 
    277  
    278 #downloadButton  .download-button strong { 
    279         font-size: 13px; 
    280         color: #fff; 
    281 } 
    282  
    283 #downloadButton .download-button, #downloadButton .download-button:hover { 
    284         cursor: pointer; 
    285         background: #E75454; 
    286         padding: 8px 10px; 
    287         color: #fff; 
    288         -moz-border-radius: 3px; 
    289         -khtml-border-radius: 3px;       
    290         -webkit-border-radius: 3px; 
    291         border-radius: 4px; 
    292        width:180px; 
    293 } 
    294  
    295 #downloadButton a.download-button span { 
    296         color: #ffac90; 
    297 } 
    298  
    299 #downloadButton .download-tar { 
    300         font-size: 10px; 
    301         margin-top: -1px !important; 
    302         text-align: center; 
    303         margin-bottom: 13px !important; 
    304 } 
    305268</style> 
    306269{/literal} 
    307270 
     
    320283           {/foreach} 
    321284        </optgroup> 
    322285</select> 
    323 </span> | {if $userLogin=='anonymous'}<a href='?module=Login'>Login</a>{else}<a href='?module=Login&action=logout'>Logout</a>{/if}</a> 
     286</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> 
    324287</small> 
    325288</form> 
    326289</span> 
    327290 
    328291<span id="h1"><a href='http://piwik.org'>Piwik</a> </span><span id="subh1"> # open source web analytics</span><br> 
    329  
     292<br> 
    330293<div id="stuff"> 
    331294        <div> 
    332                 <span id="messageToUsers"> 
    333                 <a href='http://piwik.org'>Piwik</a> is a collaborative project and still Beta. If you want to help, please <u><a href="mailto:hello@piwik.org?subject=Piwik">contact us</a></u>. 
    334                 <span id='downloadButton'><a class="download-button" href="http://piwik.org/blog/2008/04/piwik-jobs/"><strong>Want to be paid to work on Piwik?</strong></a><br></span> 
    335                 </span>  
     295                <span id="messageToUsers"><a href='http://piwik.org'>Piwik</a> is a collaborative project and still Beta. If you want to help, please <u><a href="mailto:hello@piwik.org?subject=Piwik">contact us</a></u>.</span>  
    336296                {include file="Home/templates/links_misc_modules.tpl"} 
    337297        </div> 
    338298</div> 
     
    340300 
    341301<noscript> 
    342302<span id="javascriptDisable"> 
    343 JavaScript must be enabled in order for you to use Piwik in standard view.<br>  
    344 However, it seems JavaScript is either disabled or not supported by your browser.<br>  
    345 To use standard view, enable JavaScript by changing your browser options, then <a href=''>try again</a>.<br> 
     303{'Home_JavascriptDisabled'|translate:'<a href="">':'</a>'} 
    346304</span> 
    347305</noscript> 
    348306{include file="Home/templates/period_select.tpl"} 
    349307 
    350 <br> 
     308<br><br> 
    351309{include file="Home/templates/menu.tpl"} 
    352310 
    353311<div style='clear:both'></div> 
    354312 
    355 <div id="loadingPiwik" {if $basicHtmlView}style="display:none"{/if}><img src="themes/default/images/loading-blue.gif"> Loading data...</div> 
    356 <div id="loadingError">Oops&hellip; problem during the request, please try again.</div> 
     313<div id="loadingPiwik" {if $basicHtmlView}style="display:none"{/if}><img src="themes/default/images/loading-blue.gif"> {'General_LoadingData'|translate}</div> 
     314<div id="loadingError">{'General_ErrorRequest'|translate}</div> 
    357315<div id='content'> 
    358316{if $content}{$content}{/if} 
    359317</div> 
  • plugins/Home/Home.php

     
    2020                        'author' => 'Piwik', 
    2121                        'homepage' => 'http://piwik.org/', 
    2222                        'version' => '0.1', 
    23                         'translationAvailable' => false, 
     23                        'translationAvailable' => true, 
    2424                ); 
    2525        } 
    2626} 
  • plugins/Provider/Provider.php

     
    2323                        'author' => 'Piwik', 
    2424                        'homepage' => 'http://piwik.org/', 
    2525                        'version' => '0.1', 
     26                        'translationAvailable' => true, 
    2627                        'LogStatsPlugin' => true, // this plugin must be loaded during the stats logging 
    2728                ); 
    2829                 
     
    4849                Zend_Registry::get('db')->query($query); 
    4950        } 
    5051         
     52        function postLoad() 
     53        { 
     54                // when the plugin is loaded during LogStats these functions are not defined 
     55                if(function_exists('Piwik_AddWidget')) 
     56                { 
     57                        Piwik_AddWidget( 'Provider', 'getProvider', Piwik_Translate('Provider_WidgetProviders')); 
     58                        Piwik_RenameMenuEntry('Visitors', Piwik_Translate('UserCountry_SubmenuLocations'),  
     59                                                                        'Visitors', Piwik_Translate('Provider_SubmenuLocationsProvider')); 
     60                        Piwik_AddAction('template_headerUserCountry', array('Piwik_Provider','headerUserCountry')); 
     61                        Piwik_AddAction('template_footerUserCountry', array('Piwik_Provider','footerUserCountry')); 
     62                }                
     63        } 
     64         
    5165        function getListHooksRegistered() 
    5266        { 
    5367                $hooks = array( 
     
    166180        } 
    167181} 
    168182 
    169 // when the plugin is loaded during LogStats these functions are not defined 
    170 if(function_exists('Piwik_AddWidget')) 
    171 { 
    172         Piwik_AddWidget( 'Provider', 'getProvider', 'Providers'); 
    173         Piwik_RenameMenuEntry('Visitors', 'Locations', 'Visitors', 'Locations & provider' ); 
    174         Piwik_AddAction('template_headerUserCountry', array('Piwik_Provider','headerUserCountry')); 
    175         Piwik_AddAction('template_footerUserCountry', array('Piwik_Provider','footerUserCountry')); 
    176 } 
    177  brakuje znaku końca linii na końcu pliku  
  • plugins/Provider/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'Provider_WidgetProviders' => 'Providers', 
     4        'Provider_SubmenuLocationsProvider' => 'Locations & provider' 
     5); 
  • plugins/PluginsAdmin/PluginsAdmin.php

     
    1515        { 
    1616                return array( 
    1717                        // name must be the className prefix! 
    18                         'name' => 'Plugins administration', 
     18                        'name' => 'PluginsAdmin', 
    1919                        'description' => '', 
    2020                        'author' => 'Piwik', 
    2121                        'homepage' => 'http://piwik.org/', 
    2222                        'version' => '0.1', 
    23                         'translationAvailable' => false, 
     23                        'translationAvailable' => true, 
    2424                ); 
    2525        } 
     26         
     27        function postLoad() 
     28        { 
     29                Piwik_AddAdminMenu(Piwik_Translate('PluginsAdmin_MenuPlugins'), array('module' => 'PluginsAdmin'));              
     30        } 
    2631} 
    2732 
    2833 
    29 Piwik_AddAdminMenu('Plugins', array('module' => 'PluginsAdmin')); 
    30  
  • plugins/PluginsAdmin/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'PluginsAdmin_Plugins' => 'Plugins', 
     4        'PluginsAdmin_Activated' => 'Activated', 
     5        'PluginsAdmin_ActivatedHelp' => 'This plugin cannot be deactivated', 
     6        'PluginsAdmin_Deactivate' => 'Deactivate', 
     7        'PluginsAdmin_Activate' => 'Activate',   
     8 
     9        'PluginsAdmin_MenuPlugins' => 'Plugins', 
     10); 
  • plugins/PluginsAdmin/templates/manage.tpl

     
    2020        <td>{$plugin.info.description}&nbsp;</td> 
    2121        <td class="center"><a href="{$plugin.info.homepage}">{$plugin.info.author}</a></td> 
    2222        <td>{$plugin.info.version}</td> 
    23         <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> 
    24 {else}<a href=?module=PluginsAdmin&action=activate&pluginName={$name}>Activate</a>{/if}</td> 
     23        <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> 
     24{else}<a href=?module=PluginsAdmin&action=activate&pluginName={$name}>{'PluginsAdmin_Activate'|translate}</a>{/if}</td> 
    2525        </tr> 
    2626{/foreach} 
    2727 
  • plugins/Widgetize/templates/iframe.tpl

     
    11<html> 
    22<body> 
    33 
     4{loadJavascriptTranslations modules='Home'} 
     5 
    46<script type="text/javascript" src="libs/jquery/jquery.js"></script> 
    57<script type="text/javascript" src="themes/default/common.js"></script> 
    68<script type="text/javascript" src="libs/jquery/jquery.dimensions.js"></script> 
     
    1618{$content} 
    1719 
    1820</body> 
    19 </html> 
    20  brakuje znaku końca linii na końcu pliku  
     21</html> 
  • plugins/Widgetize/templates/js.tpl

     
     1{loadJavascriptTranslations noHtml=1 modules='Home'} 
     2 
    13document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.js"><\/scr'+'ipt>'); 
    24document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}themes/default/common.js"><\/scr'+'ipt>'); 
    35document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.dimensions.js"><\/scr'+'ipt>'); 
     
    1113document.write('<link rel="stylesheet" href="{$piwikUrl}plugins/Home/templates/datatable.css">'); 
    1214 
    1315var content = '{$content|escape:'javascript'}'; 
    14 document.write(content); 
    15  brakuje znaku końca linii na końcu pliku  
     16document.write(content); 
  • plugins/UsersManager/API.php

     
    185185                return $user; 
    186186        } 
    187187         
     188        /** 
     189         * Returns the user information (login, password md5, alias, email, date_registered, etc.) 
     190         *  
     191         * @param string the user email 
     192         *  
     193         * @return array the user information 
     194         */ 
     195        static public function getUserByEmail( $userEmail ) 
     196        { 
     197                Piwik::checkUserIsSuperUser(); 
     198                self::checkUserExists($userLogin); 
     199                 
     200                $db = Zend_Registry::get('db'); 
     201                $user = $db->fetchRow("SELECT *  
     202                                                                FROM ".Piwik::prefixTable("user") 
     203                                                                ." WHERE email = ?", $userEmail); 
     204                return $user; 
     205        } 
     206         
    188207        static private function checkLogin($userLogin) 
    189208        { 
    190209                if(self::userExists($userLogin)) 
    191210                { 
    192                         throw new Exception("Login $userLogin already exists."); 
     211                        throw new Exception(sprintf(Piwik_TranslateException('UsersManager_ExceptionLoginExists'),$userLogin)); 
    193212                } 
    194213                 
    195214                if(!self::isValidLoginString($userLogin)) 
    196215                { 
    197                         throw new Exception("The login must contain only letters, numbers, or the characters '_' or '-' or '.'"); 
     216                        throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLogin')); 
    198217                } 
    199218        } 
    200219                 
     
    202221        { 
    203222                if(!self::isValidPasswordString($password)) 
    204223                { 
    205                         throw new Exception("The password length must be between 6 and 26 characters."); 
     224                        throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidPassword')); 
    206225                } 
    207226        } 
    208227         
     
    210229        { 
    211230                if(!Piwik::isValidEmailString($email)) 
    212231                { 
    213                         throw new Exception("The email doesn't have a valid format."); 
     232                        throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidEmail')); 
    214233                } 
    215234        } 
    216235                 
     
    343362                 
    344363                if(!self::userExists($userLogin)) 
    345364                { 
    346                         throw new Exception("User '$userLogin' doesn't exist therefore it can't be deleted."); 
     365                        throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionDeleteDoesNotExist"),$userLogin)); 
    347366                } 
    348367                 
    349368                 
     
    364383                                                                                                        WHERE login = ?", $userLogin); 
    365384                return $count != 0; 
    366385        } 
     386         
     387        /** 
     388         * Returns true if user with given email (userEmail) is known in the database 
     389         * 
     390         * @return bool true if the user is known 
     391         */ 
     392          
     393        static public function userEmailExists( $userEmail ) 
     394        { 
     395                Piwik::checkUserHasSomeAdminAccess();    
     396                $count = Zend_Registry::get('db')->fetchOne("SELECT count(*)  
     397                                                                                                        FROM ".Piwik::prefixTable("user"). "  
     398                                                                                                        WHERE email = ?", $userEmail); 
     399                return $count != 0;      
     400        } 
    367401 
    368402        /** 
    369403         * Set an access level to a given user for a list of websites ID. 
     
    389423                if($userLogin == 'anonymous' 
    390424                        && $access == 'admin') 
    391425                { 
    392                         throw new Exception("You cannot grant 'admin' access to the 'anonymous' user."); 
     426                        throw new Exception(Piwik_TranslateException("UsersManager_ExceptionAdminAnonymous")); 
    393427                } 
    394428                 
    395429                // in case idSites is null we grant access to all the websites on which the current connected user 
     
    441475        { 
    442476                if(!self::userExists($userLogin)) 
    443477                { 
    444                         throw new Exception("User '$userLogin' doesn't exist."); 
     478                        throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist"),$userLogin)); 
    445479                } 
    446480        } 
    447481         
     
    449483        { 
    450484                if($userLogin == 'anonymous') 
    451485                { 
    452                         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."); 
     486                        throw new Exception(Piwik_TranslateException("UsersManager_ExceptionEditAnonymous")); 
    453487                } 
    454488        } 
    455489         
     
    462496                 
    463497                if(!in_array($access,$accessList)) 
    464498                { 
    465                         throw new Exception("The parameter access must have one of the following values : [ ". implode(", ", $accessList)." ]"); 
     499                        throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionAccessValues"),implode(", ", $accessList))); 
    466500                } 
    467501        } 
    468502         
     
    550584                return $l >= 6 && $l <= 26; 
    551585        } 
    552586 
    553 } 
    554  brakuje znaku końca linii na końcu pliku  
     587} 
  • plugins/UsersManager/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'UsersManager_ManageAccess' => 'Manage access', 
     4        'UsersManager_Sites' => 'Sites', 
     5        'UsersManager_AllWebsites' => 'All websites', 
     6        'UsersManager_ApplyToAllWebsites' => 'Apply to all websites', 
     7        'UsersManager_User' => 'User', 
     8        'UsersManager_PrivNone' => 'No access', 
     9        'UsersManager_PrivView' => 'View', 
     10        'UsersManager_PrivAdmin' => 'Admin', 
     11        'UsersManager_ChangeAllConfirm' => 'Are you sure you want to change \'%s\' permissions on all the websites?', 
     12        'UsersManager_Login' => 'Login', 
     13        'UsersManager_Password' => 'Password', 
     14        'UsersManager_Email' => 'Email', 
     15        'UsersManager_Alias' => 'Alias', 
     16        'UsersManager_Token' => 'token_auth', 
     17        'UsersManager_Edit' => 'Edit', 
     18        'UsersManager_AddUser' => 'Add a new user', 
     19         
     20        'UsersManager_MenuUsers' => 'Users', 
     21 
     22        'UsersManager_DeleteConfirm_js' => 'Are you sure you want to delete the user %s?', 
     23         
     24        'UsersManager_ExceptionLoginExists' => "Login '%s' already exists.", 
     25        'UsersManager_ExceptionInvalidLogin' => "The login must contain only letters, numbers, or the characters '_' or '-' or '.'", 
     26        'UsersManager_ExceptionInvalidPassword' => "The password length must be between 6 and 26 characters.", 
     27        'UsersManager_ExceptionInvalidEmail' => "The email doesn't have a valid format.", 
     28        'UsersManager_ExceptionDeleteDoesNotExist' => "User '%s' doesn't exist therefore it can't be deleted.", 
     29        'UsersManager_ExceptionAdminAnonymous' => "You cannot grant 'admin' access to the 'anonymous' user.", 
     30        '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.", 
     31        'UsersManager_ExceptionUserDoesNotExist' => "User '%s' doesn't exist.", 
     32        'UsersManager_ExceptionAccessValues' => "The parameter access must have one of the following values : [ %s ]", 
     33 
     34); 
  • plugins/UsersManager/UsersManager.php

     
    1919        { 
    2020                $info = array( 
    2121                        // name must be the className prefix! 
    22                         'name' => 'UserManager', 
     22                        'name' => 'UsersManager', 
    2323                        'description' => 'Description', 
    2424                        'author' => 'Piwik', 
    2525                        'homepage' => 'http://piwik.org/', 
    2626                        'version' => '0.1', 
    27                         'translationAvailable' => false, 
     27                        'translationAvailable' => true, 
    2828                ); 
    2929                 
    3030                return $info; 
    3131        } 
    3232         
     33        function postLoad() 
     34        { 
     35                Piwik_AddAdminMenu(Piwik_Translate('UsersManager_MenuUsers'), array('module' => 'UsersManager'));                
     36        } 
    3337} 
    3438 
    35 Piwik_AddAdminMenu('Users', array('module' => 'UsersManager')); 
    36  
    37  
  • plugins/UsersManager/templates/UsersManager.js

     
    222222                        ajaxHideError(); 
    223223                        var idRow = $(this).attr('id'); 
    224224                        var loginToDelete = $(this).parent().parent().find('#userLogin').html(); 
    225                         if(confirm('Are you sure you want to delete the user "'+loginToDelete+'"?')) 
     225                        if( confirm(sprintf(_pk_translate('UsersManager_DeleteConfirm','Are you sure you want to delete the user %s'),'"'+loginToDelete+'"')) ) 
    226226                        { 
    227227                                $.ajax( getDeleteUserAJAX( loginToDelete ) ); 
    228228                        } 
  • plugins/UsersManager/templates/UsersManager.tpl

     
     1{loadJavascriptTranslations modules='UsersManager'} 
    12<script type="text/javascript" src="libs/jquery/jquery.js"></script> 
    23<script type="text/javascript" src="themes/default/common.js"></script> 
    34<link rel="stylesheet" href="themes/default/common-admin.css"> 
     
    1819</style> 
    1920{/literal} 
    2021 
    21 <h2>Manage access</h2> 
     22<h2>{'UsersManager_ManageAccess'|translate}</h2> 
    2223 
    2324<div id="sites"> 
    2425<form method="post" action="{url actionToLoad=index}" id="accessSites"> 
    25         <p>Sites: <select id="selectIdsite" name="idsite" onchange="this.form.submit()"> 
     26        <p>{'UsersManager_Sites'|translate}: <select id="selectIdsite" name="idsite" onchange="this.form.submit()"> 
    2627         
    27         <optgroup label="All websites"> 
    28                 <option label="All websites" value="-1" {if $idSiteSelected==-1} selected="selected"{/if}>Apply to all websites</option> 
     28        <optgroup label="{'UsersManager_AllWebsites'|translate}"> 
     29                <option label="{'UsersManager_AllWebsites'|translate}" value="-1" {if $idSiteSelected==-1} selected="selected"{/if}>{'UsersManager_ApplyToAllWebsites'|translate}</option> 
    2930        </optgroup> 
    30         <optgroup label="Sites"> 
     31        <optgroup label="{'UsersManager_Sites'|translate}"> 
    3132                {foreach from=$websites item=info} 
    3233                        <option value="{$info.idsite}" {if $idSiteSelected==$info.idsite} selected="selected"{/if}>{$info.name}</option> 
    3334                {/foreach} 
     
    4041<table id="access"> 
    4142<thead> 
    4243<tr> 
    43         <th>User</th> 
    44         <th>No access</th> 
    45         <th>View</th> 
    46         <th>Admin</th> 
     44        <th>{'UsersManager_User'|translate}</th> 
     45        <th>{'UsersManager_PrivNone'|translate}</th> 
     46        <th>{'UsersManager_PrivView'|translate}</th> 
     47        <th>{'UsersManager_PrivAdmin'|translate}</th> 
    4748</tr> 
    4849</thead> 
    4950 
     
    6162</tbody> 
    6263</table> 
    6364 
    64 <div id="accessUpdated">Done!</div> 
     65<div id="accessUpdated">{'General_Done'|translate}!</div> 
    6566 
    6667<div class="dialog" id="confirm">  
    67         <p>Are you sure you want to change '<span id='login'></span>' permissions on all the websites?</p> 
    68         <input id="yes" type="button" value="Yes"/> 
    69         <input id="no" type="button" value="No"/> 
     68        <p>{'UsersManager_ChangeAllConfirm'|translate:"<span id='login'></span>"}</p> 
     69        <input id="yes" type="button" value="{'General_Yes'|translate}"/> 
     70        <input id="no" type="button" value="{'General_No'|translate}"/> 
    7071</div>  
    7172 
    7273<h2>Manage users</h2> 
    7374 
    7475<div id="ajaxError" style="display:none"></div> 
    75 <div id="ajaxLoading" style="display:none">Loading... <img src="themes/default/loading.gif"></div> 
     76<div id="ajaxLoading" style="display:none">{'General_LoadingData'|translate} <img src="themes/default/loading.gif"></div> 
    7677<table id="users"> 
    7778        <thead> 
    7879                <tr> 
    79                         <th>Login</th> 
    80                         <th>Password</th> 
    81                         <th>Email</th> 
    82                         <th>Alias</th> 
    83                         <th>token_auth</th> 
    84                         <th>Edit</th> 
    85                         <th>Delete</th> 
     80                        <th>{'UsersManager_Login'|translate}</th> 
     81                        <th>{'UsersManager_Password'|translate}</th> 
     82                        <th>{'UsersManager_Email'|translate}</th> 
     83                        <th>{'UsersManager_Alias'|translate}</th> 
     84                        <th>{'UsersManager_Token'|translate}</th> 
     85                        <th>{'General_Edit'|translate}</th> 
     86                        <th>{'General_Delete'|translate}</th> 
    8687                </tr> 
    8788        </thead> 
    8889         
     
    103104        </tbody> 
    104105</table> 
    105106 
    106 <div id="addrow"><img src='plugins/UsersManager/images/add.png'> Add a new user</div> 
     107<div id="addrow"><img src='plugins/UsersManager/images/add.png'> {'UsersManager_AddUser'|translate}</div> 
    107108<script type="text/javascript" src="plugins/UsersManager/templates/UsersManager.js"></script> 
  • plugins/UserSettings/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'UserSettings_BrowserFamilies' => 'Browser families', 
     4        'UserSettings_Browsers' => 'Browsers', 
     5        'UserSettings_Plugins' => 'Plugins', 
     6        'UserSettings_Configurations' => 'Configurations', 
     7        'UserSettings_OperatinsSystems' => 'Operating systems', 
     8        'UserSettings_Resolutions' => 'Resolutions', 
     9        'UserSettings_WideScreen' => 'Wide Screen', 
     10         
     11        'UserSettings_WidgetResolutions' => 'Screen resolutions', 
     12        'UserSettings_WidgetBrowsers' => 'Visitor browsers', 
     13        'UserSettings_WidgetPlugins' => 'List of Plugins', 
     14        'UserSettings_WidgetWidescreen' => 'Normal / Widescreen', 
     15        'UserSettings_WidgetBrowserFamilies' => 'Browsers by family', 
     16        'UserSettings_WidgetOperatingSystems' => 'Operating systems', 
     17        'UserSettings_WidgetGlobalVisitors' => 'Global visitors configuration', 
     18 
     19        'UserSettings_SubmenuSettings' => 'Settings', 
     20); 
  • plugins/UserSettings/UserSettings.php

     
    3838                        'author' => 'Piwik', 
    3939                        'homepage' => 'http://piwik.org/', 
    4040                        'version' => '0.1', 
     41                        'translationAvailable' => true, 
    4142                ); 
    4243                 
    4344                return $info; 
    4445        } 
    4546         
     47        function postLoad() 
     48        { 
     49                Piwik_AddWidget( 'UserSettings', 'getResolution', Piwik_Translate('UserSettings_WidgetResolutions')); 
     50                Piwik_AddWidget( 'UserSettings', 'getBrowser', Piwik_Translate('UserSettings_WidgetBrowsers')); 
     51                Piwik_AddWidget( 'UserSettings', 'getPlugin', Piwik_Translate('UserSettings_WidgetPlugins')); 
     52                Piwik_AddWidget( 'UserSettings', 'getWideScreen', Piwik_Translate('UserSettings_WidgetWidescreen')); 
     53                Piwik_AddWidget( 'UserSettings', 'getBrowserType', Piwik_Translate('UserSettings_WidgetBrowserFamilies')); 
     54                Piwik_AddWidget( 'UserSettings', 'getOS', Piwik_Translate('UserSettings_WidgetOperatingSystems')); 
     55                Piwik_AddWidget( 'UserSettings', 'getConfiguration', Piwik_Translate('UserSettings_WidgetGlobalVisitors')); 
     56 
     57                Piwik_AddMenu('Visitors', Piwik_Translate('UserSettings_SubmenuSettings'), array('module' => 'UserSettings')); 
     58        } 
     59         
    4660        function getListHooksRegistered() 
    4761        { 
    4862                $hooks = array( 
     
    204218        return strlen($value) > 5; 
    205219} 
    206220 
    207  
    208 Piwik_AddWidget( 'UserSettings', 'getResolution', 'Screen resolutions'); 
    209 Piwik_AddWidget( 'UserSettings', 'getBrowser', 'Visitor browsers'); 
    210 Piwik_AddWidget( 'UserSettings', 'getPlugin', 'List of Plugins'); 
    211 Piwik_AddWidget( 'UserSettings', 'getWideScreen', ' Normal / Widescreen'); 
    212 Piwik_AddWidget( 'UserSettings', 'getBrowserType', 'Browsers by family'); 
    213 Piwik_AddWidget( 'UserSettings', 'getOS', 'Operating systems'); 
    214 Piwik_AddWidget( 'UserSettings', 'getConfiguration', 'Global visitors configuration'); 
    215  
    216  
    217 Piwik_AddMenu('Visitors', 'Settings', array('module' => 'UserSettings')); 
  • plugins/UserSettings/index.tpl

     
    11<div id='leftcolumn'> 
    2         <h2>Browser families</h2> 
     2        <h2>{'UserSettings_BrowserFamilies'|translate}</h2> 
    33        {$dataTableBrowserType} 
    44         
    5         <h2>Browsers</h2> 
     5        <h2>{'UserSettings_Browsers'|translate}</h2> 
    66        {$dataTableBrowser} 
    77         
    8         <h2>Plugins</h2> 
     8        <h2>{'UserSettings_Plugins'|translate}</h2> 
    99        {$dataTablePlugin} 
    1010</div> 
    1111 
    1212<div id='rightcolumn'> 
    13         <h2>Configurations</h2> 
     13        <h2>{'UserSettings_Configurations'|translate}</h2> 
    1414        {$dataTableConfiguration} 
    1515         
    16         <h2>Operating systems</h2> 
     16        <h2>{'UserSettings_OperatinsSystems'|translate}</h2> 
    1717        {$dataTableOS} 
    1818         
    19         <h2>Resolutions</h2> 
     19        <h2>{'UserSettings_Resolutions'|translate}</h2> 
    2020        {$dataTableResolution} 
    2121         
    22         <h2>Wide Screen</h2> 
     22        <h2>{'UserSettings_WideScreen'|translate}</h2> 
    2323        {$dataTableWideScreen} 
    2424</div>   
    2525 
  • plugins/UserSettings/Controller.php

     
    114114                 
    115115                return $this->renderView($view, $fetch); 
    116116        } 
    117 } 
    118  brakuje znaku końca linii na końcu pliku  
     117} 
  • plugins/VisitsSummary/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'VisitsSummary_NbVisits' => '%s visits', 
     4        'VisitsSummary_NbUniqueVisitors' => '%s unique visitors', 
     5        'VisitsSummary_NbActions' => '%s actions (page views)', 
     6        'VisitsSummary_TotalTime' => '%s total time spent by the visitors', 
     7        'VisitsSummary_MaxNbActions' => '%s max actions in one visit', 
     8        'VisitsSummary_NbBounced' => '%s visitors have bounced (left the site after one page)', 
     9        'VisitsSummary_Evolution' => 'Evolution on the last 30 %ss', 
     10        'VisitsSummary_Report' => 'Report', 
     11        'VisitsSummary_GenerateTime' => '%s seconds to generate the page', 
     12        'VisitsSummary_GenerateQueries' => '%s queries executed', 
     13 
     14        'VisitsSummary_WidgetLastVisits' => 'Last visits graph', 
     15        'VisitsSummary_WidgetVisits' => 'Visits overview', 
     16        'VisitsSummary_WidgetLastVisitors' => 'Last unique visitors graph', 
     17        'VisitsSummary_WidgetOverviewGraph' => 'Overview with graph', 
     18 
     19        'VisitsSummary_SubmenuOverview' => 'Overview', 
     20 
     21); 
  • plugins/VisitsSummary/VisitsSummary.php

     
    1919        { 
    2020                $info = array( 
    2121                        // name must be the className prefix! 
    22                         'name' => 'Piwik_VisitsSummary', 
     22                        'name' => 'VisitsSummary', 
    2323                        'description' => 'Description', 
    2424                        'author' => 'Piwik', 
    2525                        'homepage' => 'http://piwik.org/', 
    2626                        'version' => '0.1', 
    27                         'translationAvailable' => false, 
     27                        'translationAvailable' => true, 
    2828                ); 
    2929                 
    3030                return $info; 
    3131        } 
    3232         
     33        function postLoad() 
     34        { 
     35                Piwik_AddWidget( 'VisitsSummary', 'getLastVisitsGraph', Piwik_Translate('VisitsSummary_WidgetLastVisits')); 
     36                Piwik_AddWidget( 'VisitsSummary', 'getSparklines', Piwik_Translate('VisitsSummary_WidgetVisits')); 
     37                Piwik_AddWidget( 'VisitsSummary', 'getLastUniqueVisitorsGraph', Piwik_Translate('VisitsSummary_WidgetLastVisitors')); 
     38                Piwik_AddWidget( 'VisitsSummary', 'index', Piwik_Translate('VisitsSummary_WidgetOverviewGraph')); 
     39 
     40                Piwik_AddMenu('Visitors', Piwik_Translate('VisitsSummary_SubmenuOverview'), array('module' => 'VisitsSummary'), true); 
     41        } 
    3342} 
    3443 
    3544require_once "ViewDataTable.php"; 
     
    122131                return $this->renderView($view, $fetch); 
    123132        } 
    124133         
    125 }                
     134} 
    126135 
    127 Piwik_AddWidget( 'VisitsSummary', 'getLastVisitsGraph', 'Last visits graph'); 
    128 Piwik_AddWidget( 'VisitsSummary', 'getSparklines', 'Visits overview'); 
    129 Piwik_AddWidget( 'VisitsSummary', 'getLastUniqueVisitorsGraph', 'Last unique visitors graph'); 
    130 Piwik_AddWidget( 'VisitsSummary', 'index', 'Overview with graph'); 
    131  
    132 Piwik_AddMenu('Visitors', 'Overview', array('module' => 'VisitsSummary'), true); 
    133  brakuje znaku końca linii na końcu pliku  
  • plugins/VisitsSummary/index.tpl

     
    11<script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 
    22 
    33<a name="evolutionGraph" graphId="VisitsSummarygetLastVisitsGraph"></a> 
    4 <h2>Evolution on the last 30 {$period}s</h2> 
     4<h2>{'VisitsSummary_Evolution'|translate:$period}</h2> 
    55{$graphEvolutionVisitsSummary} 
    66 
    7 <h2>Report</h2> 
     7<h2>{'VisitsSummary_Report'|translate}</h2> 
    88{include file=VisitsSummary/sparklines.tpl} 
    99 
    1010 
    1111<br><br><br> 
    12 <p style='color:lightgrey; size:0.8em;'>{$totalTimeGeneration} seconds {if $totalNumberOfQueries != 0}/ {$totalNumberOfQueries}  queries{/if} to generate the page</p> 
     12<p style='color:lightgrey; size:0.8em;'> 
     13{'VisitsSummary_GenerateTime'|translate:$totalTimeGeneration:$totalNumberOfQueries} 
     14{if $totalNumberOfQueries != 0}, {'VisitsSummary_GenerateQueries'|translate:$totalNumberOfQueries}{/if} 
     15</p> 
  • plugins/VisitsSummary/sparklines.tpl

     
    11<div id="to remove this div" class="parentDiv"> 
    2 <p><img class="sparkline" src="{$urlSparklineNbVisits}" /> <span><strong>{$nbVisits} </strong>visits</span></p> 
    3 <p><img class="sparkline" src="{$urlSparklineNbUniqVisitors}" /> <span><strong>{$nbUniqVisitors}</strong> unique visitors</span></p> 
    4 <p><img class="sparkline" src="{$urlSparklineNbActions}" /> <span><strong>{$nbActions}</strong> actions (page views)</span></p> 
    5 <p><img class="sparkline" src="{$urlSparklineSumVisitLength}" /> <span><strong>{$sumVisitLength|sumtime}</strong> total time spent by the visitors</span></p> 
    6 <p><img class="sparkline" src="{$urlSparklineMaxActions}" /> <span><strong>{$maxActions}</strong> max actions in one visit</span></p> 
    7 <p><img class="sparkline" src="{$urlSparklineBounceCount}" /> <span><strong>{$bounceCount} </strong>visitors have bounced (left the site after one page)</span></p> 
    8  
    9 </div> 
    10  brakuje znaku końca linii na końcu pliku  
     2<p><img class="sparkline" src="{$urlSparklineNbVisits}" /> <span> 
     3        {'VisitsSummary_NbVisits'|translate:"<strong>$nbVisits</strong>"}</span></p> 
     4<p><img class="sparkline" src="{$urlSparklineNbUniqVisitors}" /> <span> 
     5        {'VisitsSummary_NbUniqueVisitors'|translate:"<strong>$nbUniqVisitors</strong>"}</span></p> 
     6<p><img class="sparkline" src="{$urlSparklineNbActions}" /> <span> 
     7        {'VisitsSummary_NbActions'|translate:"<strong>$nbActions</strong>"}</span></p> 
     8<p><img class="sparkline" src="{$urlSparklineSumVisitLength}" /> <span> 
     9        {assign var=sumtimeVisitLength value=$sumVisitLength|sumtime} 
     10        {'VisitsSummary_TotalTime'|translate:"<strong>$sumtimeVisitLength</strong>"}</span></p> 
     11<p><img class="sparkline" src="{$urlSparklineMaxActions}" /> <span> 
     12        {'VisitsSummary_MaxNbActions'|translate:"<strong>$maxActions</strong>"}</span></p> 
     13<p><img class="sparkline" src="{$urlSparklineBounceCount}" /> <span> 
     14        {'VisitsSummary_NbBounced'|translate:"<strong>$bounceCount</strong>"}</span></p> 
     15</div> 
  • plugins/Actions/API.php

     
    6666        public function getDownloads( $idSite, $period, $date, $expanded = false, $idSubtable = false ) 
    6767        { 
    6868                $dataTable = $this->getDataTable('Actions_downloads', $idSite, $period, $date, $expanded, $idSubtable ); 
    69                 $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'url', create_function('$url', 'return $url;'))); 
     69                $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('full_url', 'url', create_function('$url', 'return $url;'))); 
    7070                $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromActionsUrl')); 
    7171                $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncateActionsPath')); 
    7272                 
     
    7676        public function getOutlinks( $idSite, $period, $date, $expanded = false, $idSubtable = false ) 
    7777        { 
    7878                $dataTable = $this->getDataTable('Actions_outlink', $idSite, $period, $date, $expanded, $idSubtable ); 
    79                 $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('label', 'url', create_function('$url', 'return $url;'))); 
     79                $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array('full_url', 'url', create_function('$url', 'return $url;'))); 
    8080                $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromActionsUrl')); 
    8181                $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncateActionsPath')); 
    8282                return $dataTable; 
  • plugins/Actions/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'Actions_SubmenuPages' => 'Pages', 
     4        'Actions_SubmenuOutlinks' => 'Outlinks', 
     5        'Actions_SubmenuDownloads' => 'Downloads', 
     6 
     7); 
  • plugins/Actions/Actions.php

     
    3737                        'author' => 'Piwik', 
    3838                        'homepage' => 'http://piwik.org/', 
    3939                        'version' => '0.1', 
     40                        'translationAvailable' => true 
    4041                ); 
    4142                 
    4243                return $info; 
     
    4950        function uninstall() 
    5051        { 
    5152        } 
    52          
     53 
     54        function postLoad() 
     55        { 
     56                Piwik_AddWidget( 'Actions', 'getActions', Piwik_Translate('Actions_SubmenuPages')); 
     57                Piwik_AddWidget( 'Actions', 'getDownloads', Piwik_Translate('Actions_SubmenuDownloads')); 
     58                Piwik_AddWidget( 'Actions', 'getOutlinks', Piwik_Translate('Actions_SubmenuOutlinks')); 
     59 
     60                Piwik_AddMenu('Actions', Piwik_Translate('Actions_SubmenuPages'), array('module' => 'Actions', 'action' => 'getActions')); 
     61                Piwik_AddMenu('Actions', Piwik_Translate('Actions_SubmenuOutlinks'), array('module' => 'Actions', 'action' => 'getOutlinks')); 
     62                Piwik_AddMenu('Actions', Piwik_Translate('Actions_SubmenuDownloads'), array('module' => 'Actions', 'action' => 'getDownloads'));                 
     63        } 
     64                 
    5365        function getListHooksRegistered() 
    5466        { 
    5567                $hooks = array( 
     
    282294                                $currentTable = new Piwik_DataTable_Row( 
    283295                                        array(  Piwik_DataTable_Row::COLUMNS =>  
    284296                                                        array(  'label' => (string)$actionName, 
     297                                                                        'full_url' => (string)$row['name'], 
    285298                                                                ) 
    286299                                                ) 
    287300                                        ); 
     
    330343                 
    331344                return $rowsProcessed; 
    332345        } 
    333  
    334346} 
    335347 
    336  
    337 Piwik_AddWidget( 'Actions', 'getActions', 'Pages'); 
    338 Piwik_AddWidget( 'Actions', 'getDownloads', 'Downloads'); 
    339 Piwik_AddWidget( 'Actions', 'getOutlinks', 'Outlinks'); 
    340  
    341 Piwik_AddMenu('Actions', 'Pages', array('module' => 'Actions', 'action' => 'getActions')); 
    342 Piwik_AddMenu('Actions', 'Outlinks', array('module' => 'Actions', 'action' => 'getOutlinks')); 
    343 Piwik_AddMenu('Actions', 'Downloads', array('module' => 'Actions', 'action' => 'getDownloads')); 
    344  
    345  
  • plugins/Installation/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'Installation_Installation' => 'Installation', 
     4        'Installation_InstallationStatus' => 'Installation status', 
     5        'Installation_PercentDone' => '%s %% Done', 
     6                 
     7        'Installation_NoConfigFound' =>  
     8                "The Piwik configuration file couldn't be found and you are trying to access a Piwik page.<br>". 
     9                "<b>&nbsp;&nbsp;&raquo; You can <a href='index.php'>install Piwik now</a></b>". 
     10                "<br><small>If you installed Piwik before and have some tables in your DB, don't worry,". 
     11                "you can reuse the same tables and keep your existing data!</small>", 
     12 
     13        'Installation_MysqlSetup' => 'Mysql database setup', 
     14        'Installation_MysqlErrorConnect' => 'Error while trying to connect to the Mysql database', 
     15 
     16        'Installation_JsTag' => 'Javascript tag',        
     17        'Installation_JsTagHelp' =>  
     18                '<p>To count all visitors, you must insert the javascript code on all of your pages.</p>'. 
     19                '<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>'. 
     20                '<p>Here is the code you have to insert: (copy and paste on all your pages) </p>', 
     21 
     22        'Installation_Congratulations' => 'Congratulations', 
     23        'Installation_ContratulationsHelp' =>  
     24                '<p>Congratulations! Your Piwik installation is complete.</p>'. 
     25                '<p>Make sure your javascript code is entered on your pages, and wait for your first visitors!</p>', 
     26        'Installation_GoToPiwik' => 'Go to Piwik', 
     27 
     28        'Installation_SetupWebsite' => 'Setup a website', 
     29        'Installation_SetupWebsiteError' => 'There was an error when adding the website', 
     30 
     31        'Installation_GeneralSetup' => 'General Setup', 
     32        'Installation_GeneralSetupSuccess' => 'General Setup configured with success', 
     33 
     34        'Installation_SystemCheck' => 'System check', 
     35        'Installation_SystemCheckPhp' => 'PHP version', 
     36        'Installation_SystemCheckPdo' => 'Pdo extension',                                
     37        'Installation_SystemCheckPdoMysql' => 'Pdo_Mysql extension', 
     38        'Installation_SystemCheckPdoError' => 'You need to enable the <code>php_pdo</code> and <code>php_pdo_mysql</code> extensions in your php.ini file.',                     
     39        'Installation_SystemCheckPdoErrorHelp' =>  
     40                "On a windows server you can add the lines      <code>extension=php_pdo.dll\nextension=php_pdo_mysql.dll</code> in your php.ini". 
     41                '<br><br>On a Linux server you can compile php with the following option <code>--with-pdo-mysql </code>'. 
     42                '<br><br>More information on the <a style="color:red" href="http://php.net/pdo">PHP website</a>.', 
     43        'Installation_SystemCheckPhpXml' => 'PHP-XML extension', 
     44        'Installation_SystemCheckWriteDirs' => 'Directories with write access', 
     45        'Installation_SystemCheckWriteDirsHelp' => 'To fix this error on your Linux system, try typing in the following command(s)', 
     46        'Installation_SystemCheckMemoryLimit' => 'Memory limit',         
     47        'Installation_SystemCheckMemoryLimitHelp' =>  
     48                'On a high traffic website, the archiving process may require more memory than currently allowed.'. 
     49                '<br>See the directive memory_limit in your php.ini file if necessary.', 
     50        'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)', 
     51        'Installation_SystemCheckGDHelp' => 'The sparklines (small graphs) will not work.', 
     52        'Installation_SystemCheckTimeLimit' => 'set_time_limit() allowed', 
     53        'Installation_SystemCheckTimeLimitHelp' =>  
     54                'On a high traffic website, executing the archiving process may require more time than currently allowed.'. 
     55                '<br>See the directive max_execution_time  in your php.ini file if necessary', 
     56        'Installation_SystemCheckMail' => 'mail() allowed', 
     57        'Installation_SystemCheckError' => 'An error occured - must be fixed before you proceed', 
     58        'Installation_SystemCheckWarning' => 'Piwik will work normally but some features may be missing', 
     59         
     60        'Installation_Tables' => 'Creating the tables', 
     61        'Installation_TablesWarning' => 'Some <span id="linkToggle">Piwik tables</span> are already installed in the DB', 
     62        'Installation_TablesFound' => 'The following tables have been found in the database', 
     63        'Installation_TablesWarningHelp' => 'Either choose to reuse the existing database tables or select a clean install to erase all existing data in the database.', 
     64        'Installation_TablesReuse' => 'Reuse the existing tables', 
     65        'Installation_TablesDelete' => 'Delete the detected tables', 
     66        'Installation_TablesDeletedSuccess' => 'Existing Piwik tables deleted with success', 
     67        'Installation_TablesCreatedSuccess' => 'Tables created with success!', 
     68        'Installation_TablesDeleteConfirm' => 'Are you sure you want to delete all the Piwik tables from this database?', 
     69 
     70        'Installation_Welcome' => 'Welcome!', 
     71        'Installation_WelcomeHelp' =>  
     72                '<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p>'. 
     73                '<p>This process is split up into %s easy steps and will take around 5 minutes.</p>',    
     74); 
  • plugins/Installation/Installation.php

     
    2929                        'author' => 'Piwik', 
    3030                        'homepage' => 'http://piwik.org/', 
    3131                        'version' => '0.1', 
    32                         'translationAvailable' => false, 
     32                        'translationAvailable' => true, 
    3333                ); 
    3434                 
    3535                return $info; 
     
    6767                } 
    6868                else 
    6969                { 
    70                         Piwik::exitWithErrorMessage(" 
    71                                 The Piwik configuration file couldn't be found and you are trying to access a Piwik page.<br> 
    72                                 <b>&nbsp;&nbsp;&raquo; You can <a href='index.php'>install Piwik now</a></b> 
    73                                 <br><small>If you installed Piwik before and have some tables in your DB, don't worry,  
    74                                 you can reuse the same tables and keep your existing data!</small>"); 
     70                        Piwik::exitWithErrorMessage(Piwik_Translate('Installation_NoConfigFound')); 
    7571                } 
    7672                exit; 
    7773        }        
    78 } 
    79  brakuje znaku końca linii na końcu pliku  
     74} 
  • plugins/Installation/templates/systemCheck.tpl

     
    22{assign var=error value="<img src='themes/default/images/error.png' />"} 
    33{assign var=warning value="<img src='themes/default/images/warning.png' />"} 
    44 
    5 <h1>System check</h1> 
     5<h1>{'Installation_SystemCheck'|translate}</h1> 
    66 
    77 
    88<table class="infosServer"> 
    99        <tr> 
    10                 <td class="label">PHP version &gt; {$infos.phpVersion_minimum}</td> 
     10                <td class="label">{'Installation_SystemCheckPhp'|translate} &gt; {$infos.phpVersion_minimum}</td> 
    1111                <td>{if $infos.phpVersion_ok}{$ok}{else}{$error}{/if}</td> 
    1212        </tr><tr> 
    13                 <td class="label">Pdo extension</td> 
     13                <td class="label">{'Installation_SystemCheckPdo'|translate}</td> 
    1414                <td>{if $infos.pdo_ok}{$ok} 
    1515                {else}{$error}{/if}      
    1616                </td> 
    1717        </tr>   
    1818        <tr> 
    19                 <td class="label">Pdo_Mysql extension</td> 
     19                <td class="label">{'Installation_SystemCheckPdoMysql'|translate}</td> 
    2020                <td>{if $infos.pdo_mysql_ok}{$ok} 
    2121                {else}{$error} 
    2222                {/if} 
    2323                 
    2424                {if !$infos.pdo_mysql_ok || !$infos.pdo_ok} 
    25                         <p class="error" style="width:80%">You need to enable the <code>php_pdo</code> and <code>php_pdo_mysql</code> extensions in your  
    26                         php.ini file. 
     25                        <p class="error" style="width:80%">{'Installation_SystemCheckPdoError'|translate} 
    2726                        <small> 
    28                         <br><br>On a windows server you can add the lines  
    29                         <code>extension=php_pdo.dll 
    30                                 extension=php_pdo_mysql.dll</code> in your php.ini  
    31                          
    32                         <br><br>On a Linux server you can compile php with the following option 
    33                         <code>--with-pdo-mysql </code>  
    34                          
    35                         <br><br>More information on the <a style="color:red" href='http://php.net/pdo'>PHP website</a>. 
     27                        <br><br> 
     28                        {'Installation_SystemCheckPdoErrorHelp'|translate} 
    3629                        </small> 
    3730                        </p> 
    3831                {/if} 
     
    4235         
    4336        {* We don't use utf8_encode currently but I think we will soon so I leave the code here 
    4437        <tr> 
    45                 <td class="label">PHP-XML extension <br> (utf8_decode function)</td> 
     38                <td class="label">{'Installation_SystemCheckPhpXml'|translate} <br> (utf8_decode function)</td> 
    4639            <td>{if $infos.phpXml_ok}{$ok}{else}{$error}{/if}</td> 
    4740        </tr> 
    4841        *} 
    4942        <tr> 
    5043                <td valign="top"> 
    51                         Directories with write access 
     44                        {'Installation_SystemCheckWriteDirs'|translate} 
    5245                </td> 
    5346                <td> 
    5447                        {foreach from=$infos.directories key=dir item=bool} 
     
    6457{if $problemWithSomeDirectories} 
    6558        <br> 
    6659        <div class="error"> 
    67                 To fix this error on your Linux system, try typing in the following command(s): 
     60                        {'Installation_SystemCheckWriteDirsHelp'|translate}: 
    6861        {foreach from=$infos.directories key=dir item=bool} 
    6962                <ul>{if !$bool} 
    7063                        <li>chmod a+w {$basePath}{$dir}</li> 
     
    7770<h1>Optional</h1> 
    7871<table class="infos"> 
    7972        <tr> 
    80                 <td class="label">Memory limit</td> 
     73                <td class="label">{'Installation_SystemCheckMemoryLimit'|translate}</td> 
    8174                <td> 
    8275                        {$infos.memoryCurrent} 
    8376                        {if $infos.memory_ok}{$ok}{else}{$warning}  
    84                                 <br><i>On a high traffic website, the archiving process may require more memory than currently allowed. 
    85                                 <br>See the directive memory_limit in your php.ini file if necessary.</i>{/if}   
     77                                <br><i>{'Installation_SystemCheckMemoryLimitHelp'|translate}</i>{/if}    
    8678                </td> 
    8779        </tr> 
    8880        <tr> 
    89                 <td class="label">GD &gt; 2.x (graphics)</td> 
     81                <td class="label">{'Installation_SystemCheckGD'|translate}</td> 
    9082                <td> 
    91                         {if $infos.gd_ok}{$ok}{else}{$warning} <br><i>The sparklines (small graphs) will not work.</i>{/if} 
     83                        {if $infos.gd_ok}{$ok}{else}{$warning} <br><i>{'Installation_SystemCheckGDHelp'|translate}</i>{/if} 
    9284                </td> 
    9385        </tr> 
    9486        <tr> 
    95                 <td class="label">set_time_limit() allowed</td> 
     87                <td class="label">{'Installation_SystemCheckTimeLimit'|translate}</td> 
    9688                <td>{if $infos.setTimeLimit_ok}{$ok}{else}{$warning} 
    97                         <br><i>On a high traffic website, executing the archiving process may require more time than currently allowed. 
    98                                 <br>See the directive max_execution_time  in your php.ini file if necessary.</i>{/if}</td> 
     89                        <br><i>{'Installation_SystemCheckTimeLimitHelp'|translate}</i>{/if}</td> 
    9990        </tr> 
    10091        <tr> 
    101                 <td class="label">mail() allowed</td> 
     92                <td class="label">{'Installation_SystemCheckMail'|translate}</td> 
    10293                <td>{if $infos.mail_ok}{$ok}{else}{$warning}{/if}</td> 
    10394        </tr> 
    10495</table> 
    10596<p><small> 
    10697Legend: 
    10798<br> 
    108 {$ok} Ok<br> 
    109 {$error} Error to be fixed<br> 
    110 {$warning} Warning: Piwik will work normally but some features may be missing<br> 
     99{$ok} {'General_Ok'|translate}<br> 
     100{$error} {'General_Error'|translate}: {'Installation_SystemCheckError'|translate} <br> 
     101{$warning} {'General_Warning'|translate}: {'Installation_SystemCheckWarning'|translate} <br> 
    111102</small></p> 
    112103 
    113104{if !$showNextStep} 
    114105<p class="nextStep"> 
    115         <a href="{url}">Refresh the page &raquo;</a> 
     106        <a href="{url}">{'General_Refresh'|translate} &raquo;</a> 
    116107</p> 
    117108 
    118109{/if} 
  • plugins/Installation/templates/databaseSetup.tpl

     
    1 <h1>Mysql database setup</h1> 
     1<h1>{'Installation_MysqlSetup'|translate}</h1> 
    22 
    33{if isset($errorMessage)} 
    44        <div class="error"> 
    55                <img src="themes/default/images/error_medium.png"> 
    6                 Error while trying to connect to the Mysql database: 
     6                {'Installation_MysqlErrorConnect'|translate}: 
    77                <br>{$errorMessage} 
    88                 
    99        </div> 
     
    1111 
    1212{if isset($form_data)} 
    1313        {include file=default/genericForm.tpl} 
    14 {/if} 
    15  brakuje znaku końca linii na końcu pliku  
     14{/if} 
  • plugins/Installation/templates/displayJavascriptCode.tpl

     
    3131        <img src="themes/default/images/success_medium.png"> 
    3232</span> 
    3333{/if} 
    34 <h1>Javascript tag</h1> 
    35 <p>To count all visitors, you must insert the javascript code on all of your pages.</p> 
    36 <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> 
    37 <p>Here is the code you have to insert: (copy and paste on all your pages) </P> 
     34<h1>{'Installation_JsTag'|translate}</h1> 
     35{'Installation_JsTagHelp'|translate} 
    3836<code> 
    3937{$javascriptTag} 
    4038</code> 
  • plugins/Installation/templates/finished.tpl

     
    1 <h1>Congratulations</h1> 
     1<h1>{'Installation_Congratulations'|translate}</h1> 
    22 
    3 <p>Congratulations! Your Piwik installation is complete.</p> 
     3{'Installation_ContratulationsHelp'|translate} 
    44 
    5 <p>Make sure your javascript code is entered on your pages,  
    6 and wait for your first visitors!</p> 
    75 
    8  
    96<p class="nextStep"> 
    10         <a href="{url module='' action=''}">Go to Piwik &raquo;</a> 
     7        <a href="{url module='' action=''}">{'Installation_GoToPiwik'|translate} &raquo;</a> 
    118</p> 
  • plugins/Installation/templates/firstWebsiteSetup.tpl

     
    22 
    33{if isset($displayGeneralSetupSuccess)} 
    44<span id="toFade" class="success"> 
    5         General Setup configured with success 
     5        {'Installation_GeneralSetupSuccess'|translate} 
    66        <img src="themes/default/images/success_medium.png"> 
    77</span> 
    88{/if} 
    99 
    10 <h1>Setup a website</h1> 
     10<h1>{'Installation_SetupWebsite'|translate}</h1> 
    1111 
    1212 
    1313 
    1414{if isset($errorMessage)} 
    1515        <div class="error"> 
    1616                <img src="themes/default/images/error_medium.png"> 
    17                 There was an error when adding the website: 
     17                {'Installation_SetupWebsiteError'|translate}: 
    1818                <br>- {$errorMessage} 
    1919                 
    2020        </div> 
     
    2323 
    2424{if isset($form_data)} 
    2525        {include file=default/genericForm.tpl} 
    26 {/if} 
    27  brakuje znaku końca linii na końcu pliku  
     26{/if} 
  • plugins/Installation/templates/welcome.tpl

     
    1 <h1>Welcome!</h1> 
    2 <p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p> 
     1<h1>{'Installation_Welcome'|translate}</h1> 
    32 
    4 <p>This process is split up into {$totalNumberOfSteps} easy steps and will take around 5 minutes.</p> 
    5  brakuje znaku końca linii na końcu pliku  
     3{'Installation_WelcomeHelp'|translate:$totalNumberOfSteps} 
  • plugins/Installation/templates/generalSetup.tpl

     
    1 <h1>General Setup</h1> 
     1<h1>{'Installation_GeneralSetup'|translate}</h1> 
    22 
    33{if isset($form_data)} 
    44        {include file=default/genericForm.tpl} 
    5 {/if} 
    6  brakuje znaku końca linii na końcu pliku  
     5{/if} 
  • plugins/Installation/templates/tablesCreation.tpl

     
    1 <h1>Creating the tables</h1> 
     1<h1>{'Installation_Tables'|translate}</h1> 
    22{if isset($someTablesInstalled)} 
    3         <div class="warning">Some <span id="linkToggle">Piwik tables</span> are already installed in the DB 
     3        <div class="warning">{'Installation_TablesWarning'|translate} 
    44        <img src="themes/default/images/warning_medium.png"> 
    55        </div> 
    6         <div id="toggle" style="display:none;color:#4F2410"><small><i>The following tables have been found in the database:  
     6        <div id="toggle" style="display:none;color:#4F2410"><small><i>{'Installation_TablesFound'|translate}: 
    77                <br>{$tablesInstalled} </i></small></div> 
    88 
    9         <p>Either choose to reuse the existing database tables or select a clean install  
    10         to erase all existing data in the database.</p> 
     9        <p>{'Installation_TablesWarningHelp'|translate}</p> 
    1110         
    12         <p class="nextStep"><a href="{url action=$nextModuleName}">Reuse the existing tables &raquo;</a></p> 
    13         <p class="nextStep" id="eraseAllTables"><a href="{url deleteTables=1}">Delete the detected tables &raquo;</a></p> 
     11        <p class="nextStep"><a href="{url action=$nextModuleName}">{'Installation_TablesReuse'|translate} &raquo;</a></p> 
     12        <p class="nextStep" id="eraseAllTables"><a href="{url deleteTables=1}">{'Installation_TablesDelete'|translate} &raquo;</a></p> 
    1413                                 
    1514{/if} 
    1615 
    1716{if isset($existingTablesDeleted)} 
    18         <div class="success"> Existing Piwik tables deleted with success 
     17        <div class="success"> {'Installation_TablesDeletedSuccess'|translate}  
    1918        <img src="themes/default/images/success_medium.png"></div> 
    2019{/if} 
    2120 
    2221 
    2322{if isset($tablesCreated)} 
    24         <div class="success"> Tables created with success!  
     23        <div class="success"> {'Installation_TablesCreatedSuccess'|translate}  
    2524        <img src="themes/default/images/success_medium.png"></div> 
    2625{/if} 
    2726 
     
    3231{literal} 
    3332<script> 
    3433$(document).ready( function(){ 
    35         var strConfirmEraseTables = "Are you sure you want to delete all the Piwik tables from this database?"; 
     34        {/literal} 
     35        var strConfirmEraseTables = "{'Installation_TablesDeleteConfirm'|translate} "; 
     36        {literal}        
    3637         
    3738        // toggle the display of the tables detected during the installation when clicking 
    3839        // on the span "linkToggle" 
     
    6465        ; 
    6566}); 
    6667</script> 
    67 {/literal} 
    68  brakuje znaku końca linii na końcu pliku  
     68{/literal} 
  • plugins/Installation/templates/structure.tpl

     
    11 
    22<html> 
    33<head> 
    4 <title>Piwik &raquo; Installation</title> 
     4<title>Piwik &raquo; {'Installation_Installation'|translate}</title> 
    55</head> 
    66<body> 
    77 
     
    194194                        {include file="$subTemplateToLoad"} 
    195195                        {if $showNextStep} 
    196196                                <p class="nextStep"> 
    197                                         <a href="{url action=$nextModuleName}">Next &raquo;</a> 
     197                                        <a href="{url action=$nextModuleName}">{'General_Next'|translate} &raquo;</a> 
    198198                                </p> 
    199199                        {/if} 
    200200                </div> 
    201201                 
    202202                <div class="both"></div> 
    203203                 
    204                 <h3>Installation status</h3> 
     204                <h3>{'Installation_InstallationStatus'|translate}</h3> 
    205205                 
    206206                <div id="installPercent"> 
    207207                <p style="width: {$percentDone}%;"></p> 
    208208        </div> 
    209209         
    210         {$percentDone}% Done 
     210        {'Installation_PercentDone'|translate:$percentDone}  
    211211</div> 
  • plugins/AdminHome/templates/index.tpl

     
    4242</div> 
    4343 
    4444<div id="footer" style="border-top:1px solid gray; margin-top:20px;padding-top:10px;"> 
    45 <a href='?module=Home'>Back to Piwik homepage</a> 
     45<a href='?module=Home'>{'General_BackToHomepage'|translate}</a> 
    4646 
    4747</div> 
  • plugins/UserCountry/lang/en.php

     
    11<?php 
    22$translations = array ( 
    33 
     4        'UserCountry_Country' => 'Country', 
     5        'UserCountry_Continent' => 'Continent', 
     6        'UserCountry_DistinctCountries' => '%s distinct countries', 
     7        'UserCountry_SubmenuLocations' => 'Locations', 
     8        'UserCountry_WidgetContinents' => 'Visitor continents', 
     9        'UserCountry_WidgetCountries' => 'Visitor countries', 
     10         
    411        // Countries 
    512        'country_ac' => 'Ascension Islands', 
    613        'country_ad' => 'Andorra', 
  • plugins/UserCountry/index.tpl

     
    22 
    33<script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 
    44 
    5 <h2>Country</h2> 
     5<h2>{'UserCountry_Country'|translate}</h2> 
    66{$dataTableCountry} 
    77 
    8 <h2>Continent</h2> 
     8<h2>{'UserCountry_Continent'|translate}</h2> 
    99{$dataTableContinent} 
    1010 
    11 <p><img class="sparkline" src="{$urlSparklineCountries}" /> <span><strong>{$numberDistinctCountries} </strong> distinct countries</span></p>     
     11<p><img class="sparkline" src="{$urlSparklineCountries}" /> <span> 
     12{'UserCountry_DistinctCountries'|translate:"<strong>$numberDistinctCountries</strong>"} </span></p>      
    1213 
    13 {postEvent name="template_footerUserCountry"} 
    14  brakuje znaku końca linii na końcu pliku  
     14{postEvent name="template_footerUserCountry"} 
  • plugins/UserCountry/UserCountry.php

     
    3030                return $info; 
    3131        } 
    3232         
     33        public function postLoad() 
     34        { 
     35                Piwik_AddWidget( 'UserCountry', 'getContinent', Piwik_Translate('UserCountry_WidgetContinents')); 
     36                Piwik_AddWidget( 'UserCountry', 'getCountry', Piwik_Translate('UserCountry_WidgetCountries')); 
     37 
     38                Piwik_AddMenu('Visitors', Piwik_Translate('UserCountry_SubmenuLocations'), array('module' => 'UserCountry')); 
     39        } 
     40         
    3341        function getListHooksRegistered() 
    3442        { 
    3543                $hooks = array( 
     
    140148         
    141149} 
    142150 
    143 Piwik_AddWidget( 'UserCountry', 'getContinent', 'Visitor continents'); 
    144 Piwik_AddWidget( 'UserCountry', 'getCountry', 'Visitor countries'); 
    145  
    146 Piwik_AddMenu('Visitors', 'Locations', array('module' => 'UserCountry')); 
    147  
  • plugins/Login/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'Login_PluginDescription' => 'Login screen, gives credentials to users', 
     4        'Login_LoginPasswordNotCorrect' => 'Username & Password not correct', 
     5        'Login_Login' => 'Username', 
     6        'Login_Password' => 'Password', 
     7        'Login_LoginOrEmail' => 'Login or E-mail', 
     8        'Login_LogIn' => 'Log in', 
     9        'Login_Logout' => 'Logout', 
     10        'Login_LostYourPassword' => 'Lost your password?',       
     11        'Login_RemindPassword' => 'Remind password', 
     12        'Login_PasswordReminder' => 'Please enter your username and e-mail address. We will send you a new password to your mailbox.', 
     13        'Login_InvalidUsernameEmail' => 'Invalid username and/or e-mail address', 
     14         
     15        'Login_MailTopicPasswordRecovery' => 'Password recovery', 
     16        'Login_MailBodyPasswordRecovery' => "Hi %1s,\n\nYour new password is: %2s\n\nYou can login now at: %3s", 
     17        'Login_PasswordSent' => 'Password has been just sent. Check your e-mail.' 
     18); 
  • plugins/Login/lang/fr.php

     
     1<?php 
     2$translations = array( 
     3        'Login_LoginPasswordNotCorrect' => 'Utilisateur & Mot de passe not correct', 
     4        'Login_Login' => 'Utilisateur', 
     5        'Login_Password' => 'Mot de passe', 
     6        'Login_LogIn' => 'Log in',       
     7); 
  • plugins/Login/Controller.php

     
    1111 
    1212require_once "UsersManager/API.php"; 
    1313require_once "Login/Form.php"; 
     14require_once "Login/PasswordForm.php"; 
    1415require_once "View.php"; 
    1516 
    1617 
     
    2930        { 
    3031                $form = new Piwik_Login_Form; 
    3132                $AccessErrorString = false; 
    32                  
     33 
     34                $currentUrl = Piwik_Url::getCurrentUrl(); 
     35                // get url from POSTed form or GET parameter (getting back from password remind form) 
     36                $urlToRedirect = Piwik_Common::getRequestVar('form_url', htmlspecialchars($currentUrl), 'string'); 
     37                                         
    3338                if($form->validate()) 
    3439                { 
    3540                        // value submitted in form 
     
    3742                        $password = $form->getSubmitValue('form_password'); 
    3843                        $password = md5($password); 
    3944                         
    40                         $baseUrl = Piwik_Url::getCurrentUrlWithoutQueryString();  
    41                         $currentUrl = Piwik_Url::getCurrentUrl();                
    42                         $urlToRedirect = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string', $_POST); 
    43                          
    44                         $urlToRedirect = htmlspecialchars_decode($urlToRedirect); 
    45                          
    4645                        $tokenAuth = Piwik_UsersManager_API::getTokenAuth($login, $password); 
    4746         
    4847                        Piwik_Login::prepareAuthObject($login, $tokenAuth); 
     
    5958                                $cookie->set('token_auth', $tokenAuth); 
    6059                                $cookie->save(); 
    6160                                 
     61                                $urlToRedirect = htmlspecialchars_decode($urlToRedirect);                                
    6262                                Piwik_Url::redirectToUrl($urlToRedirect); 
    6363                        } 
    6464                        else 
     
    6666                                $messageNoAccess = Piwik_Translate('Login_LoginPasswordNotCorrect'); 
    6767                        } 
    6868                } 
    69                 $view = new Piwik_View('Login/templates/login.tpl');     
     69                $view = new Piwik_View('Login/templates/login.tpl'); 
     70                // make navigation login form -> reset password -> login form remember your first url 
     71                $view->urlToRedirect = $urlToRedirect; 
    7072                $view->AccessErrorString = $messageNoAccess; 
    7173                $view->linkTitle = Piwik::getRandomTitle(); 
    7274                $view->addForm( $form ); 
     
    7476                echo $view->render(); 
    7577        } 
    7678         
     79        function lostpassword($messageNoAccess = null) 
     80        { 
     81                $form = new Piwik_Login_PasswordForm; 
     82                $AccessErrorString = false; 
     83                 
     84                $currentUrl = Piwik_Url::getCurrentUrlWithoutQueryString();      
     85                $urlToRedirect = Piwik_Common::getRequestVar('form_url', htmlspecialchars($currentUrl), 'string'); 
     86                 
     87                if($form->validate()) 
     88                { 
     89                        // value submitted in form (login or email) 
     90                        $loginMail = $form->getSubmitValue('form_login'); 
     91 
     92                        // get admin privileges before calling API 
     93                        Piwik::setUserIsSuperUser(); 
     94                         
     95                        $user = null; 
     96                         
     97                        // determine if given value is login or email 
     98                        if( Piwik_UsersManager_API::userExists($loginMail) ) 
     99                        { 
     100                                $user = Piwik_UsersManager_API::getUser($loginMail); 
     101                        } 
     102                        else if( Piwik_UsersManager_API::userEmailExists($loginMail) ) 
     103                        { 
     104                                $user = Piwik_UsersManager_API::getUserByEmail($loginMail); 
     105 
     106                        } 
     107                         
     108                        // if user exists 
     109                        if( $user != null ) 
     110                        { 
     111                                $login = $user['login']; 
     112                                $email = $user['email']; 
     113                                                         
     114                                $randomPassword = Piwik_Common::getRandomString(8); 
     115                                 
     116                                Piwik_UsersManager_API::updateUser($login, $randomPassword); 
     117 
     118                                // send email with new password 
     119                                $mail = new Piwik_Mail();                                
     120                                $mail->addTo($email, $login); 
     121                                $mail->setSubject(Piwik_Translate('Login_MailTopicPasswordRecovery'));                           
     122                                $mail->setBodyText(sprintf(Piwik_Translate('Login_MailBodyPasswordRecovery'), 
     123                                        $login, $randomPassword, Piwik_Url::getCurrentUrlWithoutQueryString()));                                 
     124                                $mail->send(); 
     125                                                 
     126                                $view = new Piwik_View('Login/templates/passwordsent.tpl'); 
     127                                $view->linkTitle = Piwik::getRandomTitle(); 
     128                                $view->urlToRedirect = $urlToRedirect; 
     129                                echo $view->render(); 
     130 
     131                                return; 
     132                        } 
     133                        else 
     134                        { 
     135                                $messageNoAccess = Piwik_Translate('Login_InvalidUsernameEmail'); 
     136                        } 
     137                }        
     138                $view = new Piwik_View('Login/templates/lostpassword.tpl');      
     139                $view->AccessErrorString = $messageNoAccess; 
     140                // make navigation login form -> reset password -> login form remember your first url            
     141                $view->urlToRedirect = $urlToRedirect; 
     142                $view->linkTitle = Piwik::getRandomTitle(); 
     143                $view->addForm( $form ); 
     144                $view->subTemplate = 'genericForm.tpl'; 
     145                echo $view->render();            
     146        } 
     147         
    77148        function logout() 
    78149        {                
    79150                $authCookieName = 'piwik-auth'; 
  • plugins/Login/Form.php

     
    2626         
    2727        function init() 
    2828        { 
    29                 $urlToGoAfter = Piwik_Url::getCurrentUrl();                      
     29                // if form_url is not defined go to current url 
     30                $urlToGoAfter = Piwik_Common::getRequestVar('form_url', Piwik_Url::getCurrentUrl(), 'string'); 
    3031                 
    3132                // if the current url to redirect contains module=login we insteaed redirect to the referer url 
    3233                if(stripos($urlToGoAfter,'module=login') !== false) 
  • plugins/Login/PasswordForm.php

     
     1<?php 
     2/** 
     3 * Piwik - Open source web analytics 
     4 *  
     5 * @link http://piwik.org 
     6 * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later 
     7 * @version $Id: Form.php 390 2008-03-19 01:31:11Z matt $ 
     8 *  
     9 * @package Piwik_Login 
     10 */ 
     11 
     12require_once "modules/Form.php"; 
     13 
     14/** 
     15 *  
     16 * @package Piwik_Login 
     17 */ 
     18class Piwik_Login_PasswordForm extends Piwik_Form 
     19{ 
     20        function __construct() 
     21        { 
     22                parent::__construct(); 
     23                // reset  
     24                $this->updateAttributes('id="loginform" name="loginform"'); 
     25        } 
     26         
     27        function init() 
     28        { 
     29                $urlToGoAfter = Piwik_Common::getRequestVar('form_url', Piwik_Url::getCurrentUrlWithoutQueryString(), 'string'); 
     30                         
     31                $formElements = array( 
     32                        array('text', 'form_login'), 
     33                        array('hidden', 'form_url', $urlToGoAfter), 
     34                ); 
     35                $this->addElements( $formElements ); 
     36                 
     37                $formRules = array( 
     38                        array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_LoginOrEmail')), 'required'),            
     39                        array('hidden', 'form_url', $urlToGoAfter),                      
     40                ); 
     41                $this->addRules( $formRules );   
     42                 
     43                $this->addElement('submit', 'submit');   
     44        } 
     45         
     46         
     47} 
     48 
  • plugins/Login/templates/login.css

     
    3737 
    3838form p { margin-bottom: 24px; } 
    3939 
     40.updated, .login #login_error, .login .message { 
     41        background-color: #ffffe0; 
     42        border-color: #e6db55; 
     43} 
     44 
    4045#login { width: 292px; margin: 7em auto; margin-top: 20px; } 
    4146 
    42 #login_error { 
     47#login_error, .message { 
    4348        margin: 0 0 16px 8px; 
    4449        border-width: 1px; 
    4550        border-style: solid; 
  • plugins/Login/templates/lostpassword.tpl

     
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     2<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> 
     3<head> 
     4        <title>Piwik &rsaquo; Lost password</title> 
     5        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     6         
     7        {literal} 
     8        <script type="text/javascript"> 
     9                function focusit() { 
     10                        document.getElementById('form_login').focus(); 
     11                } 
     12                window.onload = focusit; 
     13        </script> 
     14        {/literal} 
     15<link rel="stylesheet" href="plugins/Login/templates/login.css"> 
     16</head> 
     17 
     18<body class="login"> 
     19<!-- shamelessly taken from wordpress 2.5 - thank you guys!!! --> 
     20 
     21<div id="logo"> 
     22        <a href="http://piwik.org" title="{$linkTitle}"><span class="h1">Piwik <span class="description"># open source web analytics</span></span></a> 
     23</div> 
     24 
     25<div id="login"> 
     26 
     27{if $form_data.errors} 
     28<div id="login_error">   
     29        {foreach from=$form_data.errors item=data} 
     30                <strong>{'General_Error'|translate}</strong>: {$data}<br /> 
     31        {/foreach} 
     32</div> 
     33{/if} 
     34 
     35{if $AccessErrorString} 
     36<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div> 
     37{/if} 
     38 
     39<p class="message"> 
     40{'Login_PasswordReminder'|translate} 
     41</p> 
     42 
     43<form {$form_data.attributes}> 
     44 
     45        <p> 
     46                <label>{'Login_LoginOrEmail'|translate}:<br /> 
     47                <input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label> 
     48        </p> 
     49        {$form_data.form_url.html} 
     50        <p class="submit"> 
     51                <input type="submit" value="{'Login_RemindPassword'|translate}" tabindex="100" /> 
     52        </p> 
     53</form> 
     54 
     55 
     56<p id="nav"> 
     57<a href="?module=Login&form_url={$urlToRedirect}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a> 
     58</p> 
     59 
     60</div> 
     61 
     62</body> 
     63</html> 
     64 
     65 
     66 
  • plugins/Login/templates/login.tpl

     
    2727{if $form_data.errors} 
    2828<div id="login_error">   
    2929        {foreach from=$form_data.errors item=data} 
    30                 <strong>ERROR</strong>: {$data}<br /> 
     30                <strong>{'General_Error'|translate}</strong>: {$data}<br /> 
    3131        {/foreach} 
    3232</div> 
    3333{/if} 
    3434 
    3535{if $AccessErrorString} 
    36 <div id="login_error"><strong>ERROR</strong>: {$AccessErrorString}<br /></div> 
     36<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div> 
    3737{/if} 
    3838 
    3939<form {$form_data.attributes}> 
    4040        <p> 
    41                 <label>{'Login_Login'|translate}<br /> 
     41                <label>{'Login_Login'|translate}:<br /> 
    4242                <input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label> 
    4343        </p> 
    4444 
    4545        <p> 
    46                 <label>{'Login_Password'|translate}<br /> 
     46                <label>{'Login_Password'|translate}:<br /> 
    4747                <input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label> 
    4848        </p> 
    4949        {* 
     
    5555        </p> 
    5656</form> 
    5757 
    58 {* 
     58 
    5959<p id="nav"> 
    60 <a href="" title="Password Lost and Found">Lost your password?</a> 
     60<a href="?module=Login&action=lostpassword&form_url={$urlToRedirect}" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a> 
    6161</p> 
    62 *} 
     62 
    6363</div> 
    6464 
    6565</body> 
  • plugins/Login/templates/passwordsent.tpl

     
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     2<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> 
     3<head> 
     4        <title>Piwik &rsaquo; Lost password</title> 
     5        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     6        <link rel="stylesheet" href="plugins/Login/templates/login.css"> 
     7</head> 
     8 
     9<body class="login"> 
     10<!-- shamelessly taken from wordpress 2.5 - thank you guys!!! --> 
     11 
     12<div id="logo"> 
     13        <a href="http://piwik.org" title="{$linkTitle}"><span class="h1">Piwik <span class="description"># open source web analytics</span></span></a> 
     14</div> 
     15 
     16<div id="login"> 
     17 
     18<p class="message"> 
     19{'Login_PasswordSent'|translate} 
     20</p> 
     21 
     22<p id="nav"> 
     23<a href="?module=Login&form_url={$urlToRedirect}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a> 
     24</p> 
     25 
     26</div> 
     27 
     28</body> 
     29</html> 
     30 
     31 
     32 
  • plugins/Login/Login.php

     
    2727                        'author' => 'Piwik', 
    2828                        'homepage' => 'http://piwik.org/', 
    2929                        'version' => '0.1', 
    30                         'translationAvailable' => false, 
     30                        'translationAvailable' => true, 
    3131                ); 
    3232                 
    3333                return $info; 
  • plugins/API/API.php

     
    2020                        'author' => 'Piwik', 
    2121                        'homepage' => 'http://piwik.org/', 
    2222                        'version' => '0.1', 
    23                         'translationAvailable' => false, 
     23                        'translationAvailable' => true, 
    2424                ); 
    2525        } 
    2626} 
  • plugins/API/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'API_QuickDocumentation' =>  
     4                "<h1>API quick documentation</h1>". 
     5                "<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>". 
     6                "<p>You can try the different formats available for every method. It is very easy to extract any data you want from piwik!</p>". 
     7                "<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>". 
     8                "<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>", 
     9        'API_LoadedAPIs' => 'Loaded successfully %s APIs', 
     10         
     11 
     12); 
  • plugins/API/Controller.php

     
    5656        { 
    5757                $token_auth = Zend_Registry::get('auth')->getTokenAuth(); 
    5858                echo "<style>body{ font-family:georgia,arial; font-size:0.95em;} </style>"; 
    59                 echo "<h1>API quick documentation</h1>"; 
    60                 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>"; 
    61                 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>"; 
    62                 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>"; 
    63                 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>"; 
     59                echo sprintf(Piwik_Translate('API_QuickDocumentation'),$token_auth); 
    6460 
     61 
    6562                $loaded = $this->init(); 
    66                 echo "<p><i> Loaded successfully $loaded APIs</i></p>\n"; 
     63                echo "<p><i> ".sprintf(Piwik_Translate('API_LoadedAPIs'),$loaded)."</i></p>\n"; 
    6764                 
    6865                echo Piwik_API_Proxy::getInstance()->getAllInterfaceString(); 
    69                 echo "<p><a href='?module=Home'>Back to Piwik homepage</a></p>"; 
     66                echo "<p><a href='?module=Home'>".Piwik_Translate('General_BackToHomepage')."</a></p>"; 
    7067        } 
    7168         
    7269} 
  • plugins/Referers/lang/en.php

     
    11<?php 
    22$translations = array( 
     3        'Referers_SearchEngines' => 'Search Engines', 
     4         
     5        'Referers_Keywords' => 'Keywords', 
    36        'Referers_DirectEntry' => 'Direct Entry', 
    4         'Referers_SearchEngines' => 'Search Engines', 
    5         'Referers_Websites' => 'Websites', 
    6         'Referers_Partners' => 'Partners', 
    7         'Referers_Newsletters' => 'Newsletters', 
    8         'Referers_Campaigns' => 'Campaigns', 
     7         
     8        'Referers_Evolution' => 'Evolution over the period', 
     9         
     10        'Referers_Type' => 'Referer Type',       
     11        'Referers_TypeDirectEntries' => '%s direct entries', 
     12        'Referers_TypeSearchEngines' => '%s from search engines', 
     13        'Referers_TypePartners' => '%s from partners', 
     14        'Referers_TypeWebsites' => '%s from websites', 
     15        'Referers_TypeNewsletters' => '%s from newsletters', 
     16        'Referers_TypeCampaigns' => '%s from campaigns', 
     17         
     18        'Referers_Other' => 'Other', 
     19        'Referers_OtherDistinctSearchEngines' => '%s distinct search engines', 
     20        'Referers_OtherDistinctKeywords' => '%s distinct keywords', 
     21        'Referers_OtherDistinctWebsites' => '%1s distinct websites (using %2s distinct urls)', 
     22        'Referers_OtherDistinctPartners' => '%1s distinct partners (using %2s distinct urls)', 
     23        'Referers_OtherDistinctCampaigns' => '%s distinct campaigns', 
     24         
     25        'Referers_TagCloud' => 'Tag cloud output', 
     26         
     27        'Referers_SubmenuEvolution' => 'Evolution', 
     28        'Referers_SubmenuSearchEngines' => 'Search engines & keywords', 
     29        'Referers_SubmenuWebsites' => 'Websites', 
     30        'Referers_SubmenuCampaigns' => 'Campaigns', 
     31        'Referers_SubmenuPartners' => 'Partners', 
     32 
     33        'Referers_WidgetKeywords' => 'List of Keywords', 
     34        'Referers_WidgetPartners' => 'List of Partners', 
     35        'Referers_WidgetCampaigns' => 'List of Campaigns', 
     36        'Referers_WidgetExternalWebsites' => 'List of external Websites', 
     37        'Referers_WidgetSearchEngines' => 'Best search engines', 
     38        'Referers_WidgetOverview' => 'Overview', 
     39 
    940); 
    1041  
  • plugins/Referers/Referers.php

     
    3434                 
    3535                return $info; 
    3636        } 
     37         
     38        function postLoad() 
     39        { 
     40                Piwik_AddWidget( 'Referers', 'getKeywords', Piwik_Translate('Referers_WidgetKeywords')); 
     41                Piwik_AddWidget( 'Referers', 'getPartners', Piwik_Translate('Referers_WidgetPartners')); 
     42                Piwik_AddWidget( 'Referers', 'getCampaigns', Piwik_Translate('Referers_WidgetCampaigns')); 
     43                Piwik_AddWidget( 'Referers', 'getWebsites', Piwik_Translate('Referers_WidgetExternalWebsites')); 
     44                Piwik_AddWidget( 'Referers', 'getSearchEngines', Piwik_Translate('Referers_WidgetSearchEngines')); 
     45                Piwik_AddWidget( 'Referers', 'getRefererType', Piwik_Translate('Referers_WidgetOverview')); 
     46 
     47                Piwik_AddMenu('Referers', Piwik_Translate('Referers_SubmenuEvolution'), array('module' => 'Referers')); 
     48                Piwik_AddMenu('Referers', Piwik_Translate('Referers_SubmenuSearchEngines'), array('module' => 'Referers', 'action' => 'getSearchEnginesAndKeywords')); 
     49                Piwik_AddMenu('Referers', Piwik_Translate('Referers_SubmenuWebsites'), array('module' => 'Referers', 'action' => 'getWebsites')); 
     50                Piwik_AddMenu('Referers', Piwik_Translate('Referers_SubmenuCampaigns'), array('module' => 'Referers', 'action' => 'getCampaigns')); 
     51                Piwik_AddMenu('Referers', Piwik_Translate('Referers_SubmenuPartners'), array('module' => 'Referers', 'action' => 'getPartners'));        
     52        } 
    3753                 
    3854        function getListHooksRegistered() 
    3955        { 
     
    302318        } 
    303319} 
    304320 
    305  
    306  
    307 Piwik_AddWidget( 'Referers', 'getKeywords', 'List of Keywords'); 
    308 Piwik_AddWidget( 'Referers', 'getPartners', 'List of Partners'); 
    309 Piwik_AddWidget( 'Referers', 'getCampaigns', 'List of Campaigns'); 
    310 Piwik_AddWidget( 'Referers', 'getWebsites', 'List of external Websites'); 
    311 Piwik_AddWidget( 'Referers', 'getSearchEngines', 'Best search engines'); 
    312 Piwik_AddWidget( 'Referers', 'getRefererType', 'Overview'); 
    313  
    314 Piwik_AddMenu('Referers', 'Evolution', array('module' => 'Referers')); 
    315 Piwik_AddMenu('Referers', 'Search engines & keywords', array('module' => 'Referers', 'action' => 'getSearchEnginesAndKeywords')); 
    316 Piwik_AddMenu('Referers', 'Websites', array('module' => 'Referers', 'action' => 'getWebsites')); 
    317 Piwik_AddMenu('Referers', 'Campaigns', array('module' => 'Referers', 'action' => 'getCampaigns')); 
    318 Piwik_AddMenu('Referers', 'Partners', array('module' => 'Referers', 'action' => 'getPartners')); 
    319  
  • plugins/Referers/searchEngines_Keywords.tpl

     
    11<div id='leftcolumn'> 
    2         <h2>Search engines</h2> 
     2        <h2>{'Referers_SearchEngines'|translate}</h2> 
    33        {$searchEngines} 
    44</div> 
    55 
    66<div id='rightcolumn'> 
    7         <h2>Keywords</h2> 
     7        <h2>{'Referers_Keywords'|translate}</h2> 
    88        {$keywords} 
    99</div> 
  • plugins/Referers/index.tpl

     
    11<script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 
    22 
    33        <a name="evolutionGraph" graphId="{$nameGraphEvolutionReferers}"></a> 
    4         <h2>Evolution over the period</h2> 
     4        <h2>{'Referers_Evolution'|translate}</h2> 
    55        {$graphEvolutionReferers} 
    66         
    7         <h2>Referer Type</h2> 
     7        <h2>{'Referers_Type'|translate}</h2> 
    88        <table> 
    99                <tr><td> 
    10                         <p><img class="sparkline" src="{$urlSparklineDirectEntry}" /> <span><strong>{$visitorsFromDirectEntry} </strong> direct entries</span></p> 
    11                         <p><img class="sparkline" src="{$urlSparklineSearchEngines}" /> <span><strong>{$visitorsFromSearchEngines} </strong>  from search engines</span></p> 
    12                         <p><img class="sparkline" src="{$urlSparklinePartners}" /> <span><strong>{$visitorsFromPartners} </strong> from partners</span></p> 
     10                        <p><img class="sparkline" src="{$urlSparklineDirectEntry}" /> <span> 
     11                        {'Referers_TypeDirectEntries'|translate:"<strong>$visitorsFromDirectEntry</strong>"}</span></p> 
     12                        <p><img class="sparkline" src="{$urlSparklineSearchEngines}" /> <span> 
     13                        {'Referers_TypeSearchEngines'|translate:"<strong>$visitorsFromSearchEngines</strong>"}</span></p> 
     14                        <p><img class="sparkline" src="{$urlSparklinePartners}" /> <span> 
     15                        {'Referers_TypePartners'|translate:"<strong>$visitorsFromPartners</strong>"}</span></p> 
    1316                </td><td> 
    14                         <p><img class="sparkline" src="{$urlSparklineWebsites}" /> <span><strong>{$visitorsFromWebsites} </strong> from websites</span></p> 
    15                         <p><img class="sparkline" src="{$urlSparklineNewsletters}" /> <span><strong>{$visitorsFromNewsletters} </strong>  from newsletters</span></p> 
    16                         <p><img class="sparkline" src="{$urlSparklineCampaigns}" /> <span><strong>{$visitorsFromCampaigns} </strong>  from campaigns</span></p> 
     17                        <p><img class="sparkline" src="{$urlSparklineWebsites}" /> <span> 
     18                        {'Referers_TypeWebsites'|translate:"<strong>$visitorsFromWebsites</strong>"}</span></p> 
     19                        <p><img class="sparkline" src="{$urlSparklineNewsletters}" /> <span> 
     20                        {'Referers_TypeNewsletters'|translate:"<strong>$visitorsFromNewsletters</strong>"}</span></p> 
     21                        <p><img class="sparkline" src="{$urlSparklineCampaigns}" /> <span> 
     22                        {'Referers_TypeCampaigns'|translate:"<strong>$visitorsFromCampaigns</strong>"}</span></p> 
    1723                </td></tr> 
    1824        </table> 
    1925         
    20         <h2>Other</h2> 
     26        <h2>{'Referers_Other'|translate}</h2> 
    2127        <table> 
    2228                <tr><td> 
    23                         <p><img class="sparkline" src="{$urlSparklineDistinctSearchEngines}" /> <span><strong>{$numberDistinctSearchEngines} </strong>  distinct search engines</span></p> 
    24                         <p><img class="sparkline" src="{$urlSparklineDistinctKeywords}" /> <span><strong>{$numberDistinctKeywords} </strong> distinct keywords</span></p> 
     29                        <p><img class="sparkline" src="{$urlSparklineDistinctSearchEngines}" /> <span> 
     30                        {'Referers_OtherDistinctSearchEngines'|translate:"<strong>$numberDistinctSearchEngines</strong>"}</span></p> 
     31                        <p><img class="sparkline" src="{$urlSparklineDistinctKeywords}" /> <span> 
     32                        {'Referers_OtherDistinctKeywords'|translate:"<strong>$numberDistinctKeywords</strong>"}</span></p> 
    2533                </td><td> 
    26                         <p><img class="sparkline" src="{$urlSparklineDistinctWebsites}" /> <span><strong>{$numberDistinctWebsites} </strong>  distinct websites (using <strong>{$numberDistinctWebsitesUrls}</strong> distinct urls)</span></p> 
    27                         <p><img class="sparkline" src="{$urlSparklineDistinctPartners}" /> <span><strong>{$numberDistinctPartners} </strong>   distinct partners (using <strong>{$numberDistinctPartnersUrls}</strong> distinct urls)</span></p> 
    28                         <p><img class="sparkline" src="{$urlSparklineDistinctCampaigns}" /> <span><strong>{$numberDistinctCampaigns} </strong>  distinct campaigns</span></p> 
     34                        <p><img class="sparkline" src="{$urlSparklineDistinctWebsites}" /> <span> 
     35                        {'Referers_OtherDistinctWebsites'|translate:"<strong>$numberDistinctWebsites</strong>":"<strong>$numberDistinctWebsitesUrls</strong>"}</span></p> 
     36                        <p><img class="sparkline" src="{$urlSparklineDistinctPartners}" /> <span> 
     37                        {'Referers_OtherDistinctPartners'|translate:"<strong>$numberDistinctPartners</strong>":"<strong>$numberDistinctPartnersUrls</strong>"}</span></p> 
     38                        <p><img class="sparkline" src="{$urlSparklineDistinctCampaigns}" /> <span>  
     39                        {'Referers_OtherDistinctCampaigns'|translate:"<strong>$numberDistinctCampaigns</strong>"}</span></p> 
    2940                        </td></tr> 
    3041        </table> 
    3142         
    32         <p>Tag cloud output</p> 
    33         {$dataTableRefererType} 
    34  brakuje znaku końca linii na końcu pliku  
     43        <p>{'Referers_TagCloud'|translate}</p> 
     44        {$dataTableRefererType} 
  • plugins/Referers/Controller.php

     
    352352                return $this->getNumericValue('Referers.' . __FUNCTION__); 
    353353        } 
    354354         
    355 } 
    356  brakuje znaku końca linii na końcu pliku  
     355} 
  • plugins/VisitTime/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'VisitTime_LocalTime' => 'Visit per local time', 
     4        'VisitTime_ServerTime' => 'Visit per server time', 
     5         
     6        'VisitTime_WidgetLocalTime' => 'Visits by local time', 
     7        'VisitTime_WidgetServerTime' => 'Visits by server time', 
     8 
     9        'VisitTime_SubmenuTimes' => 'Times', 
     10); 
  • plugins/VisitTime/VisitTime.php

     
    2929                        'author' => 'Piwik', 
    3030                        'homepage' => 'http://piwik.org/', 
    3131                        'version' => '0.1', 
     32                        'translationAvailable' => true 
    3233                ); 
    3334                 
    3435                return $info; 
    3536        } 
    3637         
     38        function postLoad() 
     39        { 
     40                Piwik_AddWidget( 'VisitTime', 'getVisitInformationPerLocalTime', Piwik_Translate('VisitTime_WidgetLocalTime')); 
     41                Piwik_AddWidget( 'VisitTime', 'getVisitInformationPerServerTime', Piwik_Translate('VisitTime_WidgetServerTime')); 
     42 
     43                Piwik_AddMenu('Visitors', Piwik_Translate('VisitTime_SubmenuTimes'), array('module' => 'VisitTime')); 
     44        } 
     45         
    3746        function getListHooksRegistered() 
    3847        { 
    3948                $hooks = array( 
     
    8897        } 
    8998} 
    9099 
    91  
    92 Piwik_AddWidget( 'VisitTime', 'getVisitInformationPerLocalTime', 'Visits by local time'); 
    93 Piwik_AddWidget( 'VisitTime', 'getVisitInformationPerServerTime', 'Visits by server time'); 
    94  
    95 Piwik_AddMenu('Visitors', 'Times', array('module' => 'VisitTime')); 
    96  
  • plugins/VisitTime/index.tpl

     
    11<div id='leftcolumn'> 
    2 <h2>Visit per local time</h2> 
     2<h2>{'VisitTime_LocalTime'|translate}</h2> 
    33{$dataTableVisitInformationPerLocalTime} 
    44</div> 
    55 
    66<div id='rightcolumn'> 
    7 <h2>Visit per server time</h2> 
     7<h2>{'VisitTime_ServerTime'|translate}</h2> 
    88{$dataTableVisitInformationPerServerTime} 
    9 </div> 
    10  brakuje znaku końca linii na końcu pliku  
     9</div> 
  • plugins/VisitorInterest/lang/en.php

     
     1<?php 
     2$translations = array( 
     3        'VisitorInterest_VisitsPerDuration' => 'Visits per visit duration', 
     4        'VisitorInterest_VisitsPerNbOfPages' => 'Visits per number of pages', 
     5         
     6        'VisitorInterest_WidgetLengths' => 'Visits lengths', 
     7        'VisitorInterest_WidgetPages' => 'Pages per visit', 
     8 
     9        'VisitorInterest_SubmenuFrequencyLoyalty' => 'Frequency & Loyalty', 
     10 
     11); 
  • plugins/VisitorInterest/VisitorInterest.php

     
    4949                        'author' => 'Piwik', 
    5050                        'homepage' => 'http://piwik.org/', 
    5151                        'version' => '0.1', 
     52                        'translationAvailable' => true 
    5253                ); 
    5354                 
    5455                return $info; 
    5556        } 
     57         
     58        function postLoad() 
     59        { 
     60                Piwik_AddWidget( 'VisitorInterest', 'getNumberOfVisitsPerVisitDuration', Piwik_Translate('VisitorInterest_WidgetLengths')); 
     61                Piwik_AddWidget( 'VisitorInterest', 'getNumberOfVisitsPerPage', Piwik_Translate('VisitorInterest_WidgetPages')); 
     62                 
     63                Piwik_RenameMenuEntry('Visitors', Piwik_Translate('VisitFrequency_SubmenuFrequency'),  
     64                                                                'Visitors', Piwik_Translate('VisitorInterest_SubmenuFrequencyLoyalty') ); 
     65                 
     66                Piwik_AddAction('template_headerVisitsFrequency', array('Piwik_VisitorInterest','headerVisitsFrequency')); 
     67                Piwik_AddAction('template_footerVisitsFrequency', array('Piwik_VisitorInterest','footerVisitsFrequency')); 
     68        } 
     69         
    5670        function getListHooksRegistered() 
    5771        { 
    5872                $hooks = array( 
     
    162176        } 
    163177} 
    164178 
    165  
    166  
    167 Piwik_AddWidget( 'VisitorInterest', 'getNumberOfVisitsPerVisitDuration', 'Visits lengths'); 
    168 Piwik_AddWidget( 'VisitorInterest', 'getNumberOfVisitsPerPage', 'Pages per visit'); 
    169  
    170 Piwik_RenameMenuEntry('Visitors', 'Frequency', 'Visitors', 'Frequency & Loyalty' ); 
    171 Piwik_AddAction('template_headerVisitsFrequency', array('Piwik_VisitorInterest','headerVisitsFrequency')); 
    172 Piwik_AddAction('template_footerVisitsFrequency', array('Piwik_VisitorInterest','footerVisitsFrequency')); 
    173  
    174  
  • plugins/VisitorInterest/index.tpl

     
    11 
    2         <h2>Visits per visit duration</h2> 
     2        <h2>{'VisitorInterest_VisitsPerDuration'|translate}</h2> 
    33        {$dataTableNumberOfVisitsPerVisitDuration} 
    4         <h2>Visits per number of pages</h2> 
    5         {$dataTableNumberOfVisitsPerPage} 
    6  brakuje znaku końca linii na końcu pliku  
     4        <h2>{'VisitorInterest_VisitsPerNbOfPages'|translate}</h2> 
     5        {$dataTableNumberOfVisitsPerPage} 
  • libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Protocol 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Plain.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Protocol_Smtp 
     26 */ 
     27require_once 'Zend/Mail/Protocol/Smtp.php'; 
     28 
     29 
     30/** 
     31 * Performs PLAIN authentication 
     32 * 
     33 * @category   Zend 
     34 * @package    Zend_Mail 
     35 * @subpackage Protocol 
     36 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     37 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     38 */ 
     39class Zend_Mail_Protocol_Smtp_Auth_Plain extends Zend_Mail_Protocol_Smtp 
     40{ 
     41    /** 
     42     * PLAIN username 
     43     * 
     44     * @var string 
     45     */ 
     46    protected $_username; 
     47 
     48 
     49    /** 
     50     * PLAIN password 
     51     * 
     52     * @var string 
     53     */ 
     54    protected $_password; 
     55 
     56 
     57    /** 
     58     * Constructor. 
     59     * 
     60     * @param  string $host   (Default: 127.0.0.1) 
     61     * @param  int    $port   (Default: null) 
     62     * @param  array  $config Auth-specific parameters 
     63     * @return void 
     64     */ 
     65    public function __construct($host = '127.0.0.1', $port = null, $config = null) 
     66    { 
     67        if (is_array($config)) { 
     68            if (isset($config['username'])) { 
     69                $this->_username = $config['username']; 
     70            } 
     71            if (isset($config['password'])) { 
     72                $this->_password = $config['password']; 
     73            } 
     74        } 
     75 
     76        parent::__construct($host, $port, $config); 
     77    } 
     78 
     79 
     80    /** 
     81     * Perform PLAIN authentication with supplied credentials 
     82     * 
     83     * @return void 
     84     */ 
     85    public function auth() 
     86    { 
     87        // Ensure AUTH has not already been initiated. 
     88        parent::auth(); 
     89 
     90        $this->_send('AUTH PLAIN'); 
     91        $this->_expect(334); 
     92        $this->_send(base64_encode(chr(0) . $this->_username . chr(0) . $this->_password)); 
     93        $this->_expect(235); 
     94        $this->_auth = true; 
     95    } 
     96} 
  • libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Protocol 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Crammd5.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Protocol_Smtp 
     26 */ 
     27require_once 'Zend/Mail/Protocol/Smtp.php'; 
     28 
     29 
     30/** 
     31 * Performs CRAM-MD5 authentication 
     32 * 
     33 * @category   Zend 
     34 * @package    Zend_Mail 
     35 * @subpackage Protocol 
     36 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     37 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     38 */ 
     39class Zend_Mail_Protocol_Smtp_Auth_Crammd5 extends Zend_Mail_Protocol_Smtp 
     40{ 
     41    /** 
     42     * Constructor. 
     43     * 
     44     * @param  string $host   (Default: 127.0.0.1) 
     45     * @param  int    $port   (Default: null) 
     46     * @param  array  $config Auth-specific parameters 
     47     * @return void 
     48     */ 
     49    public function __construct($host = '127.0.0.1', $port = null, $config = null) 
     50    { 
     51        if (is_array($config)) { 
     52            if (isset($config['username'])) { 
     53                $this->_username = $config['username']; 
     54            } 
     55            if (isset($config['password'])) { 
     56                $this->_password = $config['password']; 
     57            } 
     58        } 
     59 
     60        parent::__construct($host, $port, $config); 
     61    } 
     62 
     63 
     64    /** 
     65     * @todo Perform CRAM-MD5 authentication with supplied credentials 
     66     * 
     67     * @return void 
     68     */ 
     69    public function auth() 
     70    { 
     71        // Ensure AUTH has not already been initiated. 
     72        parent::auth(); 
     73 
     74        $this->_send('AUTH CRAM-MD5'); 
     75        $challenge = $this->_expect(334); 
     76        $challenge = base64_decode($challenge); 
     77        $digest = $this->_hmacMd5($this->_password, $challenge); 
     78        $this->_send(base64_encode($this->_username . ' ' . $digest)); 
     79        $this->_expect(235); 
     80        $this->_auth = true; 
     81    } 
     82 
     83 
     84    /** 
     85     * Prepare CRAM-MD5 response to server's ticket 
     86     * 
     87     * @param  string $key   Challenge key (usually password) 
     88     * @param  string $data  Challenge data 
     89     * @param  string $block Length of blocks 
     90     * @return string 
     91     */ 
     92    protected function _hmacMd5($key, $data, $block = 64) 
     93    { 
     94        if (strlen($key) > 64) { 
     95            $key = pack('H32', md5($key)); 
     96        } elseif (strlen($key) < 64) { 
     97            $key = str_pad($key, $block, chr(0)); 
     98        } 
     99 
     100        $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); 
     101        $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); 
     102 
     103        $inner = pack('H32', md5($k_ipad . $data)); 
     104        $digest = md5($k_opad . $inner); 
     105 
     106        return $digest; 
     107    } 
     108} 
  • libs/Zend/Mail/Protocol/Smtp/Auth/Login.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Protocol 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Login.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Protocol_Smtp 
     26 */ 
     27require_once 'Zend/Mail/Protocol/Smtp.php'; 
     28 
     29 
     30/** 
     31 * Performs LOGIN authentication 
     32 * 
     33 * @category   Zend 
     34 * @package    Zend_Mail 
     35 * @subpackage Protocol 
     36 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     37 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     38 */ 
     39class Zend_Mail_Protocol_Smtp_Auth_Login extends Zend_Mail_Protocol_Smtp 
     40{ 
     41    /** 
     42     * LOGIN username 
     43     * 
     44     * @var string 
     45     */ 
     46    protected $_username; 
     47 
     48 
     49    /** 
     50     * LOGIN password 
     51     * 
     52     * @var string 
     53     */ 
     54    protected $_password; 
     55 
     56 
     57    /** 
     58     * Constructor. 
     59     * 
     60     * @param  string $host   (Default: 127.0.0.1) 
     61     * @param  int    $port   (Default: null) 
     62     * @param  array  $config Auth-specific parameters 
     63     * @return void 
     64     */ 
     65    public function __construct($host = '127.0.0.1', $port = null, $config = null) 
     66    { 
     67        if (is_array($config)) { 
     68            if (isset($config['username'])) { 
     69                $this->_username = $config['username']; 
     70            } 
     71            if (isset($config['password'])) { 
     72                $this->_password = $config['password']; 
     73            } 
     74        } 
     75 
     76        parent::__construct($host, $port, $config); 
     77    } 
     78 
     79 
     80    /** 
     81     * Perform LOGIN authentication with supplied credentials 
     82     * 
     83     * @return void 
     84     */ 
     85    public function auth() 
     86    { 
     87        // Ensure AUTH has not already been initiated. 
     88        parent::auth(); 
     89 
     90        $this->_send('AUTH LOGIN'); 
     91        $this->_expect(334); 
     92        $this->_send(base64_encode($this->_username)); 
     93        $this->_expect(334); 
     94        $this->_send(base64_encode($this->_password)); 
     95        $this->_expect(235); 
     96        $this->_auth = true; 
     97    } 
     98} 
  • libs/Zend/Mail/Protocol/Exception.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Protocol 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Exception 
     26 */ 
     27require_once 'Zend/Mail/Exception.php'; 
     28 
     29 
     30/** 
     31 * @category   Zend 
     32 * @package    Zend_Mail 
     33 * @subpackage Protocol 
     34 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     35 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     36 */ 
     37class Zend_Mail_Protocol_Exception extends Zend_Mail_Exception 
     38{} 
     39 
  • libs/Zend/Mail/Protocol/Pop3.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Protocol 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Pop3.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @category   Zend 
     26 * @package    Zend_Mail 
     27 * @subpackage Protocol 
     28 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     29 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     30 */ 
     31class Zend_Mail_Protocol_Pop3 
     32{ 
     33    /** 
     34     * saves if server supports top 
     35     * @var null|bool 
     36     */ 
     37    public $hasTop = null; 
     38 
     39    /** 
     40     * socket to pop3 
     41     * @var null|resource 
     42     */ 
     43    protected $_socket; 
     44 
     45    /** 
     46     * greeting timestamp for apop 
     47     * @var null|string 
     48     */ 
     49    protected $_timestamp; 
     50 
     51 
     52    /** 
     53     * Public constructor 
     54     * 
     55     * @param  string      $host  hostname of IP address of POP3 server, if given connect() is called 
     56     * @param  int|null    $port  port of POP3 server, null for default (110 or 995 for ssl) 
     57     * @param  bool|string $ssl   use ssl? 'SSL', 'TLS' or false 
     58     * @throws Zend_Mail_Protocol_Exception 
     59     */ 
     60    public function __construct($host = '', $port = null, $ssl = false) 
     61    { 
     62        if ($host) { 
     63            $this->connect($host, $port, $ssl); 
     64        } 
     65    } 
     66 
     67 
     68    /** 
     69     * Public destructor 
     70     */ 
     71    public function __destruct() 
     72    { 
     73        $this->logout(); 
     74    } 
     75 
     76 
     77    /** 
     78     * Open connection to POP3 server 
     79     * 
     80     * @param  string      $host  hostname of IP address of POP3 server 
     81     * @param  int|null    $port  of POP3 server, default is 110 (995 for ssl) 
     82     * @param  string|bool $ssl   use 'SSL', 'TLS' or false 
     83     * @return string welcome message 
     84     * @throws Zend_Mail_Protocol_Exception 
     85     */ 
     86    public function connect($host, $port = null, $ssl = false) 
     87    { 
     88        if ($ssl == 'SSL') { 
     89            $host = 'ssl://' . $host; 
     90        } 
     91 
     92        if ($port === null) { 
     93            $port = $ssl == 'SSL' ? 995 : 110; 
     94        } 
     95 
     96        $this->_socket = @fsockopen($host, $port); 
     97        if (!$this->_socket) { 
     98            /** 
     99             * @see Zend_Mail_Protocol_Exception 
     100             */ 
     101            require_once 'Zend/Mail/Protocol/Exception.php'; 
     102            throw new Zend_Mail_Protocol_Exception('cannot connect to host'); 
     103        } 
     104 
     105        $welcome = $this->readResponse(); 
     106 
     107        strtok($welcome, '<'); 
     108        $this->_timestamp = strtok('>'); 
     109        if (!strpos($this->_timestamp, '@')) { 
     110            $this->_timestamp = null; 
     111        } else { 
     112            $this->_timestamp = '<' . $this->_timestamp . '>'; 
     113        } 
     114 
     115        if ($ssl === 'TLS') { 
     116            $this->request('STLS'); 
     117            $result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); 
     118            if (!$result) { 
     119                /** 
     120                 * @see Zend_Mail_Protocol_Exception 
     121                 */ 
     122                require_once 'Zend/Mail/Protocol/Exception.php'; 
     123                throw new Zend_Mail_Protocol_Exception('cannot enable TLS'); 
     124            } 
     125        } 
     126 
     127        return $welcome; 
     128    } 
     129 
     130 
     131    /** 
     132     * Send a request 
     133     * 
     134     * @param string $request your request without newline 
     135     * @return null 
     136     * @throws Zend_Mail_Protocol_Exception 
     137     */ 
     138    public function sendRequest($request) 
     139    { 
     140        $result = @fputs($this->_socket, $request . "\r\n"); 
     141        if (!$result) { 
     142            /** 
     143             * @see Zend_Mail_Protocol_Exception 
     144             */ 
     145            require_once 'Zend/Mail/Protocol/Exception.php'; 
     146            throw new Zend_Mail_Protocol_Exception('send failed - connection closed?'); 
     147        } 
     148    } 
     149 
     150 
     151    /** 
     152     * read a response 
     153     * 
     154     * @param  boolean $multiline response has multiple lines and should be read until "<nl>.<nl>" 
     155     * @return string response 
     156     * @throws Zend_Mail_Protocol_Exception 
     157     */ 
     158    public function readResponse($multiline = false) 
     159    { 
     160        $result = @fgets($this->_socket); 
     161        if (!is_string($result)) { 
     162            /** 
     163             * @see Zend_Mail_Protocol_Exception 
     164             */ 
     165            require_once 'Zend/Mail/Protocol/Exception.php'; 
     166            throw new Zend_Mail_Protocol_Exception('read failed - connection closed?'); 
     167        } 
     168 
     169        $result = trim($result); 
     170        if (strpos($result, ' ')) { 
     171            list($status, $message) = explode(' ', $result, 2); 
     172        } else { 
     173            $status = $result; 
     174            $message = ''; 
     175        } 
     176 
     177        if ($status != '+OK') { 
     178            /** 
     179             * @see Zend_Mail_Protocol_Exception 
     180             */ 
     181            require_once 'Zend/Mail/Protocol/Exception.php'; 
     182            throw new Zend_Mail_Protocol_Exception('last request failed'); 
     183        } 
     184 
     185        if ($multiline) { 
     186            $message = ''; 
     187            $line = fgets($this->_socket); 
     188            while ($line && trim($line) != '.') { 
     189                $message .= $line; 
     190                $line = fgets($this->_socket); 
     191            }; 
     192        } 
     193 
     194        return $message; 
     195    } 
     196 
     197 
     198    /** 
     199     * Send request and get resposne 
     200     * 
     201     * @see sendRequest(), readResponse() 
     202     * 
     203     * @param  string $request    request 
     204     * @param  bool   $multiline  multiline response? 
     205     * @return string             result from readResponse() 
     206     * @throws Zend_Mail_Protocol_Exception 
     207     */ 
     208    public function request($request, $multiline = false) 
     209    { 
     210        $this->sendRequest($request); 
     211        return $this->readResponse($multiline); 
     212    } 
     213 
     214 
     215    /** 
     216     * End communication with POP3 server (also closes socket) 
     217     * 
     218     * @return null 
     219     */ 
     220    public function logout() 
     221    { 
     222        if (!$this->_socket) { 
     223            return; 
     224        } 
     225 
     226        try { 
     227            $this->request('QUIT'); 
     228        } catch (Zend_Mail_Protocol_Exception $e) { 
     229            // ignore error - we're closing the socket anyway 
     230        } 
     231 
     232        fclose($this->_socket); 
     233        $this->_socket = null; 
     234    } 
     235 
     236 
     237    /** 
     238     * Get capabilities from POP3 server 
     239     * 
     240     * @return array list of capabilities 
     241     * @throws Zend_Mail_Protocol_Exception 
     242     */ 
     243    public function capa() 
     244    { 
     245        $result = $this->request('CAPA', true); 
     246        return explode("\n", $result); 
     247    } 
     248 
     249 
     250    /** 
     251     * Login to POP3 server. Can use APOP 
     252     * 
     253     * @param  string $user      username 
     254     * @param  string $password  password 
     255     * @param  bool   $try_apop  should APOP be tried? 
     256     * @return void 
     257     * @throws Zend_Mail_Protocol_Exception 
     258     */ 
     259    public function login($user, $password, $tryApop = true) 
     260    { 
     261        if ($tryApop && $this->_timestamp) { 
     262            try { 
     263                $this->request("APOP $user " . md5($this->_timestamp . $password)); 
     264                return; 
     265            } catch (Zend_Mail_Protocol_Exception $e) { 
     266                // ignore 
     267            } 
     268        } 
     269 
     270        $result = $this->request("USER $user"); 
     271        $result = $this->request("PASS $password"); 
     272    } 
     273 
     274 
     275    /** 
     276     * Make STAT call for message count and size sum 
     277     * 
     278     * @param  int $messages  out parameter with count of messages 
     279     * @param  int $octets    out parameter with size in octects of messages 
     280     * @return void 
     281     * @throws Zend_Mail_Protocol_Exception 
     282     */ 
     283    public function status(&$messages, &$octets) 
     284    { 
     285        $messages = 0; 
     286        $octets = 0; 
     287        $result = $this->request('STAT'); 
     288 
     289        list($messages, $octets) = explode(' ', $result); 
     290    } 
     291 
     292 
     293    /** 
     294     * Make LIST call for size of message(s) 
     295     * 
     296     * @param  int|null $msgno number of message, null for all 
     297     * @return int|array size of given message or list with array(num => size) 
     298     * @throws Zend_Mail_Protocol_Exception 
     299     */ 
     300    public function getList($msgno = null) 
     301    { 
     302        if ($msgno !== null) { 
     303            $result = $this->request("LIST $msgno"); 
     304 
     305            list(, $result) = explode(' ', $result); 
     306            return (int)$result; 
     307        } 
     308 
     309        $result = $this->request('LIST', true); 
     310        $messages = array(); 
     311        $line = strtok($result, "\n"); 
     312        while ($line) { 
     313            list($no, $size) = explode(' ', trim($line)); 
     314            $messages[(int)$no] = (int)$size; 
     315            $line = strtok("\n"); 
     316        } 
     317 
     318        return $messages; 
     319    } 
     320 
     321 
     322    /** 
     323     * Make UIDL call for getting a uniqueid 
     324     * 
     325     * @param  int|null $msgno number of message, null for all 
     326     * @return string|array uniqueid of message or list with array(num => uniqueid) 
     327     * @throws Zend_Mail_Protocol_Exception 
     328     */ 
     329    public function uniqueid($msgno = null) 
     330    { 
     331        if ($msgno !== null) { 
     332            $result = $this->request("UIDL $msgno"); 
     333 
     334            list(, $result) = explode(' ', $result); 
     335            return $result; 
     336        } 
     337 
     338        $result = $this->request('UIDL', true); 
     339 
     340        $result = explode("\n", $result); 
     341        $messages = array(); 
     342        foreach ($result as $line) { 
     343            if (!$line) { 
     344                continue; 
     345            } 
     346            list($no, $id) = explode(' ', trim($line), 2); 
     347            $messages[(int)$no] = $id; 
     348        } 
     349 
     350        return $messages; 
     351 
     352    } 
     353 
     354 
     355    /** 
     356     * Make TOP call for getting headers and maybe some body lines 
     357     * This method also sets hasTop - before it it's not known if top is supported 
     358     * 
     359     * The fallback makes normale RETR call, which retrieves the whole message. Additional 
     360     * lines are not removed. 
     361     * 
     362     * @param  int  $msgno    number of message 
     363     * @param  int  $lines    number of wanted body lines (empty line is inserted after header lines) 
     364     * @param  bool $fallback fallback with full retrieve if top is not supported 
     365     * @return string message headers with wanted body lines 
     366     * @throws Zend_Mail_Protocol_Exception 
     367     */ 
     368    public function top($msgno, $lines = 0, $fallback = false) 
     369    { 
     370        if ($this->hasTop === false) { 
     371            if ($fallback) { 
     372                return $this->retrieve($msgno); 
     373            } else { 
     374                /** 
     375                 * @see Zend_Mail_Protocol_Exception 
     376                 */ 
     377                require_once 'Zend/Mail/Protocol/Exception.php'; 
     378                throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted'); 
     379            } 
     380        } 
     381        $this->hasTop = true; 
     382 
     383        $lines = (!$lines || $lines < 1) ? 0 : (int)$lines; 
     384 
     385        try { 
     386            $result = $this->request("TOP $msgno $lines", true); 
     387        } catch (Zend_Mail_Protocol_Exception $e) { 
     388            $this->hasTop = false; 
     389            if ($fallback) { 
     390                $result = $this->retrieve($msgno); 
     391            } else { 
     392                throw $e; 
     393            } 
     394        } 
     395 
     396        return $result; 
     397    } 
     398 
     399 
     400    /** 
     401     * Make a RETR call for retrieving a full message with headers and body 
     402     * 
     403     * @deprecated since 1.1.0; this method has a typo - please use retrieve() 
     404     * @param  int $msgno  message number 
     405     * @return string message 
     406     * @throws Zend_Mail_Protocol_Exception 
     407     */ 
     408    public function retrive($msgno) 
     409    { 
     410        return $this->retrieve($msgno); 
     411    } 
     412 
     413 
     414    /** 
     415     * Make a RETR call for retrieving a full message with headers and body 
     416     * 
     417     * @param  int $msgno  message number 
     418     * @return string message 
     419     * @throws Zend_Mail_Protocol_Exception 
     420     */ 
     421    public function retrieve($msgno) 
     422    { 
     423        $result = $this->request("RETR $msgno", true); 
     424        return $result; 
     425    } 
     426 
     427    /** 
     428     * Make a NOOP call, maybe needed for keeping the server happy 
     429     * 
     430     * @return null 
     431     * @throws Zend_Mail_Protocol_Exception 
     432     */ 
     433    public function noop() 
     434    { 
     435        $this->request('NOOP'); 
     436    } 
     437 
     438 
     439    /** 
     440     * Make a DELE count to remove a message 
     441     * 
     442     * @return null 
     443     * @throws Zend_Mail_Protocol_Exception 
     444     */ 
     445    public function delete($msgno) 
     446    { 
     447        $this->request("DELE $msgno"); 
     448    } 
     449 
     450 
     451    /** 
     452     * Make RSET call, which rollbacks delete requests 
     453     * 
     454     * @return null 
     455     * @throws Zend_Mail_Protocol_Exception 
     456     */ 
     457    public function undelete() 
     458    { 
     459        $this->request('RSET'); 
     460    } 
     461} 
  • libs/Zend/Mail/Protocol/Abstract.php

     
     1<?php 
     2 
     3/** 
     4 * Zend Framework 
     5 * 
     6 * LICENSE 
     7 * 
     8 * This source file is subject to the new BSD license that is bundled 
     9 * with this package in the file LICENSE.txt. 
     10 * It is also available through the world-wide-web at this URL: 
     11 * http://framework.zend.com/license/new-bsd 
     12 * If you did not receive a copy of the license and are unable to 
     13 * obtain it through the world-wide-web, please send an email 
     14 * to license@zend.com so we can send you a copy immediately. 
     15 *  
     16 * @category   Zend 
     17 * @package    Zend_Mail 
     18 * @subpackage Protocol 
     19 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     20 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     21 * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $ 
     22 */ 
     23 
     24 
     25/** 
     26 * @see Zend_Validate 
     27 */ 
     28require_once 'Zend/Validate.php'; 
     29 
     30 
     31/** 
     32 * @see Zend_Validate_Hostname 
     33 */ 
     34require_once 'Zend/Validate/Hostname.php'; 
     35 
     36 
     37/** 
     38 * Zend_Mail_Protocol_Abstract 
     39 * 
     40 * Provides low-level methods for concrete adapters to communicate with a remote mail server and track requests and responses. 
     41 *  
     42 * @category   Zend 
     43 * @package    Zend_Mail 
     44 * @subpackage Protocol 
     45 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     46 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     47 * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $ 
     48 * @todo Implement proxy settings 
     49 */ 
     50abstract class Zend_Mail_Protocol_Abstract 
     51{ 
     52    /** 
     53     * Mail default EOL string 
     54     */ 
     55    const EOL = "\r\n"; 
     56 
     57 
     58    /** 
     59     * Default timeout in seconds for initiating session 
     60     */ 
     61    const TIMEOUT_CONNECTION = 30; 
     62 
     63 
     64    /** 
     65     * Hostname or IP address of remote server 
     66     * @var string 
     67     */ 
     68    protected $_host; 
     69 
     70 
     71    /** 
     72     * Port number of connection 
     73     * @var integer 
     74     */ 
     75    protected $_port; 
     76 
     77 
     78    /** 
     79     * Instance of Zend_Validate to check hostnames 
     80     * @var Zend_Validate 
     81     */ 
     82    protected $_validHost; 
     83 
     84 
     85    /** 
     86     * Socket connection resource 
     87     * @var resource 
     88     */ 
     89    protected $_socket; 
     90 
     91 
     92    /** 
     93     * Last request sent to server 
     94     * @var string 
     95     */ 
     96    protected $_request; 
     97 
     98 
     99    /** 
     100     * Array of server responses to last request 
     101     * @var array 
     102     */ 
     103    protected $_response; 
     104 
     105 
     106    /** 
     107     * String template for parsing server responses using sscanf (default: 3 digit code and response string) 
     108     * @var resource 
     109     */ 
     110    protected $_template = '%d%s'; 
     111 
     112 
     113    /** 
     114     * Log of mail requests and server responses for a session 
     115     * @var string 
     116     */ 
     117    private $_log; 
     118 
     119 
     120    /** 
     121     * Constructor. 
     122     * 
     123     * @param  string  $host OPTIONAL Hostname of remote connection (default: 127.0.0.1) 
     124     * @param  integer $port OPTIONAL Port number (default: null) 
     125     * @throws Zend_Mail_Protocol_Exception 
     126     * @return void 
     127     */ 
     128    public function __construct($host = '127.0.0.1', $port = null) 
     129    { 
     130        $this->_validHost = new Zend_Validate(); 
     131        $this->_validHost->addValidator(new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL)); 
     132 
     133        if (!$this->_validHost->isValid($host)) { 
     134            /** 
     135             * @see Zend_Mail_Protocol_Exception 
     136             */ 
     137            require_once 'Zend/Mail/Protocol/Exception.php'; 
     138            throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages())); 
     139        } 
     140 
     141        $this->_host = $host; 
     142        $this->_port = $port; 
     143    } 
     144 
     145 
     146    /** 
     147     * Class destructor to cleanup open resources 
     148     * 
     149     * @return void 
     150     */ 
     151    public function __destruct() 
     152    { 
     153        $this->_disconnect(); 
     154    } 
     155 
     156 
     157    /** 
     158     * Create a connection to the remote host 
     159     * 
     160     * Concrete adapters for this class will implement their own unique connect scripts, using the _connect() method to create the socket resource. 
     161     */ 
     162    abstract public function connect(); 
     163 
     164 
     165    /** 
     166     * Retrieve the last client request 
     167     * 
     168     * @return string 
     169     */ 
     170    public function getRequest() 
     171    { 
     172        return $this->_request; 
     173    } 
     174 
     175 
     176    /** 
     177     * Retrieve the last server response 
     178     * 
     179     * @return array 
     180     */ 
     181    public function getResponse() 
     182    { 
     183        return $this->_response; 
     184    } 
     185 
     186 
     187    /** 
     188     * Retrieve the transaction log 
     189     * 
     190     * @return string 
     191     */ 
     192    public function getLog() 
     193    { 
     194        return $this->_log; 
     195    } 
     196 
     197 
     198    /** 
     199     * Reset the transaction log 
     200     * 
     201     * @return void 
     202     */ 
     203    public function resetLog() 
     204    { 
     205        $this->_log = ''; 
     206    } 
     207 
     208 
     209    /** 
     210     * Connect to the server using the supplied transport and target 
     211     * 
     212     * An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222' 
     213     * 
     214     * @param  string $remote Remote 
     215     * @throws Zend_Mail_Protocol_Exception 
     216     * @return boolean 
     217     */ 
     218    protected function _connect($remote) 
     219    { 
     220        $errorNum = 0; 
     221        $errorStr = ''; 
     222 
     223        // open connection 
     224        $this->_socket = stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION); 
     225 
     226        if ($this->_socket === false) { 
     227            if ($errorNum == 0) { 
     228                $errorStr = 'Could not open socket'; 
     229            } 
     230            /** 
     231             * @see Zend_Mail_Protocol_Exception 
     232             */ 
     233            require_once 'Zend/Mail/Protocol/Exception.php'; 
     234            throw new Zend_Mail_Protocol_Exception($errorStr); 
     235        } 
     236 
     237        if (($result = stream_set_timeout($this->_socket, self::TIMEOUT_CONNECTION)) === false) { 
     238            /** 
     239             * @see Zend_Mail_Protocol_Exception 
     240             */ 
     241            require_once 'Zend/Mail/Protocol/Exception.php'; 
     242            throw new Zend_Mail_Protocol_Exception('Could not set stream timeout'); 
     243        } 
     244 
     245        return $result; 
     246    } 
     247 
     248 
     249    /** 
     250     * Disconnect from remote host and free resource 
     251     * 
     252     * @return void 
     253     */ 
     254    protected function _disconnect() 
     255    { 
     256        if (is_resource($this->_socket)) { 
     257            fclose($this->_socket); 
     258        } 
     259    } 
     260 
     261 
     262    /** 
     263     * Send the given request followed by a LINEEND to the server. 
     264     * 
     265     * @param  string $request 
     266     * @throws Zend_Mail_Protocol_Exception 
     267     * @return integer|boolean Number of bytes written to remote host 
     268     */ 
     269    protected function _send($request) 
     270    { 
     271        if (!is_resource($this->_socket)) { 
     272            /** 
     273             * @see Zend_Mail_Protocol_Exception 
     274             */ 
     275            require_once 'Zend/Mail/Protocol/Exception.php'; 
     276            throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host); 
     277        } 
     278 
     279        $this->_request = $request; 
     280 
     281        $result = fwrite($this->_socket, $request . self::EOL); 
     282 
     283        // Save request to internal log 
     284        $this->_log .= $request . self::EOL; 
     285 
     286        if ($result === false) { 
     287            /** 
     288             * @see Zend_Mail_Protocol_Exception 
     289             */ 
     290            require_once 'Zend/Mail/Protocol/Exception.php'; 
     291            throw new Zend_Mail_Protocol_Exception('Could not send request to ' . $this->_host); 
     292        } 
     293 
     294        return $result; 
     295    } 
     296 
     297 
     298    /** 
     299     * Get a line from the stream. 
     300     * 
     301     * @var    integer $timeout Per-request timeout value if applicable 
     302     * @throws Zend_Mail_Protocol_Exception 
     303     * @return string 
     304     */ 
     305    protected function _receive($timeout = null) 
     306    { 
     307        if (!is_resource($this->_socket)) { 
     308            /** 
     309             * @see Zend_Mail_Protocol_Exception 
     310             */ 
     311            require_once 'Zend/Mail/Protocol/Exception.php'; 
     312            throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host); 
     313        } 
     314 
     315        // Adapters may wish to supply per-commend timeouts according to appropriate RFC 
     316        if ($timeout !== null) { 
     317           stream_set_timeout($this->_socket, $timeout); 
     318        } 
     319 
     320        // Retrieve response 
     321        $reponse = fgets($this->_socket, 1024); 
     322 
     323        // Save request to internal log 
     324        $this->_log .= $reponse; 
     325 
     326        // Check meta data to ensure connection is still valid 
     327        $info = stream_get_meta_data($this->_socket); 
     328 
     329        if (!empty($info['timed_out'])) { 
     330            /** 
     331             * @see Zend_Mail_Protocol_Exception 
     332             */ 
     333            require_once 'Zend/Mail/Protocol/Exception.php'; 
     334            throw new Zend_Mail_Protocol_Exception($this->_host . ' has timed out'); 
     335        } 
     336 
     337        if ($reponse === false) { 
     338            /** 
     339             * @see Zend_Mail_Protocol_Exception 
     340             */ 
     341            require_once 'Zend/Mail/Protocol/Exception.php'; 
     342            throw new Zend_Mail_Protocol_Exception('Could not read from ' . $this->_host); 
     343        } 
     344 
     345        return $reponse; 
     346    } 
     347 
     348 
     349    /** 
     350     * Parse server response for successful codes 
     351     * 
     352     * Read the response from the stream and check for expected return code. 
     353     * Throws a Zend_Mail_Protocol_Exception if an unexpected code is returned. 
     354     * 
     355     * @param  string|array $code One or more codes that indicate a successful response 
     356     * @throws Zend_Mail_Protocol_Exception 
     357     * @return string Last line of response string 
     358     */ 
     359    protected function _expect($code, $timeout = null) 
     360    { 
     361        $this->_response = array(); 
     362        $cmd = ''; 
     363        $msg = ''; 
     364 
     365        if (!is_array($code)) { 
     366            $code = array($code); 
     367        } 
     368 
     369        do { 
     370            $this->_response[] = $result = $this->_receive($timeout); 
     371            sscanf($result, $this->_template, $cmd, $msg); 
     372 
     373            if ($cmd === null || !in_array($cmd, $code)) { 
     374                /** 
     375                 * @see Zend_Mail_Protocol_Exception 
     376                 */ 
     377                require_once 'Zend/Mail/Protocol/Exception.php'; 
     378                throw new Zend_Mail_Protocol_Exception($result); 
     379            } 
     380 
     381        } while (strpos($msg, '-') === 0); // The '-' message prefix indicates an information string instead of a response string. 
     382 
     383        return $msg; 
     384    } 
     385} 
  • libs/Zend/Mail/Protocol/Smtp.php

     
     1<?php 
     2 
     3/** 
     4 * Zend Framework 
     5 * 
     6 * LICENSE 
     7 * 
     8 * This source file is subject to the new BSD license that is bundled 
     9 * with this package in the file LICENSE.txt. 
     10 * It is also available through the world-wide-web at this URL: 
     11 * http://framework.zend.com/license/new-bsd 
     12 * If you did not receive a copy of the license and are unable to 
     13 * obtain it through the world-wide-web, please send an email 
     14 * to license@zend.com so we can send you a copy immediately. 
     15 *  
     16 * @category   Zend 
     17 * @package    Zend_Mail 
     18 * @subpackage Protocol 
     19 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     20 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     21 * @version    $Id: Smtp.php 8064 2008-02-16 10:58:39Z thomas $ 
     22 */ 
     23 
     24 
     25/** 
     26 * @see Zend_Mime 
     27 */ 
     28require_once 'Zend/Mime.php'; 
     29 
     30 
     31/** 
     32 * @see Zend_Mail_Protocol_Abstract 
     33 */ 
     34require_once 'Zend/Mail/Protocol/Abstract.php'; 
     35 
     36 
     37/** 
     38 * Smtp implementation of Zend_Mail_Protocol_Abstract 
     39 * 
     40 * Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT 
     41 *  
     42 * @category   Zend 
     43 * @package    Zend_Mail 
     44 * @subpackage Protocol 
     45 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     46 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     47 */ 
     48class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract 
     49{ 
     50    /** 
     51     * The transport method for the socket 
     52     * 
     53     * @var string 
     54     */ 
     55    protected $_transport = 'tcp'; 
     56 
     57 
     58    /** 
     59     * Indicates that a session is requested to be secure 
     60     * 
     61     * @var string 
     62     */ 
     63    protected $_secure; 
     64 
     65 
     66    /** 
     67     * Indicates an smtp session has been started by the HELO command 
     68     * 
     69     * @var boolean 
     70     */ 
     71    protected $_sess = false; 
     72 
     73 
     74    /** 
     75     * Indicates the HELO command has been issues 
     76     * 
     77     * @var unknown_type 
     78     */ 
     79    protected $_helo = false; 
     80 
     81 
     82    /** 
     83     * Indicates an smtp AUTH has been issued and authenticated 
     84     * 
     85     * @var unknown_type 
     86     */ 
     87    protected $_auth = false; 
     88 
     89 
     90    /** 
     91     * Indicates a MAIL command has been issued 
     92     * 
     93     * @var unknown_type 
     94     */ 
     95    protected $_mail = false; 
     96 
     97 
     98    /** 
     99     * Indicates one or more RCTP commands have been issued 
     100     * 
     101     * @var unknown_type 
     102     */ 
     103    protected $_rcpt = false; 
     104 
     105 
     106    /** 
     107     * Indicates that DATA has been issued and sent 
     108     * 
     109     * @var unknown_type 
     110     */ 
     111    protected $_data = null; 
     112 
     113 
     114    /** 
     115     * Constructor. 
     116     * 
     117     * @param  string  $host 
     118     * @param  integer $port 
     119     * @param  array   $config 
     120     * @return void 
     121     * @throws Zend_Mail_Protocol_Exception 
     122     */ 
     123    public function __construct($host = '127.0.0.1', $port = null, array $config = array()) 
     124    { 
     125        if (isset($config['ssl'])) { 
     126            switch (strtolower($config['ssl'])) { 
     127                case 'tls': 
     128                    $this->_secure = 'tls'; 
     129                    break; 
     130 
     131                case 'ssl': 
     132                    $this->_transport = 'ssl'; 
     133                    $this->_secure = 'ssl'; 
     134                    if ($port == null) { 
     135                        $port = 465; 
     136                    } 
     137                    break; 
     138 
     139                default: 
     140                    /** 
     141                     * @see Zend_Mail_Protocol_Exception 
     142                     */ 
     143                    require_once 'Zend/Mail/Protocol/Exception.php'; 
     144                    throw new Zend_Mail_Protocol_Exception($config['ssl'] . ' is unsupported SSL type'); 
     145                    break; 
     146            } 
     147        } 
     148 
     149        // If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null. 
     150        if ($port == null) { 
     151            if (($port = ini_get('smtp_port')) == '') { 
     152                $port = 25; 
     153            } 
     154        } 
     155 
     156        parent::__construct($host, $port); 
     157    } 
     158 
     159 
     160    /** 
     161     * Connect to the server with the parameters given in the constructor. 
     162     * 
     163     * @return boolean 
     164     */ 
     165    public function connect() 
     166    { 
     167        return $this->_connect($this->_transport . '://' . $this->_host . ':'. $this->_port); 
     168    } 
     169 
     170 
     171    /** 
     172     * Initiate HELO/EHLO sequence and set flag to indicate valid smtp session 
     173     * 
     174     * @param  string $host The client hostname or IP address (default: 127.0.0.1) 
     175     * @throws Zend_Mail_Protocol_Exception 
     176     * @return void 
     177     */ 
     178    public function helo($host = '127.0.0.1') 
     179    { 
     180        // Respect RFC 2821 and disallow HELO attempts if session is already initiated. 
     181        if ($this->_sess === true) { 
     182            /** 
     183             * @see Zend_Mail_Protocol_Exception 
     184             */ 
     185            require_once 'Zend/Mail/Protocol/Exception.php'; 
     186            throw new Zend_Mail_Protocol_Exception('Cannot issue HELO to existing session'); 
     187        } 
     188 
     189        // Validate client hostname 
     190        if (!$this->_validHost->isValid($host)) { 
     191            /** 
     192             * @see Zend_Mail_Protocol_Exception 
     193             */ 
     194            require_once 'Zend/Mail/Protocol/Exception.php'; 
     195            throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessage())); 
     196        } 
     197 
     198        // Initiate helo sequence 
     199        $this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     200        $this->_ehlo($host); 
     201 
     202        // If a TLS session is required, commence negotiation 
     203        if ($this->_secure == 'tls') { 
     204            $this->_send('STARTTLS'); 
     205            $this->_expect(220, 180); 
     206            if (!stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { 
     207                /** 
     208                 * @see Zend_Mail_Protocol_Exception 
     209                 */ 
     210                require_once 'Zend/Mail/Protocol/Exception.php'; 
     211                throw new Zend_Mail_Protocol_Exception('Unable to connect via TLS'); 
     212            } 
     213            $this->_ehlo($host); 
     214        } 
     215 
     216        $this->_startSession(); 
     217        $this->auth(); 
     218    } 
     219 
     220 
     221    /** 
     222     * Send EHLO or HELO depending on capabilities of smtp host 
     223     * 
     224     * @param  string $host The client hostname or IP address (default: 127.0.0.1) 
     225     * @throws Zend_Mail_Protocol_Exception 
     226     * @return void 
     227     */ 
     228    protected function _ehlo($host) 
     229    { 
     230        // Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO. 
     231        try { 
     232            $this->_send('EHLO ' . $host); 
     233            $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     234        } catch (Zend_Mail_Protocol_Exception $e) { 
     235            $this->_send('HELO ' . $host); 
     236            $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     237        } catch (Zend_Mail_Protocol_Exception $e) { 
     238            throw $e; 
     239        } 
     240    } 
     241 
     242 
     243    /** 
     244     * Issues MAIL command 
     245     * 
     246     * @param  string $from Sender mailbox 
     247     * @throws Zend_Mail_Protocol_Exception 
     248     * @return void 
     249     */ 
     250    public function mail($from) 
     251    { 
     252        if ($this->_sess !== true) { 
     253            /** 
     254             * @see Zend_Mail_Protocol_Exception 
     255             */ 
     256            require_once 'Zend/Mail/Protocol/Exception.php'; 
     257            throw new Zend_Mail_Protocol_Exception('A valid session has not been started'); 
     258        } 
     259 
     260        $this->_send('MAIL FROM:<' . $from . '>'); 
     261        $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     262 
     263        // Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821 
     264        $this->_mail = true; 
     265        $this->_rcpt = false; 
     266        $this->_data = false; 
     267    } 
     268 
     269 
     270    /** 
     271     * Issues RCPT command 
     272     * 
     273     * @param  string $to Receiver(s) mailbox 
     274     * @throws Zend_Mail_Protocol_Exception 
     275     * @return void 
     276     */ 
     277    public function rcpt($to) 
     278    { 
     279        if ($this->_mail !== true) { 
     280            /** 
     281             * @see Zend_Mail_Protocol_Exception 
     282             */ 
     283            require_once 'Zend/Mail/Protocol/Exception.php'; 
     284            throw new Zend_Mail_Protocol_Exception('No sender reverse path has been supplied'); 
     285        } 
     286 
     287        // Set rcpt to true, as per 4.1.1.3 of RFC 2821 
     288        $this->_send('RCPT TO:<' . $to . '>'); 
     289        $this->_expect(array(250, 251), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     290        $this->_rcpt = true; 
     291    } 
     292 
     293 
     294    /** 
     295     * Issues DATA command 
     296     * 
     297     * @param  string $data 
     298     * @throws Zend_Mail_Protocol_Exception 
     299     * @return void 
     300     */ 
     301    public function data($data) 
     302    { 
     303        // Ensure recipients have been set 
     304        if ($this->_rcpt !== true) { 
     305            /** 
     306             * @see Zend_Mail_Protocol_Exception 
     307             */ 
     308            require_once 'Zend/Mail/Protocol/Exception.php'; 
     309            throw new Zend_Mail_Protocol_Exception('No recipient forward path has been supplied'); 
     310        } 
     311 
     312        $this->_send('DATA'); 
     313        $this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2 
     314 
     315        foreach (explode(Zend_Mime::LINEEND, $data) as $line) { 
     316            if (strpos($line, '.') === 0) { 
     317                // Escape lines prefixed with a '.' 
     318                $line = '.' . $line; 
     319            } 
     320            $this->_send($line); 
     321        } 
     322 
     323        $this->_send('.'); 
     324        $this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2 
     325        $this->_data = true; 
     326    } 
     327 
     328 
     329    /** 
     330     * Issues the RSET command end validates answer 
     331     * 
     332     * Can be used to restore a clean smtp communication state when a transaction has been cancelled or commencing a new transaction. 
     333     * 
     334     * @return void 
     335     */ 
     336    public function rset() 
     337    { 
     338        $this->_send('RSET'); 
     339        // MS ESMTP doesn't follow RFC, see [ZF-1377] 
     340        $this->_expect(array(250, 220)); 
     341 
     342        $this->_mail = false; 
     343        $this->_rcpt = false; 
     344        $this->_data = false; 
     345    } 
     346 
     347 
     348    /** 
     349     * Issues the NOOP command end validates answer 
     350     * 
     351     * Not used by Zend_Mail, could be used to keep a connection alive or check if it is still open. 
     352     * 
     353     * @return void 
     354     */ 
     355    public function noop() 
     356    { 
     357        $this->_send('NOOP'); 
     358        $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     359    } 
     360 
     361 
     362    /** 
     363     * Issues the VRFY command end validates answer 
     364     * 
     365     * Not used by Zend_Mail. 
     366     * 
     367     * @param  string $user User Name or eMail to verify 
     368     * @return void 
     369     */ 
     370    public function vrfy($user) 
     371    { 
     372        $this->_send('VRFY ' . $user); 
     373        $this->_expect(array(250, 251, 252), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     374    } 
     375 
     376 
     377    /** 
     378     * Issues the QUIT command and clears the current session 
     379     * 
     380     * @return void 
     381     */ 
     382    public function quit() 
     383    { 
     384        if ($this->_sess) { 
     385            $this->_send('QUIT'); 
     386            $this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2 
     387            $this->_stopSession(); 
     388        } 
     389    } 
     390 
     391 
     392    /** 
     393     * Default authentication method 
     394     * 
     395     * This default method is implemented by AUTH adapters to properly authenticate to a remote host. 
     396     * 
     397     * @throws Zend_Mail_Protocol_Exception 
     398     * @return void 
     399     */ 
     400    public function auth() 
     401    { 
     402        if ($this->_auth === true) { 
     403            /** 
     404             * @see Zend_Mail_Protocol_Exception 
     405             */ 
     406            require_once 'Zend/Mail/Protocol/Exception.php'; 
     407            throw new Zend_Mail_Protocol_Exception('Already authenticated for this session'); 
     408        } 
     409    } 
     410 
     411 
     412    /** 
     413     * Closes connection 
     414     * 
     415     * @return void 
     416     */ 
     417    public function disconnect() 
     418    { 
     419        $this->_disconnect(); 
     420    } 
     421 
     422 
     423    /** 
     424     * Start mail session 
     425     * 
     426     * @return void 
     427     */ 
     428    protected function _startSession() 
     429    { 
     430        $this->_sess = true; 
     431    } 
     432 
     433 
     434    /** 
     435     * Stop mail session 
     436     * 
     437     * @return void 
     438     */ 
     439    protected function _stopSession() 
     440    { 
     441        $this->_sess = false; 
     442    } 
     443} 
  • libs/Zend/Mail/Protocol/Imap.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Protocol 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Imap.php 8928 2008-03-20 19:41:41Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @category   Zend 
     26 * @package    Zend_Mail 
     27 * @subpackage Protocol 
     28 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     29 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     30 */ 
     31class Zend_Mail_Protocol_Imap 
     32{ 
     33    /** 
     34     * socket to imap server 
     35     * @var resource|null 
     36     */ 
     37    protected $_socket; 
     38 
     39    /** 
     40     * counter for request tag 
     41     * @var int 
     42     */ 
     43    protected $_tagCount = 0; 
     44 
     45 
     46    /** 
     47     * Public constructor 
     48     * 
     49     * @param  string   $host  hostname of IP address of IMAP server, if given connect() is called 
     50     * @param  int|null $port  port of IMAP server, null for default (143 or 993 for ssl) 
     51     * @param  bool     $ssl   use ssl? 'SSL', 'TLS' or false 
     52     * @throws Zend_Mail_Protocol_Exception 
     53     */ 
     54    function __construct($host = '', $port = null, $ssl = false) 
     55    { 
     56        if ($host) { 
     57            $this->connect($host, $port, $ssl); 
     58        } 
     59    } 
     60 
     61    /** 
     62     * Public destructor 
     63     */ 
     64    public function __destruct() 
     65    { 
     66        $this->logout(); 
     67    } 
     68 
     69    /** 
     70     * Open connection to POP3 server 
     71     * 
     72     * @param  string      $host  hostname of IP address of POP3 server 
     73     * @param  int|null    $port  of IMAP server, default is 143 (993 for ssl) 
     74     * @param  string|bool $ssl   use 'SSL', 'TLS' or false 
     75     * @return string welcome message 
     76     * @throws Zend_Mail_Protocol_Exception 
     77     */ 
     78    public function connect($host, $port = null, $ssl = false) 
     79    { 
     80        if ($ssl == 'SSL') { 
     81            $host = 'ssl://' . $host; 
     82        } 
     83 
     84        if ($port === null) { 
     85            $port = $ssl === 'SSL' ? 993 : 143; 
     86        } 
     87 
     88        $this->_socket = @fsockopen($host, $port); 
     89        if (!$this->_socket) { 
     90            /** 
     91             * @see Zend_Mail_Protocol_Exception 
     92             */ 
     93            require_once 'Zend/Mail/Protocol/Exception.php'; 
     94            throw new Zend_Mail_Protocol_Exception('cannot connect to host'); 
     95        } 
     96 
     97        if (!$this->_assumedNextLine('* OK')) { 
     98            /** 
     99             * @see Zend_Mail_Protocol_Exception 
     100             */ 
     101            require_once 'Zend/Mail/Protocol/Exception.php'; 
     102            throw new Zend_Mail_Protocol_Exception('host doesn\'t allow connection'); 
     103        } 
     104 
     105        if ($ssl === 'TLS') { 
     106            $result = $this->requestAndResponse('STARTTLS'); 
     107            $result = $result && stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); 
     108            if (!$result) { 
     109                /** 
     110                 * @see Zend_Mail_Protocol_Exception 
     111                 */ 
     112                require_once 'Zend/Mail/Protocol/Exception.php'; 
     113                throw new Zend_Mail_Protocol_Exception('cannot enable TLS'); 
     114            } 
     115        } 
     116    } 
     117 
     118    /** 
     119     * get the next line from socket with error checking, but nothing else 
     120     * 
     121     * @return string next line 
     122     * @throws Zend_Mail_Protocol_Exception 
     123     */ 
     124    protected function _nextLine() 
     125    { 
     126        $line = @fgets($this->_socket); 
     127        if ($line === false) { 
     128            /** 
     129             * @see Zend_Mail_Protocol_Exception 
     130             */ 
     131            require_once 'Zend/Mail/Protocol/Exception.php'; 
     132            throw new Zend_Mail_Protocol_Exception('cannot read - connection closed?'); 
     133        } 
     134 
     135        return $line; 
     136    } 
     137 
     138    /** 
     139     * get next line and assume it starts with $start. some requests give a simple 
     140     * feedback so we can quickly check if we can go on. 
     141     * 
     142     * @param  string $start the first bytes we assume to be in the next line 
     143     * @return bool line starts with $start 
     144     * @throws Zend_Mail_Protocol_Exception 
     145     */ 
     146    protected function _assumedNextLine($start) 
     147    { 
     148        $line = $this->_nextLine(); 
     149        return strpos($line, $start) === 0; 
     150    } 
     151 
     152    /** 
     153     * get next line and split the tag. that's the normal case for a response line 
     154     * 
     155     * @param  string $tag tag of line is returned by reference 
     156     * @return string next line 
     157     * @throws Zend_Mail_Protocol_Exception 
     158     */ 
     159    protected function _nextTaggedLine(&$tag) 
     160    { 
     161        $line = $this->_nextLine(); 
     162 
     163        // seperate tag from line 
     164        list($tag, $line) = explode(' ', $line, 2); 
     165 
     166        return $line; 
     167    } 
     168 
     169    /** 
     170     * split a given line in tokens. a token is literal of any form or a list 
     171     * 
     172     * @param  string $line line to decode 
     173     * @return array tokens, literals are returned as string, lists as array 
     174     * @throws Zend_Mail_Protocol_Exception 
     175     */ 
     176    protected function _decodeLine($line) 
     177    { 
     178        $tokens = array(); 
     179        $stack = array(); 
     180 
     181        /* 
     182            We start to decode the response here. The unterstood tokens are: 
     183                literal 
     184                "literal" or also "lit\\er\"al" 
     185                {bytes}<NL>literal 
     186                (literals*) 
     187            All tokens are returned in an array. Literals in braces (the last unterstood 
     188            token in the list) are returned as an array of tokens. I.e. the following response: 
     189                "foo" baz {3}<NL>bar ("f\\\"oo" bar) 
     190            would be returned as: 
     191                array('foo', 'baz', 'bar', array('f\\\"oo', 'bar')); 
     192                 
     193            // TODO: add handling of '[' and ']' to parser for easier handling of response text  
     194        */ 
     195        //  replace any trailling <NL> including spaces with a single space 
     196        $line = rtrim($line) . ' '; 
     197        while (($pos = strpos($line, ' ')) !== false) { 
     198            $token = substr($line, 0, $pos); 
     199            while ($token[0] == '(') { 
     200                array_push($stack, $tokens); 
     201                $tokens = array(); 
     202                $token = substr($token, 1); 
     203            } 
     204            if ($token[0] == '"') { 
     205                if (preg_match('%^"((.|\\\\|\\")*?)" *%', $line, $matches)) { 
     206                    $tokens[] = $matches[1]; 
     207                    $line = substr($line, strlen($matches[0])); 
     208                    continue; 
     209                } 
     210            } 
     211            if ($token[0] == '{') { 
     212                $endPos = strpos($token, '}'); 
     213                $chars = substr($token, 1, $endPos - 1); 
     214                if (is_numeric($chars)) { 
     215                    $token = ''; 
     216                    while (strlen($token) < $chars) { 
     217                        $token .= $this->_nextLine(); 
     218                    } 
     219                    $line = ''; 
     220                    if (strlen($token) > $chars) { 
     221                        $line = substr($token, $chars); 
     222                        $token = substr($token, 0, $chars); 
     223                    } else { 
     224                        $line .= $this->_nextLine(); 
     225                    } 
     226                    $tokens[] = $token; 
     227                    $line = trim($line) . ' '; 
     228                    continue; 
     229                } 
     230            } 
     231            if ($stack && $token[strlen($token) - 1] == ')') { 
     232                // closing braces are not seperated by spaces, so we need to count them 
     233                $braces = strlen($token); 
     234                $token = rtrim($token, ')'); 
     235                // only count braces if more than one 
     236                $braces -= strlen($token) + 1; 
     237                // only add if token had more than just closing braces 
     238                if ($token) { 
     239                    $tokens[] = $token; 
     240                } 
     241                $token = $tokens; 
     242                $tokens = array_pop($stack); 
     243                // special handline if more than one closing brace 
     244                while ($braces-- > 0) { 
     245                    $tokens[] = $token; 
     246                    $token = $tokens; 
     247                    $tokens = array_pop($stack); 
     248                } 
     249            } 
     250            $tokens[] = $token; 
     251            $line = substr($line, $pos + 1); 
     252        } 
     253 
     254        // maybe the server forgot to send some closing braces 
     255        while ($stack) { 
     256            $child = $tokens; 
     257            $tokens = array_pop($stack); 
     258            $tokens[] = $child; 
     259        } 
     260 
     261        return $tokens; 
     262    } 
     263 
     264    /** 
     265     * read a response "line" (could also be more than one real line if response has {..}<NL>) 
     266     * and do a simple decode 
     267     * 
     268     * @param  array|string  $tokens    decoded tokens are returned by reference, if $dontParse 
     269     *                                  is true the unparsed line is returned here 
     270     * @param  string        $wantedTag check for this tag for response code. Default '*' is 
     271     *                                  continuation tag. 
     272     * @param  bool          $dontParse if true only the unparsed line is returned $tokens 
     273     * @return bool if returned tag matches wanted tag 
     274     * @throws Zend_Mail_Protocol_Exception 
     275     */ 
     276    public function readLine(&$tokens = array(), $wantedTag = '*', $dontParse = false) 
     277    { 
     278        $line = $this->_nextTaggedLine($tag); 
     279        if (!$dontParse) { 
     280            $tokens = $this->_decodeLine($line); 
     281        } else { 
     282            $tokens = $line; 
     283        } 
     284 
     285        // if tag is wanted tag we might be at the end of a multiline response 
     286        return $tag == $wantedTag; 
     287    } 
     288 
     289    /** 
     290     * read all lines of response until given tag is found (last line of response) 
     291     * 
     292     * @param  string       $tag       the tag of your request 
     293     * @param  string|array $filter    you can filter the response so you get only the 
     294     *                                 given response lines 
     295     * @param  bool         $dontParse if true every line is returned unparsed instead of 
     296     *                                 the decoded tokens 
     297     * @return null|bool|array tokens if success, false if error, null if bad request 
     298     * @throws Zend_Mail_Protocol_Exception 
     299     */ 
     300    public function readResponse($tag, $dontParse = false) 
     301    { 
     302        $lines = array(); 
     303        while (!$this->readLine($tokens, $tag, $dontParse)) { 
     304            $lines[] = $tokens; 
     305        } 
     306 
     307        if ($dontParse) { 
     308            // last to chars are still needed for response code 
     309            $tokens = array(substr($tokens, 0, 2)); 
     310        } 
     311        // last line has response code 
     312        if ($tokens[0] == 'OK') { 
     313            return $lines ? $lines : true; 
     314        } else if ($tokens[0] == 'NO'){ 
     315            return false; 
     316        } 
     317        return null; 
     318    } 
     319 
     320    /** 
     321     * send a request 
     322     * 
     323     * @param  string $command your request command 
     324     * @param  array  $tokens  additional parameters to command, use escapeString() to prepare 
     325     * @param  string $tag     provide a tag otherwise an autogenerated is returned 
     326     * @return null 
     327     * @throws Zend_Mail_Protocol_Exception 
     328     */ 
     329    public function sendRequest($command, $tokens = array(), &$tag = null) 
     330    { 
     331        if (!$tag) { 
     332            ++$this->_tagCount; 
     333            $tag = 'TAG' . $this->_tagCount; 
     334        } 
     335 
     336        $line = $tag . ' ' . $command; 
     337 
     338        foreach ($tokens as $token) { 
     339            if (is_array($token)) { 
     340                if (@fputs($this->_socket, $line . ' ' . $token[0] . "\r\n") === false) { 
     341                    /** 
     342                     * @see Zend_Mail_Protocol_Exception 
     343                     */ 
     344                    require_once 'Zend/Mail/Protocol/Exception.php'; 
     345                    throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?'); 
     346                } 
     347                if (!$this->_assumedNextLine('+ OK')) { 
     348                    /** 
     349                     * @see Zend_Mail_Protocol_Exception 
     350                     */ 
     351                    require_once 'Zend/Mail/Protocol/Exception.php'; 
     352                    throw new Zend_Mail_Protocol_Exception('cannot send literal string'); 
     353                } 
     354                $line = $token[1]; 
     355            } else { 
     356                $line .= ' ' . $token; 
     357            } 
     358        } 
     359 
     360        if (@fputs($this->_socket, $line . "\r\n") === false) { 
     361            /** 
     362             * @see Zend_Mail_Protocol_Exception 
     363             */ 
     364            require_once 'Zend/Mail/Protocol/Exception.php'; 
     365            throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?'); 
     366        } 
     367    } 
     368 
     369    /** 
     370     * send a request and get response at once 
     371     * 
     372     * @param  string $command   command as in sendRequest() 
     373     * @param  array  $tokens    parameters as in sendRequest() 
     374     * @param  bool   $dontParse if true unparsed lines are returned instead of tokens 
     375     * @return mixed response as in readResponse() 
     376     * @throws Zend_Mail_Protocol_Exception 
     377     */ 
     378    public function requestAndResponse($command, $tokens = array(), $dontParse = false) 
     379    { 
     380        $this->sendRequest($command, $tokens, $tag); 
     381        $response = $this->readResponse($tag, $dontParse); 
     382 
     383        return $response; 
     384    } 
     385 
     386    /** 
     387     * escape one or more literals i.e. for sendRequest 
     388     * 
     389     * @param  string|array $string the literal/-s 
     390     * @return string|array escape literals, literals with newline ar returned 
     391     *                      as array('{size}', 'string'); 
     392     */ 
     393    public function escapeString($string) 
     394    { 
     395        if (func_num_args() < 2) { 
     396            if (strpos($string, "\n") !== false) { 
     397                return array('{' . strlen($string) . '}', $string); 
     398            } else { 
     399                return '"' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $string) . '"'; 
     400            } 
     401        } 
     402        $result = array(); 
     403        foreach (func_get_args() as $string) { 
     404            $result[] = $this->escapeString($string); 
     405        } 
     406        return $result; 
     407    } 
     408 
     409    /** 
     410     * escape a list with literals or lists 
     411     * 
     412     * @param  array $list list with literals or lists as PHP array 
     413     * @return string escaped list for imap 
     414     */ 
     415    public function escapeList($list) 
     416    { 
     417        $result = array(); 
     418        foreach ($list as $k => $v) { 
     419            if (!is_array($v)) { 
     420//              $result[] = $this->escapeString($v); 
     421                $result[] = $v; 
     422                continue; 
     423            } 
     424            $result[] = $this->escapeList($v); 
     425        } 
     426        return '(' . implode(' ', $result) . ')'; 
     427    } 
     428 
     429    /** 
     430     * Login to IMAP server. 
     431     * 
     432     * @param  string $user      username 
     433     * @param  string $password  password 
     434     * @return bool success 
     435     * @throws Zend_Mail_Protocol_Exception 
     436     */ 
     437    public function login($user, $password) 
     438    { 
     439        return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true); 
     440    } 
     441 
     442    /** 
     443     * logout of imap server 
     444     * 
     445     * @return bool success 
     446     */ 
     447    public function logout() 
     448    { 
     449        $result = false; 
     450        if ($this->_socket) { 
     451            try { 
     452                $result = $this->requestAndResponse('LOGOUT', array(), true); 
     453            } catch (Zend_Mail_Protocol_Exception $e) { 
     454                // ignoring exception 
     455            } 
     456            fclose($this->_socket); 
     457            $this->_socket = null; 
     458        } 
     459        return $result; 
     460    } 
     461 
     462 
     463    /** 
     464     * Get capabilities from IMAP server 
     465     * 
     466     * @return array list of capabilities 
     467     * @throws Zend_Mail_Protocol_Exception 
     468     */ 
     469    public function capability() 
     470    { 
     471        $response = $this->requestAndResponse('CAPABILITY'); 
     472 
     473        if (!$response) { 
     474            return $response; 
     475        } 
     476 
     477        $capabilities = array(); 
     478        foreach ($response as $line) { 
     479            $capabilities = array_merge($capabilities, $line); 
     480        } 
     481        return $capabilities; 
     482    } 
     483 
     484    /** 
     485     * Examine and select have the same response. The common code for both 
     486     * is in this method 
     487     * 
     488     * @param  string $command can be 'EXAMINE' or 'SELECT' and this is used as command 
     489     * @param  string $box which folder to change to or examine 
     490     * @return bool|array false if error, array with returned information 
     491     *                    otherwise (flags, exists, recent, uidvalidity) 
     492     * @throws Zend_Mail_Protocol_Exception 
     493     */ 
     494    public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX') 
     495    { 
     496        $this->sendRequest($command, array($this->escapeString($box)), $tag); 
     497 
     498        $result = array(); 
     499        while (!$this->readLine($tokens, $tag)) { 
     500            if ($tokens[0] == 'FLAGS') { 
     501                array_shift($tokens); 
     502                $result['flags'] = $tokens; 
     503                continue; 
     504            } 
     505            switch ($tokens[1]) { 
     506                case 'EXISTS': 
     507                case 'RECENT': 
     508                    $result[strtolower($tokens[1])] = $tokens[0]; 
     509                    break; 
     510                case '[UIDVALIDITY': 
     511                    $result['uidvalidity'] = (int)$tokens[2]; 
     512                    break; 
     513                default: 
     514                    // ignore 
     515            } 
     516        } 
     517 
     518        if ($tokens[0] != 'OK') { 
     519            return false; 
     520        } 
     521        return $result; 
     522    } 
     523 
     524    /** 
     525     * change folder 
     526     * 
     527     * @param  string $box change to this folder 
     528     * @return bool|array see examineOrselect() 
     529     * @throws Zend_Mail_Protocol_Exception 
     530     */ 
     531    public function select($box = 'INBOX') 
     532    { 
     533        return $this->examineOrSelect('SELECT', $box); 
     534    } 
     535 
     536    /** 
     537     * examine folder 
     538     * 
     539     * @param  string $box examine this folder 
     540     * @return bool|array see examineOrselect() 
     541     * @throws Zend_Mail_Protocol_Exception 
     542     */ 
     543    public function examine($box = 'INBOX') 
     544    { 
     545        return $this->examineOrSelect('EXAMINE', $box); 
     546    } 
     547 
     548    /** 
     549     * fetch one or more items of one or more messages 
     550     * 
     551     * @param  string|array $items items to fetch from message(s) as string (if only one item) 
     552     *                             or array of strings 
     553     * @param  int          $from  message for items or start message if $to !== null 
     554     * @param  int|null     $to    if null only one message ($from) is fetched, else it's the 
     555     *                             last message, INF means last message avaible 
     556     * @return string|array if only one item of one message is fetched it's returned as string 
     557     *                      if items of one message are fetched it's returned as (name => value) 
     558     *                      if one items of messages are fetched it's returned as (msgno => value) 
     559     *                      if items of messages are fetchted it's returned as (msgno => (name => value)) 
     560     * @throws Zend_Mail_Protocol_Exception 
     561     */ 
     562    public function fetch($items, $from, $to = null) 
     563    { 
     564        if (is_array($from)) { 
     565            $set = implode(',', $from); 
     566        } else if ($to === null) { 
     567            $set = (int)$from; 
     568        } else if ($to === INF) { 
     569            $set = (int)$from . ':*'; 
     570        } else { 
     571            $set = (int)$from . ':' . (int)$to; 
     572        } 
     573 
     574        $items = (array)$items; 
     575        $itemList = $this->escapeList($items); 
     576 
     577        $this->sendRequest('FETCH', array($set, $itemList), $tag); 
     578 
     579        $result = array(); 
     580        while (!$this->readLine($tokens, $tag)) { 
     581            // ignore other responses 
     582            if ($tokens[1] != 'FETCH') { 
     583                continue; 
     584            } 
     585            // ignore other messages 
     586            if ($to === null && !is_array($from) && $tokens[0] != $from) { 
     587                continue; 
     588            } 
     589            // if we only want one item we return that one directly 
     590            if (count($items) == 1) { 
     591                if ($tokens[2][0] == $items[0]) { 
     592                    $data = $tokens[2][1]; 
     593                } else { 
     594                    // maybe the server send an other field we didn't wanted 
     595                    $count = count($tokens[2]); 
     596                    // we start with 2, because 0 was already checked 
     597                    for ($i = 2; $i < $count; $i += 2) { 
     598                        if ($tokens[2][$i] != $items[0]) { 
     599                            continue; 
     600                        } 
     601                        $data = $tokens[2][$i + 1]; 
     602                        break; 
     603                    } 
     604                } 
     605            } else { 
     606                $data = array(); 
     607                while (key($tokens[2]) !== null) { 
     608                    $data[current($tokens[2])] = next($tokens[2]); 
     609                    next($tokens[2]); 
     610                } 
     611            } 
     612            // if we want only one message we can ignore everything else and just return 
     613            if ($to === null && !is_array($from) && $tokens[0] == $from) { 
     614                // we still need to read all lines 
     615                while (!$this->readLine($tokens, $tag)); 
     616                return $data; 
     617            } 
     618            $result[$tokens[0]] = $data; 
     619        } 
     620 
     621        if ($to === null && !is_array($from)) { 
     622            /** 
     623             * @see Zend_Mail_Protocol_Exception 
     624             */ 
     625            require_once 'Zend/Mail/Protocol/Exception.php'; 
     626            throw new Zend_Mail_Protocol_Exception('the single id was not found in response'); 
     627        } 
     628 
     629        return $result; 
     630    } 
     631 
     632    /** 
     633     * get mailbox list 
     634     * 
     635     * this method can't be named after the IMAP command 'LIST', as list is a reserved keyword 
     636     * 
     637     * @param  string $reference mailbox reference for list 
     638     * @param  string $mailbox   mailbox name match with wildcards 
     639     * @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..)) 
     640     * @throws Zend_Mail_Protocol_Exception 
     641     */ 
     642    public function listMailbox($reference = '', $mailbox = '*') 
     643    { 
     644        $result = array(); 
     645        $list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox)); 
     646        if (!$list) { 
     647            return $result; 
     648        } 
     649 
     650        foreach ($list as $item) { 
     651            if (count($item) != 4 || $item[0] != 'LIST') { 
     652                continue; 
     653            } 
     654            $result[$item[3]] = array('delim' => $item[2], 'flags' => $item[1]); 
     655        } 
     656 
     657        return $result; 
     658    } 
     659 
     660    /** 
     661     * set flags 
     662     * 
     663     * @param  array       $flags  flags to set, add or remove - see $mode 
     664     * @param  int         $from   message for items or start message if $to !== null 
     665     * @param  int|null    $to     if null only one message ($from) is fetched, else it's the 
     666     *                             last message, INF means last message avaible 
     667     * @param  string|null $mode   '+' to add flags, '-' to remove flags, everything else sets the flags as given 
     668     * @param  bool        $silent if false the return values are the new flags for the wanted messages 
     669     * @return bool|array new flags if $silent is false, else true or false depending on success 
     670     * @throws Zend_Mail_Protocol_Exception 
     671     */ 
     672    public function store(array $flags, $from, $to = null, $mode = null, $silent = true) 
     673    { 
     674        $item = 'FLAGS'; 
     675        if ($mode == '+' || $mode == '-') { 
     676            $item = $mode . $item; 
     677        } 
     678        if ($silent) { 
     679            $item .= '.SILENT'; 
     680        } 
     681 
     682        $flags = $this->escapeList($flags); 
     683        $set = (int)$from; 
     684        if ($to != null) { 
     685            $set .= ':' . ($to == INF ? '*' : (int)$to); 
     686        } 
     687 
     688        $result = $this->requestAndResponse('STORE', array($set, $item, $flags), $silent); 
     689 
     690        if ($silent) { 
     691            return $result ? true : false; 
     692        } 
     693 
     694        $tokens = $result; 
     695        $result = array(); 
     696        foreach ($tokens as $token) { 
     697            if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') { 
     698                continue; 
     699            } 
     700            $result[$token[0]] = $token[2][1]; 
     701        } 
     702 
     703        return $result; 
     704    } 
     705 
     706    /** 
     707     * append a new message to given folder 
     708     * 
     709     * @param string $folder  name of target folder 
     710     * @param string $message full message content 
     711     * @param array  $flags   flags for new message 
     712     * @param string $date    date for new message 
     713     * @return bool success 
     714     * @throws Zend_Mail_Protocol_Exception 
     715     */ 
     716    public function append($folder, $message, $flags = null, $date = null) 
     717    { 
     718        $tokens = array(); 
     719        $tokens[] = $this->escapeString($folder); 
     720        if ($flags !== null) { 
     721            $tokens[] = $this->escapeList($flags); 
     722        } 
     723        if ($date !== null) { 
     724            $tokens[] = $this->escapeString($date); 
     725        } 
     726        $tokens[] = $this->escapeString($message); 
     727 
     728        return $this->requestAndResponse('APPEND', $tokens, true); 
     729    } 
     730 
     731    /** 
     732     * copy message set from current folder to other folder 
     733     * 
     734     * @param string   $folder destination folder 
     735     * @param int|null $to     if null only one message ($from) is fetched, else it's the 
     736     *                         last message, INF means last message avaible 
     737     * @return bool success 
     738     * @throws Zend_Mail_Protocol_Exception 
     739     */ 
     740    public function copy($folder, $from, $to = null) 
     741    { 
     742        $set = (int)$from; 
     743        if ($to != null) { 
     744            $set .= ':' . ($to == INF ? '*' : (int)$to); 
     745        } 
     746 
     747        return $this->requestAndResponse('COPY', array($set, $this->escapeString($folder)), true); 
     748    } 
     749 
     750    /** 
     751     * create a new folder (and parent folders if needed) 
     752     * 
     753     * @param string $folder folder name 
     754     * @return bool success 
     755     */ 
     756    public function create($folder) 
     757    { 
     758        return $this->requestAndResponse('CREATE', array($this->escapeString($folder)), true); 
     759    } 
     760 
     761    /** 
     762     * rename an existing folder 
     763     * 
     764     * @param string $old old name 
     765     * @param string $new new name 
     766     * @return bool success 
     767     */ 
     768    public function rename($old, $new) 
     769    { 
     770        return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true); 
     771    } 
     772 
     773    /** 
     774     * remove a folder 
     775     * 
     776     * @param string $folder folder name 
     777     * @return bool success 
     778     */ 
     779    public function delete($folder) 
     780    { 
     781        return $this->requestAndResponse('DELETE', array($this->escapeString($folder)), true); 
     782    } 
     783 
     784    /** 
     785     * permanently remove messages 
     786     * 
     787     * @return bool success 
     788     */ 
     789    public function expunge() 
     790    { 
     791        // TODO: parse response? 
     792        return $this->requestAndResponse('EXPUNGE'); 
     793    } 
     794 
     795    /** 
     796     * send noop 
     797     * 
     798     * @return bool success 
     799     */ 
     800    public function noop() 
     801    { 
     802        // TODO: parse response 
     803        return $this->requestAndResponse('NOOP'); 
     804    } 
     805} 
  • libs/Zend/Mail/Storage/Folder.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Folder.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @category   Zend 
     26 * @package    Zend_Mail 
     27 * @subpackage Storage 
     28 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     29 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     30 */ 
     31class Zend_Mail_Storage_Folder implements RecursiveIterator 
     32{ 
     33    /** 
     34     * subfolders of folder array(localName => Zend_Mail_Storage_Folder folder) 
     35     * @var array 
     36     */ 
     37    protected $_folders; 
     38 
     39    /** 
     40     * local name (name of folder in parent folder) 
     41     * @var string 
     42     */ 
     43    protected $_localName; 
     44 
     45    /** 
     46     * global name (absolute name of folder) 
     47     * @var string 
     48     */ 
     49    protected $_globalName; 
     50 
     51    /** 
     52     * folder is selectable if folder is able to hold messages, else it's just a parent folder 
     53     * @var bool 
     54     */ 
     55    protected $_selectable = true; 
     56 
     57    /** 
     58     * create a new mail folder instance 
     59     * 
     60     * @param string $localName  name of folder in current subdirectory 
     61     * @param string $globalName absolute name of folder 
     62     * @param bool   $selectable if true folder holds messages, if false it's just a parent for subfolders 
     63     * @param array  $folders    init with given instances of Zend_Mail_Storage_Folder as subfolders 
     64     */ 
     65    public function __construct($localName, $globalName = '', $selectable = true, array $folders = array()) 
     66    { 
     67        $this->_localName  = $localName; 
     68        $this->_globalName = $globalName ? $globalName : $localName; 
     69        $this->_selectable = $selectable; 
     70        $this->_folders    = $folders; 
     71    } 
     72 
     73    /** 
     74     * implements RecursiveIterator::hasChildren() 
     75     * 
     76     * @return bool current element has children 
     77     */ 
     78    public function hasChildren() 
     79    { 
     80        $current = $this->current(); 
     81        return $current && $current instanceof Zend_Mail_Storage_Folder && !$current->isLeaf(); 
     82    } 
     83 
     84    /** 
     85     * implements RecursiveIterator::getChildren() 
     86     * 
     87     * @return Zend_Mail_Storage_Folder same as self::current() 
     88     */ 
     89    public function getChildren() 
     90    { 
     91        return $this->current(); 
     92    } 
     93 
     94    /** 
     95     * implements Iterator::valid() 
     96     * 
     97     * @return bool check if there's a current element 
     98     */ 
     99    public function valid() 
     100    { 
     101        return key($this->_folders) !== null; 
     102    } 
     103 
     104    /** 
     105     * implements Iterator::next() 
     106     * 
     107     * @return null 
     108     */ 
     109    public function next() 
     110    { 
     111        next($this->_folders); 
     112    } 
     113 
     114    /** 
     115     * implements Iterator::key() 
     116     * 
     117     * @return string key/local name of current element 
     118     */ 
     119    public function key() 
     120    { 
     121        return key($this->_folders); 
     122    } 
     123 
     124    /** 
     125     * implements Iterator::current() 
     126     * 
     127     * @return Zend_Mail_Storage_Folder current folder 
     128     */ 
     129    public function current() 
     130    { 
     131        return current($this->_folders); 
     132    } 
     133 
     134    /** 
     135     * implements Iterator::rewind() 
     136     * 
     137     * @return null 
     138     */ 
     139    public function rewind() 
     140    { 
     141        reset($this->_folders); 
     142    } 
     143 
     144    /** 
     145     * get subfolder named $name 
     146     * 
     147     * @param  string $name wanted subfolder 
     148     * @return Zend_Mail_Storage_Folder folder named $folder 
     149     * @throws Zend_Mail_Storage_Exception 
     150     */ 
     151    public function __get($name) 
     152    { 
     153        if (!isset($this->_folders[$name])) { 
     154            /** 
     155             * @see Zend_Mail_Storage_Exception 
     156             */ 
     157            require_once 'Zend/Mail/Storage/Exception.php'; 
     158            throw new Zend_Mail_Storage_Exception("no subfolder named $name"); 
     159        } 
     160 
     161        return $this->_folders[$name]; 
     162    } 
     163 
     164    /** 
     165     * add or replace subfolder named $name 
     166     * 
     167     * @param string $name local name of subfolder 
     168     * @param Zend_Mail_Storage_Folder $folder instance for new subfolder 
     169     * @return null 
     170     */ 
     171    public function __set($name, Zend_Mail_Storage_Folder $folder) 
     172    { 
     173        $this->_folders[$name] = $folder; 
     174    } 
     175 
     176    /** 
     177     * remove subfolder named $name 
     178     * 
     179     * @param string $name local name of subfolder 
     180     * @return null 
     181     */ 
     182    public function __unset($name) 
     183    { 
     184        unset($this->_folders[$name]); 
     185    } 
     186 
     187    /** 
     188     * magic method for easy output of global name 
     189     * 
     190     * @return string global name of folder 
     191     */ 
     192    public function __toString() 
     193    { 
     194        return (string)$this->getGlobalName(); 
     195    } 
     196 
     197    /** 
     198     * get local name 
     199     * 
     200     * @return string local name 
     201     */ 
     202    public function getLocalName() 
     203    { 
     204        return $this->_localName; 
     205    } 
     206 
     207    /** 
     208     * get global name 
     209     * 
     210     * @return string global name 
     211     */ 
     212    public function getGlobalName() 
     213    { 
     214        return $this->_globalName; 
     215    } 
     216 
     217    /** 
     218     * is this folder selectable? 
     219     * 
     220     * @return bool selectable 
     221     */ 
     222    public function isSelectable() 
     223    { 
     224        return $this->_selectable; 
     225    } 
     226 
     227    /** 
     228     * check if folder has no subfolder 
     229     * 
     230     * @return bool true if no subfolders 
     231     */ 
     232    public function isLeaf() 
     233    { 
     234        return empty($this->_folders); 
     235    } 
     236} 
  • libs/Zend/Mail/Storage/Exception.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Exception 
     26 */ 
     27require_once 'Zend/Mail/Exception.php'; 
     28 
     29 
     30/** 
     31 * @category   Zend 
     32 * @package    Zend_Mail 
     33 * @subpackage Storage 
     34 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     35 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     36 */ 
     37class Zend_Mail_Storage_Exception extends Zend_Mail_Exception 
     38{} 
     39 
  • libs/Zend/Mail/Storage/Maildir.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Maildir.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Storage_Abstract 
     26 */ 
     27require_once 'Zend/Mail/Storage/Abstract.php'; 
     28 
     29/** 
     30 * @see Zend_Mail_Message 
     31 */ 
     32require_once 'Zend/Mail/Message.php'; 
     33 
     34/** 
     35 * @see Zend_Mail_Storage 
     36 */ 
     37require_once 'Zend/Mail/Storage.php'; 
     38 
     39 
     40/** 
     41 * @category   Zend 
     42 * @package    Zend_Mail 
     43 * @subpackage Storage 
     44 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     45 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     46 */ 
     47class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract 
     48{ 
     49    /** 
     50     * data of found message files in maildir dir 
     51     * @var array 
     52     */ 
     53    protected $_files = array(); 
     54 
     55    /** 
     56     * known flag chars in filenames 
     57     * 
     58     * This list has to be in alphabetical order for setFlags() 
     59     * 
     60     * @var array 
     61     */ 
     62    protected static $_knownFlags = array('D' => Zend_Mail_Storage::FLAG_DRAFT, 
     63                                          'F' => Zend_Mail_Storage::FLAG_FLAGGED, 
     64                                          'P' => Zend_Mail_Storage::FLAG_PASSED, 
     65                                          'R' => Zend_Mail_Storage::FLAG_ANSWERED, 
     66                                          'S' => Zend_Mail_Storage::FLAG_SEEN, 
     67                                          'T' => Zend_Mail_Storage::FLAG_DELETED); 
     68 
     69    /** 
     70     * Count messages all messages in current box 
     71     * 
     72     * @return int number of messages 
     73     * @throws Zend_Mail_Storage_Exception 
     74     */ 
     75    public function countMessages() 
     76    { 
     77        return count($this->_files); 
     78    } 
     79 
     80    /** 
     81     * Get one or all fields from file structure. Also checks if message is valid 
     82     * 
     83     * @param  int         $id    message number 
     84     * @param  string|null $field wanted field 
     85     * @return string|array wanted field or all fields as array 
     86     * @throws Zend_Mail_Storage_Exception 
     87     */ 
     88    protected function _getFileData($id, $field = null) 
     89    { 
     90        if (!isset($this->_files[$id - 1])) { 
     91            /** 
     92             * @see Zend_Mail_Storage_Exception 
     93             */ 
     94            require_once 'Zend/Mail/Storage/Exception.php'; 
     95            throw new Zend_Mail_Storage_Exception('id does not exist'); 
     96        } 
     97 
     98        if (!$field) { 
     99            return $this->_files[$id - 1]; 
     100        } 
     101 
     102        if (!isset($this->_files[$id - 1][$field])) { 
     103            /** 
     104             * @see Zend_Mail_Storage_Exception 
     105             */ 
     106            require_once 'Zend/Mail/Storage/Exception.php'; 
     107            throw new Zend_Mail_Storage_Exception('field does not exist'); 
     108        } 
     109 
     110        return $this->_files[$id - 1][$field]; 
     111    } 
     112 
     113    /** 
     114     * Get a list of messages with number and size 
     115     * 
     116     * @param  int|null $id number of message or null for all messages 
     117     * @return int|array size of given message of list with all messages as array(num => size) 
     118     * @throws Zend_Mail_Storage_Exception 
     119     */ 
     120    public function getSize($id = null) 
     121    { 
     122        if ($id !== null) { 
     123            return filesize($this->_getFileData($id, 'filename')); 
     124        } 
     125 
     126        $result = array(); 
     127        foreach ($this->_files as $num => $pos) { 
     128            $result[$num + 1] = filesize($this->_files[$num]['filename']); 
     129        } 
     130 
     131        return $result; 
     132    } 
     133 
     134 
     135 
     136    /** 
     137     * Fetch a message 
     138     * 
     139     * @param  int $id number of message 
     140     * @return Zend_Mail_Message 
     141     * @throws Zend_Mail_Storage_Exception 
     142     */ 
     143    public function getMessage($id) 
     144    { 
     145        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $this->getRawHeader($id), 
     146                                              'flags'   => $this->_getFileData($id, 'flags'))); 
     147    } 
     148 
     149    /* 
     150     * Get raw header of message or part 
     151     * 
     152     * @param  int               $id       number of message 
     153     * @param  null|array|string $part     path to part or null for messsage header 
     154     * @param  int               $topLines include this many lines with header (after an empty line) 
     155     * @return string raw header 
     156     * @throws Zend_Mail_Storage_Exception 
     157     */ 
     158    public function getRawHeader($id, $part = null, $topLines = 0) 
     159    { 
     160        if ($part !== null) { 
     161            // TODO: implement 
     162            /** 
     163             * @see Zend_Mail_Storage_Exception 
     164             */ 
     165            require_once 'Zend/Mail/Storage/Exception.php'; 
     166            throw new Zend_Mail_Storage_Exception('not implemented'); 
     167        } 
     168 
     169        $fh = fopen($this->_getFileData($id, 'filename'), 'r'); 
     170 
     171        $content = ''; 
     172        while (!feof($fh)) { 
     173            $line = fgets($fh); 
     174            if (!trim($line)) { 
     175                break; 
     176            } 
     177            $content .= $line; 
     178        } 
     179 
     180        fclose($fh); 
     181        return $content; 
     182    } 
     183 
     184    /* 
     185     * Get raw content of message or part 
     186     * 
     187     * @param  int               $id   number of message 
     188     * @param  null|array|string $part path to part or null for messsage content 
     189     * @return string raw content 
     190     * @throws Zend_Mail_Storage_Exception 
     191     */ 
     192    public function getRawContent($id, $part = null) 
     193    { 
     194        if ($part !== null) { 
     195            // TODO: implement 
     196            /** 
     197             * @see Zend_Mail_Storage_Exception 
     198             */ 
     199            require_once 'Zend/Mail/Storage/Exception.php'; 
     200            throw new Zend_Mail_Storage_Exception('not implemented'); 
     201        } 
     202 
     203        $fh = fopen($this->_getFileData($id, 'filename'), 'r'); 
     204 
     205        while (!feof($fh)) { 
     206            $line = fgets($fh); 
     207            if (!trim($line)) { 
     208                break; 
     209            } 
     210        } 
     211 
     212        $content = stream_get_contents($fh); 
     213        fclose($fh); 
     214        return $content; 
     215    } 
     216 
     217    /** 
     218     * Create instance with parameters 
     219     * Supported parameters are: 
     220     *   - dirname dirname of mbox file 
     221     * 
     222     * @param  $params array mail reader specific parameters 
     223     * @throws Zend_Mail_Storage_Exception 
     224     */ 
     225    public function __construct($params) 
     226    { 
     227        if (is_array($params)) { 
     228            $params = (object)$params; 
     229        } 
     230 
     231        if (!isset($params->dirname) || !is_dir($params->dirname)) { 
     232            /** 
     233             * @see Zend_Mail_Storage_Exception 
     234             */ 
     235            require_once 'Zend/Mail/Storage/Exception.php'; 
     236            throw new Zend_Mail_Storage_Exception('no valid dirname given in params'); 
     237        } 
     238 
     239        if (!$this->_isMaildir($params->dirname)) { 
     240            /** 
     241             * @see Zend_Mail_Storage_Exception 
     242             */ 
     243            require_once 'Zend/Mail/Storage/Exception.php'; 
     244            throw new Zend_Mail_Storage_Exception('invalid maildir given'); 
     245        } 
     246 
     247        $this->_has['top'] = true; 
     248        $this->_has['flags'] = true; 
     249        $this->_openMaildir($params->dirname); 
     250    } 
     251 
     252    /** 
     253     * check if a given dir is a valid maildir 
     254     * 
     255     * @param string $dirname name of dir 
     256     * @return bool dir is valid maildir 
     257     */ 
     258    protected function _isMaildir($dirname) 
     259    { 
     260        if (file_exists($dirname . '/new') && !is_dir($dirname . '/new')) { 
     261            return false; 
     262        } 
     263        if (file_exists($dirname . '/tmp') && !is_dir($dirname . '/tmp')) { 
     264            return false; 
     265        } 
     266        return is_dir($dirname . '/cur'); 
     267    } 
     268 
     269    /** 
     270     * open given dir as current maildir 
     271     * 
     272     * @param string $dirname name of maildir 
     273     * @return null 
     274     * @throws Zend_Mail_Storage_Exception 
     275     */ 
     276    protected function _openMaildir($dirname) 
     277    { 
     278        if ($this->_files) { 
     279            $this->close(); 
     280        } 
     281 
     282        $dh = @opendir($dirname . '/cur/'); 
     283        if (!$dh) { 
     284            /** 
     285             * @see Zend_Mail_Storage_Exception 
     286             */ 
     287            require_once 'Zend/Mail/Storage/Exception.php'; 
     288            throw new Zend_Mail_Storage_Exception('cannot open maildir'); 
     289        } 
     290        $this->_getMaildirFiles($dh, $dirname . '/cur/'); 
     291        closedir($dh); 
     292 
     293        $dh = @opendir($dirname . '/new/'); 
     294        if ($dh) { 
     295            $this->_getMaildirFiles($dh, $dirname . '/new/', array(Zend_Mail_Storage::FLAG_RECENT)); 
     296            closedir($dh); 
     297        } else if (file_exists($dirname . '/new/')) { 
     298            /** 
     299             * @see Zend_Mail_Storage_Exception 
     300             */ 
     301            require_once 'Zend/Mail/Storage/Exception.php'; 
     302            throw new Zend_Mail_Storage_Exception('cannot read recent mails in maildir'); 
     303        } 
     304    } 
     305 
     306    /** 
     307     * find all files in opened dir handle and add to maildir files 
     308     * 
     309     * @param resource $dh            dir handle used for search 
     310     * @param string   $dirname       dirname of dir in $dh 
     311     * @param array    $default_flags default flags for given dir 
     312     * @return null 
     313     */ 
     314    protected function _getMaildirFiles($dh, $dirname, $default_flags = array()) 
     315    { 
     316        while (($entry = readdir($dh)) !== false) { 
     317            if ($entry[0] == '.' || !is_file($dirname . $entry)) { 
     318                continue; 
     319            } 
     320 
     321            @list($uniq, $info) = explode(':', $entry, 2); 
     322            @list($version, $flags) = explode(',', $info, 2); 
     323            if ($version != 2) { 
     324                $flags = ''; 
     325            } 
     326 
     327            $named_flags = $default_flags; 
     328            $length = strlen($flags); 
     329            for ($i = 0; $i < $length; ++$i) { 
     330                $flag = $flags[$i]; 
     331                $named_flags[$flag] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag; 
     332            } 
     333 
     334            $this->_files[] = array('uniq'     => $uniq, 
     335                                    'flags'    => $named_flags, 
     336                                    'filename' => $dirname . $entry); 
     337        } 
     338    } 
     339 
     340 
     341    /** 
     342     * Close resource for mail lib. If you need to control, when the resource 
     343     * is closed. Otherwise the destructor would call this. 
     344     * 
     345     * @return void 
     346     */ 
     347    public function close() 
     348    { 
     349        $this->_files = array(); 
     350    } 
     351 
     352 
     353    /** 
     354     * Waste some CPU cycles doing nothing. 
     355     * 
     356     * @return void 
     357     */ 
     358    public function noop() 
     359    { 
     360        return true; 
     361    } 
     362 
     363 
     364    /** 
     365     * stub for not supported message deletion 
     366     * 
     367     * @return null 
     368     * @throws Zend_Mail_Storage_Exception 
     369     */ 
     370    public function removeMessage($id) 
     371    { 
     372        /** 
     373         * @see Zend_Mail_Storage_Exception 
     374         */ 
     375        require_once 'Zend/Mail/Storage/Exception.php'; 
     376        throw new Zend_Mail_Storage_Exception('maildir is (currently) read-only'); 
     377    } 
     378 
     379    /** 
     380     * get unique id for one or all messages 
     381     * 
     382     * if storage does not support unique ids it's the same as the message number 
     383     * 
     384     * @param int|null $id message number 
     385     * @return array|string message number for given message or all messages as array 
     386     * @throws Zend_Mail_Storage_Exception 
     387     */ 
     388    public function getUniqueId($id = null) 
     389    { 
     390        if ($id) { 
     391            return $this->_getFileData($id, 'uniq'); 
     392        } 
     393 
     394        $ids = array(); 
     395        foreach ($this->_files as $num => $file) { 
     396            $ids[$num + 1] = $file['uniq']; 
     397        } 
     398        return $ids; 
     399    } 
     400 
     401    /** 
     402     * get a message number from a unique id 
     403     * 
     404     * I.e. if you have a webmailer that supports deleting messages you should use unique ids 
     405     * as parameter and use this method to translate it to message number right before calling removeMessage() 
     406     * 
     407     * @param string $id unique id 
     408     * @return int message number 
     409     * @throws Zend_Mail_Storage_Exception 
     410     */ 
     411    public function getNumberByUniqueId($id) 
     412    { 
     413        foreach ($this->_files as $num => $file) { 
     414            if ($file['uniq'] == $id) { 
     415                return $num + 1; 
     416            } 
     417        } 
     418 
     419        /** 
     420         * @see Zend_Mail_Storage_Exception 
     421         */ 
     422        require_once 'Zend/Mail/Storage/Exception.php'; 
     423        throw new Zend_Mail_Storage_Exception('unique id not found'); 
     424    } 
     425} 
  • libs/Zend/Mail/Storage/Pop3.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Pop3.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Storage_Abstract 
     26 */ 
     27require_once 'Zend/Mail/Storage/Abstract.php'; 
     28 
     29/** 
     30 * @see Zend_Mail_Protocol_Pop3 
     31 */ 
     32require_once 'Zend/Mail/Protocol/Pop3.php'; 
     33 
     34/** 
     35 * @see Zend_Mail_Message 
     36 */ 
     37require_once 'Zend/Mail/Message.php'; 
     38 
     39 
     40/** 
     41 * @category   Zend 
     42 * @package    Zend_Mail 
     43 * @subpackage Storage 
     44 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     45 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     46 */ 
     47class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract 
     48{ 
     49    /** 
     50     * protocol handler 
     51     * @var null|Zend_Mail_Protocol_Pop3 
     52     */ 
     53    protected $_protocol; 
     54 
     55 
     56    /** 
     57     * Count messages all messages in current box 
     58     * 
     59     * @return int number of messages 
     60     * @throws Zend_Mail_Storage_Exception 
     61     * @throws Zend_Mail_Protocol_Exception 
     62     */ 
     63    public function countMessages() 
     64    { 
     65        $this->_protocol->status($count, $null); 
     66        return (int)$count; 
     67    } 
     68 
     69    /** 
     70     * get a list of messages with number and size 
     71     * 
     72     * @param int $id number of message 
     73     * @return int|array size of given message of list with all messages as array(num => size) 
     74     * @throws Zend_Mail_Protocol_Exception 
     75     */ 
     76    public function getSize($id = 0) 
     77    { 
     78        $id = $id ? $id : null; 
     79        return $this->_protocol->getList($id); 
     80    } 
     81 
     82    /** 
     83     * Fetch a message 
     84     * 
     85     * @param int $id number of message 
     86     * @return Zend_Mail_Message 
     87     * @throws Zend_Mail_Protocol_Exception 
     88     */ 
     89    public function getMessage($id) 
     90    { 
     91        $bodyLines = 0; 
     92        $message = $this->_protocol->top($id, $bodyLines, true); 
     93 
     94        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message, 
     95                                              'noToplines' => $bodyLines < 1)); 
     96    } 
     97 
     98    /* 
     99     * Get raw header of message or part 
     100     * 
     101     * @param  int               $id       number of message 
     102     * @param  null|array|string $part     path to part or null for messsage header 
     103     * @param  int               $topLines include this many lines with header (after an empty line) 
     104     * @return string raw header 
     105     * @throws Zend_Mail_Protocol_Exception 
     106     * @throws Zend_Mail_Storage_Exception 
     107     */ 
     108    public function getRawHeader($id, $part = null, $topLines = 0) 
     109    { 
     110        if ($part !== null) { 
     111            // TODO: implement 
     112            /** 
     113             * @see Zend_Mail_Storage_Exception 
     114             */ 
     115            require_once 'Zend/Mail/Storage/Exception.php'; 
     116            throw new Zend_Mail_Storage_Exception('not implemented'); 
     117        } 
     118 
     119        return $this->_protocol->top($id, 0, true); 
     120    } 
     121 
     122    /* 
     123     * Get raw content of message or part 
     124     * 
     125     * @param  int               $id   number of message 
     126     * @param  null|array|string $part path to part or null for messsage content 
     127     * @return string raw content 
     128     * @throws Zend_Mail_Protocol_Exception 
     129     * @throws Zend_Mail_Storage_Exception 
     130     */ 
     131    public function getRawContent($id, $part = null) 
     132    { 
     133        if ($part !== null) { 
     134            // TODO: implement 
     135            /** 
     136             * @see Zend_Mail_Storage_Exception 
     137             */ 
     138            require_once 'Zend/Mail/Storage/Exception.php'; 
     139            throw new Zend_Mail_Storage_Exception('not implemented'); 
     140        } 
     141 
     142        $content = $this->_protocol->retrieve($id); 
     143        // TODO: find a way to avoid decoding the headers 
     144        Zend_Mime_Decode::splitMessage($content, $null, $body); 
     145        return $body; 
     146    } 
     147 
     148    /** 
     149     * create instance with parameters 
     150     * Supported paramters are 
     151     *   - host hostname or ip address of POP3 server 
     152     *   - user username 
     153     *   - password password for user 'username' [optional, default = ''] 
     154     *   - port port for POP3 server [optional, default = 110] 
     155     *   - ssl 'SSL' or 'TLS' for secure sockets 
     156     * 
     157     * @param  $params array  mail reader specific parameters 
     158     * @throws Zend_Mail_Storage_Exception 
     159     * @throws Zend_Mail_Protocol_Exception 
     160     */ 
     161    public function __construct($params) 
     162    { 
     163        if (is_array($params)) { 
     164            $params = (object)$params; 
     165        } 
     166 
     167        $this->_has['fetchPart'] = false; 
     168        $this->_has['top']       = null; 
     169        $this->_has['uniqueid']  = null; 
     170 
     171        if ($params instanceof Zend_Mail_Protocol_Pop3) { 
     172            $this->_protocol = $params; 
     173            return; 
     174        } 
     175 
     176        if (!isset($params->user)) { 
     177            /** 
     178             * @see Zend_Mail_Storage_Exception 
     179             */ 
     180            require_once 'Zend/Mail/Storage/Exception.php'; 
     181            throw new Zend_Mail_Storage_Exception('need at least user in params'); 
     182        } 
     183 
     184        $host     = isset($params->host)     ? $params->host     : 'localhost'; 
     185        $password = isset($params->password) ? $params->password : ''; 
     186        $port     = isset($params->port)     ? $params->port     : null; 
     187        $ssl      = isset($params->ssl)      ? $params->ssl      : false; 
     188 
     189        $this->_protocol = new Zend_Mail_Protocol_Pop3(); 
     190        $this->_protocol->connect($host, $port, $ssl); 
     191        $this->_protocol->login($params->user, $password); 
     192    } 
     193 
     194    /** 
     195     * Close resource for mail lib. If you need to control, when the resource 
     196     * is closed. Otherwise the destructor would call this. 
     197     * 
     198     * @return null 
     199     */ 
     200    public function close() 
     201    { 
     202        $this->_protocol->logout(); 
     203    } 
     204 
     205    /** 
     206     * Keep the server busy. 
     207     * 
     208     * @return null 
     209     * @throws Zend_Mail_Protocol_Exception 
     210     */ 
     211    public function noop() 
     212    { 
     213        return $this->_protocol->noop(); 
     214    } 
     215 
     216    /** 
     217     * Remove a message from server. If you're doing that from a web enviroment 
     218     * you should be careful and use a uniqueid as parameter if possible to 
     219     * identify the message. 
     220     * 
     221     * @param  int $id number of message 
     222     * @return null 
     223     * @throws Zend_Mail_Protocol_Exception 
     224     */ 
     225    public function removeMessage($id) 
     226    { 
     227        $this->_protocol->delete($id); 
     228    } 
     229 
     230    /** 
     231     * get unique id for one or all messages 
     232     * 
     233     * if storage does not support unique ids it's the same as the message number 
     234     * 
     235     * @param int|null $id message number 
     236     * @return array|string message number for given message or all messages as array 
     237     * @throws Zend_Mail_Storage_Exception 
     238     */ 
     239    public function getUniqueId($id = null) 
     240    { 
     241        if (!$this->hasUniqueid) { 
     242            if ($id) { 
     243                return $id; 
     244            } 
     245            $count = $this->countMessages(); 
     246            if ($count < 1) { 
     247                return array();  
     248            } 
     249            $range = range(1, $count); 
     250            return array_combine($range, $range); 
     251        } 
     252 
     253        return $this->_protocol->uniqueid($id); 
     254    } 
     255 
     256    /** 
     257     * get a message number from a unique id 
     258     * 
     259     * I.e. if you have a webmailer that supports deleting messages you should use unique ids 
     260     * as parameter and use this method to translate it to message number right before calling removeMessage() 
     261     * 
     262     * @param string $id unique id 
     263     * @return int message number 
     264     * @throws Zend_Mail_Storage_Exception 
     265     */ 
     266    public function getNumberByUniqueId($id) 
     267    { 
     268        if (!$this->hasUniqueid) { 
     269            return $id; 
     270        } 
     271 
     272        $ids = $this->getUniqueId(); 
     273        foreach ($ids as $k => $v) { 
     274            if ($v == $id) { 
     275                return $k; 
     276            } 
     277        } 
     278 
     279        /** 
     280         * @see Zend_Mail_Storage_Exception 
     281         */ 
     282        require_once 'Zend/Mail/Storage/Exception.php'; 
     283        throw new Zend_Mail_Storage_Exception('unique id not found'); 
     284    } 
     285 
     286    /** 
     287     * Special handling for hasTop and hasUniqueid. The headers of the first message is 
     288     * retrieved if Top wasn't needed/tried yet. 
     289     * 
     290     * @see Zend_Mail_Storage_Abstract:__get() 
     291     * @param  string $var 
     292     * @return string 
     293     * @throws Zend_Mail_Storage_Exception 
     294     */ 
     295    public function __get($var) 
     296    { 
     297        $result = parent::__get($var); 
     298        if ($result !== null) { 
     299            return $result; 
     300        } 
     301 
     302        if (strtolower($var) == 'hastop') { 
     303            if ($this->_protocol->hasTop === null) { 
     304                // need to make a real call, because not all server are honest in their capas 
     305                try { 
     306                    $this->_protocol->top(1, 0, false); 
     307                } catch(Zend_Mail_Exception $e) { 
     308                    // ignoring error 
     309                } 
     310            } 
     311            $this->_has['top'] = $this->_protocol->hasTop; 
     312            return $this->_protocol->hasTop; 
     313        } 
     314 
     315        if (strtolower($var) == 'hasuniqueid') { 
     316            $id = null; 
     317            try { 
     318                $id = $this->_protocol->uniqueid(1); 
     319            } catch(Zend_Mail_Exception $e) { 
     320                // ignoring error 
     321            } 
     322            $this->_has['uniqueid'] = $id ? true : false; 
     323            return $this->_has['uniqueid']; 
     324        } 
     325 
     326        return $result; 
     327    } 
     328} 
  • libs/Zend/Mail/Storage/Writable/Interface.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Interface.php 8928 2008-03-20 19:41:41Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @category   Zend 
     26 * @package    Zend_Mail 
     27 * @subpackage Storage 
     28 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     29 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     30 */ 
     31 
     32interface Zend_Mail_Storage_Writable_Interface 
     33{ 
     34    /** 
     35     * create a new folder 
     36     * 
     37     * This method also creates parent folders if necessary. Some mail storages may restrict, which folder 
     38     * may be used as parent or which chars may be used in the folder name 
     39     * 
     40     * @param string                          $name         global name of folder, local name if $parentFolder is set 
     41     * @param string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent 
     42     * @return null 
     43     * @throws Zend_Mail_Storage_Exception 
     44     */ 
     45    public function createFolder($name, $parentFolder = null); 
     46 
     47    /** 
     48     * remove a folder 
     49     * 
     50     * @param string|Zend_Mail_Storage_Folder $name      name or instance of folder 
     51     * @return null 
     52     * @throws Zend_Mail_Storage_Exception 
     53     */ 
     54    public function removeFolder($name); 
     55 
     56    /** 
     57     * rename and/or move folder 
     58     * 
     59     * The new name has the same restrictions as in createFolder() 
     60     * 
     61     * @param string|Zend_Mail_Storage_Folder $oldName name or instance of folder 
     62     * @param string                          $newName new global name of folder 
     63     * @return null 
     64     * @throws Zend_Mail_Storage_Exception 
     65     */ 
     66    public function renameFolder($oldName, $newName); 
     67 
     68    /** 
     69     * append a new message to mail storage 
     70     * 
     71     * @param  string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class 
     72     * @param  null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken 
     73     * @param  null|array                                 $flags   set flags for new message, else a default set is used 
     74     * @throws Zend_Mail_Storage_Exception 
     75     */ 
     76    public function appendMessage($message, $folder = null, $flags = null); 
     77 
     78    /** 
     79     * copy an existing message 
     80     * 
     81     * @param  int                             $id     number of message 
     82     * @param  string|Zend_Mail_Storage_Folder $folder name or instance of targer folder 
     83     * @return null 
     84     * @throws Zend_Mail_Storage_Exception 
     85     */ 
     86    public function copyMessage($id, $folder); 
     87 
     88    /** 
     89     * set flags for message 
     90     * 
     91     * NOTE: this method can't set the recent flag. 
     92     * 
     93     * @param  int   $id    number of message 
     94     * @param  array $flags new flags for message 
     95     * @throws Zend_Mail_Storage_Exception 
     96     */ 
     97    public function setFlags($id, $flags); 
     98} 
     99 brakuje znaku końca linii na końcu pliku  
  • libs/Zend/Mail/Storage/Writable/Maildir.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Maildir.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Storage_Folder_Maildir 
     26 */ 
     27require_once 'Zend/Mail/Storage/Folder/Maildir.php'; 
     28 
     29/** 
     30 * @see Zend_Mail_Storage_Writable_Interface 
     31 */ 
     32require_once 'Zend/Mail/Storage/Writable/Interface.php'; 
     33 
     34 
     35/** 
     36 * @category   Zend 
     37 * @package    Zend_Mail 
     38 * @subpackage Storage 
     39 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     40 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     41 */ 
     42class Zend_Mail_Storage_Writable_Maildir extends    Zend_Mail_Storage_Folder_Maildir 
     43                                         implements Zend_Mail_Storage_Writable_Interface 
     44{ 
     45        /** 
     46         * use quota and size of quota if given 
     47         * @var bool|int 
     48         */ 
     49        protected $_quota; 
     50 
     51    /** 
     52     * create a new folder 
     53     * 
     54     * This method also creates parent folders if necessary. Some mail storages may restrict, which folder 
     55     * may be used as parent or which chars may be used in the folder name 
     56     * 
     57     * @param   string                          $name         global name of folder, local name if $parentFolder is set 
     58     * @param   string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent 
     59     * @return  string only used internally (new created maildir) 
     60     * @throws  Zend_Mail_Storage_Exception 
     61     */ 
     62    public function createFolder($name, $parentFolder = null) 
     63    { 
     64        if ($parentFolder instanceof Zend_Mail_Storage_Folder) { 
     65            $folder = $parentFolder->getGlobalName() . $this->_delim . $name; 
     66        } else if ($parentFolder != null) { 
     67            $folder = rtrim($parentFolder, $this->_delim) . $this->_delim . $name; 
     68        } else { 
     69            $folder = $name; 
     70        } 
     71 
     72        $folder = trim($folder, $this->_delim); 
     73 
     74        // first we check if we try to create a folder that does exist 
     75        $exists = null; 
     76        try { 
     77            $exists = $this->getFolders($folder); 
     78        } catch (Zend_Mail_Exception $e) { 
     79            // ok 
     80        } 
     81        if ($exists) { 
     82            /** 
     83             * @see Zend_Mail_Storage_Exception 
     84             */ 
     85            require_once 'Zend/Mail/Storage/Exception.php'; 
     86            throw new Zend_Mail_Storage_Exception('folder already exists'); 
     87        } 
     88 
     89        if (strpos($folder, $this->_delim . $this->_delim) !== false) { 
     90            /** 
     91             * @see Zend_Mail_Storage_Exception 
     92             */ 
     93            require_once 'Zend/Mail/Storage/Exception.php'; 
     94            throw new Zend_Mail_Storage_Exception('invalid name - folder parts may not be empty'); 
     95        } 
     96 
     97        if (strpos($folder, 'INBOX' . $this->_delim) === 0) { 
     98            $folder = substr($folder, 6); 
     99        } 
     100 
     101        $fulldir = $this->_rootdir . '.' . $folder; 
     102 
     103        // check if we got tricked and would create a dir outside of the rootdir or not as direct child 
     104        if (strpos($folder, DIRECTORY_SEPARATOR) !== false || strpos($folder, '/') !== false 
     105            || dirname($fulldir) . DIRECTORY_SEPARATOR != $this->_rootdir) { 
     106            /** 
     107             * @see Zend_Mail_Storage_Exception 
     108             */ 
     109            require_once 'Zend/Mail/Storage/Exception.php'; 
     110            throw new Zend_Mail_Storage_Exception('invalid name - no directory seprator allowed in folder name'); 
     111        } 
     112 
     113        // has a parent folder? 
     114        $parent = null; 
     115        if (strpos($folder, $this->_delim)) { 
     116            // let's see if the parent folder exists 
     117            $parent = substr($folder, 0, strrpos($folder, $this->_delim)); 
     118            try { 
     119                $this->getFolders($parent); 
     120            } catch (Zend_Mail_Exception $e) { 
     121                // does not - create parent folder 
     122                $this->createFolder($parent); 
     123            } 
     124        } 
     125 
     126        if (!@mkdir($fulldir) || !@mkdir($fulldir . DIRECTORY_SEPARATOR . 'cur')) { 
     127            /** 
     128             * @see Zend_Mail_Storage_Exception 
     129             */ 
     130            require_once 'Zend/Mail/Storage/Exception.php'; 
     131            throw new Zend_Mail_Storage_Exception('error while creating new folder, may be created incompletly'); 
     132        } 
     133 
     134        mkdir($fulldir . DIRECTORY_SEPARATOR . 'new'); 
     135        mkdir($fulldir . DIRECTORY_SEPARATOR . 'tmp'); 
     136 
     137        $localName = $parent ? substr($folder, strlen($parent) + 1) : $folder; 
     138        $this->getFolders($parent)->$localName = new Zend_Mail_Storage_Folder($localName, $folder, true); 
     139 
     140        return $fulldir; 
     141    } 
     142 
     143    /** 
     144     * remove a folder 
     145     * 
     146     * @param   string|Zend_Mail_Storage_Folder $name      name or instance of folder 
     147     * @return  null 
     148     * @throws  Zend_Mail_Storage_Exception 
     149     */ 
     150    public function removeFolder($name) 
     151    { 
     152        // TODO: This could fail in the middle of the task, which is not optimal. 
     153        // But there is no defined standard way to mark a folder as removed and there is no atomar fs-op 
     154        // to remove a directory. Also moving the folder to a/the trash folder is not possible, as 
     155        // all parent folders must be created. What we could do is add a dash to the front of the 
     156        // directory name and it should be ignored as long as other processes obey the standard. 
     157 
     158        if ($name instanceof Zend_Mail_Storage_Folder) { 
     159            $name = $name->getGlobalName(); 
     160        } 
     161 
     162        $name = trim($name, $this->_delim); 
     163        if (strpos($name, 'INBOX' . $this->_delim) === 0) { 
     164            $name = substr($name, 6); 
     165        } 
     166 
     167        // check if folder exists and has no children 
     168        if (!$this->getFolders($name)->isLeaf()) { 
     169            /** 
     170             * @see Zend_Mail_Storage_Exception 
     171             */ 
     172            require_once 'Zend/Mail/Storage/Exception.php'; 
     173            throw new Zend_Mail_Storage_Exception('delete children first'); 
     174        } 
     175 
     176        if ($name == 'INBOX' || $name == DIRECTORY_SEPARATOR || $name == '/') { 
     177            /** 
     178             * @see Zend_Mail_Storage_Exception 
     179             */ 
     180            require_once 'Zend/Mail/Storage/Exception.php'; 
     181            throw new Zend_Mail_Storage_Exception('wont delete INBOX'); 
     182        } 
     183 
     184        if ($name == $this->getCurrentFolder()) { 
     185            /** 
     186             * @see Zend_Mail_Storage_Exception 
     187             */ 
     188            require_once 'Zend/Mail/Storage/Exception.php'; 
     189            throw new Zend_Mail_Storage_Exception('wont delete selected folder'); 
     190        } 
     191 
     192        foreach (array('tmp', 'new', 'cur', '.') as $subdir) { 
     193            $dir = $this->_rootdir . '.' . $name . DIRECTORY_SEPARATOR . $subdir; 
     194            if (!file_exists($dir)) { 
     195                continue; 
     196            } 
     197            $dh = opendir($dir); 
     198            if (!$dh) { 
     199                /** 
     200                 * @see Zend_Mail_Storage_Exception 
     201                 */ 
     202                require_once 'Zend/Mail/Storage/Exception.php'; 
     203                throw new Zend_Mail_Storage_Exception("error opening $subdir"); 
     204            } 
     205            while (($entry = readdir($dh)) !== false) { 
     206                if ($entry == '.' || $entry == '..') { 
     207                    continue; 
     208                } 
     209                if (!unlink($dir . DIRECTORY_SEPARATOR . $entry)) { 
     210                    /** 
     211                     * @see Zend_Mail_Storage_Exception 
     212                     */ 
     213                    require_once 'Zend/Mail/Storage/Exception.php'; 
     214                    throw new Zend_Mail_Storage_Exception("error cleaning $subdir"); 
     215                } 
     216            } 
     217            closedir($dh); 
     218            if ($subdir !== '.') { 
     219                if (!rmdir($dir)) { 
     220                    /** 
     221                     * @see Zend_Mail_Storage_Exception 
     222                     */ 
     223                    require_once 'Zend/Mail/Storage/Exception.php'; 
     224                    throw new Zend_Mail_Storage_Exception("error removing $subdir"); 
     225                } 
     226            } 
     227        } 
     228 
     229        if (!rmdir($this->_rootdir . '.' . $name)) { 
     230            // at least we should try to make it a valid maildir again 
     231            mkdir($this->_rootdir . '.' . $name . DIRECTORY_SEPARATOR . 'cur'); 
     232            /** 
     233             * @see Zend_Mail_Storage_Exception 
     234             */ 
     235            require_once 'Zend/Mail/Storage/Exception.php'; 
     236            throw new Zend_Mail_Storage_Exception("error removing maindir"); 
     237        } 
     238 
     239        $parent = strpos($name, $this->_delim) ? substr($name, 0, strrpos($name, $this->_delim)) : null; 
     240        $localName = $parent ? substr($name, strlen($parent) + 1) : $name; 
     241        unset($this->getFolders($parent)->$localName); 
     242    } 
     243 
     244    /** 
     245     * rename and/or move folder 
     246     * 
     247     * The new name has the same restrictions as in createFolder() 
     248     * 
     249     * @param   string|Zend_Mail_Storage_Folder $oldName name or instance of folder 
     250     * @param   string                          $newName new global name of folder 
     251     * @return  null 
     252     * @throws  Zend_Mail_Storage_Exception 
     253     */ 
     254    public function renameFolder($oldName, $newName) 
     255    { 
     256        // TODO: This is also not atomar and has similar problems as removeFolder() 
     257 
     258        if ($oldName instanceof Zend_Mail_Storage_Folder) { 
     259            $oldName = $oldName->getGlobalName(); 
     260        } 
     261 
     262        $oldName = trim($oldName, $this->_delim); 
     263        if (strpos($oldName, 'INBOX' . $this->_delim) === 0) { 
     264            $oldName = substr($oldName, 6); 
     265        } 
     266 
     267        $newName = trim($newName, $this->_delim); 
     268        if (strpos($newName, 'INBOX' . $this->_delim) === 0) { 
     269            $newName = substr($newName, 6); 
     270        } 
     271 
     272        if (strpos($newName, $oldName . $this->_delim) === 0) { 
     273            /** 
     274             * @see Zend_Mail_Storage_Exception 
     275             */ 
     276            require_once 'Zend/Mail/Storage/Exception.php'; 
     277            throw new Zend_Mail_Storage_Exception('new folder cannot be a child of old folder'); 
     278        } 
     279 
     280        // check if folder exists and has no children 
     281        $folder = $this->getFolders($oldName); 
     282 
     283        if ($oldName == 'INBOX' || $oldName == DIRECTORY_SEPARATOR || $oldName == '/') { 
     284            /** 
     285             * @see Zend_Mail_Storage_Exception 
     286             */ 
     287            require_once 'Zend/Mail/Storage/Exception.php'; 
     288            throw new Zend_Mail_Storage_Exception('wont rename INBOX'); 
     289        } 
     290 
     291        if ($oldName == $this->getCurrentFolder()) { 
     292            /** 
     293             * @see Zend_Mail_Storage_Exception 
     294             */ 
     295            require_once 'Zend/Mail/Storage/Exception.php'; 
     296            throw new Zend_Mail_Storage_Exception('wont rename selected folder'); 
     297        } 
     298 
     299        $newdir = $this->createFolder($newName); 
     300 
     301        if (!$folder->isLeaf()) { 
     302            foreach ($folder as $k => $v) { 
     303                $this->renameFolder($v->getGlobalName(), $newName . $this->_delim . $k); 
     304            } 
     305        } 
     306 
     307        $olddir = $this->_rootdir . '.' . $folder; 
     308        foreach (array('tmp', 'new', 'cur') as $subdir) { 
     309            $subdir = DIRECTORY_SEPARATOR . $subdir; 
     310            if (!file_exists($olddir . $subdir)) { 
     311                continue; 
     312            } 
     313            // using copy or moving files would be even better - but also much slower 
     314            if (!rename($olddir . $subdir, $newdir . $subdir)) { 
     315                /** 
     316                 * @see Zend_Mail_Storage_Exception 
     317                 */ 
     318                require_once 'Zend/Mail/Storage/Exception.php'; 
     319                throw new Zend_Mail_Storage_Exception('error while moving ' . $subdir); 
     320            } 
     321        } 
     322        // create a dummy if removing fails - otherwise we can't read it next time 
     323        mkdir($olddir . DIRECTORY_SEPARATOR . 'cur'); 
     324        $this->removeFolder($oldName); 
     325    } 
     326 
     327    /** 
     328     * create a uniqueid for maildir filename 
     329     * 
     330     * This is nearly the format defined in the maildir standard. The microtime() call should already 
     331     * create a uniqueid, the pid is for multicore/-cpu machine that manage to call this function at the 
     332     * exact same time, and uname() gives us the hostname for multiple machines accessing the same storage. 
     333     * 
     334     * If someone disables posix we create a random number of the same size, so this method should also 
     335     * work on Windows - if you manage to get maildir working on Windows. 
     336     * Microtime could also be disabled, altough I've never seen it. 
     337     * 
     338     * @return string new uniqueid 
     339     */ 
     340    protected function _createUniqueId() 
     341    { 
     342        $id = ''; 
     343        $id .= function_exists('microtime') ? microtime(true) : (time() . ' ' . rand(0, 100000)); 
     344        $id .= '.' . (function_exists('posix_getpid') ? posix_getpid() : rand(50, 65535)); 
     345        $id .= '.' . php_uname('n'); 
     346 
     347        return $id; 
     348    } 
     349 
     350    /** 
     351     * open a temporary maildir file 
     352     * 
     353     * makes sure tmp/ exists and create a file with a unique name 
     354     * you should close the returned filehandle! 
     355     * 
     356     * @param   string $folder name of current folder without leading . 
     357     * @return  array array('dirname' => dir of maildir folder, 'uniq' => unique id, 'filename' => name of create file 
     358     *                     'handle'  => file opened for writing) 
     359     * @throws  Zend_Mail_Storage_Exception 
     360     */ 
     361    protected function _createTmpFile($folder = 'INBOX') 
     362    { 
     363        if ($folder == 'INBOX') { 
     364                $tmpdir = $this->_rootdir . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; 
     365        } else { 
     366                $tmpdir = $this->_rootdir . '.' . $folder . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; 
     367            } 
     368        if (!file_exists($tmpdir)) { 
     369            if (!mkdir($tmpdir)) { 
     370                /** 
     371                 * @see Zend_Mail_Storage_Exception 
     372                 */ 
     373                require_once 'Zend/Mail/Storage/Exception.php'; 
     374                throw new Zend_Mail_Storage_Exception('problems creating tmp dir'); 
     375            } 
     376        } 
     377 
     378        // we should retry to create a unique id if a file with the same name exists 
     379        // to avoid a script timeout we only wait 1 second (instead of 2) and stop 
     380        // after a defined retry count 
     381        // if you change this variable take into account that it can take up to $max_tries seconds 
     382        // normally we should have a valid unique name after the first try, we're just following the "standard" here 
     383        $max_tries = 5; 
     384        for ($i = 0; $i < $max_tries; ++$i) { 
     385            $uniq = $this->_createUniqueId(); 
     386            if (!file_exists($tmpdir . $uniq)) { 
     387                // here is the race condition! - as defined in the standard 
     388                // to avoid having a long time between stat()ing the file and creating it we're opening it here 
     389                // to mark the filename as taken 
     390                $fh = fopen($tmpdir . $uniq, 'w'); 
     391                if (!$fh) { 
     392                    /** 
     393                     * @see Zend_Mail_Storage_Exception 
     394                     */ 
     395                    require_once 'Zend/Mail/Storage/Exception.php'; 
     396                    throw new Zend_Mail_Storage_Exception('could not open temp file'); 
     397                } 
     398                break; 
     399            } 
     400            sleep(1); 
     401        } 
     402 
     403        if (!$fh) { 
     404            /** 
     405             * @see Zend_Mail_Storage_Exception 
     406             */ 
     407            require_once 'Zend/Mail/Storage/Exception.php'; 
     408            throw new Zend_Mail_Storage_Exception("tried $max_tries unique ids for a temp file, but all were taken" 
     409                                                . ' - giving up'); 
     410        } 
     411 
     412        return array('dirname' => $this->_rootdir . '.' . $folder, 'uniq' => $uniq, 'filename' => $tmpdir . $uniq, 
     413                     'handle' => $fh); 
     414    } 
     415 
     416    /** 
     417     * create an info string for filenames with given flags 
     418     * 
     419     * @param   array $flags wanted flags, with the reference you'll get the set flags with correct key (= char for flag) 
     420     * @return  string info string for version 2 filenames including the leading colon 
     421     * @throws  Zend_Mail_Storage_Exception 
     422     */ 
     423    protected function _getInfoString(&$flags) 
     424    { 
     425        // accessing keys is easier, faster and it removes duplicated flags 
     426        $wanted_flags = array_flip($flags); 
     427        if (isset($wanted_flags[Zend_Mail_Storage::FLAG_RECENT])) { 
     428            /** 
     429             * @see Zend_Mail_Storage_Exception 
     430             */ 
     431            require_once 'Zend/Mail/Storage/Exception.php'; 
     432            throw new Zend_Mail_Storage_Exception('recent flag may not be set'); 
     433        } 
     434 
     435        $info = ':2,'; 
     436        $flags = array(); 
     437        foreach (Zend_Mail_Storage_Maildir::$_knownFlags as $char => $flag) { 
     438            if (!isset($wanted_flags[$flag])) { 
     439                continue; 
     440            } 
     441            $info .= $char; 
     442            $flags[$char] = $flag; 
     443            unset($wanted_flags[$flag]); 
     444        } 
     445 
     446        if (!empty($wanted_flags)) { 
     447            $wanted_flags = implode(', ', array_keys($wanted_flags)); 
     448            /** 
     449             * @see Zend_Mail_Storage_Exception 
     450             */ 
     451            require_once 'Zend/Mail/Storage/Exception.php'; 
     452            throw new Zend_Mail_Storage_Exception('unknown flag(s): ' . $wanted_flags); 
     453        } 
     454 
     455        return $info; 
     456    } 
     457 
     458    /** 
     459     * append a new message to mail storage 
     460     * 
     461     * @param   string|stream                              $message message as string or stream resource 
     462     * @param   null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken 
     463     * @param   null|array                                 $flags   set flags for new message, else a default set is used 
     464     * @param   bool                                       $recent  handle this mail as if recent flag has been set, 
     465     *                                                              should only be used in delivery 
     466     * @throws  Zend_Mail_Storage_Exception 
     467     */ 
     468     // not yet * @param string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class 
     469 
     470    public function appendMessage($message, $folder = null, $flags = null, $recent = false) 
     471    { 
     472        if ($this->_quota && $this->checkQuota()) { 
     473            /** 
     474             * @see Zend_Mail_Storage_Exception 
     475             */ 
     476            require_once 'Zend/Mail/Storage/Exception.php'; 
     477            throw new Zend_Mail_Storage_Exception('storage is over quota!');                     
     478        } 
     479 
     480        if ($folder === null) { 
     481            $folder = $this->_currentFolder; 
     482        } 
     483 
     484        if (!($folder instanceof Zend_Mail_Storage_Folder)) { 
     485            $folder = $this->getFolders($folder); 
     486        } 
     487 
     488        if ($flags === null) { 
     489            $flags = array(Zend_Mail_Storage::FLAG_SEEN); 
     490        } 
     491        $info = $this->_getInfoString($flags); 
     492        $temp_file = $this->_createTmpFile($folder->getGlobalName()); 
     493 
     494        // TODO: handle class instances for $message 
     495        if (is_resource($message) && get_resource_type($message) == 'stream') { 
     496                stream_copy_to_stream($message, $temp_file['handle']); 
     497        } else { 
     498                fputs($temp_file['handle'], $message); 
     499            } 
     500        fclose($temp_file['handle']); 
     501 
     502        // we're adding the size to the filename for maildir++ 
     503        $size = filesize($temp_file['filename']); 
     504        if ($size) { 
     505            $info = ',S=' . $size . $info; 
     506        } 
     507        $new_filename = $temp_file['dirname'] . DIRECTORY_SEPARATOR; 
     508        $new_filename .= $recent ? 'new' : 'cur'; 
     509        $new_filename .= DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info; 
     510 
     511        // we're throwing any exception after removing our temp file and saving it to this variable instead 
     512        $exception = null; 
     513 
     514        if (!link($temp_file['filename'], $new_filename)) { 
     515            /** 
     516             * @see Zend_Mail_Storage_Exception 
     517             */ 
     518            require_once 'Zend/Mail/Storage/Exception.php'; 
     519            $exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir'); 
     520        } 
     521        @unlink($temp_file['filename']); 
     522 
     523        if ($exception) { 
     524            throw $exception; 
     525        } 
     526 
     527        $this->_files[] = array('uniq'     => $temp_file['uniq'], 
     528                                'flags'    => $flags, 
     529                                'filename' => $new_filename); 
     530        if ($this->_quota) { 
     531                $this->_addQuotaEntry((int)$size, 1); 
     532            } 
     533    } 
     534 
     535    /** 
     536     * copy an existing message 
     537     * 
     538     * @param   int                             $id     number of message 
     539     * @param   string|Zend_Mail_Storage_Folder $folder name or instance of targer folder 
     540     * @return  null 
     541     * @throws  Zend_Mail_Storage_Exception 
     542     */ 
     543    public function copyMessage($id, $folder) 
     544    { 
     545        if ($this->_quota && $this->checkQuota()) { 
     546            /** 
     547             * @see Zend_Mail_Storage_Exception 
     548             */ 
     549            require_once 'Zend/Mail/Storage/Exception.php'; 
     550            throw new Zend_Mail_Storage_Exception('storage is over quota!');                     
     551        } 
     552     
     553        if (!($folder instanceof Zend_Mail_Storage_Folder)) { 
     554            $folder = $this->getFolders($folder); 
     555        } 
     556 
     557        $filedata = $this->_getFileData($id); 
     558        $old_file = $filedata['filename']; 
     559        $flags = $filedata['flags']; 
     560 
     561        // copied message can't be recent 
     562        while (($key = array_search(Zend_Mail_Storage::FLAG_RECENT, $flags)) !== false) { 
     563            unset($flags[$key]); 
     564        } 
     565        $info = $this->_getInfoString($flags); 
     566 
     567        // we're creating the copy as temp file before moving to cur/ 
     568        $temp_file = $this->_createTmpFile($folder->getGlobalName()); 
     569        // we don't write directly to the file 
     570        fclose($temp_file['handle']); 
     571 
     572        // we're adding the size to the filename for maildir++ 
     573        // TODO: maybe we should support maildirsize or we just let the MDA do the work 
     574        $size = filesize($old_file); 
     575        if ($size) { 
     576            $info = ',S=' . $size . $info; 
     577        } 
     578        $new_file = $temp_file['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $temp_file['uniq'] . $info; 
     579 
     580        // we're throwing any exception after removing our temp file and saving it to this variable instead 
     581        $exception = null; 
     582 
     583        if (!copy($old_file, $temp_file['filename'])) { 
     584            /** 
     585             * @see Zend_Mail_Storage_Exception 
     586             */ 
     587            require_once 'Zend/Mail/Storage/Exception.php'; 
     588            $exception = new Zend_Mail_Storage_Exception('cannot copy message file'); 
     589        } else if (!link($temp_file['filename'], $new_file)) { 
     590            /** 
     591             * @see Zend_Mail_Storage_Exception 
     592             */ 
     593            require_once 'Zend/Mail/Storage/Exception.php'; 
     594            $exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir'); 
     595        } 
     596        @unlink($temp_file['filename']); 
     597 
     598        if ($exception) { 
     599            throw $exception; 
     600        } 
     601 
     602        if ($folder->getGlobalName() == $this->_currentFolder 
     603            || ($this->_currentFolder == 'INBOX' && $folder->getGlobalName() == '/')) { 
     604            $this->_files[] = array('uniq'     => $temp_file['uniq'], 
     605                                    'flags'    => $flags, 
     606                                    'filename' => $new_file); 
     607        } 
     608         
     609        if ($this->_quota) { 
     610                $this->_addQuotaEntry((int)$size, 1); 
     611            } 
     612    } 
     613 
     614    /** 
     615     * set flags for message 
     616     * 
     617     * NOTE: this method can't set the recent flag. 
     618     * 
     619     * @param   int   $id    number of message 
     620     * @param   array $flags new flags for message 
     621     * @throws  Zend_Mail_Storage_Exception 
     622     */ 
     623    public function setFlags($id, $flags) 
     624    { 
     625        $info = $this->_getInfoString($flags); 
     626        $filedata = $this->_getFileData($id); 
     627 
     628        // TODO: move file from new to cur 
     629        $new_filename = dirname($filedata['filename']) . DIRECTORY_SEPARATOR . "$filedata[uniq]$info"; 
     630 
     631        if (!@rename($filedata['filename'], $new_filename)) { 
     632            /** 
     633             * @see Zend_Mail_Storage_Exception 
     634             */ 
     635            require_once 'Zend/Mail/Storage/Exception.php'; 
     636            throw new Zend_Mail_Storage_Exception('cannot rename file'); 
     637        } 
     638 
     639        $filedata['flags']    = $flags; 
     640        $filedata['filename'] = $new_filename; 
     641 
     642        $this->_files[$id - 1] = $filedata; 
     643    } 
     644 
     645 
     646    /** 
     647     * stub for not supported message deletion 
     648     * 
     649     * @return  null 
     650     * @throws  Zend_Mail_Storage_Exception 
     651     */ 
     652    public function removeMessage($id) 
     653    { 
     654        $filename = $this->_getFileData($id, 'filename'); 
     655         
     656        if ($this->_quota) { 
     657                $size = filesize($filename); 
     658            } 
     659         
     660        if (!@unlink($filename)) { 
     661            /** 
     662             * @see Zend_Mail_Storage_Exception 
     663             */ 
     664            require_once 'Zend/Mail/Storage/Exception.php'; 
     665            throw new Zend_Mail_Storage_Exception('cannot remove message'); 
     666        } 
     667        unset($this->_files[$id - 1]); 
     668        // remove the gap 
     669        $this->_files = array_values($this->_files); 
     670        if ($this->_quota) { 
     671                $this->_addQuotaEntry(0 - (int)$size, -1); 
     672            } 
     673    } 
     674     
     675        /** 
     676         * enable/disable quota and set a quota value if wanted or needed 
     677         * 
     678         * You can enable/disable quota with true/false. If you don't have 
     679         * a MDA or want to enforce a quota value you can also set this value 
     680         * here. Use array('size' => SIZE_QUOTA, 'count' => MAX_MESSAGE) do 
     681         * define your quota. Order of these fields does matter! 
     682         * 
     683         * @param bool|array $value new quota value 
     684         * @return null 
     685         */ 
     686    public function setQuota($value) { 
     687        $this->_quota = $value; 
     688    } 
     689     
     690    /** 
     691     * get currently set quota 
     692     * 
     693     * @see Zend_Mail_Storage_Writable_Maildir::setQuota() 
     694     * 
     695     * @return bool|array 
     696     */ 
     697    public function getQuota($fromStorage = false) { 
     698        if ($fromStorage) { 
     699                        $fh = @fopen($this->_rootdir . 'maildirsize', 'r'); 
     700                        if (!$fh) { 
     701                                /** 
     702                                 * @see Zend_Mail_Storage_Exception 
     703                                 */ 
     704                                require_once 'Zend/Mail/Storage/Exception.php'; 
     705                                throw new Zend_Mail_Storage_Exception('cannot open maildirsize'); 
     706                        } 
     707                        $definition = fgets($fh); 
     708                        fclose($fh); 
     709                        $definition = explode(',', trim($definition)); 
     710                        $quota = array(); 
     711                        foreach ($definition as $member) { 
     712                                $key = $member[strlen($member) - 1]; 
     713                                if ($key == 'S' || $key == 'C') { 
     714                                        $key = $key == 'C' ? 'count' : 'size'; 
     715                                } 
     716                                $quota[$key] = substr($member, 0, -1); 
     717                        } 
     718                        return $quota; 
     719        } 
     720         
     721        return $this->_quota; 
     722    } 
     723     
     724    /** 
     725     * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating maildirsize" 
     726     */ 
     727    protected function _calculateMaildirsize() { 
     728        $timestamps = array(); 
     729        $messages = 0; 
     730        $total_size = 0; 
     731 
     732                if (is_array($this->_quota)) { 
     733                        $quota = $this->_quota; 
     734                } else { 
     735                        try { 
     736                                $quota = $this->getQuota(true); 
     737                        } catch (Zend_Mail_Storage_Exception $e) { 
     738                                throw new Zend_Mail_Storage_Exception('no quota defintion found'); 
     739                        } 
     740                } 
     741         
     742        $folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST); 
     743                foreach ($folders as $folder) { 
     744                        $subdir = $folder->getGlobalName(); 
     745                        if ($subdir == 'INBOX') { 
     746                                $subdir = ''; 
     747                        } else { 
     748                                $subdir = '.' . $subdir; 
     749                        } 
     750                        if ($subdir == 'Trash') { 
     751                                continue; 
     752                        } 
     753                         
     754                        foreach (array('cur', 'new') as $subsubdir) { 
     755                                $dirname = $this->_rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR; 
     756                                if (!file_exists($dirname)) { 
     757                                        continue; 
     758                                } 
     759                                // NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime 
     760                                // and as we are accessing the directory it would make the whole calculation useless.    
     761                                $timestamps[$dirname] = filemtime($dirname); 
     762 
     763                                $dh = opendir($dirname); 
     764                                // NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will  
     765                                // therefore not be fully enforeced, but next request will fail anyway, if problem persists. 
     766                                if (!$dh) { 
     767                                        continue; 
     768                                } 
     769                                 
     770                                                                 
     771                                while (($entry = readdir()) !== false) { 
     772                                        if ($entry[0] == '.' || !is_file($dirname . $entry)) { 
     773                        continue; 
     774                        } 
     775                         
     776                        if (strpos($entry, ',S=')) { 
     777                                strtok($entry, '='); 
     778                                $filesize = strtok(':'); 
     779                                if (is_numeric($filesize)) { 
     780                                        $total_size += $filesize; 
     781                                        ++$messages; 
     782                                        continue; 
     783                                } 
     784                        } 
     785                        $size = filesize($dirname . $entry); 
     786                        if ($size === false) { 
     787                                // ignore, as we assume file got removed 
     788                                continue; 
     789                        } 
     790                        $total_size += $size; 
     791                        ++$messages; 
     792                                } 
     793                        } 
     794                } 
     795                 
     796                $tmp = $this->_createTmpFile(); 
     797                $fh = $tmp['handle']; 
     798                $definition = array(); 
     799                foreach ($quota as $type => $value) { 
     800                        if ($type == 'size' || $type == 'count') { 
     801                                $type = $type == 'count' ? 'C' : 'S'; 
     802                        } 
     803                        $definition[] = $value . $type; 
     804                } 
     805                $definition = implode(',', $definition); 
     806                fputs($fh, "$definition\n"); 
     807                fputs($fh, "$total_size $messages\n"); 
     808                fclose($fh); 
     809                rename($tmp['filename'], $this->_rootdir . 'maildirsize'); 
     810                foreach ($timestamps as $dir => $timestamp) { 
     811                        if ($timestamp < filemtime($dir)) { 
     812                                unlink($this->_rootdir . 'maildirsize'); 
     813                                break; 
     814                        } 
     815                } 
     816                 
     817                return array('size' => $total_size, 'count' => $messages, 'quota' => $quota); 
     818    } 
     819     
     820    /** 
     821     * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating the quota for a Maildir++" 
     822     */ 
     823    protected function _calculateQuota($forceRecalc = false) { 
     824        $fh = null; 
     825                $total_size = 0; 
     826                $messages   = 0; 
     827                $maildirsize = ''; 
     828        if (!$forceRecalc && file_exists($this->_rootdir . 'maildirsize') && filesize($this->_rootdir . 'maildirsize') < 5120) { 
     829                $fh = fopen($this->_rootdir . 'maildirsize', 'r'); 
     830        } 
     831                if ($fh) { 
     832                        $maildirsize = fread($fh, 5120); 
     833                        if (strlen($maildirsize) >= 5120) { 
     834                                fclose($fh); 
     835                                $fh = null; 
     836                                $maildirsize = ''; 
     837                        } 
     838                } 
     839         
     840        if (!$fh) { 
     841                $result = $this->_calculateMaildirsize(); 
     842                $total_size = $result['size']; 
     843                $messages   = $result['count']; 
     844                $quota      = $result['quota']; 
     845        } else { 
     846                $maildirsize = explode("\n", $maildirsize); 
     847                        if (is_array($this->_quota)) { 
     848                                $quota = $this->_quota; 
     849                        } else { 
     850                                $definition = explode(',', $maildirsize[0]); 
     851                                $quota = array(); 
     852                                foreach ($definition as $member) { 
     853                                        $key = $member[strlen($member) - 1]; 
     854                                        if ($key == 'S' || $key == 'C') { 
     855                                                $key = $key == 'C' ? 'count' : 'size'; 
     856                                        } 
     857                                        $quota[$key] = substr($member, 0, -1); 
     858                                } 
     859                        } 
     860                        unset($maildirsize[0]); 
     861                        foreach ($maildirsize as $line) { 
     862                                list($size, $count) = explode(' ', trim($line)); 
     863                                $total_size += $size; 
     864                                $messages   += $count; 
     865                        } 
     866        } 
     867         
     868        $over_quota = false; 
     869        $over_quota = $over_quota || (isset($quota['size'])  && $total_size > $quota['size']);  
     870        $over_quota = $over_quota || (isset($quota['count']) && $messages   > $quota['count']); 
     871        // NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only 
     872        // one line, because $maildirsize[0] gets unsetted. 
     873        // Also we're using local time to calculate the 15 minute offset. Touching a file just for known the 
     874        // local time of the file storage isn't worth the hassle. 
     875        if ($over_quota && ($maildirsize || filemtime($this->_rootdir . 'maildirsize') > time() - 900)) { 
     876                $result = $this->_calculateMaildirsize(); 
     877                $total_size = $result['size']; 
     878                $messages   = $result['count']; 
     879                $quota      = $result['quota']; 
     880                        $over_quota = false; 
     881                        $over_quota = $over_quota || (isset($quota['size'])  && $total_size > $quota['size']);  
     882                        $over_quota = $over_quota || (isset($quota['count']) && $messages   > $quota['count']); 
     883        } 
     884         
     885        if ($fh) { 
     886                // TODO is there a safe way to keep the handle open for writing? 
     887                fclose($fh); 
     888        } 
     889         
     890        return array('size' => $total_size, 'count' => $messages, 'quota' => $quota, 'over_quota' => $over_quota); 
     891    } 
     892     
     893    protected function _addQuotaEntry($size, $count = 1) { 
     894        if (!file_exists($this->_rootdir . 'maildirsize')) { 
     895                // TODO: should get file handler from _calculateQuota 
     896        } 
     897        $size = (int)$size; 
     898        $count = (int)$count; 
     899        file_put_contents($this->_rootdir . 'maildirsize', "$size $count\n", FILE_APPEND); 
     900    } 
     901     
     902    /** 
     903     * check if storage is currently over quota 
     904     * 
     905     * @param bool $detailedResponse return known data of quota and current size and message count @see _calculateQuota() 
     906     * @return bool|array over quota state or detailed response 
     907     */ 
     908    public function checkQuota($detailedResponse = false, $forceRecalc = false) { 
     909        $result = $this->_calculateQuota($forceRecalc); 
     910        return $detailedResponse ? $result : $result['over_quota']; 
     911    } 
     912} 
  • libs/Zend/Mail/Storage/Abstract.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @category   Zend 
     26 * @package    Zend_Mail 
     27 * @subpackage Storage 
     28 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     29 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     30 */ 
     31abstract class Zend_Mail_Storage_Abstract implements Countable, ArrayAccess, SeekableIterator 
     32{ 
     33    /** 
     34     * class capabilities with default values 
     35     * @var array 
     36     */ 
     37    protected $_has = array('uniqueid'  => true, 
     38                            'delete'    => false, 
     39                            'create'    => false, 
     40                            'top'       => false, 
     41                            'fetchPart' => true, 
     42                            'flags'     => false); 
     43 
     44    /** 
     45     * current iteration position 
     46     * @var int 
     47     */ 
     48    protected $_iterationPos = 0; 
     49 
     50    /** 
     51     * maximum iteration position (= message count) 
     52     * @var null|int 
     53     */ 
     54    protected $_iterationMax = null; 
     55 
     56    /** 
     57     * used message class, change it in an extened class to extend the returned message class 
     58     * @var string 
     59     */ 
     60    protected $_messageClass = 'Zend_Mail_Message'; 
     61 
     62    /** 
     63     * Getter for has-properties. The standard has properties 
     64     * are: hasFolder, hasUniqueid, hasDelete, hasCreate, hasTop 
     65     * 
     66     * The valid values for the has-properties are: 
     67     *   - true if a feature is supported 
     68     *   - false if a feature is not supported 
     69     *   - null is it's not yet known or it can't be know if a feature is supported 
     70     * 
     71     * @param  string $var  property name 
     72     * @return bool         supported or not 
     73     * @throws Zend_Mail_Storage_Exception 
     74     */ 
     75    public function __get($var) 
     76    { 
     77        if (strpos($var, 'has') === 0) { 
     78            $var = strtolower(substr($var, 3)); 
     79            return isset($this->_has[$var]) ? $this->_has[$var] : null; 
     80        } 
     81         
     82        /** 
     83         * @see Zend_Mail_Storage_Exception 
     84         */ 
     85        require_once 'Zend/Mail/Storage/Exception.php'; 
     86        throw new Zend_Mail_Storage_Exception($var . ' not found'); 
     87    } 
     88 
     89 
     90    /** 
     91     * Get a full list of features supported by the specific mail lib and the server 
     92     * 
     93     * @return array list of features as array(featurename => true|false[|null]) 
     94     */ 
     95    public function getCapabilities() 
     96    { 
     97        return $this->_has; 
     98    } 
     99 
     100 
     101    /** 
     102     * Count messages messages in current box/folder 
     103     * 
     104     * @return int number of messages 
     105     * @throws Zend_Mail_Storage_Exception 
     106     */ 
     107    abstract public function countMessages(); 
     108 
     109 
     110    /** 
     111     * Get a list of messages with number and size 
     112     * 
     113     * @param  int $id  number of message 
     114     * @return int|array size of given message of list with all messages as array(num => size) 
     115     */ 
     116    abstract public function getSize($id = 0); 
     117 
     118 
     119    /** 
     120     * Get a message with headers and body 
     121     * 
     122     * @param  $id int number of message 
     123     * @return Zend_Mail_Message 
     124     */ 
     125    abstract public function getMessage($id); 
     126 
     127 
     128    /** 
     129     * Get raw header of message or part 
     130     * 
     131     * @param  int               $id       number of message 
     132     * @param  null|array|string $part     path to part or null for messsage header 
     133     * @param  int               $topLines include this many lines with header (after an empty line) 
     134     * @return string raw header 
     135     */ 
     136    abstract public function getRawHeader($id, $part = null, $topLines = 0); 
     137 
     138    /** 
     139     * Get raw content of message or part 
     140     * 
     141     * @param  int               $id   number of message 
     142     * @param  null|array|string $part path to part or null for messsage content 
     143     * @return string raw content 
     144     */ 
     145    abstract public function getRawContent($id, $part = null); 
     146 
     147    /** 
     148     * Create instance with parameters 
     149     * 
     150     * @param  array $params mail reader specific parameters 
     151     * @throws Zend_Mail_Storage_Exception 
     152     */ 
     153    abstract public function __construct($params); 
     154 
     155 
     156    /** 
     157     * Destructor calls close() and therefore closes the resource. 
     158     */ 
     159    public function __destruct() 
     160    { 
     161        $this->close(); 
     162    } 
     163 
     164 
     165    /** 
     166     * Close resource for mail lib. If you need to control, when the resource 
     167     * is closed. Otherwise the destructor would call this. 
     168     * 
     169     * @return null 
     170     */ 
     171    abstract public function close(); 
     172 
     173 
     174    /** 
     175     * Keep the resource alive. 
     176     * 
     177     * @return null 
     178     */ 
     179    abstract public function noop(); 
     180 
     181    /** 
     182     * delete a message from current box/folder 
     183     * 
     184     * @return null 
     185     */ 
     186    abstract public function removeMessage($id); 
     187 
     188    /** 
     189     * get unique id for one or all messages 
     190     * 
     191     * if storage does not support unique ids it's the same as the message number 
     192     * 
     193     * @param int|null $id message number 
     194     * @return array|string message number for given message or all messages as array 
     195     * @throws Zend_Mail_Storage_Exception 
     196     */ 
     197    abstract public function getUniqueId($id = null); 
     198 
     199    /** 
     200     * get a message number from a unique id 
     201     * 
     202     * I.e. if you have a webmailer that supports deleting messages you should use unique ids 
     203     * as parameter and use this method to translate it to message number right before calling removeMessage() 
     204     * 
     205     * @param string $id unique id 
     206     * @return int message number 
     207     * @throws Zend_Mail_Storage_Exception 
     208     */ 
     209    abstract public function getNumberByUniqueId($id); 
     210 
     211    // interface implementations follows 
     212 
     213    /** 
     214     * Countable::count() 
     215     * 
     216     * @return   int 
     217     */ 
     218     public function count() 
     219     { 
     220        return $this->countMessages(); 
     221     } 
     222 
     223 
     224     /** 
     225      * ArrayAccess::offsetExists() 
     226      * 
     227      * @param    int     $id 
     228      * @return   boolean 
     229      */ 
     230     public function offsetExists($id) 
     231     { 
     232        try { 
     233            if ($this->getMessage($id)) { 
     234                return true; 
     235            } 
     236        } catch(Zend_Mail_Storage_Exception $e) {} 
     237 
     238        return false; 
     239     } 
     240 
     241 
     242     /** 
     243      * ArrayAccess::offsetGet() 
     244      * 
     245      * @param    int $id 
     246      * @return   Zend_Mail_Message message object 
     247      */ 
     248     public function offsetGet($id) 
     249     { 
     250        return $this->getMessage($id); 
     251     } 
     252 
     253 
     254     /** 
     255      * ArrayAccess::offsetSet() 
     256      * 
     257      * @param    id     $id 
     258      * @param    mixed  $value 
     259      * @throws   Zend_Mail_Storage_Exception 
     260      * @return   void 
     261      */ 
     262     public function offsetSet($id, $value) 
     263     { 
     264        /** 
     265         * @see Zend_Mail_Storage_Exception 
     266         */ 
     267        require_once 'Zend/Mail/Storage/Exception.php'; 
     268        throw new Zend_Mail_Storage_Exception('cannot write mail messages via array access'); 
     269     } 
     270 
     271 
     272     /** 
     273      * ArrayAccess::offsetUnset() 
     274      * 
     275      * @param    int   $id 
     276      * @return   boolean success 
     277      */ 
     278     public function offsetUnset($id) 
     279     { 
     280        return $this->removeMessage($id); 
     281     } 
     282 
     283 
     284     /** 
     285      * Iterator::rewind() 
     286      * 
     287      * Rewind always gets the new count from the storage. Thus if you use 
     288      * the interfaces and your scripts take long you should use reset() 
     289      * from time to time. 
     290      * 
     291      * @return   void 
     292      */ 
     293     public function rewind() 
     294     { 
     295        $this->_iterationMax = $this->countMessages(); 
     296        $this->_iterationPos = 1; 
     297     } 
     298 
     299 
     300     /** 
     301      * Iterator::current() 
     302      * 
     303      * @return   Zend_Mail_Message current message 
     304      */ 
     305     public function current() 
     306     { 
     307        return $this->getMessage($this->_iterationPos); 
     308     } 
     309 
     310 
     311     /** 
     312      * Iterator::key() 
     313      * 
     314      * @return   int id of current position 
     315      */ 
     316     public function key() 
     317     { 
     318        return $this->_iterationPos; 
     319     } 
     320 
     321 
     322     /** 
     323      * Iterator::next() 
     324      * 
     325      * @return   void 
     326      */ 
     327     public function next() 
     328     { 
     329        ++$this->_iterationPos; 
     330     } 
     331 
     332 
     333     /** 
     334      * Iterator::valid() 
     335      * 
     336      * @return   boolean 
     337      */ 
     338     public function valid() 
     339     { 
     340        if ($this->_iterationMax === null) { 
     341          $this->_iterationMax = $this->countMessages(); 
     342        } 
     343        return $this->_iterationPos && $this->_iterationPos <= $this->_iterationMax; 
     344     } 
     345 
     346 
     347     /** 
     348      * SeekableIterator::seek() 
     349      * 
     350      * @param  int $pos 
     351      * @return void 
     352      * @throws OutOfBoundsException 
     353      */ 
     354     public function seek($pos) 
     355     { 
     356        if ($this->_iterationMax === null) { 
     357          $this->_iterationMax = $this->countMessages(); 
     358        } 
     359 
     360        if ($pos > $this->_iterationMax) { 
     361            throw new OutOfBoundsException('this position does not exist'); 
     362        } 
     363        $this->_iterationPos = $pos; 
     364     } 
     365 
     366} 
  • libs/Zend/Mail/Storage/Mbox.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Mbox.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Loader 
     26 * May be used in constructor, but commented out for now 
     27 */ 
     28// require_once 'Zend/Loader.php'; 
     29 
     30/** 
     31 * @see Zend_Mail_Storage_Abstract 
     32 */ 
     33require_once 'Zend/Mail/Storage/Abstract.php'; 
     34 
     35/** 
     36 * @see Zend_Mail_Message 
     37 */ 
     38require_once 'Zend/Mail/Message.php'; 
     39 
     40 
     41/** 
     42 * @category   Zend 
     43 * @package    Zend_Mail 
     44 * @subpackage Storage 
     45 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     46 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     47 */ 
     48class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract 
     49{ 
     50    /** 
     51     * file handle to mbox file 
     52     * @var null|resource 
     53     */ 
     54    protected $_fh; 
     55 
     56    /** 
     57     * filename of mbox file for __wakeup 
     58     * @var string 
     59     */ 
     60    protected $_filename; 
     61 
     62    /** 
     63     * modification date of mbox file for __wakeup 
     64     * @var int 
     65     */ 
     66    protected $_filemtime; 
     67 
     68    /** 
     69     * start and end position of messages as array('start' => start, 'seperator' => headersep, 'end' => end) 
     70     * @var array 
     71     */ 
     72    protected $_positions; 
     73 
     74 
     75    /** 
     76     * Count messages all messages in current box 
     77     * 
     78     * @return int number of messages 
     79     * @throws Zend_Mail_Storage_Exception 
     80     */ 
     81    public function countMessages() 
     82    { 
     83        return count($this->_positions); 
     84    } 
     85 
     86 
     87    /** 
     88     * Get a list of messages with number and size 
     89     * 
     90     * @param  int|null $id  number of message or null for all messages 
     91     * @return int|array size of given message of list with all messages as array(num => size) 
     92     */ 
     93    public function getSize($id = 0) 
     94    { 
     95        if ($id) { 
     96            $pos = $this->_positions[$id - 1]; 
     97            return $pos['end'] - $pos['start']; 
     98        } 
     99 
     100        $result = array(); 
     101        foreach ($this->_positions as $num => $pos) { 
     102            $result[$num + 1] = $pos['end'] - $pos['start']; 
     103        } 
     104 
     105        return $result; 
     106    } 
     107 
     108 
     109    /** 
     110     * Get positions for mail message or throw exeption if id is invalid 
     111     * 
     112     * @param int $id number of message 
     113     * @return array positions as in _positions 
     114     * @throws Zend_Mail_Storage_Exception 
     115     */ 
     116    protected function _getPos($id) 
     117    { 
     118        if (!isset($this->_positions[$id - 1])) { 
     119            /** 
     120             * @see Zend_Mail_Storage_Exception 
     121             */ 
     122            require_once 'Zend/Mail/Storage/Exception.php'; 
     123            throw new Zend_Mail_Storage_Exception('id does not exist'); 
     124        } 
     125 
     126        return $this->_positions[$id - 1]; 
     127    } 
     128 
     129 
     130    /** 
     131     * Fetch a message 
     132     * 
     133     * @param  int $id number of message 
     134     * @return Zend_Mail_Message 
     135     * @throws Zend_Mail_Storage_Exception 
     136     */ 
     137    public function getMessage($id) 
     138    { 
     139        $bodyLines = 0; // TODO: need a way to change that 
     140 
     141        $message = $this->getRawHeader($id); 
     142        // file pointer is after headers now 
     143        if ($bodyLines) { 
     144            $message .= "\n"; 
     145            while ($bodyLines-- && ftell($this->_fh) < $this->_positions[$id - 1]['end']) { 
     146                $message .= fgets($this->_fh); 
     147            } 
     148        } 
     149 
     150        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message)); 
     151    } 
     152 
     153    /* 
     154     * Get raw header of message or part 
     155     * 
     156     * @param  int               $id       number of message 
     157     * @param  null|array|string $part     path to part or null for messsage header 
     158     * @param  int               $topLines include this many lines with header (after an empty line) 
     159     * @return string raw header 
     160     * @throws Zend_Mail_Protocol_Exception 
     161     * @throws Zend_Mail_Storage_Exception 
     162     */ 
     163    public function getRawHeader($id, $part = null, $topLines = 0) 
     164    { 
     165        if ($part !== null) { 
     166            // TODO: implement 
     167            /** 
     168             * @see Zend_Mail_Storage_Exception 
     169             */ 
     170            require_once 'Zend/Mail/Storage/Exception.php'; 
     171            throw new Zend_Mail_Storage_Exception('not implemented'); 
     172        } 
     173        $messagePos = $this->_getPos($id); 
     174        // TODO: toplines 
     175        return stream_get_contents($this->_fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']); 
     176    } 
     177 
     178    /* 
     179     * Get raw content of message or part 
     180     * 
     181     * @param  int               $id   number of message 
     182     * @param  null|array|string $part path to part or null for messsage content 
     183     * @return string raw content 
     184     * @throws Zend_Mail_Protocol_Exception 
     185     * @throws Zend_Mail_Storage_Exception 
     186     */ 
     187    public function getRawContent($id, $part = null) 
     188    { 
     189        if ($part !== null) { 
     190            // TODO: implement 
     191            /** 
     192             * @see Zend_Mail_Storage_Exception 
     193             */ 
     194            require_once 'Zend/Mail/Storage/Exception.php'; 
     195            throw new Zend_Mail_Storage_Exception('not implemented'); 
     196        } 
     197        $messagePos = $this->_getPos($id); 
     198        return stream_get_contents($this->_fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']); 
     199    } 
     200 
     201    /** 
     202     * Create instance with parameters 
     203     * Supported parameters are: 
     204     *   - filename filename of mbox file 
     205     * 
     206     * @param  $params array mail reader specific parameters 
     207     * @throws Zend_Mail_Storage_Exception 
     208     */ 
     209    public function __construct($params) 
     210    { 
     211        if (is_array($params)) { 
     212            $params = (object)$params; 
     213        } 
     214     
     215        if (!isset($params->filename) /* || Zend_Loader::isReadable($params['filename']) */) { 
     216            /** 
     217             * @see Zend_Mail_Storage_Exception 
     218             */ 
     219            require_once 'Zend/Mail/Storage/Exception.php'; 
     220            throw new Zend_Mail_Storage_Exception('no valid filename given in params'); 
     221        } 
     222 
     223        $this->_openMboxFile($params->filename); 
     224        $this->_has['top']      = true; 
     225        $this->_has['uniqueid'] = false; 
     226    } 
     227 
     228    /** 
     229     * check if given file is a mbox file 
     230     * 
     231     * if $file is a resource its file pointer is moved after the first line 
     232     * 
     233     * @param  resource|string $file stream resource of name of file 
     234     * @param  bool $fileIsString file is string or resource 
     235     * @return bool file is mbox file 
     236     */ 
     237    protected function _isMboxFile($file, $fileIsString = true) 
     238    { 
     239        if ($fileIsString) { 
     240            $file = @fopen($file, 'r'); 
     241            if (!$file) { 
     242                return false; 
     243            } 
     244        } else { 
     245            fseek($file, 0); 
     246        } 
     247 
     248        $result = false; 
     249 
     250        $line = fgets($file); 
     251        if (strpos($line, 'From ') === 0) { 
     252            $result = true; 
     253        } 
     254 
     255        if ($fileIsString) { 
     256            @fclose($file); 
     257        } 
     258 
     259        return $result; 
     260    } 
     261 
     262    /** 
     263     * open given file as current mbox file 
     264     * 
     265     * @param  string $filename filename of mbox file 
     266     * @return null 
     267     * @throws Zend_Mail_Storage_Exception 
     268     */ 
     269    protected function _openMboxFile($filename) 
     270    { 
     271        if ($this->_fh) { 
     272            $this->close(); 
     273        } 
     274 
     275        $this->_fh = @fopen($filename, 'r'); 
     276        if (!$this->_fh) { 
     277            /** 
     278             * @see Zend_Mail_Storage_Exception 
     279             */ 
     280            require_once 'Zend/Mail/Storage/Exception.php'; 
     281            throw new Zend_Mail_Storage_Exception('cannot open mbox file'); 
     282        } 
     283        $this->_filename = $filename; 
     284        $this->_filemtime = filemtime($this->_filename); 
     285 
     286        if (!$this->_isMboxFile($this->_fh, false)) { 
     287            @fclose($this->_fh); 
     288            /** 
     289             * @see Zend_Mail_Storage_Exception 
     290             */ 
     291            require_once 'Zend/Mail/Storage/Exception.php'; 
     292            throw new Zend_Mail_Storage_Exception('file is not a valid mbox format'); 
     293        } 
     294 
     295        $messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0); 
     296        while (($line = fgets($this->_fh)) !== false) { 
     297            if (strpos($line, 'From ') === 0) { 
     298                $messagePos['end'] = ftell($this->_fh) - strlen($line) - 2; // + newline 
     299                if (!$messagePos['separator']) { 
     300                    $messagePos['separator'] = $messagePos['end']; 
     301                } 
     302                $this->_positions[] = $messagePos; 
     303                $messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0); 
     304            } 
     305            if (!$messagePos['separator'] && !trim($line)) { 
     306                $messagePos['separator'] = ftell($this->_fh); 
     307            } 
     308        } 
     309 
     310        $messagePos['end'] = ftell($this->_fh); 
     311        if (!$messagePos['separator']) { 
     312            $messagePos['separator'] = $messagePos['end']; 
     313        } 
     314        $this->_positions[] = $messagePos; 
     315    } 
     316 
     317    /** 
     318     * Close resource for mail lib. If you need to control, when the resource 
     319     * is closed. Otherwise the destructor would call this. 
     320     * 
     321     * @return void 
     322     */ 
     323    public function close() 
     324    { 
     325        @fclose($this->_fh); 
     326        $this->_positions = array(); 
     327    } 
     328 
     329 
     330    /** 
     331     * Waste some CPU cycles doing nothing. 
     332     * 
     333     * @return void 
     334     */ 
     335    public function noop() 
     336    { 
     337        return true; 
     338    } 
     339 
     340 
     341    /** 
     342     * stub for not supported message deletion 
     343     * 
     344     * @return null 
     345     * @throws Zend_Mail_Storage_Exception 
     346     */ 
     347    public function removeMessage($id) 
     348    { 
     349        /** 
     350         * @see Zend_Mail_Storage_Exception 
     351         */ 
     352        require_once 'Zend/Mail/Storage/Exception.php'; 
     353        throw new Zend_Mail_Storage_Exception('mbox is read-only'); 
     354    } 
     355 
     356    /** 
     357     * get unique id for one or all messages 
     358     * 
     359     * Mbox does not support unique ids (yet) - it's always the same as the message number. 
     360     * That shouldn't be a problem, because we can't change mbox files. Therefor the message 
     361     * number is save enough. 
     362     * 
     363     * @param int|null $id message number 
     364     * @return array|string message number for given message or all messages as array 
     365     * @throws Zend_Mail_Storage_Exception 
     366     */ 
     367    public function getUniqueId($id = null) 
     368    { 
     369        if ($id) { 
     370            // check if id exists 
     371            $this->_getPos($id); 
     372            return $id; 
     373        } 
     374 
     375        $range = range(1, $this->countMessages()); 
     376        return array_combine($range, $range); 
     377    } 
     378 
     379    /** 
     380     * get a message number from a unique id 
     381     * 
     382     * I.e. if you have a webmailer that supports deleting messages you should use unique ids 
     383     * as parameter and use this method to translate it to message number right before calling removeMessage() 
     384     * 
     385     * @param string $id unique id 
     386     * @return int message number 
     387     * @throws Zend_Mail_Storage_Exception 
     388     */ 
     389    public function getNumberByUniqueId($id) 
     390    { 
     391        // check if id exists 
     392        $this->_getPos($id); 
     393        return $id; 
     394    } 
     395 
     396    /** 
     397     * magic method for serialize() 
     398     * 
     399     * with this method you can cache the mbox class 
     400     * 
     401     * @return array name of variables 
     402     */ 
     403    public function __sleep() 
     404    { 
     405        return array('_filename', '_positions', '_filemtime'); 
     406    } 
     407 
     408    /** 
     409     * magic method for unserialize() 
     410     * 
     411     * with this method you can cache the mbox class 
     412     * for cache validation the mtime of the mbox file is used 
     413     * 
     414     * @return null 
     415     * @throws Zend_Mail_Storage_Exception 
     416     */ 
     417    public function __wakeup() 
     418    { 
     419        if ($this->_filemtime != @filemtime($this->_filename)) { 
     420            $this->close(); 
     421            $this->_openMboxFile($this->_filename); 
     422        } else { 
     423            $this->_fh = @fopen($this->_filename, 'r'); 
     424            if (!$this->_fh) { 
     425                /** 
     426                 * @see Zend_Mail_Storage_Exception 
     427                 */ 
     428                require_once 'Zend/Mail/Storage/Exception.php'; 
     429                throw new Zend_Mail_Storage_Exception('cannot open mbox file'); 
     430            } 
     431        } 
     432    } 
     433 
     434} 
  • libs/Zend/Mail/Storage/Folder/Interface.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @category   Zend 
     26 * @package    Zend_Mail 
     27 * @subpackage Storage 
     28 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     29 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     30 */ 
     31interface Zend_Mail_Storage_Folder_Interface 
     32{ 
     33    /** 
     34     * get root folder or given folder 
     35     * 
     36     * @param string $rootFolder get folder structure for given folder, else root 
     37     * @return Zend_Mail_Storage_Folder root or wanted folder 
     38     */ 
     39    public function getFolders($rootFolder = null); 
     40 
     41    /** 
     42     * select given folder 
     43     * 
     44     * folder must be selectable! 
     45     * 
     46     * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder 
     47     * @return null 
     48     * @throws Zend_Mail_Storage_Exception 
     49     */ 
     50    public function selectFolder($globalName); 
     51 
     52 
     53    /** 
     54     * get Zend_Mail_Storage_Folder instance for current folder 
     55     * 
     56     * @return Zend_Mail_Storage_Folder instance of current folder 
     57     * @throws Zend_Mail_Storage_Exception 
     58     */ 
     59    public function getCurrentFolder(); 
     60} 
  • libs/Zend/Mail/Storage/Folder/Maildir.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Maildir.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Storage_Folder 
     26 */ 
     27require_once 'Zend/Mail/Storage/Folder.php'; 
     28 
     29/** 
     30 * @see Zend_Mail_Storage_Folder_Interface 
     31 */ 
     32require_once 'Zend/Mail/Storage/Folder/Interface.php'; 
     33 
     34/** 
     35 * @see Zend_Mail_Storage_Maildir 
     36 */ 
     37require_once 'Zend/Mail/Storage/Maildir.php'; 
     38 
     39 
     40/** 
     41 * @category   Zend 
     42 * @package    Zend_Mail 
     43 * @subpackage Storage 
     44 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     45 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     46 */ 
     47class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir implements Zend_Mail_Storage_Folder_Interface 
     48{ 
     49    /** 
     50     * Zend_Mail_Storage_Folder root folder for folder structure 
     51     * @var Zend_Mail_Storage_Folder 
     52     */ 
     53    protected $_rootFolder; 
     54 
     55    /** 
     56     * rootdir of folder structure 
     57     * @var string 
     58     */ 
     59    protected $_rootdir; 
     60 
     61    /** 
     62     * name of current folder 
     63     * @var string 
     64     */ 
     65    protected $_currentFolder; 
     66 
     67    /** 
     68     * delim char for subfolders 
     69     * @var string 
     70     */ 
     71    protected $_delim; 
     72 
     73    /** 
     74     * Create instance with parameters 
     75     * Supported parameters are: 
     76     *   - dirname rootdir of maildir structure 
     77     *   - delim   delim char for folder structur, default is '.' 
     78     *   - folder intial selected folder, default is 'INBOX' 
     79     * 
     80     * @param  $params array mail reader specific parameters 
     81     * @throws Zend_Mail_Storage_Exception 
     82     */ 
     83    public function __construct($params) 
     84    { 
     85        if (is_array($params)) { 
     86            $params = (object)$params; 
     87        } 
     88 
     89        if (!isset($params->dirname) || !is_dir($params->dirname)) { 
     90            /** 
     91             * @see Zend_Mail_Storage_Exception 
     92             */ 
     93            require_once 'Zend/Mail/Storage/Exception.php'; 
     94            throw new Zend_Mail_Storage_Exception('no valid dirname given in params'); 
     95        } 
     96 
     97        $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; 
     98 
     99        $this->_delim = isset($params->delim) ? $params->delim : '.'; 
     100 
     101        $this->_buildFolderTree(); 
     102        $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX'); 
     103        $this->_has['top'] = true; 
     104        $this->_has['flags'] = true; 
     105    } 
     106 
     107    /** 
     108     * find all subfolders and mbox files for folder structure 
     109     * 
     110     * Result is save in Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder. 
     111     * $parentFolder and $parentGlobalName are only used internally for recursion. 
     112     * 
     113     * @return null 
     114     * @throws Zend_Mail_Storage_Exception 
     115     */ 
     116    protected function _buildFolderTree() 
     117    { 
     118        $this->_rootFolder = new Zend_Mail_Storage_Folder('/', '/', false); 
     119        $this->_rootFolder->INBOX = new Zend_Mail_Storage_Folder('INBOX', 'INBOX', true); 
     120 
     121        $dh = @opendir($this->_rootdir); 
     122        if (!$dh) { 
     123            /** 
     124             * @see Zend_Mail_Storage_Exception 
     125             */ 
     126            require_once 'Zend/Mail/Storage/Exception.php'; 
     127            throw new Zend_Mail_Storage_Exception("can't read folders in maildir"); 
     128        } 
     129        $dirs = array(); 
     130        while (($entry = readdir($dh)) !== false) { 
     131            // maildir++ defines folders must start with . 
     132            if ($entry[0] != '.' || $entry == '.' || $entry == '..') { 
     133                continue; 
     134            } 
     135            if ($this->_isMaildir($this->_rootdir . $entry)) { 
     136                $dirs[] = $entry; 
     137            } 
     138        } 
     139        closedir($dh); 
     140 
     141        sort($dirs); 
     142        $stack = array(null); 
     143        $folderStack = array(null); 
     144        $parentFolder = $this->_rootFolder; 
     145        $parent = '.'; 
     146 
     147        foreach ($dirs as $dir) { 
     148            do { 
     149                if (strpos($dir, $parent) === 0) { 
     150                    $local = substr($dir, strlen($parent)); 
     151                    if (strpos($local, $this->_delim) !== false) { 
     152                        /** 
     153                         * @see Zend_Mail_Storage_Exception 
     154                         */ 
     155                        require_once 'Zend/Mail/Storage/Exception.php'; 
     156                        throw new Zend_Mail_Storage_Exception('error while reading maildir'); 
     157                    } 
     158                    array_push($stack, $parent); 
     159                    $parent = $dir . $this->_delim; 
     160                    $folder = new Zend_Mail_Storage_Folder($local, substr($dir, 1), true); 
     161                    $parentFolder->$local = $folder; 
     162                    array_push($folderStack, $parentFolder); 
     163                    $parentFolder = $folder; 
     164                    break; 
     165                } else if ($stack) { 
     166                    $parent = array_pop($stack); 
     167                    $parentFolder = array_pop($folderStack); 
     168                } 
     169            } while ($stack); 
     170            if (!$stack) { 
     171                /** 
     172                 * @see Zend_Mail_Storage_Exception 
     173                 */ 
     174                require_once 'Zend/Mail/Storage/Exception.php'; 
     175                throw new Zend_Mail_Storage_Exception('error while reading maildir'); 
     176            } 
     177        } 
     178    } 
     179 
     180    /** 
     181     * get root folder or given folder 
     182     * 
     183     * @param string $rootFolder get folder structure for given folder, else root 
     184     * @return Zend_Mail_Storage_Folder root or wanted folder 
     185     * @throws Zend_Mail_Storage_Exception 
     186     */ 
     187    public function getFolders($rootFolder = null) 
     188    { 
     189        if (!$rootFolder || $rootFolder == 'INBOX') { 
     190            return $this->_rootFolder; 
     191        } 
     192 
     193        // rootdir is same as INBOX in maildir 
     194        if (strpos($rootFolder, 'INBOX' . $this->_delim) === 0) { 
     195            $rootFolder = substr($rootFolder, 6); 
     196        } 
     197        $currentFolder = $this->_rootFolder; 
     198        $subname = trim($rootFolder, $this->_delim); 
     199        while ($currentFolder) { 
     200            @list($entry, $subname) = @explode($this->_delim, $subname, 2); 
     201            $currentFolder = $currentFolder->$entry; 
     202            if (!$subname) { 
     203                break; 
     204            } 
     205        } 
     206 
     207        if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->_delim)) { 
     208            /** 
     209             * @see Zend_Mail_Storage_Exception 
     210             */ 
     211            require_once 'Zend/Mail/Storage/Exception.php'; 
     212            throw new Zend_Mail_Storage_Exception("folder $rootFolder not found"); 
     213        } 
     214        return $currentFolder; 
     215    } 
     216 
     217    /** 
     218     * select given folder 
     219     * 
     220     * folder must be selectable! 
     221     * 
     222     * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder 
     223     * @return null 
     224     * @throws Zend_Mail_Storage_Exception 
     225     */ 
     226    public function selectFolder($globalName) 
     227    { 
     228        $this->_currentFolder = (string)$globalName; 
     229 
     230        // getting folder from folder tree for validation 
     231        $folder = $this->getFolders($this->_currentFolder); 
     232 
     233        try { 
     234            $this->_openMaildir($this->_rootdir . '.' . $folder->getGlobalName()); 
     235        } catch(Zend_Mail_Storage_Exception $e) { 
     236            // check what went wrong 
     237            if (!$folder->isSelectable()) { 
     238                /** 
     239                 * @see Zend_Mail_Storage_Exception 
     240                 */ 
     241                require_once 'Zend/Mail/Storage/Exception.php'; 
     242                throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable"); 
     243            } 
     244            // seems like file has vanished; rebuilding folder tree - but it's still an exception 
     245            $this->_buildFolderTree($this->_rootdir); 
     246            /** 
     247             * @see Zend_Mail_Storage_Exception 
     248             */ 
     249            require_once 'Zend/Mail/Storage/Exception.php'; 
     250            throw new Zend_Mail_Storage_Exception('seems like the maildir has vanished, I\'ve rebuild the ' . 
     251                                                         'folder tree, search for an other folder and try again'); 
     252        } 
     253    } 
     254 
     255    /** 
     256     * get Zend_Mail_Storage_Folder instance for current folder 
     257     * 
     258     * @return Zend_Mail_Storage_Folder instance of current folder 
     259     * @throws Zend_Mail_Storage_Exception 
     260     */ 
     261    public function getCurrentFolder() 
     262    { 
     263        return $this->_currentFolder; 
     264    } 
     265} 
  • libs/Zend/Mail/Storage/Folder/Mbox.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Mbox.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Storage_Folder 
     26 */ 
     27require_once 'Zend/Mail/Storage/Folder.php'; 
     28 
     29/** 
     30 * @see Zend_Mail_Storage_Folder_Interface 
     31 */ 
     32require_once 'Zend/Mail/Storage/Folder/Interface.php'; 
     33 
     34/** 
     35 * @see Zend_Mail_Storage_Mbox 
     36 */ 
     37require_once 'Zend/Mail/Storage/Mbox.php'; 
     38 
     39 
     40/** 
     41 * @category   Zend 
     42 * @package    Zend_Mail 
     43 * @subpackage Storage 
     44 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     45 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     46 */ 
     47class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Zend_Mail_Storage_Folder_Interface 
     48{ 
     49    /** 
     50     * Zend_Mail_Storage_Folder root folder for folder structure 
     51     * @var Zend_Mail_Storage_Folder 
     52     */ 
     53    protected $_rootFolder; 
     54 
     55    /** 
     56     * rootdir of folder structure 
     57     * @var string 
     58     */ 
     59    protected $_rootdir; 
     60 
     61    /** 
     62     * name of current folder 
     63     * @var string 
     64     */ 
     65    protected $_currentFolder; 
     66 
     67    /** 
     68     * Create instance with parameters 
     69     * 
     70     * Disallowed parameters are: 
     71     *   - filename use Zend_Mail_Storage_Mbox for a single file 
     72     * Supported parameters are: 
     73     *   - dirname rootdir of mbox structure 
     74     *   - folder intial selected folder, default is 'INBOX' 
     75     * 
     76     * @param  $params array mail reader specific parameters 
     77     * @throws Zend_Mail_Storage_Exception 
     78     */ 
     79    public function __construct($params) 
     80    { 
     81        if (is_array($params)) { 
     82            $params = (object)$params; 
     83        } 
     84 
     85        if (isset($params->filename)) { 
     86            /** 
     87             * @see Zend_Mail_Storage_Exception 
     88             */ 
     89            require_once 'Zend/Mail/Storage/Exception.php'; 
     90            throw new Zend_Mail_Storage_Exception('use Zend_Mail_Storage_Mbox for a single file'); 
     91        } 
     92 
     93        if (!isset($params->dirname) || !is_dir($params->dirname)) { 
     94            /** 
     95             * @see Zend_Mail_Storage_Exception 
     96             */ 
     97            require_once 'Zend/Mail/Storage/Exception.php'; 
     98            throw new Zend_Mail_Storage_Exception('no valid dirname given in params'); 
     99        } 
     100 
     101        $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; 
     102 
     103        $this->_buildFolderTree($this->_rootdir); 
     104        $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX'); 
     105        $this->_has['top']      = true; 
     106        $this->_has['uniqueid'] = false; 
     107    } 
     108 
     109    /** 
     110     * find all subfolders and mbox files for folder structure 
     111     * 
     112     * Result is save in Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder. 
     113     * $parentFolder and $parentGlobalName are only used internally for recursion. 
     114     * 
     115     * @param string $currentDir call with root dir, also used for recursion. 
     116     * @param Zend_Mail_Storage_Folder|null $parentFolder used for recursion 
     117     * @param string $parentGlobalName used for rescursion 
     118     * @return null 
     119     * @throws Zend_Mail_Storage_Exception 
     120     */ 
     121    protected function _buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '') 
     122    { 
     123        if (!$parentFolder) { 
     124            $this->_rootFolder = new Zend_Mail_Storage_Folder('/', '/', false); 
     125            $parentFolder = $this->_rootFolder; 
     126        } 
     127 
     128        $dh = @opendir($currentDir); 
     129        if (!$dh) { 
     130            /** 
     131             * @see Zend_Mail_Storage_Exception 
     132             */ 
     133            require_once 'Zend/Mail/Storage/Exception.php'; 
     134            throw new Zend_Mail_Storage_Exception("can't read dir $currentDir"); 
     135        } 
     136        while (($entry = readdir($dh)) !== false) { 
     137            // ignore hidden files for mbox 
     138            if ($entry[0] == '.') { 
     139                continue; 
     140            } 
     141            $absoluteEntry = $currentDir . $entry; 
     142            $globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry; 
     143            if (is_file($absoluteEntry) && $this->_isMboxFile($absoluteEntry)) { 
     144                $parentFolder->$entry = new Zend_Mail_Storage_Folder($entry, $globalName); 
     145                continue; 
     146            } 
     147            if (!is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) { 
     148                continue; 
     149            } 
     150            $folder = new Zend_Mail_Storage_Folder($entry, $globalName, false); 
     151            $parentFolder->$entry = $folder; 
     152            $this->_buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName); 
     153        } 
     154 
     155        closedir($dh); 
     156    } 
     157 
     158    /** 
     159     * get root folder or given folder 
     160     * 
     161     * @param string $rootFolder get folder structure for given folder, else root 
     162     * @return Zend_Mail_Storage_Folder root or wanted folder 
     163     * @throws Zend_Mail_Storage_Exception 
     164     */ 
     165    public function getFolders($rootFolder = null) 
     166    { 
     167        if (!$rootFolder) { 
     168            return $this->_rootFolder; 
     169        } 
     170 
     171        $currentFolder = $this->_rootFolder; 
     172        $subname = trim($rootFolder, DIRECTORY_SEPARATOR); 
     173        while ($currentFolder) { 
     174            @list($entry, $subname) = @explode(DIRECTORY_SEPARATOR, $subname, 2); 
     175            $currentFolder = $currentFolder->$entry; 
     176            if (!$subname) { 
     177                break; 
     178            } 
     179        } 
     180 
     181        if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) { 
     182            /** 
     183             * @see Zend_Mail_Storage_Exception 
     184             */ 
     185            require_once 'Zend/Mail/Storage/Exception.php'; 
     186            throw new Zend_Mail_Storage_Exception("folder $rootFolder not found"); 
     187        } 
     188        return $currentFolder; 
     189    } 
     190 
     191    /** 
     192     * select given folder 
     193     * 
     194     * folder must be selectable! 
     195     * 
     196     * @param Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder 
     197     * @return null 
     198     * @throws Zend_Mail_Storage_Exception 
     199     */ 
     200    public function selectFolder($globalName) 
     201    { 
     202        $this->_currentFolder = (string)$globalName; 
     203 
     204        // getting folder from folder tree for validation 
     205        $folder = $this->getFolders($this->_currentFolder); 
     206 
     207        try { 
     208            $this->_openMboxFile($this->_rootdir . $folder->getGlobalName()); 
     209        } catch(Zend_Mail_Storage_Exception $e) { 
     210            // check what went wrong 
     211            if (!$folder->isSelectable()) { 
     212                /** 
     213                 * @see Zend_Mail_Storage_Exception 
     214                 */ 
     215                require_once 'Zend/Mail/Storage/Exception.php'; 
     216                throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable"); 
     217            } 
     218            // seems like file has vanished; rebuilding folder tree - but it's still an exception 
     219            $this->_buildFolderTree($this->_rootdir); 
     220            /** 
     221             * @see Zend_Mail_Storage_Exception 
     222             */ 
     223            require_once 'Zend/Mail/Storage/Exception.php'; 
     224            throw new Zend_Mail_Storage_Exception('seems like the mbox file has vanished, I\'ve rebuild the ' . 
     225                                                         'folder tree, search for an other folder and try again'); 
     226        } 
     227    } 
     228 
     229    /** 
     230     * get Zend_Mail_Storage_Folder instance for current folder 
     231     * 
     232     * @return Zend_Mail_Storage_Folder instance of current folder 
     233     * @throws Zend_Mail_Storage_Exception 
     234     */ 
     235    public function getCurrentFolder() 
     236    { 
     237        return $this->_currentFolder; 
     238    } 
     239 
     240    /** 
     241     * magic method for serialize() 
     242     * 
     243     * with this method you can cache the mbox class 
     244     * 
     245     * @return array name of variables 
     246     */ 
     247    public function __sleep() 
     248    { 
     249        return array_merge(parent::__sleep(), array('_currentFolder', '_rootFolder', '_rootdir')); 
     250    } 
     251 
     252    /** 
     253     * magic method for unserialize() 
     254     * 
     255     * with this method you can cache the mbox class 
     256     * 
     257     * @return null 
     258     */ 
     259    public function __wakeup() 
     260    { 
     261        // if cache is stall selectFolder() rebuilds the tree on error 
     262        parent::__wakeup(); 
     263    } 
     264} 
  • libs/Zend/Mail/Storage/Imap.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Storage 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Imap.php 8928 2008-03-20 19:41:41Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Storage_Abstract 
     26 */ 
     27require_once 'Zend/Mail/Storage/Abstract.php'; 
     28 
     29/** 
     30 * @see Zend_Mail_Protocol_Imap 
     31 */ 
     32require_once 'Zend/Mail/Protocol/Imap.php'; 
     33 
     34/** 
     35 * @see Zend_Mail_Storage_Writable_Interface 
     36 */ 
     37require_once 'Zend/Mail/Storage/Writable/Interface.php'; 
     38 
     39/** 
     40 * @see Zend_Mail_Storage_Folder_Interface 
     41 */ 
     42require_once 'Zend/Mail/Storage/Folder/Interface.php'; 
     43 
     44/** 
     45 * @see Zend_Mail_Storage_Folder 
     46 */ 
     47require_once 'Zend/Mail/Storage/Folder.php'; 
     48 
     49/** 
     50 * @see Zend_Mail_Message 
     51 */ 
     52require_once 'Zend/Mail/Message.php'; 
     53 
     54/** 
     55 * @see Zend_Mail_Storage 
     56 */ 
     57require_once 'Zend/Mail/Storage.php'; 
     58 
     59/** 
     60 * @category   Zend 
     61 * @package    Zend_Mail 
     62 * @subpackage Storage 
     63 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     64 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     65 */ 
     66class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract 
     67                             implements Zend_Mail_Storage_Folder_Interface, Zend_Mail_Storage_Writable_Interface 
     68{ 
     69    // TODO: with an internal cache we could optimize this class, or create an extra class with 
     70    // such optimizations. Especially the various fetch calls could be combined to one cache call 
     71 
     72    /** 
     73     * protocol handler 
     74     * @var null|Zend_Mail_Protocol_Imap 
     75     */ 
     76    protected $_protocol; 
     77 
     78    /** 
     79     * name of current folder 
     80     * @var string 
     81     */ 
     82    protected $_currentFolder = ''; 
     83 
     84    /** 
     85     * imap flags to constants translation 
     86     * @var array 
     87     */ 
     88    protected static $_knownFlags = array('\Passed'   => Zend_Mail_Storage::FLAG_PASSED, 
     89                                          '\Answered' => Zend_Mail_Storage::FLAG_ANSWERED, 
     90                                          '\Seen'     => Zend_Mail_Storage::FLAG_SEEN, 
     91                                          '\Deleted'  => Zend_Mail_Storage::FLAG_DELETED, 
     92                                          '\Draft'    => Zend_Mail_Storage::FLAG_DRAFT, 
     93                                          '\Flagged'  => Zend_Mail_Storage::FLAG_FLAGGED); 
     94 
     95    /** 
     96     * Count messages all messages in current box 
     97     * 
     98     * @return int number of messages 
     99     * @throws Zend_Mail_Storage_Exception 
     100     * @throws Zend_Mail_Protocol_Exception 
     101     */ 
     102    public function countMessages() 
     103    { 
     104        if (!$this->_currentFolder) { 
     105            /** 
     106             * @see Zend_Mail_Storage_Exception 
     107             */ 
     108            require_once 'Zend/Mail/Storage/Exception.php'; 
     109            throw new Zend_Mail_Storage_Exception('No selected folder to count'); 
     110        } 
     111 
     112        // we're reselecting the current mailbox, because STATUS is slow and shouldn't be used on the current mailbox 
     113        $result = $this->_protocol->select($this->_currentFolder); 
     114        return $result['exists']; 
     115    } 
     116 
     117    /** 
     118     * get a list of messages with number and size 
     119     * 
     120     * @param int $id number of message 
     121     * @return int|array size of given message of list with all messages as array(num => size) 
     122     * @throws Zend_Mail_Protocol_Exception 
     123     */ 
     124    public function getSize($id = 0) 
     125    { 
     126        if ($id) { 
     127            return $this->_protocol->fetch('RFC822.SIZE', $id); 
     128        } 
     129        return $this->_protocol->fetch('RFC822.SIZE', 1, INF); 
     130    } 
     131 
     132    /** 
     133     * Fetch a message 
     134     * 
     135     * @param int $id number of message 
     136     * @return Zend_Mail_Message 
     137     * @throws Zend_Mail_Protocol_Exception 
     138     */ 
     139    public function getMessage($id) 
     140    { 
     141        $data = $this->_protocol->fetch(array('FLAGS', 'RFC822.HEADER'), $id); 
     142        $header = $data['RFC822.HEADER']; 
     143 
     144        $flags = array(); 
     145        foreach ($data['FLAGS'] as $flag) { 
     146            $flags[] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag; 
     147        } 
     148 
     149        return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags)); 
     150    } 
     151 
     152    /* 
     153     * Get raw header of message or part 
     154     * 
     155     * @param  int               $id       number of message 
     156     * @param  null|array|string $part     path to part or null for messsage header 
     157     * @param  int               $topLines include this many lines with header (after an empty line) 
     158     * @param  int $topLines include this many lines with header (after an empty line) 
     159     * @return string raw header 
     160     * @throws Zend_Mail_Protocol_Exception 
     161     * @throws Zend_Mail_Storage_Exception 
     162     */ 
     163    public function getRawHeader($id, $part = null, $topLines = 0) 
     164    { 
     165        if ($part !== null) { 
     166            // TODO: implement 
     167            /** 
     168             * @see Zend_Mail_Storage_Exception 
     169             */ 
     170            require_once 'Zend/Mail/Storage/Exception.php'; 
     171            throw new Zend_Mail_Storage_Exception('not implemented'); 
     172        } 
     173 
     174        // TODO: toplines 
     175        return $this->_protocol->fetch('RFC822.HEADER', $id); 
     176    } 
     177 
     178    /* 
     179     * Get raw content of message or part 
     180     * 
     181     * @param  int               $id   number of message 
     182     * @param  null|array|string $part path to part or null for messsage content 
     183     * @return string raw content 
     184     * @throws Zend_Mail_Protocol_Exception 
     185     * @throws Zend_Mail_Storage_Exception 
     186     */ 
     187    public function getRawContent($id, $part = null) 
     188    { 
     189        if ($part !== null) { 
     190            // TODO: implement 
     191            /** 
     192             * @see Zend_Mail_Storage_Exception 
     193             */ 
     194            require_once 'Zend/Mail/Storage/Exception.php'; 
     195            throw new Zend_Mail_Storage_Exception('not implemented'); 
     196        } 
     197 
     198        return $this->_protocol->fetch('RFC822.TEXT', $id); 
     199    } 
     200 
     201    /** 
     202     * create instance with parameters 
     203     * Supported paramters are 
     204     *   - user username 
     205     *   - host hostname or ip address of IMAP server [optional, default = 'localhost'] 
     206     *   - password password for user 'username' [optional, default = ''] 
     207     *   - port port for IMAP server [optional, default = 110] 
     208     *   - ssl 'SSL' or 'TLS' for secure sockets 
     209     *   - folder select this folder [optional, default = 'INBOX'] 
     210     * 
     211     * @param  array $params mail reader specific parameters 
     212     * @throws Zend_Mail_Storage_Exception 
     213     * @throws Zend_Mail_Protocol_Exception 
     214     */ 
     215    public function __construct($params) 
     216    { 
     217        if (is_array($params)) { 
     218            $params = (object)$params; 
     219        } 
     220 
     221        $this->_has['flags'] = true; 
     222 
     223        if ($params instanceof Zend_Mail_Protocol_Imap) { 
     224            $this->_protocol = $params; 
     225            try { 
     226                $this->selectFolder('INBOX'); 
     227            } catch(Zend_Mail_Storage_Exception $e) { 
     228                /** 
     229                 * @see Zend_Mail_Storage_Exception 
     230                 */ 
     231                require_once 'Zend/Mail/Storage/Exception.php'; 
     232                throw new Zend_Mail_Storage_Exception('cannot select INBOX, is this a valid transport?'); 
     233            } 
     234            return; 
     235        } 
     236 
     237        if (!isset($params->user)) { 
     238            /** 
     239             * @see Zend_Mail_Storage_Exception 
     240             */ 
     241            require_once 'Zend/Mail/Storage/Exception.php'; 
     242            throw new Zend_Mail_Storage_Exception('need at least user in params'); 
     243        } 
     244 
     245        $host     = isset($params->host)     ? $params->host     : 'localhost'; 
     246        $password = isset($params->password) ? $params->password : ''; 
     247        $port     = isset($params->port)     ? $params->port     : null; 
     248        $ssl      = isset($params->ssl)      ? $params->ssl      : false; 
     249 
     250        $this->_protocol = new Zend_Mail_Protocol_Imap(); 
     251        $this->_protocol->connect($host, $port, $ssl); 
     252        if (!$this->_protocol->login($params->user, $password)) { 
     253            /** 
     254             * @see Zend_Mail_Storage_Exception 
     255             */ 
     256            require_once 'Zend/Mail/Storage/Exception.php'; 
     257            throw new Zend_Mail_Storage_Exception('cannot login, user or password wrong'); 
     258        } 
     259        $this->selectFolder(isset($params->folder) ? $params->folder : 'INBOX'); 
     260    } 
     261 
     262    /** 
     263     * Close resource for mail lib. If you need to control, when the resource 
     264     * is closed. Otherwise the destructor would call this. 
     265     * 
     266     * @return null 
     267     */ 
     268    public function close() 
     269    { 
     270        $this->_currentFolder = ''; 
     271        $this->_protocol->logout(); 
     272    } 
     273 
     274    /** 
     275     * Keep the server busy. 
     276     * 
     277     * @return null 
     278     * @throws Zend_Mail_Storage_Exception 
     279     */ 
     280    public function noop() 
     281    { 
     282        if (!$this->_protocol->noop()) { 
     283            /** 
     284             * @see Zend_Mail_Storage_Exception 
     285             */ 
     286            require_once 'Zend/Mail/Storage/Exception.php'; 
     287            throw new Zend_Mail_Storage_Exception('could not do nothing'); 
     288        } 
     289    } 
     290 
     291    /** 
     292     * Remove a message from server. If you're doing that from a web enviroment 
     293     * you should be careful and use a uniqueid as parameter if possible to 
     294     * identify the message. 
     295     * 
     296     * @param   int $id number of message 
     297     * @return  null 
     298     * @throws  Zend_Mail_Storage_Exception 
     299     */ 
     300    public function removeMessage($id) 
     301    { 
     302        if (!$this->_protocol->store(array(Zend_Mail_Storage::FLAG_DELETED), $id, null, '+')) { 
     303            /** 
     304             * @see Zend_Mail_Storage_Exception 
     305             */ 
     306            require_once 'Zend/Mail/Storage/Exception.php'; 
     307            throw new Zend_Mail_Storage_Exception('cannot set deleted flag'); 
     308        } 
     309        // TODO: expunge here or at close? we can handle an error here better and are more fail safe 
     310        if (!$this->_protocol->expunge()) { 
     311            /** 
     312             * @see Zend_Mail_Storage_Exception 
     313             */ 
     314            require_once 'Zend/Mail/Storage/Exception.php'; 
     315            throw new Zend_Mail_Storage_Exception('message marked as deleted, but could not expunge'); 
     316        } 
     317    } 
     318 
     319    /** 
     320     * get unique id for one or all messages 
     321     * 
     322     * if storage does not support unique ids it's the same as the message number 
     323     * 
     324     * @param int|null $id message number 
     325     * @return array|string message number for given message or all messages as array 
     326     * @throws Zend_Mail_Storage_Exception 
     327     */ 
     328    public function getUniqueId($id = null) 
     329    { 
     330        if ($id) { 
     331            return $this->_protocol->fetch('UID', $id); 
     332        } 
     333 
     334        return $this->_protocol->fetch('UID', 1, INF); 
     335    } 
     336 
     337    /** 
     338     * get a message number from a unique id 
     339     * 
     340     * I.e. if you have a webmailer that supports deleting messages you should use unique ids 
     341     * as parameter and use this method to translate it to message number right before calling removeMessage() 
     342     * 
     343     * @param string $id unique id 
     344     * @return int message number 
     345     * @throws Zend_Mail_Storage_Exception 
     346     */ 
     347    public function getNumberByUniqueId($id) 
     348    { 
     349        // TODO: use search to find number directly 
     350        $ids = $this->getUniqueId(); 
     351        foreach ($ids as $k => $v) { 
     352            if ($v == $id) { 
     353                return $k; 
     354            } 
     355        } 
     356 
     357        /** 
     358         * @see Zend_Mail_Storage_Exception 
     359         */ 
     360        require_once 'Zend/Mail/Storage/Exception.php'; 
     361        throw new Zend_Mail_Storage_Exception('unique id not found'); 
     362    } 
     363 
     364 
     365    /** 
     366     * get root folder or given folder 
     367     * 
     368     * @param  string $rootFolder get folder structure for given folder, else root 
     369     * @return Zend_Mail_Storage_Folder root or wanted folder 
     370     * @throws Zend_Mail_Storage_Exception 
     371     * @throws Zend_Mail_Protocol_Exception 
     372     */ 
     373    public function getFolders($rootFolder = null) 
     374    { 
     375        $folders = $this->_protocol->listMailbox((string)$rootFolder); 
     376        if (!$folders) { 
     377            /** 
     378             * @see Zend_Mail_Storage_Exception 
     379             */ 
     380            require_once 'Zend/Mail/Storage/Exception.php'; 
     381            throw new Zend_Mail_Storage_Exception('folder not found'); 
     382        } 
     383 
     384        ksort($folders, SORT_STRING); 
     385        $root = new Zend_Mail_Storage_Folder('/', '/', false); 
     386        $stack = array(null); 
     387        $folderStack = array(null); 
     388        $parentFolder = $root; 
     389        $parent = ''; 
     390 
     391        foreach ($folders as $globalName => $data) { 
     392            do { 
     393                if (!$parent || strpos($globalName, $parent) === 0) { 
     394                    $pos = strrpos($globalName, $data['delim']); 
     395                    if ($pos === false) { 
     396                        $localName = $globalName; 
     397                    } else { 
     398                        $localName = substr($globalName, $pos + 1); 
     399                    } 
     400                    $selectable = !$data['flags'] || !in_array('\\Noselect', $data['flags']); 
     401 
     402                    array_push($stack, $parent); 
     403                    $parent = $globalName . $data['delim']; 
     404                    $folder = new Zend_Mail_Storage_Folder($localName, $globalName, $selectable); 
     405                    $parentFolder->$localName = $folder; 
     406                    array_push($folderStack, $parentFolder); 
     407                    $parentFolder = $folder; 
     408                    break; 
     409                } else if ($stack) { 
     410                    $parent = array_pop($stack); 
     411                    $parentFolder = array_pop($folderStack); 
     412                } 
     413            } while ($stack); 
     414            if (!$stack) { 
     415                /** 
     416                 * @see Zend_Mail_Storage_Exception 
     417                 */ 
     418                require_once 'Zend/Mail/Storage/Exception.php'; 
     419                throw new Zend_Mail_Storage_Exception('error while constructing folder tree'); 
     420            } 
     421        } 
     422 
     423        return $root; 
     424    } 
     425 
     426    /** 
     427     * select given folder 
     428     * 
     429     * folder must be selectable! 
     430     * 
     431     * @param  Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder 
     432     * @return null 
     433     * @throws Zend_Mail_Storage_Exception 
     434     * @throws Zend_Mail_Protocol_Exception 
     435     */ 
     436    public function selectFolder($globalName) 
     437    { 
     438        $this->_currentFolder = $globalName; 
     439        if (!$this->_protocol->select($this->_currentFolder)) { 
     440            $this->_currentFolder = ''; 
     441            /** 
     442             * @see Zend_Mail_Storage_Exception 
     443             */ 
     444            require_once 'Zend/Mail/Storage/Exception.php'; 
     445            throw new Zend_Mail_Storage_Exception('cannot change folder, maybe it does not exist'); 
     446        } 
     447    } 
     448 
     449 
     450    /** 
     451     * get Zend_Mail_Storage_Folder instance for current folder 
     452     * 
     453     * @return Zend_Mail_Storage_Folder instance of current folder 
     454     * @throws Zend_Mail_Storage_Exception 
     455     */ 
     456    public function getCurrentFolder() 
     457    { 
     458        return $this->_currentFolder; 
     459    } 
     460 
     461    /** 
     462     * create a new folder 
     463     * 
     464     * This method also creates parent folders if necessary. Some mail storages may restrict, which folder 
     465     * may be used as parent or which chars may be used in the folder name 
     466     * 
     467     * @param  string                          $name         global name of folder, local name if $parentFolder is set 
     468     * @param  string|Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent 
     469     * @return null 
     470     * @throws Zend_Mail_Storage_Exception 
     471     */ 
     472    public function createFolder($name, $parentFolder = null) 
     473    { 
     474        // TODO: we assume / as the hierarchy delim - need to get that from the folder class! 
     475        if ($parentFolder instanceof Zend_Mail_Storage_Folder) { 
     476            $folder = $parentFolder->getGlobalName() . '/' . $name; 
     477        } else if ($parentFolder != null) { 
     478            $folder = $parentFolder . '/' . $name; 
     479        } else { 
     480            $folder = $name; 
     481        } 
     482 
     483        if (!$this->_protocol->create($folder)) { 
     484            /** 
     485             * @see Zend_Mail_Storage_Exception 
     486             */ 
     487            require_once 'Zend/Mail/Storage/Exception.php'; 
     488            throw new Zend_Mail_Storage_Exception('cannot create folder'); 
     489        } 
     490    } 
     491 
     492    /** 
     493     * remove a folder 
     494     * 
     495     * @param  string|Zend_Mail_Storage_Folder $name      name or instance of folder 
     496     * @return null 
     497     * @throws Zend_Mail_Storage_Exception 
     498     */ 
     499    public function removeFolder($name) 
     500    { 
     501        if ($name instanceof Zend_Mail_Storage_Folder) { 
     502            $name = $name->getGlobalName(); 
     503        } 
     504 
     505        if (!$this->_protocol->delete($name)) { 
     506            /** 
     507             * @see Zend_Mail_Storage_Exception 
     508             */ 
     509            require_once 'Zend/Mail/Storage/Exception.php'; 
     510            throw new Zend_Mail_Storage_Exception('cannot delete folder'); 
     511        } 
     512    } 
     513 
     514    /** 
     515     * rename and/or move folder 
     516     * 
     517     * The new name has the same restrictions as in createFolder() 
     518     * 
     519     * @param  string|Zend_Mail_Storage_Folder $oldName name or instance of folder 
     520     * @param  string                          $newName new global name of folder 
     521     * @return null 
     522     * @throws Zend_Mail_Storage_Exception 
     523     */ 
     524    public function renameFolder($oldName, $newName) 
     525    { 
     526        if ($oldName instanceof Zend_Mail_Storage_Folder) { 
     527            $oldName = $oldName->getGlobalName(); 
     528        } 
     529 
     530        if (!$this->_protocol->rename($oldName, $newName)) { 
     531            /** 
     532             * @see Zend_Mail_Storage_Exception 
     533             */ 
     534            require_once 'Zend/Mail/Storage/Exception.php'; 
     535            throw new Zend_Mail_Storage_Exception('cannot rename folder'); 
     536        } 
     537    } 
     538 
     539    /** 
     540     * append a new message to mail storage 
     541     * 
     542     * @param  string                                     $message message as string or instance of message class 
     543     * @param  null|string|Zend_Mail_Storage_Folder       $folder  folder for new message, else current folder is taken 
     544     * @param  null|array                                 $flags   set flags for new message, else a default set is used 
     545     * @throws Zend_Mail_Storage_Exception 
     546     */ 
     547     // not yet * @param string|Zend_Mail_Message|Zend_Mime_Message $message message as string or instance of message class 
     548    public function appendMessage($message, $folder = null, $flags = null) 
     549    { 
     550        if ($folder === null) { 
     551            $folder = $this->_currentFolder; 
     552        } 
     553 
     554        if ($flags === null) { 
     555            $flags = array(Zend_Mail_Storage::FLAG_SEEN); 
     556        } 
     557 
     558        // TODO: handle class instances for $message 
     559        if (!$this->_protocol->append($folder, $message, $flags)) { 
     560            /** 
     561             * @see Zend_Mail_Storage_Exception 
     562             */ 
     563            require_once 'Zend/Mail/Storage/Exception.php'; 
     564            throw new Zend_Mail_Storage_Exception('cannot create message, please check if the folder exists and your flags'); 
     565        } 
     566    } 
     567 
     568    /** 
     569     * copy an existing message 
     570     * 
     571     * @param  int                             $id     number of message 
     572     * @param  string|Zend_Mail_Storage_Folder $folder name or instance of targer folder 
     573     * @return null 
     574     * @throws Zend_Mail_Storage_Exception 
     575     */ 
     576    public function copyMessage($id, $folder) 
     577    { 
     578        if (!$this->_protocol->copy($folder, $id)) { 
     579            /** 
     580             * @see Zend_Mail_Storage_Exception 
     581             */ 
     582            require_once 'Zend/Mail/Storage/Exception.php'; 
     583            throw new Zend_Mail_Storage_Exception('cannot copy message, does the folder exist?'); 
     584        } 
     585    } 
     586 
     587 
     588    /** 
     589     * set flags for message 
     590     * 
     591     * NOTE: this method can't set the recent flag. 
     592     * 
     593     * @param  int   $id    number of message 
     594     * @param  array $flags new flags for message 
     595     * @throws Zend_Mail_Storage_Exception 
     596     */ 
     597    public function setFlags($id, $flags) 
     598    { 
     599        if (!$this->_protocol->store($flags, $id)) { 
     600            /** 
     601             * @see Zend_Mail_Storage_Exception 
     602             */ 
     603            require_once 'Zend/Mail/Storage/Exception.php'; 
     604            throw new Zend_Mail_Storage_Exception('cannot set flags, have you tried to set the recent flag or special chars?'); 
     605        } 
     606    } 
     607} 
     608 
  • libs/Zend/Mail/Exception.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $ 
     20 */ 
     21 
     22 
     23/** 
     24 * @see Zend_Exception 
     25 */ 
     26require_once 'Zend/Exception.php'; 
     27 
     28 
     29/** 
     30 * @category   Zend 
     31 * @package    Zend_Mail 
     32 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     33 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     34 */ 
     35class Zend_Mail_Exception extends Zend_Exception 
     36{} 
     37 
  • libs/Zend/Mail/Storage.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 * @version    $Id: Storage.php 8064 2008-02-16 10:58:39Z thomas $ 
     20 */ 
     21 
     22/** 
     23 * @category   Zend 
     24 * @package    Zend_Mail 
     25 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     26 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     27 */ 
     28class Zend_Mail_Storage 
     29{ 
     30    // maildir and IMAP flags, using IMAP names, where possible to be able to distinguish between IMAP 
     31    // system flags and other flags 
     32    const FLAG_PASSED   = 'Passed'; 
     33    const FLAG_SEEN     = '\Seen'; 
     34    const FLAG_ANSWERED = '\Answered'; 
     35    const FLAG_FLAGGED  = '\Flagged'; 
     36    const FLAG_DELETED  = '\Deleted'; 
     37    const FLAG_DRAFT    = '\Draft'; 
     38    const FLAG_RECENT   = '\Recent'; 
     39} 
  • libs/Zend/Mail/Message.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 * @version    $Id: Message.php 8064 2008-02-16 10:58:39Z thomas $ 
     20 */ 
     21 
     22 
     23/** 
     24 * Zend_Mail_Part 
     25 */ 
     26require_once 'Zend/Mail/Part.php'; 
     27 
     28 
     29/** 
     30 * @category   Zend 
     31 * @package    Zend_Mail 
     32 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     33 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     34 */ 
     35class Zend_Mail_Message extends Zend_Mail_Part 
     36{ 
     37    /** 
     38     * flags for this message 
     39     * @var array 
     40     */ 
     41    protected $_flags = array(); 
     42 
     43    /** 
     44     * Public constructor 
     45     * 
     46     * In addition to the parameters of Zend_Mail_Part::__construct() this constructor supports: 
     47     * - file  filename or file handle of a file with raw message content 
     48     * - flags array with flags for message, keys are ignored, use constants defined in Zend_Mail_Storage 
     49     * 
     50     * @param  string $rawMessage  full message with or without headers 
     51     * @throws Zend_Mail_Exception 
     52     */ 
     53    public function __construct(array $params) 
     54    { 
     55        if (isset($params['file'])) { 
     56            if (!is_resource($params['file'])) { 
     57                $params['raw'] = @file_get_contents($params['file']); 
     58                if ($params['raw'] === false) { 
     59                    /** 
     60                     * @see Zend_Mail_Exception 
     61                     */ 
     62                    require_once 'Zend/Mail/Exception.php'; 
     63                    throw new Zend_Mail_Exception('could not open file'); 
     64                } 
     65            } else { 
     66                $params['raw'] = stream_get_contents($params['file']); 
     67            } 
     68        } 
     69 
     70        if (!empty($params['flags'])) { 
     71            // set key and value to the same value for easy lookup 
     72            $this->_flags = array_combine($params['flags'], $params['flags']); 
     73        } 
     74 
     75        parent::__construct($params); 
     76    } 
     77 
     78    /** 
     79     * return toplines as found after headers 
     80     * 
     81     * @return string toplines 
     82     */ 
     83    public function getTopLines() 
     84    { 
     85        return $this->_topLines; 
     86    } 
     87 
     88    /** 
     89     * check if flag is set 
     90     * 
     91     * @param mixed $flag a flag name, use constants defined in Zend_Mail_Storage 
     92     * @return bool true if set, otherwise false 
     93     */ 
     94    public function hasFlag($flag) 
     95    { 
     96        return isset($this->_flags[$flag]); 
     97    } 
     98 
     99    /** 
     100     * get all set flags 
     101     * 
     102     * @return array array with flags, key and value are the same for easy lookup 
     103     */ 
     104    public function getFlags() 
     105    { 
     106        return $this->_flags; 
     107    } 
     108} 
  • libs/Zend/Mail/Transport/Sendmail.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Transport 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Sendmail.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Transport_Abstract 
     26 */ 
     27require_once 'Zend/Mail/Transport/Abstract.php'; 
     28 
     29 
     30/** 
     31 * Class for sending eMails via the PHP internal mail() function 
     32 * 
     33 * @category   Zend 
     34 * @package    Zend_Mail 
     35 * @subpackage Transport 
     36 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     37 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     38 */ 
     39class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract 
     40{ 
     41    /** 
     42     * Subject 
     43     * @var string 
     44     * @access public 
     45     */ 
     46    public $subject = null; 
     47 
     48 
     49    /** 
     50     * Config options for sendmail parameters 
     51     * 
     52     * @var string 
     53     */ 
     54    public $parameters; 
     55 
     56 
     57    /** 
     58     * EOL character string 
     59     * @var string 
     60     * @access public 
     61     */ 
     62    public $EOL = PHP_EOL; 
     63 
     64 
     65    /** 
     66     * Constructor. 
     67     * 
     68     * @param  string $parameters OPTIONAL (Default: null) 
     69     * @return void 
     70     */ 
     71    public function __construct($parameters = null) 
     72    { 
     73        $this->parameters = $parameters; 
     74    } 
     75 
     76 
     77    /** 
     78     * Send mail using PHP native mail() 
     79     * 
     80     * @access public 
     81     * @return void 
     82     * @throws Zend_Mail_Transport_Exception on mail() failure 
     83     */ 
     84    public function _sendMail() 
     85    { 
     86        if ($this->parameters === null) { 
     87            $result = mail( 
     88                $this->recipients, 
     89                $this->_mail->getSubject(), 
     90                $this->body, 
     91                $this->header); 
     92        } else { 
     93            $result = mail( 
     94                $this->recipients, 
     95                $this->_mail->getSubject(), 
     96                $this->body, 
     97                $this->header, 
     98                $this->parameters); 
     99        } 
     100        if (!$result) { 
     101            /** 
     102             * @see Zend_Mail_Transport_Exception 
     103             */ 
     104            require_once 'Zend/Mail/Transport/Exception.php'; 
     105            throw new Zend_Mail_Transport_Exception('Unable to send mail'); 
     106        } 
     107    } 
     108 
     109 
     110    /** 
     111     * Format and fix headers 
     112     * 
     113     * mail() uses its $to and $subject arguments to set the To: and Subject: 
     114     * headers, respectively. This method strips those out as a sanity check to 
     115     * prevent duplicate header entries. 
     116     * 
     117     * @access  protected 
     118     * @param   array $headers 
     119     * @return  void 
     120     * @throws  Zend_Mail_Transport_Exception 
     121     */ 
     122    protected function _prepareHeaders($headers) 
     123    { 
     124        if (!$this->_mail) { 
     125            /** 
     126             * @see Zend_Mail_Transport_Exception 
     127             */ 
     128            require_once 'Zend/Mail/Transport/Exception.php'; 
     129            throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object'); 
     130        } 
     131 
     132        // mail() uses its $to parameter to set the To: header, and the $subject 
     133        // parameter to set the Subject: header. We need to strip them out. 
     134        if (0 === strpos(PHP_OS, 'WIN')) { 
     135            // If the current recipients list is empty, throw an error 
     136            if (empty($this->recipients)) { 
     137                /** 
     138                 * @see Zend_Mail_Transport_Exception 
     139                 */ 
     140                require_once 'Zend/Mail/Transport/Exception.php'; 
     141                throw new Zend_Mail_Transport_Exception('Missing To addresses'); 
     142            } 
     143        } else { 
     144            // All others, simply grab the recipients and unset the To: header 
     145            if (!isset($headers['To'])) { 
     146                /** 
     147                 * @see Zend_Mail_Transport_Exception 
     148                 */ 
     149                require_once 'Zend/Mail/Transport/Exception.php'; 
     150                throw new Zend_Mail_Transport_Exception('Missing To header'); 
     151            } 
     152 
     153            unset($headers['To']['append']); 
     154            $this->recipients = implode(',', $headers['To']); 
     155        } 
     156 
     157        // Remove recipient header 
     158        unset($headers['To']); 
     159 
     160        // Remove subject header, if present 
     161        if (isset($headers['Subject'])) { 
     162            unset($headers['Subject']); 
     163        } 
     164 
     165        // Prepare headers 
     166        parent::_prepareHeaders($headers); 
     167    } 
     168 
     169} 
     170 
  • libs/Zend/Mail/Transport/Exception.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Transport 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mail_Exception 
     26 */ 
     27require_once 'Zend/Mail/Exception.php'; 
     28 
     29 
     30/** 
     31 * @category   Zend 
     32 * @package    Zend_Mail 
     33 * @subpackage Transport 
     34 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     35 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     36 */ 
     37class Zend_Mail_Transport_Exception extends Zend_Mail_Exception 
     38{} 
     39 
  • libs/Zend/Mail/Transport/Abstract.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Transport 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Abstract.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Mime 
     26 */ 
     27require_once 'Zend/Mime.php'; 
     28 
     29 
     30/** 
     31 * Abstract for sending eMails through different 
     32 * ways of transport 
     33 * 
     34 * @category   Zend 
     35 * @package    Zend_Mail 
     36 * @subpackage Transport 
     37 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     38 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     39 */ 
     40abstract class Zend_Mail_Transport_Abstract  
     41{ 
     42    /** 
     43     * Mail body 
     44     * @var string 
     45     * @access public 
     46     */ 
     47    public $body = ''; 
     48 
     49    /** 
     50     * MIME boundary 
     51     * @var string 
     52     * @access public 
     53     */ 
     54    public $boundary = ''; 
     55 
     56    /** 
     57     * Mail header string 
     58     * @var string 
     59     * @access public 
     60     */ 
     61    public $header = ''; 
     62 
     63    /** 
     64     * Array of message headers 
     65     * @var array 
     66     * @access protected 
     67     */ 
     68    protected $_headers = array(); 
     69 
     70    /** 
     71     * Message is a multipart message 
     72     * @var boolean 
     73     * @access protected 
     74     */ 
     75    protected $_isMultipart = false; 
     76 
     77    /** 
     78     * Zend_Mail object 
     79     * @var false|Zend_Mail 
     80     * @access protected 
     81     */ 
     82    protected $_mail = false; 
     83 
     84    /** 
     85     * Array of message parts 
     86     * @var array 
     87     * @access protected 
     88     */ 
     89    protected $_parts = array(); 
     90 
     91    /** 
     92     * Recipients string 
     93     * @var string 
     94     * @access public 
     95     */ 
     96    public $recipients = ''; 
     97 
     98    /** 
     99     * EOL character string used by transport 
     100     * @var string 
     101     * @access public 
     102     */ 
     103    public $EOL = "\r\n"; 
     104 
     105    /** 
     106     * Send an email independent from the used transport 
     107     * 
     108     * The requisite information for the email will be found in the following 
     109     * properties: 
     110     * 
     111     * - {@link $recipients} - list of recipients (string) 
     112     * - {@link $header} - message header 
     113     * - {@link $body} - message body 
     114     */ 
     115    abstract protected function _sendMail(); 
     116 
     117    /** 
     118     * Return all mail headers as an array 
     119     * 
     120     * If a boundary is given, a multipart header is generated with a 
     121     * Content-Type of either multipart/alternative or multipart/mixed depending 
     122     * on the mail parts present in the {@link $_mail Zend_Mail object} present. 
     123     * 
     124     * @param string $boundary 
     125     * @return array 
     126     */ 
     127    protected function _getHeaders($boundary) 
     128    { 
     129        if (null !== $boundary) { 
     130            // Build multipart mail 
     131            $type = $this->_mail->getType(); 
     132            if (!$type) { 
     133                if ($this->_mail->hasAttachments) { 
     134                    $type = Zend_Mime::MULTIPART_MIXED; 
     135                } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) { 
     136                    $type = Zend_Mime::MULTIPART_ALTERNATIVE; 
     137                } else { 
     138                    $type = Zend_Mime::MULTIPART_MIXED; 
     139                } 
     140            } 
     141 
     142            $this->_headers['Content-Type'] = array( 
     143                $type . '; charset="' . $this->_mail->getCharset() . '";' 
     144                . $this->EOL 
     145                . " " . 'boundary="' . $boundary . '"' 
     146            ); 
     147            $this->_headers['MIME-Version'] = array('1.0'); 
     148 
     149            $this->boundary = $boundary; 
     150        } 
     151 
     152        return $this->_headers; 
     153    } 
     154 
     155    /** 
     156     * Prepend header name to header value 
     157     * 
     158     * @param string $item 
     159     * @param string $key 
     160     * @param string $prefix 
     161     * @static 
     162     * @access protected 
     163     * @return void 
     164     */ 
     165    protected static function _formatHeader(&$item, $key, $prefix) 
     166    { 
     167        $item = $prefix . ': ' . $item; 
     168    } 
     169 
     170    /** 
     171     * Prepare header string for use in transport 
     172     * 
     173     * Prepares and generates {@link $header} based on the headers provided. 
     174     * 
     175     * @param mixed $headers 
     176     * @access protected 
     177     * @return void 
     178     * @throws Zend_Mail_Transport_Exception if any header lines exceed 998 
     179     * characters 
     180     */ 
     181    protected function _prepareHeaders($headers) 
     182    { 
     183        if (!$this->_mail) { 
     184            /** 
     185             * @see Zend_Mail_Transport_Exception 
     186             */ 
     187            require_once 'Zend/Mail/Transport/Exception.php'; 
     188            throw new Zend_Mail_Transport_Exception('Missing Zend_Mail object in _mail property'); 
     189        } 
     190 
     191        $this->header = ''; 
     192 
     193        foreach ($headers as $header => $content) { 
     194            if (isset($content['append'])) { 
     195                unset($content['append']); 
     196                $value = implode(',' . $this->EOL . ' ', $content); 
     197                $this->header .= $header . ': ' . $value . $this->EOL; 
     198            } else { 
     199                array_walk($content, array(get_class($this), '_formatHeader'), $header); 
     200                $this->header .= implode($this->EOL, $content) . $this->EOL; 
     201            } 
     202        } 
     203 
     204        // Sanity check on headers -- should not be > 998 characters 
     205        $sane = true; 
     206        foreach (explode($this->EOL, $this->header) as $line) { 
     207            if (strlen(trim($line)) > 998) { 
     208                $sane = false; 
     209                break; 
     210            } 
     211        } 
     212        if (!$sane) { 
     213            /** 
     214             * @see Zend_Mail_Transport_Exception 
     215             */ 
     216            require_once 'Zend/Mail/Transport/Exception.php'; 
     217            throw new Zend_Mail_Exception('At least one mail header line is too long'); 
     218        } 
     219    } 
     220 
     221    /** 
     222     * Generate MIME compliant message from the current configuration 
     223     * 
     224     * If both a text and HTML body are present, generates a 
     225     * multipart/alternative Zend_Mime_Part containing the headers and contents 
     226     * of each. Otherwise, uses whichever of the text or HTML parts present. 
     227     * 
     228     * The content part is then prepended to the list of Zend_Mime_Parts for 
     229     * this message. 
     230     * 
     231     * @return void 
     232     */ 
     233    protected function _buildBody() 
     234    { 
     235        if (($text = $this->_mail->getBodyText()) 
     236            && ($html = $this->_mail->getBodyHtml())) 
     237        { 
     238            // Generate unique boundary for multipart/alternative 
     239            $mime = new Zend_Mime(null); 
     240            $boundaryLine = $mime->boundaryLine($this->EOL); 
     241            $boundaryEnd  = $mime->mimeEnd($this->EOL); 
     242 
     243            $text->disposition = false; 
     244            $html->disposition = false; 
     245 
     246            $body = $boundaryLine 
     247                  . $text->getHeaders($this->EOL) 
     248                  . $this->EOL 
     249                  . $text->getContent($this->EOL) 
     250                  . $this->EOL 
     251                  . $boundaryLine 
     252                  . $html->getHeaders($this->EOL) 
     253                  . $this->EOL 
     254                  . $html->getContent($this->EOL) 
     255                  . $this->EOL 
     256                  . $boundaryEnd; 
     257 
     258            $mp           = new Zend_Mime_Part($body); 
     259            $mp->type     = Zend_Mime::MULTIPART_ALTERNATIVE; 
     260            $mp->boundary = $mime->boundary(); 
     261 
     262            $this->_isMultipart = true; 
     263 
     264            // Ensure first part contains text alternatives 
     265            array_unshift($this->_parts, $mp); 
     266 
     267            // Get headers 
     268            $this->_headers = $this->_mail->getHeaders(); 
     269            return; 
     270        } 
     271 
     272        // If not multipart, then get the body 
     273        if (false !== ($body = $this->_mail->getBodyHtml())) { 
     274            array_unshift($this->_parts, $body); 
     275        } elseif (false !== ($body = $this->_mail->getBodyText())) { 
     276            array_unshift($this->_parts, $body); 
     277        } 
     278 
     279        if (!$body) { 
     280            /** 
     281             * @see Zend_Mail_Transport_Exception 
     282             */ 
     283            require_once 'Zend/Mail/Transport/Exception.php'; 
     284            throw new Zend_Mail_Transport_Exception('No body specified'); 
     285        } 
     286 
     287        // Get headers 
     288        $this->_headers = $this->_mail->getHeaders(); 
     289        $headers = $body->getHeadersArray($this->EOL); 
     290        foreach ($headers as $header) { 
     291            // Headers in Zend_Mime_Part are kept as arrays with two elements, a 
     292            // key and a value 
     293            $this->_headers[$header[0]] = array($header[1]); 
     294        } 
     295    } 
     296 
     297    /** 
     298     * Send a mail using this transport 
     299     * 
     300     * @param  Zend_Mail $mail 
     301     * @access public 
     302     * @return void 
     303     * @throws Zend_Mail_Transport_Exception if mail is empty 
     304     */ 
     305    public function send(Zend_Mail $mail) 
     306    { 
     307        $this->_isMultipart = false; 
     308        $this->_mail        = $mail; 
     309        $this->_parts       = $mail->getParts(); 
     310        $mime               = $mail->getMime(); 
     311 
     312        // Build body content 
     313        $this->_buildBody(); 
     314 
     315        // Determine number of parts and boundary 
     316        $count    = count($this->_parts); 
     317        $boundary = null; 
     318        if ($count < 1) { 
     319            /** 
     320             * @see Zend_Mail_Transport_Exception 
     321             */ 
     322            require_once 'Zend/Mail/Transport/Exception.php'; 
     323            throw new Zend_Mail_Transport_Exception('Empty mail cannot be sent'); 
     324        } 
     325 
     326        if ($count > 1) { 
     327            // Multipart message; create new MIME object and boundary 
     328            $mime     = new Zend_Mime($this->_mail->getMimeBoundary()); 
     329            $boundary = $mime->boundary(); 
     330        } elseif ($this->_isMultipart) { 
     331            // multipart/alternative -- grab boundary 
     332            $boundary = $this->_parts[0]->boundary; 
     333        } 
     334 
     335        // Determine recipients, and prepare headers 
     336        $this->recipients = implode(',', $mail->getRecipients()); 
     337        $this->_prepareHeaders($this->_getHeaders($boundary)); 
     338 
     339        // Create message body 
     340        // This is done so that the same Zend_Mail object can be used in 
     341        // multiple transports 
     342        $message = new Zend_Mime_Message(); 
     343        $message->setParts($this->_parts); 
     344        $message->setMime($mime); 
     345        $this->body = $message->generateMessage($this->EOL); 
     346 
     347        // Send to transport! 
     348        $this->_sendMail(); 
     349    } 
     350} 
  • libs/Zend/Mail/Transport/Smtp.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 *  
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @subpackage Transport 
     18 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     19 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     20 * @version    $Id: Smtp.php 8064 2008-02-16 10:58:39Z thomas $ 
     21 */ 
     22 
     23 
     24/** 
     25 * @see Zend_Loader 
     26 */ 
     27require_once 'Zend/Loader.php'; 
     28 
     29/** 
     30 * @see Zend_Mime 
     31 */ 
     32require_once 'Zend/Mime.php'; 
     33 
     34/** 
     35 * @see Zend_Mail_Protocol_Smtp 
     36 */ 
     37require_once 'Zend/Mail/Protocol/Smtp.php'; 
     38 
     39/** 
     40 * @see Zend_Mail_Transport_Abstract 
     41 */ 
     42require_once 'Zend/Mail/Transport/Abstract.php'; 
     43 
     44 
     45/** 
     46 * SMTP connection object 
     47 * 
     48 * Loads an instance of Zend_Mail_Protocol_Smtp and forwards smtp transactions 
     49 * 
     50 * @category   Zend 
     51 * @package    Zend_Mail 
     52 * @subpackage Transport 
     53 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     54 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     55 */ 
     56class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract 
     57{ 
     58    /** 
     59     * EOL character string used by transport 
     60     * @var string 
     61     * @access public 
     62     */ 
     63    public $EOL = "\n"; 
     64 
     65    /** 
     66     * Remote smtp hostname or i.p. 
     67     * 
     68     * @var string 
     69     */ 
     70    protected $_host; 
     71 
     72 
     73    /** 
     74     * Port number 
     75     * 
     76     * @var integer|null 
     77     */ 
     78    protected $_port; 
     79 
     80 
     81    /** 
     82     * Local client hostname or i.p. 
     83     * 
     84     * @var string 
     85     */ 
     86    protected $_name = 'localhost'; 
     87 
     88 
     89    /** 
     90     * Authentication type OPTIONAL 
     91     * 
     92     * @var string 
     93     */ 
     94    protected $_auth; 
     95 
     96 
     97    /** 
     98     * Config options for authentication 
     99     * 
     100     * @var array 
     101     */ 
     102    protected $_config; 
     103 
     104 
     105    /** 
     106     * Instance of Zend_Mail_Protocol_Smtp 
     107     * 
     108     * @var Zend_Mail_Protocol_Smtp 
     109     */ 
     110    protected $_connection; 
     111 
     112 
     113    /** 
     114     * Constructor. 
     115     * 
     116     * @param  string $host OPTIONAL (Default: 127.0.0.1) 
     117     * @param  array|null $config OPTIONAL (Default: null) 
     118     * @return void 
     119     */ 
     120    public function __construct($host = '127.0.0.1', Array $config = array()) 
     121    { 
     122        if (isset($config['name'])) { 
     123            $this->_name = $config['name']; 
     124        } 
     125        if (isset($config['port'])) { 
     126            $this->_port = $config['port']; 
     127        } 
     128        if (isset($config['auth'])) { 
     129            $this->_auth = $config['auth']; 
     130        } 
     131 
     132        $this->_host = $host; 
     133        $this->_config = $config; 
     134    } 
     135 
     136 
     137    /** 
     138     * Class destructor to ensure all open connections are closed 
     139     * 
     140     * @return void 
     141     */ 
     142    public function __destruct() 
     143    { 
     144        if ($this->_connection instanceof Zend_Mail_Protocol_Smtp) { 
     145            try { 
     146                $this->_connection->quit(); 
     147            } catch (Zend_Mail_Protocol_Exception $e) { 
     148                // ignore 
     149            } 
     150            $this->_connection->disconnect(); 
     151        } 
     152    } 
     153 
     154 
     155    /** 
     156     * Sets the connection protocol instance 
     157     * 
     158     * @param Zend_Mail_Protocol_Abstract $client 
     159     * 
     160     * @return void 
     161     */ 
     162    public function setConnection(Zend_Mail_Protocol_Abstract $connection) 
     163    { 
     164        $this->_connection = $connection; 
     165    } 
     166 
     167 
     168    /** 
     169     * Gets the connection protocol instance 
     170     * 
     171     * @return Zend_Mail_Protocol|null 
     172     */ 
     173    public function getConnection() 
     174    { 
     175        return $this->_connection; 
     176    } 
     177 
     178    /** 
     179     * Send an email via the SMTP connection protocol 
     180     * 
     181     * The connection via the protocol adapter is made just-in-time to allow a 
     182     * developer to add a custom adapter if required before mail is sent. 
     183     * 
     184     * @return void 
     185     */ 
     186    public function _sendMail() 
     187    { 
     188        // If sending multiple messages per session use existing adapter 
     189        if (!($this->_connection instanceof Zend_Mail_Protocol_Smtp)) { 
     190            // Check if authentication is required and determine required class 
     191            $connectionClass = 'Zend_Mail_Protocol_Smtp'; 
     192            if ($this->_auth) { 
     193                $connectionClass .= '_Auth_' . ucwords($this->_auth); 
     194            } 
     195            Zend_Loader::loadClass($connectionClass); 
     196            $this->setConnection(new $connectionClass($this->_host, $this->_port, $this->_config)); 
     197            $this->_connection->connect(); 
     198            $this->_connection->helo($this->_name); 
     199        } else { 
     200            // Reset connection to ensure reliable transaction 
     201            $this->_connection->rset(); 
     202        } 
     203 
     204        // Set mail return path from sender email address 
     205        $this->_connection->mail($this->_mail->getReturnPath()); 
     206 
     207        // Set recipient forward paths 
     208        foreach ($this->_mail->getRecipients() as $recipient) { 
     209            $this->_connection->rcpt($recipient); 
     210        } 
     211 
     212        // Issue DATA command to client 
     213        $this->_connection->data($this->header . Zend_Mime::LINEEND . $this->body); 
     214    } 
     215 
     216    /** 
     217     * Format and fix headers 
     218     * 
     219     * Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we. 
     220     * 
     221     * @access  protected 
     222     * @param   array $headers 
     223     * @return  void 
     224     * @throws  Zend_Transport_Exception 
     225     */ 
     226    protected function _prepareHeaders($headers) 
     227    { 
     228        if (!$this->_mail) { 
     229            /** 
     230             * @see Zend_Mail_Transport_Exception 
     231             */ 
     232            require_once 'Zend/Mail/Transport/Exception.php'; 
     233            throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object'); 
     234        } 
     235 
     236        unset($headers['Bcc']); 
     237 
     238        // Prepare headers 
     239        parent::_prepareHeaders($headers); 
     240    } 
     241} 
  • libs/Zend/Mail/Part.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to version 1.0 of the Zend Framework 
     8 * license, that is bundled with this package in the file LICENSE.txt, and 
     9 * is available through the world-wide-web at the following URL: 
     10 * http://framework.zend.com/license/new-bsd. If you did not receive 
     11 * a copy of the Zend Framework license and are unable to obtain it 
     12 * through the world-wide-web, please send a note to license@zend.com 
     13 * so we can mail you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 * @version    $Id: Part.php 8064 2008-02-16 10:58:39Z thomas $ 
     20 */ 
     21 
     22 
     23/** 
     24 * @see Zend_Mime_Decode 
     25 */ 
     26require_once 'Zend/Mime/Decode.php'; 
     27 
     28 
     29/** 
     30 * @category   Zend 
     31 * @package    Zend_Mail 
     32 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     33 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     34 */ 
     35class Zend_Mail_Part implements RecursiveIterator 
     36{ 
     37    /** 
     38     * headers of part as array 
     39     * @var null|array 
     40     */ 
     41    protected $_headers; 
     42 
     43    /** 
     44     * raw part body 
     45     * @var null|string 
     46     */ 
     47    protected $_content; 
     48 
     49    /** 
     50     * toplines as fetched with headers 
     51     * @var string 
     52     */ 
     53    protected $_topLines = ''; 
     54 
     55    /** 
     56     * parts of multipart message 
     57     * @var array 
     58     */ 
     59    protected $_parts = array(); 
     60 
     61    /** 
     62     * count of parts of a multipart message 
     63     * @var null|int 
     64     */ 
     65    protected $_countParts; 
     66 
     67    /** 
     68     * current position of iterator 
     69     * @var int 
     70     */ 
     71    protected $_iterationPos = 1; 
     72 
     73    /** 
     74     * mail handler, if late fetch is active 
     75     * @var null|Zend_Mail_Storage_Abstract 
     76     */ 
     77    protected $_mail; 
     78 
     79    /** 
     80     * message number for mail handler 
     81     * @var int 
     82     */ 
     83    protected $_messageNum = 0; 
     84 
     85    /** 
     86     * Public constructor 
     87     * 
     88     * Zend_Mail_Part supports different sources for content. The possible params are: 
     89     * - handler    a instance of Zend_Mail_Storage_Abstract for late fetch 
     90     * - id         number of message for handler 
     91     * - raw        raw content with header and body as string 
     92     * - headers    headers as array (name => value) or string, if a content part is found it's used as toplines 
     93     * - noToplines ignore content found after headers in param 'headers' 
     94     * - content    content as string 
     95     * 
     96     * @param   array $params  full message with or without headers 
     97     * @throws  Zend_Mail_Exception 
     98     */ 
     99    public function __construct(array $params) 
     100    { 
     101        if (isset($params['handler'])) { 
     102            if (!$params['handler'] instanceof Zend_Mail_Storage_Abstract) { 
     103                /** 
     104                 * @see Zend_Mail_Exception 
     105                 */ 
     106                require_once 'Zend/Mail/Exception.php'; 
     107                throw new Zend_Mail_Exception('handler is not a valid mail handler'); 
     108            } 
     109            if (!isset($params['id'])) { 
     110                /** 
     111                 * @see Zend_Mail_Exception 
     112                 */ 
     113                require_once 'Zend/Mail/Exception.php'; 
     114                throw new Zend_Mail_Exception('need a message id with a handler'); 
     115            } 
     116 
     117            $this->_mail       = $params['handler']; 
     118            $this->_messageNum = $params['id']; 
     119        } 
     120 
     121        if (isset($params['raw'])) { 
     122            Zend_Mime_Decode::splitMessage($params['raw'], $this->_headers, $this->_content); 
     123        } else if (isset($params['headers'])) { 
     124            if (is_array($params['headers'])) { 
     125                $this->_headers = $params['headers']; 
     126            } else { 
     127                if (!empty($params['noToplines'])) { 
     128                    Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $null); 
     129                } else { 
     130                    Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $this->_topLines); 
     131                } 
     132            } 
     133            if (isset($params['content'])) { 
     134                $this->_content = $params['content']; 
     135            } 
     136        } 
     137    } 
     138 
     139    /** 
     140     * Check if part is a multipart message 
     141     * 
     142     * @return bool if part is multipart 
     143     */ 
     144    public function isMultipart() 
     145    { 
     146        try { 
     147            return stripos($this->contentType, 'multipart/') === 0; 
     148        } catch(Zend_Mail_Exception $e) { 
     149            return false; 
     150        } 
     151    } 
     152 
     153 
     154    /** 
     155     * Body of part 
     156     * 
     157     * If part is multipart the raw content of this part with all sub parts is returned 
     158     * 
     159     * @return string body 
     160     * @throws Zend_Mail_Exception 
     161     */ 
     162    public function getContent() 
     163    { 
     164        if ($this->_content !== null) { 
     165            return $this->_content; 
     166        } 
     167 
     168        if ($this->_mail) { 
     169            return $this->_mail->getRawContent($this->_messageNum); 
     170        } else { 
     171            /** 
     172             * @see Zend_Mail_Exception 
     173             */ 
     174            require_once 'Zend/Mail/Exception.php'; 
     175            throw new Zend_Mail_Exception('no content'); 
     176        } 
     177    } 
     178 
     179    /** 
     180     * Cache content and split in parts if multipart 
     181     * 
     182     * @return null 
     183     * @throws Zend_Mail_Exception 
     184     */ 
     185    protected function _cacheContent() 
     186    { 
     187        // caching content if we can't fetch parts 
     188        if ($this->_content === null && $this->_mail) { 
     189            $this->_content = $this->_mail->getRawContent($this->_messageNum); 
     190        } 
     191 
     192        if (!$this->isMultipart()) { 
     193            return; 
     194        } 
     195 
     196        // split content in parts 
     197        $boundary = $this->getHeaderField('content-type', 'boundary'); 
     198        if (!$boundary) { 
     199            /** 
     200             * @see Zend_Mail_Exception 
     201             */ 
     202            require_once 'Zend/Mail/Exception.php'; 
     203            throw new Zend_Mail_Exception('no boundary found in content type to split message'); 
     204        } 
     205        $parts = Zend_Mime_Decode::splitMessageStruct($this->_content, $boundary); 
     206        $counter = 1; 
     207        foreach ($parts as $part) { 
     208            $this->_parts[$counter++] = new self(array('headers' => $part['header'], 'content' => $part['body'])); 
     209        } 
     210    } 
     211 
     212    /** 
     213     * Get part of multipart message 
     214     * 
     215     * @param  int $num number of part starting with 1 for first part 
     216     * @return Zend_Mail_Part wanted part 
     217     * @throws Zend_Mail_Exception 
     218     */ 
     219    public function getPart($num) 
     220    { 
     221        if (isset($this->_parts[$num])) { 
     222            return $this->_parts[$num]; 
     223        } 
     224 
     225        if (!$this->_mail && $this->_content === null) { 
     226            /** 
     227             * @see Zend_Mail_Exception 
     228             */ 
     229            require_once 'Zend/Mail/Exception.php'; 
     230            throw new Zend_Mail_Exception('part not found'); 
     231        } 
     232 
     233        if ($this->_mail && $this->_mail->hasFetchPart) { 
     234            // TODO: fetch part 
     235            // return 
     236        } 
     237 
     238        $this->_cacheContent(); 
     239 
     240        if (!isset($this->_parts[$num])) { 
     241            /** 
     242             * @see Zend_Mail_Exception 
     243             */ 
     244            require_once 'Zend/Mail/Exception.php'; 
     245            throw new Zend_Mail_Exception('part not found'); 
     246        } 
     247 
     248        return $this->_parts[$num]; 
     249    } 
     250 
     251    /** 
     252     * Count parts of a multipart part 
     253     * 
     254     * @return int number of sub-parts 
     255     */ 
     256    public function countParts() 
     257    { 
     258        if ($this->_countParts) { 
     259            return $this->_countParts; 
     260        } 
     261 
     262        $this->_countParts = count($this->_parts); 
     263        if ($this->_countParts) { 
     264            return $this->_countParts; 
     265        } 
     266 
     267        if ($this->_mail && $this->_mail->hasFetchPart) { 
     268            // TODO: fetch part 
     269            // return 
     270        } 
     271 
     272        $this->_cacheContent(); 
     273 
     274        $this->_countParts = count($this->_parts); 
     275        return $this->_countParts; 
     276    } 
     277 
     278 
     279    /** 
     280     * Get all headers 
     281     * 
     282     * The returned headers are as saved internally. All names are lowercased. The value is a string or an array 
     283     * if a header with the same name occurs more than once. 
     284     * 
     285     * @return array headers as array(name => value) 
     286     */ 
     287    public function getHeaders() 
     288    { 
     289        if ($this->_headers === null) { 
     290            if (!$this->_mail) { 
     291                $this->_headers = array(); 
     292            } else { 
     293                $part = $this->_mail->getRawHeader($this->_messageNum); 
     294                Zend_Mime_Decode::splitMessage($part, $this->_headers, $null); 
     295            } 
     296        } 
     297 
     298        return $this->_headers; 
     299    } 
     300 
     301    /** 
     302     * Get a header in specificed format 
     303     * 
     304     * Internally headers that occur more than once are saved as array, all other as string. If $format 
     305     * is set to string implode is used to concat the values (with Zend_Mime::LINEEND as delim). 
     306     * 
     307     * @param  string $name   name of header, matches case-insensitive, but camel-case is replaced with dashes 
     308     * @param  string $format change type of return value to 'string' or 'array' 
     309     * @return string|array value of header in wanted or internal format 
     310     * @throws Zend_Mail_Exception 
     311     */ 
     312    public function getHeader($name, $format = null) 
     313    { 
     314        if ($this->_headers === null) { 
     315            $this->getHeaders(); 
     316        } 
     317 
     318        $lowerName = strtolower($name); 
     319 
     320        if (!isset($this->_headers[$lowerName])) { 
     321            $lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name)); 
     322            if (!isset($this->_headers[$lowerName])) { 
     323                /** 
     324                 * @see Zend_Mail_Exception 
     325                 */ 
     326                require_once 'Zend/Mail/Exception.php'; 
     327                throw new Zend_Mail_Exception("no Header with Name $name found"); 
     328            } 
     329        } 
     330        $name = $lowerName; 
     331 
     332        $header = $this->_headers[$name]; 
     333 
     334        switch ($format) { 
     335            case 'string': 
     336                if (is_array($header)) { 
     337                    $header = implode(Zend_Mime::LINEEND, $header); 
     338                } 
     339                break; 
     340            case 'array': 
     341                $header = (array)$header; 
     342            default: 
     343                // do nothing 
     344        } 
     345 
     346        return $header; 
     347    } 
     348     
     349    /** 
     350     * Get a specific field from a header like content type or all fields as array 
     351     * 
     352     * If the header occurs more than once, only the value from the first header 
     353     * is returned. 
     354     * 
     355     * Throws a Zend_Mail_Exception if the requested header does not exist. If 
     356     * the specific header field does not exist, returns null. 
     357     * 
     358     * @param  string $name       name of header, like in getHeader() 
     359     * @param  string $wantedPart the wanted part, default is first, if null an array with all parts is returned 
     360     * @param  string $firstName  key name for the first part 
     361     * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) 
     362     * @throws Zend_Exception, Zend_Mail_Exception 
     363     */ 
     364    public function getHeaderField($name, $wantedPart = 0, $firstName = 0) { 
     365        return Zend_Mime_Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName); 
     366    } 
     367 
     368 
     369    /** 
     370     * Getter for mail headers - name is matched in lowercase 
     371     * 
     372     * This getter is short for Zend_Mail_Part::getHeader($name, 'string') 
     373     * 
     374     * @see Zend_Mail_Part::getHeader() 
     375     * 
     376     * @param  string $name header name 
     377     * @return string value of header 
     378     * @throws Zend_Mail_Exception 
     379     */ 
     380    public function __get($name) 
     381    { 
     382        return $this->getHeader($name, 'string'); 
     383    } 
     384 
     385    /** 
     386     * magic method to get content of part 
     387     * 
     388     * @return string content 
     389     */ 
     390    public function __toString() 
     391    { 
     392        return $this->getContent(); 
     393    } 
     394 
     395    /** 
     396     * implements RecursiveIterator::hasChildren() 
     397     * 
     398     * @return bool current element has children/is multipart 
     399     */ 
     400    public function hasChildren() 
     401    { 
     402        $current = $this->current(); 
     403        return $current && $current instanceof Zend_Mail_Part && $current->isMultipart(); 
     404    } 
     405 
     406    /** 
     407     * implements RecursiveIterator::getChildren() 
     408     * 
     409     * @return Zend_Mail_Part same as self::current() 
     410     */ 
     411    public function getChildren() 
     412    { 
     413        return $this->current(); 
     414    } 
     415 
     416    /** 
     417     * implements Iterator::valid() 
     418     * 
     419     * @return bool check if there's a current element 
     420     */ 
     421    public function valid() 
     422    { 
     423        if ($this->_countParts === null) { 
     424            $this->countParts(); 
     425        } 
     426        return $this->_iterationPos && $this->_iterationPos <= $this->_countParts; 
     427    } 
     428 
     429    /** 
     430     * implements Iterator::next() 
     431     * 
     432     * @return null 
     433     */ 
     434    public function next() 
     435    { 
     436        ++$this->_iterationPos; 
     437    } 
     438 
     439    /** 
     440     * implements Iterator::key() 
     441     * 
     442     * @return string key/number of current part 
     443     */ 
     444    public function key() 
     445    { 
     446        return $this->_iterationPos; 
     447    } 
     448 
     449    /** 
     450     * implements Iterator::current() 
     451     * 
     452     * @return Zend_Mail_Part current part 
     453     */ 
     454    public function current() 
     455    { 
     456        return $this->getPart($this->_iterationPos); 
     457    } 
     458 
     459    /** 
     460     * implements Iterator::rewind() 
     461     * 
     462     * @return null 
     463     */ 
     464    public function rewind() 
     465    { 
     466        $this->countParts(); 
     467        $this->_iterationPos = 1; 
     468    } 
     469} 
  • libs/Zend/Mime/Exception.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mime 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 */ 
     20 
     21 
     22/** 
     23 * Zend_Exception 
     24 */ 
     25require_once 'Zend/Exception.php'; 
     26 
     27 
     28/** 
     29 * @category   Zend 
     30 * @package    Zend_Mime 
     31 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     32 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     33 */ 
     34class Zend_Mime_Exception extends Zend_Exception 
     35{} 
     36 
  • libs/Zend/Mime/Decode.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mime 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 */ 
     20 
     21/** 
     22 * Zend_Mime 
     23 */ 
     24require_once 'Zend/Mime.php'; 
     25 
     26/** 
     27 * @category   Zend 
     28 * @package    Zend_Mime 
     29 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     30 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     31 */ 
     32class Zend_Mime_Decode 
     33{ 
     34    /** 
     35     * Explode MIME multipart string into seperate parts 
     36     * 
     37     * Parts consist of the header and the body of each MIME part. 
     38     * 
     39     * @param  string $body     raw body of message 
     40     * @param  string $boundary boundary as found in content-type 
     41     * @return array parts with content of each part, empty if no parts found 
     42     * @throws Zend_Exception 
     43     */ 
     44    public static function splitMime($body, $boundary) 
     45    { 
     46        // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r? 
     47        $body = str_replace("\r", '', $body); 
     48 
     49        $start = 0; 
     50        $res = array(); 
     51        // find every mime part limiter and cut out the 
     52        // string before it. 
     53        // the part before the first boundary string is discarded: 
     54        $p = strpos($body, '--' . $boundary . "\n", $start); 
     55        if ($p === false) { 
     56            // no parts found! 
     57            return array(); 
     58        } 
     59 
     60        // position after first boundary line 
     61        $start = $p + 3 + strlen($boundary); 
     62 
     63        while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { 
     64            $res[] = substr($body, $start, $p-$start); 
     65            $start = $p + 3 + strlen($boundary); 
     66        } 
     67 
     68        // no more parts, find end boundary 
     69        $p = strpos($body, '--' . $boundary . '--', $start); 
     70        if ($p===false) { 
     71            throw new Zend_Exception('Not a valid Mime Message: End Missing'); 
     72        } 
     73 
     74        // the remaining part also needs to be parsed: 
     75        $res[] = substr($body, $start, $p-$start); 
     76        return $res; 
     77    } 
     78 
     79    /** 
     80     * decodes a mime encoded String and returns a 
     81     * struct of parts with header and body 
     82     * 
     83     * @param  string $message  raw message content 
     84     * @param  string $boundary boundary as found in content-type 
     85     * @param  string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} 
     86     * @return array|null parts as array('header' => array(name => value), 'body' => content), null if no parts found 
     87     * @throws Zend_Exception 
     88     */ 
     89    public static function splitMessageStruct($message, $boundary, $EOL = Zend_Mime::LINEEND) 
     90    { 
     91        $parts = self::splitMime($message, $boundary); 
     92        if (count($parts) <= 0) { 
     93            return null; 
     94        } 
     95        $result = array(); 
     96        foreach ($parts as $part) { 
     97            self::splitMessage($part, $headers, $body, $EOL); 
     98            $result[] = array('header' => $headers, 
     99                              'body'   => $body    ); 
     100        } 
     101        return $result; 
     102    } 
     103 
     104    /** 
     105     * split a message in header and body part, if no header or an 
     106     * invalid header is found $headers is empty 
     107     * 
     108     * The charset of the returned headers depend on your iconv settings. 
     109     * 
     110     * @param  string $message raw message with header and optional content 
     111     * @param  array  $headers output param, array with headers as array(name => value) 
     112     * @param  string $body    output param, content of message 
     113     * @param  string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} 
     114     * @return null 
     115     */ 
     116    public static function splitMessage($message, &$headers, &$body, $EOL = Zend_Mime::LINEEND) 
     117    { 
     118        // check for valid header at first line 
     119        $firstline = strtok($message, "\n"); 
     120        if (!preg_match('%^[^\s]+[^:]*:%', $firstline)) { 
     121            $headers = array(); 
     122            // TODO: we're ignoring \r for now - is this function fast enough and is it safe to asume noone needs \r? 
     123            $body = str_replace(array("\r", "\n"), array('', $EOL), $message); 
     124            return; 
     125        } 
     126 
     127        // find an empty line between headers and body 
     128        // default is set new line 
     129        if (strpos($message, $EOL . $EOL)) { 
     130            list($headers, $body) = explode($EOL . $EOL, $message, 2); 
     131        // next is the standard new line 
     132        } else if ($EOL != "\r\n" && strpos($message, "\r\n\r\n")) { 
     133            list($headers, $body) = explode("\r\n\r\n", $message, 2); 
     134        // next is the other "standard" new line 
     135        } else if ($EOL != "\n" && strpos($message, "\n\n")) { 
     136            list($headers, $body) = explode("\n\n", $message, 2); 
     137        // at last resort find anything that looks like a new line 
     138        } else { 
     139            @list($headers, $body) = @preg_split("%([\r\n]+)\\1%U", $message, 2); 
     140        } 
     141 
     142        $headers = iconv_mime_decode_headers($headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR); 
     143 
     144        // normalize header names 
     145        foreach ($headers as $name => $header) { 
     146            $lower = strtolower($name); 
     147            if ($lower == $name) { 
     148                continue; 
     149            } 
     150            unset($headers[$name]); 
     151            if (!isset($headers[$lower])) { 
     152                $headers[$lower] = $header; 
     153                continue; 
     154            } 
     155            if (is_array($headers[$lower])) { 
     156                $headers[$lower][] = $header; 
     157                continue; 
     158            } 
     159            $headers[$lower] = array($headers[$lower], $header); 
     160        } 
     161    } 
     162 
     163    /** 
     164     * split a content type in its different parts 
     165     * 
     166     * @param  string $type       content-type 
     167     * @param  string $wantedPart the wanted part, else an array with all parts is returned 
     168     * @return string|array wanted part or all parts as array('type' => content-type, partname => value) 
     169     */ 
     170    public static function splitContentType($type, $wantedPart = null) 
     171    { 
     172        return self::splitHeaderField($type, $wantedPart, 'type'); 
     173    } 
     174 
     175    /** 
     176     * split a header field like content type in its different parts 
     177     * 
     178     * @param  string $type       header field 
     179     * @param  string $wantedPart the wanted part, else an array with all parts is returned 
     180     * @param  string $firstName  key name for the first part 
     181     * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) 
     182     * @throws Zend_Exception 
     183     */ 
     184    public static function splitHeaderField($field, $wantedPart = null, $firstName = 0) 
     185    { 
     186        $wantedPart = strtolower($wantedPart); 
     187        $firstName = strtolower($firstName); 
     188 
     189        // special case - a bit optimized 
     190        if ($firstName === $wantedPart) { 
     191            $field = strtok($field, ';'); 
     192            return $field[0] == '"' ? substr($field, 1, -1) : $field; 
     193        } 
     194         
     195        $field = $firstName . '=' . $field; 
     196        if (!preg_match_all('%([^=]+)=("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) { 
     197            throw new Zend_Exception('not a valid header field'); 
     198        } 
     199 
     200        if ($wantedPart) { 
     201            foreach ($matches[1] as $key => $name) { 
     202                if (strcasecmp($name, $wantedPart)) { 
     203                    continue; 
     204                } 
     205                if ($matches[2][$key][0] != '"') { 
     206                    return $matches[2][$key]; 
     207                } 
     208                return substr($matches[2][$key], 1, -1); 
     209            } 
     210            return null; 
     211        } 
     212 
     213        $split = array(); 
     214        foreach ($matches[1] as $key => $name) { 
     215                $name = strtolower($name); 
     216            if ($matches[2][$key][0] == '"') { 
     217                $split[$name] = substr($matches[2][$key], 1, -1); 
     218            } else { 
     219                $split[$name] = $matches[2][$key]; 
     220            } 
     221        } 
     222 
     223        return $split; 
     224    } 
     225 
     226    /** 
     227     * decode a quoted printable encoded string 
     228     * 
     229     * The charset of the returned string depends on your iconv settings. 
     230     * 
     231     * @param  string encoded string 
     232     * @return string decoded string 
     233     */ 
     234    public static function decodeQuotedPrintable($string) 
     235    { 
     236        return iconv_mime_decode($string, ICONV_MIME_DECODE_CONTINUE_ON_ERROR); 
     237    } 
     238} 
  • libs/Zend/Mime/Message.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mime 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 */ 
     20 
     21 
     22/** 
     23 * Zend_Mime 
     24 */ 
     25require_once 'Zend/Mime.php'; 
     26 
     27/** 
     28 * Zend_Mime_Part 
     29 */ 
     30require_once 'Zend/Mime/Part.php'; 
     31 
     32 
     33/** 
     34 * @category   Zend 
     35 * @package    Zend_Mime 
     36 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     37 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     38 */ 
     39class Zend_Mime_Message 
     40{ 
     41 
     42    protected $_parts = array(); 
     43    protected $_mime = null; 
     44 
     45    /** 
     46     * Returns the list of all Zend_Mime_Parts in the message 
     47     * 
     48     * @return array of Zend_Mime_Part 
     49     */ 
     50    public function getParts() 
     51    { 
     52        return $this->_parts; 
     53    } 
     54 
     55    /** 
     56     * Sets the given array of Zend_Mime_Parts as the array for the message 
     57     * 
     58     * @param array $parts 
     59     */ 
     60    public function setParts($parts) 
     61    { 
     62        $this->_parts = $parts; 
     63    } 
     64 
     65    /** 
     66     * Append a new Zend_Mime_Part to the current message 
     67     * 
     68     * @param Zend_Mime_Part $part 
     69     */ 
     70    public function addPart(Zend_Mime_Part $part) 
     71    { 
     72        /** 
     73         * @todo check for duplicate object handle 
     74         */ 
     75        $this->_parts[] = $part; 
     76    } 
     77 
     78    /** 
     79     * Check if message needs to be sent as multipart 
     80     * MIME message or if it has only one part. 
     81     * 
     82     * @return boolean 
     83     */ 
     84    public function isMultiPart() 
     85    { 
     86        return (count($this->_parts) > 1); 
     87    } 
     88 
     89    /** 
     90     * Set Zend_Mime object for the message 
     91     * 
     92     * This can be used to set the boundary specifically or to use a subclass of 
     93     * Zend_Mime for generating the boundary. 
     94     * 
     95     * @param Zend_Mime $mime 
     96     */ 
     97    public function setMime(Zend_Mime $mime) 
     98    { 
     99        $this->_mime = $mime; 
     100    } 
     101 
     102    /** 
     103     * Returns the Zend_Mime object in use by the message 
     104     * 
     105     * If the object was not present, it is created and returned. Can be used to 
     106     * determine the boundary used in this message. 
     107     * 
     108     * @return Zend_Mime 
     109     */ 
     110    public function getMime() 
     111    { 
     112        if ($this->_mime === null) { 
     113            $this->_mime = new Zend_Mime(); 
     114        } 
     115 
     116        return $this->_mime; 
     117    } 
     118 
     119    /** 
     120     * Generate MIME-compliant message from the current configuration 
     121     * 
     122     * This can be a multipart message if more than one MIME part was added. If 
     123     * only one part is present, the content of this part is returned. If no 
     124     * part had been added, an empty string is returned. 
     125     * 
     126     * Parts are seperated by the mime boundary as defined in Zend_Mime. If 
     127     * {@link setMime()} has been called before this method, the Zend_Mime 
     128     * object set by this call will be used. Otherwise, a new Zend_Mime object 
     129     * is generated and used. 
     130     * 
     131     * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} 
     132     * @return string 
     133     */ 
     134    public function generateMessage($EOL = Zend_Mime::LINEEND) 
     135    { 
     136        if (! $this->isMultiPart()) { 
     137            $body = array_shift($this->_parts); 
     138            $body = $body->getContent($EOL); 
     139        } else { 
     140            $mime = $this->getMime(); 
     141 
     142            $boundaryLine = $mime->boundaryLine($EOL); 
     143            $body = 'This is a message in Mime Format.  If you see this, ' 
     144                  . "your mail reader does not support this format." . $EOL; 
     145 
     146            foreach (array_keys($this->_parts) as $p) { 
     147                $body .= $boundaryLine 
     148                       . $this->getPartHeaders($p, $EOL) 
     149                       . $EOL 
     150                       . $this->getPartContent($p, $EOL); 
     151            } 
     152 
     153            $body .= $mime->mimeEnd($EOL); 
     154        } 
     155 
     156        return trim($body); 
     157    } 
     158 
     159    /** 
     160     * Get the headers of a given part as an array 
     161     * 
     162     * @param int $partnum 
     163     * @return array 
     164     */ 
     165    public function getPartHeadersArray($partnum) 
     166    { 
     167        return $this->_parts[$partnum]->getHeadersArray(); 
     168    } 
     169 
     170    /** 
     171     * Get the headers of a given part as a string 
     172     * 
     173     * @param int $partnum 
     174     * @return string 
     175     */ 
     176    public function getPartHeaders($partnum, $EOL = Zend_Mime::LINEEND) 
     177    { 
     178        return $this->_parts[$partnum]->getHeaders($EOL); 
     179    } 
     180 
     181    /** 
     182     * Get the (encoded) content of a given part as a string 
     183     * 
     184     * @param int $partnum 
     185     * @return string 
     186     */ 
     187    public function getPartContent($partnum, $EOL = Zend_Mime::LINEEND) 
     188    { 
     189        return $this->_parts[$partnum]->getContent($EOL); 
     190    } 
     191 
     192    /** 
     193     * Explode MIME multipart string into seperate parts 
     194     * 
     195     * Parts consist of the header and the body of each MIME part. 
     196     * 
     197     * @param string $body 
     198     * @param string $boundary 
     199     * @return array 
     200     */ 
     201    protected static function _disassembleMime($body, $boundary) 
     202    { 
     203        $start = 0; 
     204        $res = array(); 
     205        // find every mime part limiter and cut out the 
     206        // string before it. 
     207        // the part before the first boundary string is discarded: 
     208        $p = strpos($body, '--'.$boundary."\n", $start); 
     209        if ($p === false) { 
     210            // no parts found! 
     211            return array(); 
     212        } 
     213 
     214        // position after first boundary line 
     215        $start = $p + 3 + strlen($boundary); 
     216 
     217        while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { 
     218            $res[] = substr($body, $start, $p-$start); 
     219            $start = $p + 3 + strlen($boundary); 
     220        } 
     221 
     222        // no more parts, find end boundary 
     223        $p = strpos($body, '--' . $boundary . '--', $start); 
     224        if ($p===false) { 
     225            throw new Zend_Exception('Not a valid Mime Message: End Missing'); 
     226        } 
     227 
     228        // the remaining part also needs to be parsed: 
     229        $res[] = substr($body, $start, $p-$start); 
     230        return $res; 
     231    } 
     232 
     233    /** 
     234     * Decodes a MIME encoded string and returns a Zend_Mime_Message object with 
     235     * all the MIME parts set according to the given string 
     236     * 
     237     * @param string $message 
     238     * @param string $boundary 
     239     * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} 
     240     * @return Zend_Mime_Message 
     241     */ 
     242    public static function createFromMessage($message, $boundary, $EOL = Zend_Mime::LINEEND) 
     243    { 
     244        require_once 'Zend/Mime/Decode.php'; 
     245        $parts = Zend_Mime_Decode::splitMessageStruct($message, $boundary, $EOL); 
     246 
     247        $res = new self(); 
     248        foreach ($parts as $part) { 
     249            // now we build a new MimePart for the current Message Part: 
     250            $newPart = new Zend_Mime_Part($part); 
     251            foreach ($part['header'] as $key => $value) { 
     252                /** 
     253                 * @todo check for characterset and filename 
     254                 */ 
     255                // list($key, $value) = $header; 
     256                switch($key) { 
     257                    case 'content-type': 
     258                        $newPart->type = $value; 
     259                        break; 
     260                    case 'content-transfer-encoding': 
     261                        $newPart->encoding = $value; 
     262                        break; 
     263                    case 'content-id': 
     264                        $newPart->id = trim($value,'<>'); 
     265                        break; 
     266                    case 'Content-Disposition': 
     267                        $newPart->disposition = $value; 
     268                        break; 
     269                    case 'content-description': 
     270                        $newPart->description = $value; 
     271                        break; 
     272                    default: 
     273                        throw new Zend_Exception('Unknown header ignored for MimePart:' . $key); 
     274                } 
     275            } 
     276            $res->addPart($newPart); 
     277        } 
     278        return $res; 
     279    } 
     280} 
  • libs/Zend/Mime/Part.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mime 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 */ 
     20 
     21/** 
     22 * Zend_Mime 
     23 */ 
     24require_once 'Zend/Mime.php'; 
     25 
     26/** 
     27 * Zend_Mime_Exception 
     28 */ 
     29require_once 'Zend/Mime/Exception.php'; 
     30 
     31/** 
     32 * Class representing a MIME part. 
     33 * 
     34 * @category   Zend 
     35 * @package    Zend_Mime 
     36 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     37 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     38 */ 
     39class Zend_Mime_Part { 
     40 
     41    public $type = Zend_Mime::TYPE_OCTETSTREAM; 
     42    public $encoding = Zend_Mime::ENCODING_8BIT; 
     43    public $id; 
     44    public $disposition; 
     45    public $filename; 
     46    public $description; 
     47    public $charset; 
     48    public $boundary; 
     49    protected $_content; 
     50    protected $_isStream = false; 
     51 
     52 
     53    /** 
     54     * create a new Mime Part. 
     55     * The (unencoded) content of the Part as passed 
     56     * as a string or stream 
     57     * 
     58     * @param mixed $content  String or Stream containing the content 
     59     */ 
     60    public function __construct($content) 
     61    { 
     62        $this->_content = $content; 
     63        if (is_resource($content)) { 
     64            $this->_isStream = true; 
     65        } 
     66    } 
     67 
     68    /** 
     69     * @todo setters/getters 
     70     * @todo error checking for setting $type 
     71     * @todo error checking for setting $encoding 
     72     */ 
     73 
     74    /** 
     75     * check if this part can be read as a stream. 
     76     * if true, getEncodedStream can be called, otherwise 
     77     * only getContent can be used to fetch the encoded 
     78     * content of the part 
     79     * 
     80     * @return bool 
     81     */ 
     82    public function isStream() 
     83    { 
     84      return $this->_isStream; 
     85    } 
     86 
     87    /** 
     88     * if this was created with a stream, return a filtered stream for 
     89     * reading the content. very useful for large file attachments. 
     90     * 
     91     * @return stream 
     92     * @throws Zend_Mime_Exception if not a stream or unable to append filter 
     93     */ 
     94    public function getEncodedStream() 
     95    { 
     96        if (!$this->_isStream) { 
     97            throw new Zend_Mime_Exception('Attempt to get a stream from a string part'); 
     98        } 
     99 
     100        //stream_filter_remove(); // ??? is that right? 
     101        switch ($this->encoding) { 
     102            case Zend_Mime::ENCODING_QUOTEDPRINTABLE: 
     103                $filter = stream_filter_append( 
     104                    $this->_content, 
     105                    'convert.quoted-printable-encode', 
     106                    STREAM_FILTER_READ, 
     107                    array( 
     108                        'line-length'      => 76, 
     109                        'line-break-chars' => Zend_Mime::LINEEND 
     110                    ) 
     111                ); 
     112                if (!is_resource($filter)) { 
     113                    throw new Zend_Mime_Exception('Failed to append quoted-printable filter'); 
     114                } 
     115                break; 
     116            case Zend_Mime::ENCODING_BASE64: 
     117                $filter = stream_filter_append( 
     118                    $this->_content, 
     119                    'convert.base64-encode', 
     120                    STREAM_FILTER_READ, 
     121                    array( 
     122                        'line-length'      => 76, 
     123                        'line-break-chars' => Zend_Mime::LINEEND 
     124                    ) 
     125                ); 
     126                if (!is_resource($filter)) { 
     127                    throw new Zend_Mime_Exception('Failed to append base64 filter'); 
     128                } 
     129                break; 
     130            default: 
     131        } 
     132        return $this->_content; 
     133    } 
     134 
     135    /** 
     136     * Get the Content of the current Mime Part in the given encoding. 
     137     * 
     138     * @return String 
     139     */ 
     140    public function getContent($EOL = Zend_Mime::LINEEND) 
     141    { 
     142        if ($this->_isStream) { 
     143            return stream_get_contents($this->getEncodedStream()); 
     144        } else { 
     145            return Zend_Mime::encode($this->_content, $this->encoding, $EOL); 
     146        } 
     147    } 
     148 
     149    /** 
     150     * Create and return the array of headers for this MIME part 
     151     * 
     152     * @access public 
     153     * @return array 
     154     */ 
     155    public function getHeadersArray($EOL = Zend_Mime::LINEEND) 
     156    { 
     157        $headers = array(); 
     158 
     159        $contentType = $this->type; 
     160        if ($this->charset) { 
     161            $contentType .= '; charset="' . $this->charset . '"'; 
     162        } 
     163 
     164        if ($this->boundary) { 
     165            $contentType .= ';' . $EOL 
     166                          . " boundary=\"" . $this->boundary . '"'; 
     167        } 
     168 
     169        $headers[] = array('Content-Type', $contentType); 
     170 
     171        if ($this->encoding) { 
     172            $headers[] = array('Content-Transfer-Encoding', $this->encoding); 
     173        } 
     174 
     175        if ($this->id) { 
     176            $headers[]  = array('Content-ID', '<' . $this->id . '>'); 
     177        } 
     178 
     179        if ($this->disposition) { 
     180            $disposition = $this->disposition; 
     181            if ($this->filename) { 
     182                $disposition .= '; filename="' . $this->filename . '"'; 
     183            } 
     184            $headers[] = array('Content-Disposition', $disposition); 
     185        } 
     186 
     187        if ($this->description) { 
     188            $headers[] = array('Content-Description', $this->description); 
     189        } 
     190 
     191        return $headers; 
     192    } 
     193 
     194    /** 
     195     * Return the headers for this part as a string 
     196     * 
     197     * @return String 
     198     */ 
     199    public function getHeaders($EOL = Zend_Mime::LINEEND) 
     200    { 
     201        $res = ''; 
     202        foreach ($this->getHeadersArray($EOL) as $header) { 
     203            $res .= $header[0] . ': ' . $header[1] . $EOL; 
     204        } 
     205 
     206        return $res; 
     207    } 
     208} 
  • libs/Zend/Mail.php

     
     1<?php 
     2/** 
     3 * Zend Framework 
     4 * 
     5 * LICENSE 
     6 * 
     7 * This source file is subject to the new BSD license that is bundled 
     8 * with this package in the file LICENSE.txt. 
     9 * It is also available through the world-wide-web at this URL: 
     10 * http://framework.zend.com/license/new-bsd 
     11 * If you did not receive a copy of the license and are unable to 
     12 * obtain it through the world-wide-web, please send an email 
     13 * to license@zend.com so we can send you a copy immediately. 
     14 * 
     15 * @category   Zend 
     16 * @package    Zend_Mail 
     17 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     18 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     19 * @version    $Id: Mail.php 8064 2008-02-16 10:58:39Z thomas $ 
     20 */ 
     21 
     22 
     23/** 
     24 * @see Zend_Mail_Transport_Abstract 
     25 */ 
     26require_once 'Zend/Mail/Transport/Abstract.php'; 
     27 
     28/** 
     29 * @see Zend_Mime 
     30 */ 
     31require_once 'Zend/Mime.php'; 
     32 
     33/** 
     34 * @see Zend_Mail_Transport_Abstract 
     35 */ 
     36require_once 'Zend/Mail/Transport/Abstract.php'; 
     37 
     38/** 
     39 * @see Zend_Mime_Message 
     40 */ 
     41require_once 'Zend/Mime/Message.php'; 
     42 
     43/** 
     44 * @see Zend_Mime_Part 
     45 */ 
     46require_once 'Zend/Mime/Part.php'; 
     47 
     48 
     49/** 
     50 * Class for sending an email. 
     51 * 
     52 * @category   Zend 
     53 * @package    Zend_Mail 
     54 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) 
     55 * @license    http://framework.zend.com/license/new-bsd     New BSD License 
     56 */ 
     57class Zend_Mail extends Zend_Mime_Message 
     58{ 
     59    /**#@+ 
     60     * @access protected 
     61     */ 
     62 
     63    /** 
     64     * @var Zend_Mail_Transport_Abstract 
     65     * @static 
     66     */ 
     67    protected static $_defaultTransport = null; 
     68 
     69    /** 
     70     * Mail character set 
     71     * @var string 
     72     */ 
     73    protected $_charset = null; 
     74 
     75    /** 
     76     * Mail headers 
     77     * @var array 
     78     */ 
     79    protected $_headers = array(); 
     80 
     81    /** 
     82     * From: address 
     83     * @var string 
     84     */ 
     85    protected $_from = null; 
     86 
     87    /** 
     88     * To: addresses 
     89     * @var array 
     90     */ 
     91    protected $_to = array(); 
     92 
     93    /** 
     94     * Array of all recipients 
     95     * @var array 
     96     */ 
     97    protected $_recipients = array(); 
     98 
     99    /** 
     100     * Return-Path header 
     101     * @var string 
     102     */ 
     103    protected $_returnPath = null; 
     104 
     105    /** 
     106     * Subject: header 
     107     * @var string 
     108     */ 
     109    protected $_subject = null; 
     110 
     111    /** 
     112     * Date: header 
     113     * @var string 
     114     */ 
     115    protected $_date = null; 
     116 
     117    /** 
     118     * text/plain MIME part 
     119     * @var false|Zend_Mime_Part 
     120     */ 
     121    protected $_bodyText = false; 
     122 
     123    /** 
     124     * text/html MIME part 
     125     * @var false|Zend_Mime_Part 
     126     */ 
     127    protected $_bodyHtml = false; 
     128 
     129    /** 
     130     * MIME boundary string 
     131     * @var string 
     132     */ 
     133    protected $_mimeBoundary = null; 
     134 
     135    /** 
     136     * Content type of the message 
     137     * @var string 
     138     */ 
     139    protected $_type = null; 
     140 
     141    /**#@-*/ 
     142 
     143    /** 
     144     * Flag: whether or not email has attachments 
     145     * @var boolean 
     146     */ 
     147    public $hasAttachments = false; 
     148 
     149 
     150    /** 
     151     * Sets the default mail transport for all following uses of 
     152     * Zend_Mail::send(); 
     153     * 
     154     * @todo Allow passing a string to indicate the transport to load 
     155     * @todo Allow passing in optional options for the transport to load 
     156     * @param  Zend_Mail_Transport_Abstract $transport 
     157     */ 
     158    public static function setDefaultTransport(Zend_Mail_Transport_Abstract $transport) 
     159    { 
     160        self::$_defaultTransport = $transport; 
     161    } 
     162 
     163    /** 
     164     * Public constructor 
     165     * 
     166     * @param string $charset 
     167     */ 
     168    public function __construct($charset='iso-8859-1') 
     169    { 
     170        $this->_charset = $charset; 
     171    } 
     172 
     173    /** 
     174     * Return charset string 
     175     * 
     176     * @return string 
     177     */ 
     178    public function getCharset() 
     179    { 
     180        return $this->_charset; 
     181    } 
     182 
     183    /** 
     184     * Set content type 
     185     * 
     186     * Should only be used for manually setting multipart content types. 
     187     * 
     188     * @param  string $type Content type 
     189     * @return Zend_Mail Implements fluent interface 
     190     * @throws Zend_Mail_Exception for types not supported by Zend_Mime 
     191     */ 
     192    public function setType($type) 
     193    { 
     194        $allowed = array( 
     195            Zend_Mime::MULTIPART_ALTERNATIVE, 
     196            Zend_Mime::MULTIPART_MIXED, 
     197            Zend_Mime::MULTIPART_RELATED, 
     198        ); 
     199        if (!in_array($type, $allowed)) { 
     200            /** 
     201             * @see Zend_Mail_Exception 
     202             */ 
     203            require_once 'Zend/Mail/Exception.php'; 
     204            throw new Zend_Mail_Exception('Invalid content type "' . $type . '"'); 
     205        } 
     206 
     207        $this->_type = $type; 
     208        return $this; 
     209    } 
     210 
     211    /** 
     212     * Get content type of the message 
     213     * 
     214     * @return string 
     215     */ 
     216    public function getType() 
     217    { 
     218        return $this->_type; 
     219    } 
     220 
     221    /** 
     222     * Set an arbitrary mime boundary for the message 
     223     * 
     224     * If not set, Zend_Mime will generate one. 
     225     * 
     226     * @param  string    $boundary 
     227     * @return Zend_Mail Provides fluent interface 
     228     */ 
     229    public function setMimeBoundary($boundary) 
     230    { 
     231        $this->_mimeBoundary = $boundary; 
     232 
     233        return $this; 
     234    } 
     235 
     236    /** 
     237     * Return the boundary string used for the message 
     238     * 
     239     * @return string 
     240     */ 
     241    public function getMimeBoundary() 
     242    { 
     243        return $this->_mimeBoundary; 
     244    } 
     245 
     246    /** 
     247     * Sets the text body for the message. 
     248     * 
     249     * @param  string $txt 
     250     * @param  string $charset 
     251     * @param  string $encoding 
     252     * @return Zend_Mail Provides fluent interface 
     253    */ 
     254    public function setBodyText($txt, $charset = null, $encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE) 
     255    { 
     256        if ($charset === null) { 
     257            $charset = $this->_charset; 
     258        } 
     259 
     260        $mp = new Zend_Mime_Part($txt); 
     261        $mp->encoding = $encoding; 
     262        $mp->type = Zend_Mime::TYPE_TEXT; 
     263        $mp->disposition = Zend_Mime::DISPOSITION_INLINE; 
     264        $mp->charset = $charset; 
     265 
     266        $this->_bodyText = $mp; 
     267 
     268        return $this; 
     269    } 
     270 
     271    /** 
     272     * Return text body Zend_Mime_Part or string 
     273     * 
     274     * @param  bool textOnly Whether to return just the body text content or the MIME part; defaults to false, the MIME part 
     275     * @return false|Zend_Mime_Part|string 
     276     */ 
     277    public function getBodyText($textOnly = false) 
     278    { 
     279        if ($textOnly && $this->_bodyText) { 
     280            $body = $this->_bodyText; 
     281            return $body->getContent(); 
     282        } 
     283 
     284        return $this->_bodyText; 
     285    } 
     286 
     287    /** 
     288     * Sets the HTML body for the message 
     289     * 
     290     * @param  string    $html 
     291     * @param  string    $charset 
     292     * @param  string    $encoding 
     293     * @return Zend_Mail Provides fluent interface 
     294     */ 
     295    public function setBodyHtml($html, $charset = null, $encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE) 
     296    { 
     297        if ($charset === null) { 
     298            $charset = $this->_charset; 
     299        } 
     300 
     301        $mp = new Zend_Mime_Part($html); 
     302        $mp->encoding = $encoding; 
     303        $mp->type = Zend_Mime::TYPE_HTML; 
     304        $mp->disposition = Zend_Mime::DISPOSITION_INLINE; 
     305        $mp->charset = $ch