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
1 1 <?php 2 3 // sets locale for dates, always use UTF-8! 4 setlocale(LC_TIME, 'en_US.UTF-8'); 5 2 6 $translations = array( 3 7 'General_Unknown' => 'Unknown', 4 8 '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… 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', 10 30 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
2 2 $translations = array( 3 3 'General_Unknown' => 'Inconnu', 4 4 '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 11 5 ); -
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
2 2 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 3 3 4 4 <a name="evolutionGraph" graphId="VisitFrequencygetLastVisitsReturningGraph"></a> 5 <h2> Evolution over the period</h2>5 <h2>{'VisitFrequency_Evolution'|translate}</h2> 6 6 {$graphEvolutionVisitFrequency} 7 7 8 8 {include file=VisitFrequency/sparklines.tpl} 9 9 10 {postEvent name="template_footerVisitsFrequency"} 11 brakuje znaku koÅca linii na koÅcu pliku 10 {postEvent name="template_footerVisitsFrequency"} -
plugins/VisitFrequency/VisitFrequency.php
18 18 public function getInformation() 19 19 { 20 20 $info = array( 21 'name' => 'Visit orFrequency',21 'name' => 'VisitFrequency', 22 22 'description' => 'VisitorFrequency', 23 23 'author' => 'Piwik', 24 24 'homepage' => 'http://piwik.org/', 25 25 'version' => '0.1', 26 'translationAvailable' => true 26 27 ); 27 28 28 29 return $info; 29 30 } 30 31 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 31 40 function getListHooksRegistered() 32 41 { 33 42 $hooks = array( … … 87 96 } 88 97 } 89 98 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
1 1 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
270 270 271 271 if($nbSites == 1) 272 272 { 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")); 275 274 } 276 275 277 276 $db = Zend_Registry::get('db'); … … 300 299 if(!is_array($urls) 301 300 || count($urls) == 0) 302 301 { 303 throw new Exception( "You must specify at least one URL for the site.");302 throw new Exception(Piwik_TranslateException("SitesManager_ExceptionNoUrl")); 304 303 } 305 304 } 306 305 … … 477 476 { 478 477 if(empty($siteName)) 479 478 { 480 throw new Exception( "The site name can't be empty.");479 throw new Exception(Piwik_TranslateException("SitesManager_ExceptionEmptyName")); 481 480 } 482 481 } 483 482 … … 493 492 { 494 493 if(!self::isValidUrl($url)) 495 494 { 496 throw new Exception( "The url '$url' is not a valid URL.");495 throw new Exception(sprintf(Piwik_TranslateException("SitesManager_ExceptionInvalidUrl"),$url)); 497 496 } 498 497 } 499 498 } -
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
24 24 'author' => 'Piwik', 25 25 'homepage' => 'http://piwik.org/', 26 26 'version' => '0.1', 27 'translationAvailable' => false,27 'translationAvailable' => true, 28 28 ); 29 29 30 30 return $info; 31 31 } 32 32 33 function postLoad() 34 { 35 Piwik_AddAdminMenu(Piwik_Translate('SitesManager_MenuSites'), array('module' => 'SitesManager')); 36 } 33 37 } 34 38 35 Piwik_AddAdminMenu('Sites', array('module' => 'SitesManager'));36 -
plugins/SitesManager/Controller.php
39 39 40 40 echo $view->render(); 41 41 } 42 } 43 brakuje znaku koÅca linii na koÅcu pliku 42 } -
plugins/SitesManager/templates/SitesManager.tpl
1 {loadJavascriptTranslations modules='SitesManager'} 2 1 3 <script type="text/javascript" src="plugins/SitesManager/templates/SitesManager.js"></script> 2 4 3 <h2> Sites</h2>5 <h2>{'SitesManager_Sites'|translate}</h2> 4 6 <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> 6 8 7 9 {if $sites|@count == 0} 8 You don't have any website to administrate.10 {'SitesManager_NoWebsites'|translate} 9 11 {else} 10 12 <table id="editSites" border=1 cellpadding="10"> 11 13 <thead> 12 14 <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> 16 18 <th> </th> 17 19 <th> </th> 18 <th> Javascript code</th>20 <th> {'SitesManager_JsCode'|translate} </th> 19 21 </tr> 20 22 </thead> 21 23 <tbody> … … 25 27 <td id="siteName" class="editableSite">{$site.name}</td> 26 28 <td id="urls" class="editableSite">{foreach from=$site.alias_urls item=url}{$url}<br>{/foreach}</td> 27 29 <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> 30 32 </tr> 31 33 {/foreach} 32 34 33 35 </tbody> 34 36 </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> 36 38 {/if} 37 39 -
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> 2 2 3 3 <code> 4 4 {$jsTag} -
plugins/SitesManager/templates/SitesManager.js
108 108 var idRow = $(this).attr('id'); 109 109 var nameToDelete = $(this).parent().parent().find('#siteName').html(); 110 110 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+')')) ) 112 112 { 113 113 $.ajax( getDeleteSiteAJAX( idsiteToDelete ) ); 114 114 } -
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 */ 18 class 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 12 class 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
20 20 'author' => 'Piwik', 21 21 'homepage' => 'http://piwik.org/', 22 22 'version' => '0.1', 23 'translationAvailable' => true, 23 24 ); 24 25 } 25 26 -
plugins/Dashboard/templates/Dashboard.js
1 2 3 //label and string used in the javascript4 //overide this object for dataTable_translation5 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 16 1 //there is a problem with loop for-in when we extends javascript Array 17 2 //so I prefer using a separate function to do this 18 3 function contains(array, searchElem) { … … 158 143 //format the div for upcomming ajax loading and set a temporary content 159 144 $(this) .attr('plugin', plugin) 160 145 .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(); 162 147 self.dashboard.ajaxLoading(plugin, action); 163 148 } 164 149 }); … … 208 193 if(contains(widgets, plugin+'.'+action)) 209 194 { 210 195 $(this).addClass('menuDisabled'); 211 $(this).attr('title', dashboard_translation.titleWidgetInDashboard);196 $(this).attr('title', _pk_translate('Dashboard_TitleWidgetInDashboard','Widget already in dashboard')); 212 197 } 213 198 else 214 199 { 215 200 $(this).removeClass('menuDisabled'); 216 $(this).attr('title', dashboard_translation.titleClickToAdd);201 $(this).attr('title', _pk_translate('Dashboard_TitleClickToAdd','Click to add to dashboard')); 217 202 } 218 203 }); 219 204 }, … … 343 328 if(typeof onTop == "undefined") 344 329 onTop = false; 345 330 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>'; 347 332 348 333 if(onTop) 349 334 { … … 390 375 { 391 376 var self = this; 392 377 393 var title = dashboard_translation.widgetNotFound;378 var title = _pk_translate('Dashboard_WidgetNotFound','Widget not found'); 394 379 var widgets = piwik.availableWidgets[plugin]; 395 380 for(var i in widgets) 396 381 { -
plugins/Dashboard/templates/index.tpl
1 {loadJavascriptTranslations modules='Home Dashboard'} 2 1 3 <script type="text/javascript"> 2 4 {* define some global constants for the following javascript includes *} 3 5 var piwik = new Object; … … 22 24 23 25 <div class="dialog" id="confirm"> 24 26 <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}"/> 28 30 </div> 29 31 30 32 <div class="button" id="addWidget"> 31 Add a widget...33 {'Dashboard_AddWidget'|translate} 32 34 </div> 33 35 34 36 <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> 37 39 <div class="subMenu" id="sub1"> 38 40 </div> 39 41 … … 42 44 43 45 <div class="subMenu" id="sub3"> 44 46 <div class="widget"> 45 <div class="handle" title=" Add previewed widget to the dashboard">47 <div class="handle" title="{'Dashboard_AddPreviewedWidget'|translate}"> 46 48 <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}"/> 48 50 </div> 49 <div class="widgetTitle"> Widget preview</div>51 <div class="widgetTitle">{'Dashboard_WidgetPreview'|translate}</div> 50 52 </div> 51 53 <div class="widgetDiv previewDiv"></div> 52 54 </div> -
plugins/Dashboard/templates/header.tpl
1 1 {* This header is for loading the dashboard in stand alone mode*} 2 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> 3 3 4 {loadJavascriptTranslations modules='Home Dashboard'} 5 4 6 <script type="text/javascript" src="libs/jquery/jquery.js"></script> 5 7 6 8 <script type="text/javascript" src="themes/default/common.js"></script> … … 20 22 <script type="text/javascript" src="libs/jquery/ui.sortable_modif.js"></script> 21 23 22 24 <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
37 37 { 38 38 if(($currentLogin = Piwik::getCurrentUserLogin()) != 'anonymous') 39 39 { 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 /> <b><a href='?module=Login&action=logout'>› Logout from Piwik</a></b><br />"); 40 Piwik_ExitWithMessage( sprintf(Piwik_Translate('Home_NoPrivileges'),$currentLogin). 41 "<br /><br /> <b><a href='?module=Login&action=logout'>› ".Piwik_Translate('General_Logout')."</a></b><br />"); 43 42 } 44 43 else 45 44 { … … 54 53 // date 55 54 $view->date = $this->strDate; 56 55 $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')); 58 57 59 58 // period 60 59 $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 ); 62 68 63 69 $found = array_search($currentPeriod,$otherPeriodsAvailable); 64 70 if($found !== false) … … 68 74 69 75 $view->period = $currentPeriod; 70 76 $view->otherPeriods = $otherPeriodsAvailable; 77 $view->periodsNames = $otherPeriodsNames; 71 78 72 79 // other 73 80 $view->idSite = Piwik_Common::getRequestVar('idSite'); … … 117 124 118 125 119 126 120 } 121 brakuje znaku koÅca linii na koÅcu pliku 127 } -
plugins/Home/templates/datatable.tpl
3 3 {$arrayDataTable.message} 4 4 {else} 5 5 {if count($arrayDataTable) == 0} 6 <div id="emptyDatatable"> No data for this table.</div>6 <div id="emptyDatatable">{'Home_TableNoData'|translate}</div> 7 7 {else} 8 8 <a name="{$id}"></a> 9 9 <table cellspacing="0" class="dataTable"> 10 10 <thead> 11 11 <tr> 12 12 {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> 14 14 {/foreach} 15 15 </tr> 16 16 </thead> -
plugins/Home/templates/period_select.tpl
1 1 <div id="periodString"> 2 2 <span id="date"><img src='plugins/Home/templates/images/more_date.gif' style="vertical-align:middle"> {$prettyDate}</span> - 3 3 <span id="periods"> 4 <span id="currentPeriod">{$period |ucfirst}</span>4 <span id="currentPeriod">{$periodsNames.$period}</span> 5 5 <span id="otherPeriods"> 6 6 {foreach from=$otherPeriods item=thisPeriod} 7 | <a href='{url period=$thisPeriod}'>{$ thisPeriod|ucfirst}</a>7 | <a href='{url period=$thisPeriod}'>{$periodsNames.$thisPeriod}</a> 8 8 {/foreach} 9 9 </span> 10 10 </span> 11 11 <span id="calendar"></span> 12 12 </div> 13 13 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"> 1 3 <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
144 144 prevText: "", 145 145 nextText: "", 146 146 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')], 148 169 }, 149 170 currentDate); 150 171 } -
plugins/Home/templates/datatable_actions_subdatable.tpl
3 3 {$arrayDataTable.message} 4 4 {else} 5 5 {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> 7 7 {else} 8 8 {foreach from=$arrayDataTable item=row} 9 9 <tr {if $row.idsubdatatable}class="subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable"{/if}> … … 16 16 </tr> 17 17 {/foreach} 18 18 {/if} 19 {/if} 20 brakuje znaku koÅca linii na koÅcu pliku 19 {/if} -
plugins/Home/templates/datatable_actions_recursive.tpl
3 3 {$arrayDataTable.message} 4 4 {else} 5 5 {if count($arrayDataTable) == 0} 6 <div id="emptyDatatable"> No data for this table.</div>6 <div id="emptyDatatable">{'Home_TableNoData'|translate}</div> 7 7 {else} 8 8 <table cellspacing="0" class="dataTable dataTableActions"> 9 9 <thead> 10 10 <tr> 11 11 {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> 13 13 {/foreach} 14 14 </tr> 15 15 </thead> … … 41 41 {include file="Home/templates/datatable_actions_js.tpl"} 42 42 43 43 {/if} 44 </div> 45 brakuje znaku koÅca linii na koÅcu pliku 44 </div> -
plugins/Home/templates/menu.css
24 24 border-left: 1px solid #fff; 25 25 float: left; 26 26 list-style: none; 27 z-index: 999;27 z-index: 49; 28 28 } 29 29 30 30 .nav li.current ul { 31 z-index: 999;31 z-index: 49; 32 32 } 33 33 34 34 .nav li.sfHover ul,ul.nav li:hover ul { 35 z-index: 1000;35 z-index: 50; 36 36 } 37 37 38 38 /* LEVEL2 NORMAL */ … … 108 108 when and how it appears*/ 109 109 .superfish li:hover ul,.superfish li li:hover ul { 110 110 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 javascript3 //overide this object for dataTable_translation4 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_ 4210 loading: 'Loading...'11 };12 }13 14 1 //----------------------------------------------------------------------------- 15 2 // Data Table 16 3 //----------------------------------------------------------------------------- … … 281 268 { 282 269 if(Number(self.param.filter_excludelowpop) != 0) 283 270 { 284 string = dataTable_translation.includeLowPop;271 string = _pk_translate('Home_IncludeAllPopulation','Include all population'); 285 272 } 286 273 else 287 274 { 288 string = dataTable_translation.excludeLowPop;275 string = _pk_translate('Home_ExcludeLowPopulation','Exclude low population'); 289 276 } 290 277 $(this).html(string); 291 278 } … … 423 410 // only show this string if there is some rows in the datatable 424 411 if(totalRows != 0) 425 412 { 426 var str = offset + '-' + offsetEndDisp + dataTable_translation.pageOf + totalRows;413 var str = sprintf(_pk_translate('Home_PageOf','%s of %s'),offset + '-' + offsetEndDisp,totalRows); 427 414 $(this).text(str); 428 415 } 429 416 } … … 631 618 <tr>\ 632 619 <td colspan="'+numberOfColumns+'" class="cellSubDataTable">\ 633 620 <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>\ 635 622 </div>\ 636 623 </td>\ 637 624 </tr>\ … … 999 986 $('img',domElem).attr('src', 'themes/default/images/plus.png'); 1000 987 } 1001 988 1002 1003 brakuje znaku koÅca linii na koÅcu pliku 989 -
plugins/Home/templates/datatable_footer.tpl
7 7 </span> 8 8 9 9 <span id="dataTablePages"></span> 10 <span id="dataTablePrevious">< Previous</span>11 <span id="dataTableNext"> Next></span>10 <span id="dataTablePrevious">< {'General_Previous'|translate}</span> 11 <span id="dataTableNext">{'General_Next'|translate} ></span> 12 12 <div> 13 13 <span id="exportDataTable"> 14 14 <span id="exportToFormat" style="display:none"> … … 19 19 <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="JSON" filter_limit="100">Json</a> | 20 20 <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="PHP" filter_limit="100">Php</a> 21 21 </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> 26 26 </span> 27 27 <span id="exportDataTableShow" style="display:none"> 28 28 <img src="plugins/Home/templates/images/more.png" /> 29 29 </span> 30 30 </span> 31 31 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> 33 33 </div> 34 34 </div> 35 35 -
plugins/Home/templates/datatable_actions.tpl
3 3 {$arrayDataTable.message} 4 4 {else} 5 5 {if count($arrayDataTable) == 0} 6 <div id="emptyDatatable"> No data for this table.</div>6 <div id="emptyDatatable">{'Home_TableNoData'|translate}</div> 7 7 {else} 8 8 <table cellspacing="0" class="dataTable dataTableActions"> 9 9 <thead> -
plugins/Home/templates/graph.tpl
6 6 <form class="formEmbedCode" id="{$formId}"> 7 7 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"> 8 8 9 | <a target="_blank" href="{$urlData}"> Graph data</a>9 | <a target="_blank" href="{$urlData}">{'General_GraphData'|translate}</a> 10 10 </form> 11 11 12 12 {include file="Home/templates/datatable_footer.tpl"} -
plugins/Home/templates/index.tpl
4 4 </head> 5 5 <body> 6 6 7 {loadJavascriptTranslations modules='Home'} 7 8 8 9 <script type="text/javascript"> 9 10 var period = "{$period}"; … … 174 175 /* style for the date picking */ 175 176 #periodString { 176 177 margin-left:350px; 177 margin-top:10px;178 178 } 179 179 180 180 #periodString #date, #periodString #periods, … … 265 265 font-weight:bold; 266 266 color:#F88D22; 267 267 } 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 }305 268 </style> 306 269 {/literal} 307 270 … … 320 283 {/foreach} 321 284 </optgroup> 322 285 </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> 324 287 </small> 325 288 </form> 326 289 </span> 327 290 328 291 <span id="h1"><a href='http://piwik.org'>Piwik</a> </span><span id="subh1"> # open source web analytics</span><br> 329 292 <br> 330 293 <div id="stuff"> 331 294 <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> 336 296 {include file="Home/templates/links_misc_modules.tpl"} 337 297 </div> 338 298 </div> … … 340 300 341 301 <noscript> 342 302 <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>'} 346 304 </span> 347 305 </noscript> 348 306 {include file="Home/templates/period_select.tpl"} 349 307 350 <br> 308 <br><br> 351 309 {include file="Home/templates/menu.tpl"} 352 310 353 311 <div style='clear:both'></div> 354 312 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… 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> 357 315 <div id='content'> 358 316 {if $content}{$content}{/if} 359 317 </div> -
plugins/Home/Home.php
20 20 'author' => 'Piwik', 21 21 'homepage' => 'http://piwik.org/', 22 22 'version' => '0.1', 23 'translationAvailable' => false,23 'translationAvailable' => true, 24 24 ); 25 25 } 26 26 } -
plugins/Provider/Provider.php
23 23 'author' => 'Piwik', 24 24 'homepage' => 'http://piwik.org/', 25 25 'version' => '0.1', 26 'translationAvailable' => true, 26 27 'LogStatsPlugin' => true, // this plugin must be loaded during the stats logging 27 28 ); 28 29 … … 48 49 Zend_Registry::get('db')->query($query); 49 50 } 50 51 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 51 65 function getListHooksRegistered() 52 66 { 53 67 $hooks = array( … … 166 180 } 167 181 } 168 182 169 // when the plugin is loaded during LogStats these functions are not defined170 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
15 15 { 16 16 return array( 17 17 // name must be the className prefix! 18 'name' => 'Plugins administration',18 'name' => 'PluginsAdmin', 19 19 'description' => '', 20 20 'author' => 'Piwik', 21 21 'homepage' => 'http://piwik.org/', 22 22 'version' => '0.1', 23 'translationAvailable' => false,23 'translationAvailable' => true, 24 24 ); 25 25 } 26 27 function postLoad() 28 { 29 Piwik_AddAdminMenu(Piwik_Translate('PluginsAdmin_MenuPlugins'), array('module' => 'PluginsAdmin')); 30 } 26 31 } 27 32 28 33 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
20 20 <td>{$plugin.info.description} </td> 21 21 <td class="center"><a href="{$plugin.info.homepage}">{$plugin.info.author}</a></td> 22 22 <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> 25 25 </tr> 26 26 {/foreach} 27 27 -
plugins/Widgetize/templates/iframe.tpl
1 1 <html> 2 2 <body> 3 3 4 {loadJavascriptTranslations modules='Home'} 5 4 6 <script type="text/javascript" src="libs/jquery/jquery.js"></script> 5 7 <script type="text/javascript" src="themes/default/common.js"></script> 6 8 <script type="text/javascript" src="libs/jquery/jquery.dimensions.js"></script> … … 16 18 {$content} 17 19 18 20 </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 1 3 document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.js"><\/scr'+'ipt>'); 2 4 document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}themes/default/common.js"><\/scr'+'ipt>'); 3 5 document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.dimensions.js"><\/scr'+'ipt>'); … … 11 13 document.write('<link rel="stylesheet" href="{$piwikUrl}plugins/Home/templates/datatable.css">'); 12 14 13 15 var content = '{$content|escape:'javascript'}'; 14 document.write(content); 15 brakuje znaku koÅca linii na koÅcu pliku 16 document.write(content); -
plugins/UsersManager/API.php
185 185 return $user; 186 186 } 187 187 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 188 207 static private function checkLogin($userLogin) 189 208 { 190 209 if(self::userExists($userLogin)) 191 210 { 192 throw new Exception( "Login $userLogin already exists.");211 throw new Exception(sprintf(Piwik_TranslateException('UsersManager_ExceptionLoginExists'),$userLogin)); 193 212 } 194 213 195 214 if(!self::isValidLoginString($userLogin)) 196 215 { 197 throw new Exception( "The login must contain only letters, numbers, or the characters '_' or '-' or '.'");216 throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLogin')); 198 217 } 199 218 } 200 219 … … 202 221 { 203 222 if(!self::isValidPasswordString($password)) 204 223 { 205 throw new Exception( "The password length must be between 6 and 26 characters.");224 throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidPassword')); 206 225 } 207 226 } 208 227 … … 210 229 { 211 230 if(!Piwik::isValidEmailString($email)) 212 231 { 213 throw new Exception( "The email doesn't have a valid format.");232 throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidEmail')); 214 233 } 215 234 } 216 235 … … 343 362 344 363 if(!self::userExists($userLogin)) 345 364 { 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)); 347 366 } 348 367 349 368 … … 364 383 WHERE login = ?", $userLogin); 365 384 return $count != 0; 366 385 } 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 } 367 401 368 402 /** 369 403 * Set an access level to a given user for a list of websites ID. … … 389 423 if($userLogin == 'anonymous' 390 424 && $access == 'admin') 391 425 { 392 throw new Exception( "You cannot grant 'admin' access to the 'anonymous' user.");426 throw new Exception(Piwik_TranslateException("UsersManager_ExceptionAdminAnonymous")); 393 427 } 394 428 395 429 // in case idSites is null we grant access to all the websites on which the current connected user … … 441 475 { 442 476 if(!self::userExists($userLogin)) 443 477 { 444 throw new Exception( "User '$userLogin' doesn't exist.");478 throw new Exception(sprintf(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist"),$userLogin)); 445 479 } 446 480 } 447 481 … … 449 483 { 450 484 if($userLogin == 'anonymous') 451 485 { 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")); 453 487 } 454 488 } 455 489 … … 462 496 463 497 if(!in_array($access,$accessList)) 464 498 { 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))); 466 500 } 467 501 } 468 502 … … 550 584 return $l >= 6 && $l <= 26; 551 585 } 552 586 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
19 19 { 20 20 $info = array( 21 21 // name must be the className prefix! 22 'name' => 'User Manager',22 'name' => 'UsersManager', 23 23 'description' => 'Description', 24 24 'author' => 'Piwik', 25 25 'homepage' => 'http://piwik.org/', 26 26 'version' => '0.1', 27 'translationAvailable' => false,27 'translationAvailable' => true, 28 28 ); 29 29 30 30 return $info; 31 31 } 32 32 33 function postLoad() 34 { 35 Piwik_AddAdminMenu(Piwik_Translate('UsersManager_MenuUsers'), array('module' => 'UsersManager')); 36 } 33 37 } 34 38 35 Piwik_AddAdminMenu('Users', array('module' => 'UsersManager'));36 37 -
plugins/UsersManager/templates/UsersManager.js
222 222 ajaxHideError(); 223 223 var idRow = $(this).attr('id'); 224 224 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+'"')) ) 226 226 { 227 227 $.ajax( getDeleteUserAJAX( loginToDelete ) ); 228 228 } -
plugins/UsersManager/templates/UsersManager.tpl
1 {loadJavascriptTranslations modules='UsersManager'} 1 2 <script type="text/javascript" src="libs/jquery/jquery.js"></script> 2 3 <script type="text/javascript" src="themes/default/common.js"></script> 3 4 <link rel="stylesheet" href="themes/default/common-admin.css"> … … 18 19 </style> 19 20 {/literal} 20 21 21 <h2> Manage access</h2>22 <h2>{'UsersManager_ManageAccess'|translate}</h2> 22 23 23 24 <div id="sites"> 24 25 <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()"> 26 27 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> 29 30 </optgroup> 30 <optgroup label=" Sites">31 <optgroup label="{'UsersManager_Sites'|translate}"> 31 32 {foreach from=$websites item=info} 32 33 <option value="{$info.idsite}" {if $idSiteSelected==$info.idsite} selected="selected"{/if}>{$info.name}</option> 33 34 {/foreach} … … 40 41 <table id="access"> 41 42 <thead> 42 43 <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> 47 48 </tr> 48 49 </thead> 49 50 … … 61 62 </tbody> 62 63 </table> 63 64 64 <div id="accessUpdated"> Done!</div>65 <div id="accessUpdated">{'General_Done'|translate}!</div> 65 66 66 67 <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}"/> 70 71 </div> 71 72 72 73 <h2>Manage users</h2> 73 74 74 75 <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> 76 77 <table id="users"> 77 78 <thead> 78 79 <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> 86 87 </tr> 87 88 </thead> 88 89 … … 103 104 </tbody> 104 105 </table> 105 106 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> 107 108 <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
38 38 'author' => 'Piwik', 39 39 'homepage' => 'http://piwik.org/', 40 40 'version' => '0.1', 41 'translationAvailable' => true, 41 42 ); 42 43 43 44 return $info; 44 45 } 45 46 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 46 60 function getListHooksRegistered() 47 61 { 48 62 $hooks = array( … … 204 218 return strlen($value) > 5; 205 219 } 206 220 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
1 1 <div id='leftcolumn'> 2 <h2> Browser families</h2>2 <h2>{'UserSettings_BrowserFamilies'|translate}</h2> 3 3 {$dataTableBrowserType} 4 4 5 <h2> Browsers</h2>5 <h2>{'UserSettings_Browsers'|translate}</h2> 6 6 {$dataTableBrowser} 7 7 8 <h2> Plugins</h2>8 <h2>{'UserSettings_Plugins'|translate}</h2> 9 9 {$dataTablePlugin} 10 10 </div> 11 11 12 12 <div id='rightcolumn'> 13 <h2> Configurations</h2>13 <h2>{'UserSettings_Configurations'|translate}</h2> 14 14 {$dataTableConfiguration} 15 15 16 <h2> Operating systems</h2>16 <h2>{'UserSettings_OperatinsSystems'|translate}</h2> 17 17 {$dataTableOS} 18 18 19 <h2> Resolutions</h2>19 <h2>{'UserSettings_Resolutions'|translate}</h2> 20 20 {$dataTableResolution} 21 21 22 <h2> Wide Screen</h2>22 <h2>{'UserSettings_WideScreen'|translate}</h2> 23 23 {$dataTableWideScreen} 24 24 </div> 25 25 -
plugins/UserSettings/Controller.php
114 114 115 115 return $this->renderView($view, $fetch); 116 116 } 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
19 19 { 20 20 $info = array( 21 21 // name must be the className prefix! 22 'name' => ' Piwik_VisitsSummary',22 'name' => 'VisitsSummary', 23 23 'description' => 'Description', 24 24 'author' => 'Piwik', 25 25 'homepage' => 'http://piwik.org/', 26 26 'version' => '0.1', 27 'translationAvailable' => false,27 'translationAvailable' => true, 28 28 ); 29 29 30 30 return $info; 31 31 } 32 32 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 } 33 42 } 34 43 35 44 require_once "ViewDataTable.php"; … … 122 131 return $this->renderView($view, $fetch); 123 132 } 124 133 125 } 134 } 126 135 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
1 1 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 2 2 3 3 <a name="evolutionGraph" graphId="VisitsSummarygetLastVisitsGraph"></a> 4 <h2> Evolution on the last 30 {$period}s</h2>4 <h2>{'VisitsSummary_Evolution'|translate:$period}</h2> 5 5 {$graphEvolutionVisitsSummary} 6 6 7 <h2> Report</h2>7 <h2>{'VisitsSummary_Report'|translate}</h2> 8 8 {include file=VisitsSummary/sparklines.tpl} 9 9 10 10 11 11 <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
1 1 <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
66 66 public function getDownloads( $idSite, $period, $date, $expanded = false, $idSubtable = false ) 67 67 { 68 68 $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;'))); 70 70 $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromActionsUrl')); 71 71 $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncateActionsPath')); 72 72 … … 76 76 public function getOutlinks( $idSite, $period, $date, $expanded = false, $idSubtable = false ) 77 77 { 78 78 $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;'))); 80 80 $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromActionsUrl')); 81 81 $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncateActionsPath')); 82 82 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
37 37 'author' => 'Piwik', 38 38 'homepage' => 'http://piwik.org/', 39 39 'version' => '0.1', 40 'translationAvailable' => true 40 41 ); 41 42 42 43 return $info; … … 49 50 function uninstall() 50 51 { 51 52 } 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 53 65 function getListHooksRegistered() 54 66 { 55 67 $hooks = array( … … 282 294 $currentTable = new Piwik_DataTable_Row( 283 295 array( Piwik_DataTable_Row::COLUMNS => 284 296 array( 'label' => (string)$actionName, 297 'full_url' => (string)$row['name'], 285 298 ) 286 299 ) 287 300 ); … … 330 343 331 344 return $rowsProcessed; 332 345 } 333 334 346 } 335 347 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> » 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 > 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
29 29 'author' => 'Piwik', 30 30 'homepage' => 'http://piwik.org/', 31 31 'version' => '0.1', 32 'translationAvailable' => false,32 'translationAvailable' => true, 33 33 ); 34 34 35 35 return $info; … … 67 67 } 68 68 else 69 69 { 70 Piwik::exitWithErrorMessage(" 71 The Piwik configuration file couldn't be found and you are trying to access a Piwik page.<br> 72 <b> » 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')); 75 71 } 76 72 exit; 77 73 } 78 } 79 brakuje znaku koÅca linii na koÅcu pliku 74 } -
plugins/Installation/templates/systemCheck.tpl
2 2 {assign var=error value="<img src='themes/default/images/error.png' />"} 3 3 {assign var=warning value="<img src='themes/default/images/warning.png' />"} 4 4 5 <h1> System check</h1>5 <h1>{'Installation_SystemCheck'|translate}</h1> 6 6 7 7 8 8 <table class="infosServer"> 9 9 <tr> 10 <td class="label"> PHP version> {$infos.phpVersion_minimum}</td>10 <td class="label">{'Installation_SystemCheckPhp'|translate} > {$infos.phpVersion_minimum}</td> 11 11 <td>{if $infos.phpVersion_ok}{$ok}{else}{$error}{/if}</td> 12 12 </tr><tr> 13 <td class="label"> Pdo extension</td>13 <td class="label">{'Installation_SystemCheckPdo'|translate}</td> 14 14 <td>{if $infos.pdo_ok}{$ok} 15 15 {else}{$error}{/if} 16 16 </td> 17 17 </tr> 18 18 <tr> 19 <td class="label"> Pdo_Mysql extension</td>19 <td class="label">{'Installation_SystemCheckPdoMysql'|translate}</td> 20 20 <td>{if $infos.pdo_mysql_ok}{$ok} 21 21 {else}{$error} 22 22 {/if} 23 23 24 24 {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} 27 26 <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} 36 29 </small> 37 30 </p> 38 31 {/if} … … 42 35 43 36 {* We don't use utf8_encode currently but I think we will soon so I leave the code here 44 37 <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> 46 39 <td>{if $infos.phpXml_ok}{$ok}{else}{$error}{/if}</td> 47 40 </tr> 48 41 *} 49 42 <tr> 50 43 <td valign="top"> 51 Directories with write access44 {'Installation_SystemCheckWriteDirs'|translate} 52 45 </td> 53 46 <td> 54 47 {foreach from=$infos.directories key=dir item=bool} … … 64 57 {if $problemWithSomeDirectories} 65 58 <br> 66 59 <div class="error"> 67 To fix this error on your Linux system, try typing in the following command(s):60 {'Installation_SystemCheckWriteDirsHelp'|translate}: 68 61 {foreach from=$infos.directories key=dir item=bool} 69 62 <ul>{if !$bool} 70 63 <li>chmod a+w {$basePath}{$dir}</li> … … 77 70 <h1>Optional</h1> 78 71 <table class="infos"> 79 72 <tr> 80 <td class="label"> Memory limit</td>73 <td class="label">{'Installation_SystemCheckMemoryLimit'|translate}</td> 81 74 <td> 82 75 {$infos.memoryCurrent} 83 76 {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} 86 78 </td> 87 79 </tr> 88 80 <tr> 89 <td class="label"> GD > 2.x (graphics)</td>81 <td class="label">{'Installation_SystemCheckGD'|translate}</td> 90 82 <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} 92 84 </td> 93 85 </tr> 94 86 <tr> 95 <td class="label"> set_time_limit() allowed</td>87 <td class="label">{'Installation_SystemCheckTimeLimit'|translate}</td> 96 88 <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> 99 90 </tr> 100 91 <tr> 101 <td class="label"> mail() allowed</td>92 <td class="label">{'Installation_SystemCheckMail'|translate}</td> 102 93 <td>{if $infos.mail_ok}{$ok}{else}{$warning}{/if}</td> 103 94 </tr> 104 95 </table> 105 96 <p><small> 106 97 Legend: 107 98 <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> 111 102 </small></p> 112 103 113 104 {if !$showNextStep} 114 105 <p class="nextStep"> 115 <a href="{url}"> Refresh the page»</a>106 <a href="{url}">{'General_Refresh'|translate} »</a> 116 107 </p> 117 108 118 109 {/if} -
plugins/Installation/templates/databaseSetup.tpl
1 <h1> Mysql database setup</h1>1 <h1>{'Installation_MysqlSetup'|translate}</h1> 2 2 3 3 {if isset($errorMessage)} 4 4 <div class="error"> 5 5 <img src="themes/default/images/error_medium.png"> 6 Error while trying to connect to the Mysql database:6 {'Installation_MysqlErrorConnect'|translate}: 7 7 <br>{$errorMessage} 8 8 9 9 </div> … … 11 11 12 12 {if isset($form_data)} 13 13 {include file=default/genericForm.tpl} 14 {/if} 15 brakuje znaku koÅca linii na koÅcu pliku 14 {/if} -
plugins/Installation/templates/displayJavascriptCode.tpl
31 31 <img src="themes/default/images/success_medium.png"> 32 32 </span> 33 33 {/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} 38 36 <code> 39 37 {$javascriptTag} 40 38 </code> -
plugins/Installation/templates/finished.tpl
1 <h1> Congratulations</h1>1 <h1>{'Installation_Congratulations'|translate}</h1> 2 2 3 <p>Congratulations! Your Piwik installation is complete.</p> 3 {'Installation_ContratulationsHelp'|translate} 4 4 5 <p>Make sure your javascript code is entered on your pages,6 and wait for your first visitors!</p>7 5 8 9 6 <p class="nextStep"> 10 <a href="{url module='' action=''}"> Go to Piwik»</a>7 <a href="{url module='' action=''}">{'Installation_GoToPiwik'|translate} »</a> 11 8 </p> -
plugins/Installation/templates/firstWebsiteSetup.tpl
2 2 3 3 {if isset($displayGeneralSetupSuccess)} 4 4 <span id="toFade" class="success"> 5 General Setup configured with success5 {'Installation_GeneralSetupSuccess'|translate} 6 6 <img src="themes/default/images/success_medium.png"> 7 7 </span> 8 8 {/if} 9 9 10 <h1> Setup a website</h1>10 <h1>{'Installation_SetupWebsite'|translate}</h1> 11 11 12 12 13 13 14 14 {if isset($errorMessage)} 15 15 <div class="error"> 16 16 <img src="themes/default/images/error_medium.png"> 17 There was an error when adding the website:17 {'Installation_SetupWebsiteError'|translate}: 18 18 <br>- {$errorMessage} 19 19 20 20 </div> … … 23 23 24 24 {if isset($form_data)} 25 25 {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> 3 2 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> 2 2 3 3 {if isset($form_data)} 4 4 {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> 2 2 {if isset($someTablesInstalled)} 3 <div class="warning"> Some <span id="linkToggle">Piwik tables</span> are already installed in the DB3 <div class="warning">{'Installation_TablesWarning'|translate} 4 4 <img src="themes/default/images/warning_medium.png"> 5 5 </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}: 7 7 <br>{$tablesInstalled} </i></small></div> 8 8 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> 11 10 12 <p class="nextStep"><a href="{url action=$nextModuleName}"> Reuse the existing tables»</a></p>13 <p class="nextStep" id="eraseAllTables"><a href="{url deleteTables=1}"> Delete the detected tables»</a></p>11 <p class="nextStep"><a href="{url action=$nextModuleName}">{'Installation_TablesReuse'|translate} »</a></p> 12 <p class="nextStep" id="eraseAllTables"><a href="{url deleteTables=1}">{'Installation_TablesDelete'|translate} »</a></p> 14 13 15 14 {/if} 16 15 17 16 {if isset($existingTablesDeleted)} 18 <div class="success"> Existing Piwik tables deleted with success17 <div class="success"> {'Installation_TablesDeletedSuccess'|translate} 19 18 <img src="themes/default/images/success_medium.png"></div> 20 19 {/if} 21 20 22 21 23 22 {if isset($tablesCreated)} 24 <div class="success"> Tables created with success!23 <div class="success"> {'Installation_TablesCreatedSuccess'|translate} 25 24 <img src="themes/default/images/success_medium.png"></div> 26 25 {/if} 27 26 … … 32 31 {literal} 33 32 <script> 34 33 $(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} 36 37 37 38 // toggle the display of the tables detected during the installation when clicking 38 39 // on the span "linkToggle" … … 64 65 ; 65 66 }); 66 67 </script> 67 {/literal} 68 brakuje znaku koÅca linii na koÅcu pliku 68 {/literal} -
plugins/Installation/templates/structure.tpl
1 1 2 2 <html> 3 3 <head> 4 <title>Piwik » Installation</title>4 <title>Piwik » {'Installation_Installation'|translate}</title> 5 5 </head> 6 6 <body> 7 7 … … 194 194 {include file="$subTemplateToLoad"} 195 195 {if $showNextStep} 196 196 <p class="nextStep"> 197 <a href="{url action=$nextModuleName}"> Next»</a>197 <a href="{url action=$nextModuleName}">{'General_Next'|translate} »</a> 198 198 </p> 199 199 {/if} 200 200 </div> 201 201 202 202 <div class="both"></div> 203 203 204 <h3> Installation status</h3>204 <h3>{'Installation_InstallationStatus'|translate}</h3> 205 205 206 206 <div id="installPercent"> 207 207 <p style="width: {$percentDone}%;"></p> 208 208 </div> 209 209 210 { $percentDone}% Done210 {'Installation_PercentDone'|translate:$percentDone} 211 211 </div> -
plugins/AdminHome/templates/index.tpl
42 42 </div> 43 43 44 44 <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> 46 46 47 47 </div> -
plugins/UserCountry/lang/en.php
1 1 <?php 2 2 $translations = array ( 3 3 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 4 11 // Countries 5 12 'country_ac' => 'Ascension Islands', 6 13 'country_ad' => 'Andorra', -
plugins/UserCountry/index.tpl
2 2 3 3 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 4 4 5 <h2> Country</h2>5 <h2>{'UserCountry_Country'|translate}</h2> 6 6 {$dataTableCountry} 7 7 8 <h2> Continent</h2>8 <h2>{'UserCountry_Continent'|translate}</h2> 9 9 {$dataTableContinent} 10 10 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> 12 13 13 {postEvent name="template_footerUserCountry"} 14 brakuje znaku koÅca linii na koÅcu pliku 14 {postEvent name="template_footerUserCountry"} -
plugins/UserCountry/UserCountry.php
30 30 return $info; 31 31 } 32 32 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 33 41 function getListHooksRegistered() 34 42 { 35 43 $hooks = array( … … 140 148 141 149 } 142 150 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
11 11 12 12 require_once "UsersManager/API.php"; 13 13 require_once "Login/Form.php"; 14 require_once "Login/PasswordForm.php"; 14 15 require_once "View.php"; 15 16 16 17 … … 29 30 { 30 31 $form = new Piwik_Login_Form; 31 32 $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 33 38 if($form->validate()) 34 39 { 35 40 // value submitted in form … … 37 42 $password = $form->getSubmitValue('form_password'); 38 43 $password = md5($password); 39 44 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 46 45 $tokenAuth = Piwik_UsersManager_API::getTokenAuth($login, $password); 47 46 48 47 Piwik_Login::prepareAuthObject($login, $tokenAuth); … … 59 58 $cookie->set('token_auth', $tokenAuth); 60 59 $cookie->save(); 61 60 61 $urlToRedirect = htmlspecialchars_decode($urlToRedirect); 62 62 Piwik_Url::redirectToUrl($urlToRedirect); 63 63 } 64 64 else … … 66 66 $messageNoAccess = Piwik_Translate('Login_LoginPasswordNotCorrect'); 67 67 } 68 68 } 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; 70 72 $view->AccessErrorString = $messageNoAccess; 71 73 $view->linkTitle = Piwik::getRandomTitle(); 72 74 $view->addForm( $form ); … … 74 76 echo $view->render(); 75 77 } 76 78 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 77 148 function logout() 78 149 { 79 150 $authCookieName = 'piwik-auth'; -
plugins/Login/Form.php
26 26 27 27 function init() 28 28 { 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'); 30 31 31 32 // if the current url to redirect contains module=login we insteaed redirect to the referer url 32 33 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 12 require_once "modules/Form.php"; 13 14 /** 15 * 16 * @package Piwik_Login 17 */ 18 class 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
37 37 38 38 form p { margin-bottom: 24px; } 39 39 40 .updated, .login #login_error, .login .message { 41 background-color: #ffffe0; 42 border-color: #e6db55; 43 } 44 40 45 #login { width: 292px; margin: 7em auto; margin-top: 20px; } 41 46 42 #login_error {47 #login_error, .message { 43 48 margin: 0 0 16px 8px; 44 49 border-width: 1px; 45 50 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 › 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
27 27 {if $form_data.errors} 28 28 <div id="login_error"> 29 29 {foreach from=$form_data.errors item=data} 30 <strong> ERROR</strong>: {$data}<br />30 <strong>{'General_Error'|translate}</strong>: {$data}<br /> 31 31 {/foreach} 32 32 </div> 33 33 {/if} 34 34 35 35 {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> 37 37 {/if} 38 38 39 39 <form {$form_data.attributes}> 40 40 <p> 41 <label>{'Login_Login'|translate} <br />41 <label>{'Login_Login'|translate}:<br /> 42 42 <input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label> 43 43 </p> 44 44 45 45 <p> 46 <label>{'Login_Password'|translate} <br />46 <label>{'Login_Password'|translate}:<br /> 47 47 <input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label> 48 48 </p> 49 49 {* … … 55 55 </p> 56 56 </form> 57 57 58 {* 58 59 59 <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> 61 61 </p> 62 *} 62 63 63 </div> 64 64 65 65 </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 › 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
27 27 'author' => 'Piwik', 28 28 'homepage' => 'http://piwik.org/', 29 29 'version' => '0.1', 30 'translationAvailable' => false,30 'translationAvailable' => true, 31 31 ); 32 32 33 33 return $info; -
plugins/API/API.php
20 20 'author' => 'Piwik', 21 21 'homepage' => 'http://piwik.org/', 22 22 'version' => '0.1', 23 'translationAvailable' => false,23 'translationAvailable' => true, 24 24 ); 25 25 } 26 26 } -
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
56 56 { 57 57 $token_auth = Zend_Registry::get('auth')->getTokenAuth(); 58 58 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); 64 60 61 65 62 $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"; 67 64 68 65 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>"; 70 67 } 71 68 72 69 } -
plugins/Referers/lang/en.php
1 1 <?php 2 2 $translations = array( 3 'Referers_SearchEngines' => 'Search Engines', 4 5 'Referers_Keywords' => 'Keywords', 3 6 '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 9 40 ); 10 41 -
plugins/Referers/Referers.php
34 34 35 35 return $info; 36 36 } 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 } 37 53 38 54 function getListHooksRegistered() 39 55 { … … 302 318 } 303 319 } 304 320 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
1 1 <div id='leftcolumn'> 2 <h2> Search engines</h2>2 <h2>{'Referers_SearchEngines'|translate}</h2> 3 3 {$searchEngines} 4 4 </div> 5 5 6 6 <div id='rightcolumn'> 7 <h2> Keywords</h2>7 <h2>{'Referers_Keywords'|translate}</h2> 8 8 {$keywords} 9 9 </div> -
plugins/Referers/index.tpl
1 1 <script type="text/javascript" src="plugins/Home/templates/sparkline.js"></script> 2 2 3 3 <a name="evolutionGraph" graphId="{$nameGraphEvolutionReferers}"></a> 4 <h2> Evolution over the period</h2>4 <h2>{'Referers_Evolution'|translate}</h2> 5 5 {$graphEvolutionReferers} 6 6 7 <h2> Referer Type</h2>7 <h2>{'Referers_Type'|translate}</h2> 8 8 <table> 9 9 <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> 13 16 </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> 17 23 </td></tr> 18 24 </table> 19 25 20 <h2> Other</h2>26 <h2>{'Referers_Other'|translate}</h2> 21 27 <table> 22 28 <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> 25 33 </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> 29 40 </td></tr> 30 41 </table> 31 42 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
352 352 return $this->getNumericValue('Referers.' . __FUNCTION__); 353 353 } 354 354 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
29 29 'author' => 'Piwik', 30 30 'homepage' => 'http://piwik.org/', 31 31 'version' => '0.1', 32 'translationAvailable' => true 32 33 ); 33 34 34 35 return $info; 35 36 } 36 37 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 37 46 function getListHooksRegistered() 38 47 { 39 48 $hooks = array( … … 88 97 } 89 98 } 90 99 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
1 1 <div id='leftcolumn'> 2 <h2> Visit per local time</h2>2 <h2>{'VisitTime_LocalTime'|translate}</h2> 3 3 {$dataTableVisitInformationPerLocalTime} 4 4 </div> 5 5 6 6 <div id='rightcolumn'> 7 <h2> Visit per server time</h2>7 <h2>{'VisitTime_ServerTime'|translate}</h2> 8 8 {$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
49 49 'author' => 'Piwik', 50 50 'homepage' => 'http://piwik.org/', 51 51 'version' => '0.1', 52 'translationAvailable' => true 52 53 ); 53 54 54 55 return $info; 55 56 } 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 56 70 function getListHooksRegistered() 57 71 { 58 72 $hooks = array( … … 162 176 } 163 177 } 164 178 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
1 1 2 <h2> Visits per visit duration</h2>2 <h2>{'VisitorInterest_VisitsPerDuration'|translate}</h2> 3 3 {$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 */ 27 require_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 */ 39 class 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 */ 27 require_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 */ 39 class 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 */ 27 require_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 */ 39 class 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 */ 27 require_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 */ 37 class 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 */ 31 class 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 */ 28 require_once 'Zend/Validate.php'; 29 30 31 /** 32 * @see Zend_Validate_Hostname 33 */ 34 require_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 */ 50 abstract 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 */ 28 require_once 'Zend/Mime.php'; 29 30 31 /** 32 * @see Zend_Mail_Protocol_Abstract 33 */ 34 require_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 */ 48 class 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 */ 31 class 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 */ 31 class 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 */ 27 require_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 */ 37 class 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 */ 27 require_once 'Zend/Mail/Storage/Abstract.php'; 28 29 /** 30 * @see Zend_Mail_Message 31 */ 32 require_once 'Zend/Mail/Message.php'; 33 34 /** 35 * @see Zend_Mail_Storage 36 */ 37 require_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 */ 47 class 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 */ 27 require_once 'Zend/Mail/Storage/Abstract.php'; 28 29 /** 30 * @see Zend_Mail_Protocol_Pop3 31 */ 32 require_once 'Zend/Mail/Protocol/Pop3.php'; 33 34 /** 35 * @see Zend_Mail_Message 36 */ 37 require_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 */ 47 class 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 32 interface 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 */ 27 require_once 'Zend/Mail/Storage/Folder/Maildir.php'; 28 29 /** 30 * @see Zend_Mail_Storage_Writable_Interface 31 */ 32 require_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 */ 42 class 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 */ 31 abstract 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 */ 33 require_once 'Zend/Mail/Storage/Abstract.php'; 34 35 /** 36 * @see Zend_Mail_Message 37 */ 38 require_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 */ 48 class 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 */ 31 interface 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 */ 27 require_once 'Zend/Mail/Storage/Folder.php'; 28 29 /** 30 * @see Zend_Mail_Storage_Folder_Interface 31 */ 32 require_once 'Zend/Mail/Storage/Folder/Interface.php'; 33 34 /** 35 * @see Zend_Mail_Storage_Maildir 36 */ 37 require_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 */ 47 class 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 */ 27 require_once 'Zend/Mail/Storage/Folder.php'; 28 29 /** 30 * @see Zend_Mail_Storage_Folder_Interface 31 */ 32 require_once 'Zend/Mail/Storage/Folder/Interface.php'; 33 34 /** 35 * @see Zend_Mail_Storage_Mbox 36 */ 37 require_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 */ 47 class 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 */ 27 require_once 'Zend/Mail/Storage/Abstract.php'; 28 29 /** 30 * @see Zend_Mail_Protocol_Imap 31 */ 32 require_once 'Zend/Mail/Protocol/Imap.php'; 33 34 /** 35 * @see Zend_Mail_Storage_Writable_Interface 36 */ 37 require_once 'Zend/Mail/Storage/Writable/Interface.php'; 38 39 /** 40 * @see Zend_Mail_Storage_Folder_Interface 41 */ 42 require_once 'Zend/Mail/Storage/Folder/Interface.php'; 43 44 /** 45 * @see Zend_Mail_Storage_Folder 46 */ 47 require_once 'Zend/Mail/Storage/Folder.php'; 48 49 /** 50 * @see Zend_Mail_Message 51 */ 52 require_once 'Zend/Mail/Message.php'; 53 54 /** 55 * @see Zend_Mail_Storage 56 */ 57 require_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 */ 66 class 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 */ 26 require_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 */ 35 class 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 */ 28 class 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 */ 26 require_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 */ 35 class 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 */ 27 require_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 */ 39 class 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 */ 27 require_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 */ 37 class 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 */ 27 require_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 */ 40 abstract 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 */ 27 require_once 'Zend/Loader.php'; 28 29 /** 30 * @see Zend_Mime 31 */ 32 require_once 'Zend/Mime.php'; 33 34 /** 35 * @see Zend_Mail_Protocol_Smtp 36 */ 37 require_once 'Zend/Mail/Protocol/Smtp.php'; 38 39 /** 40 * @see Zend_Mail_Transport_Abstract 41 */ 42 require_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 */ 56 class 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 */ 26 require_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 */ 35 class 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 */ 25 require_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 */ 34 class 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 */ 24 require_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 */ 32 class 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 */ 25 require_once 'Zend/Mime.php'; 26 27 /** 28 * Zend_Mime_Part 29 */ 30 require_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 */ 39 class 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 */ 24 require_once 'Zend/Mime.php'; 25 26 /** 27 * Zend_Mime_Exception 28 */ 29 require_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 */ 39 class 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 */ 26 require_once 'Zend/Mail/Transport/Abstract.php'; 27 28 /** 29 * @see Zend_Mime 30 */ 31 require_once 'Zend/Mime.php'; 32 33 /** 34 * @see Zend_Mail_Transport_Abstract 35 */ 36 require_once 'Zend/Mail/Transport/Abstract.php'; 37 38 /** 39 * @see Zend_Mime_Message 40 */ 41 require_once 'Zend/Mime/Message.php'; 42 43 /** 44 * @see Zend_Mime_Part 45 */ 46 require_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 */ 57 class 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
