添加 Piwik 到代码库中。

+YUCHENG HU+

git-svn-id: https://svn.code.sf.net/p/hawebs/svn@475 a2543c7e-f6e9-4f8a-8bff-1ffc34733512
This commit is contained in:
YuCheng Hu
2010-07-10 04:25:56 +00:00
parent 14f631f50c
commit 171d362ecf
39 changed files with 2354 additions and 0 deletions
+299
View File
@@ -0,0 +1,299 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: API.php 2333 2010-06-22 04:58:13Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Live
*/
/**
* @see plugins/Referers/functions.php
*/
require_once PIWIK_INCLUDE_PATH . '/plugins/Live/Visitor.php';
/**
* @package Piwik_Live
*/
class Piwik_Live_API
{
static private $instance = null;
/*
* @return Piwik_Live_API
*/
static public function getInstance()
{
if (self::$instance == null)
{
$c = __CLASS__;
self::$instance = new $c();
}
return self::$instance;
}
const TYPE_FETCH_VISITS = 1;
const TYPE_FETCH_PAGEVIEWS = 2;
/*
* @return Piwik_DataTable
*/
public function getLastVisitForVisitor( $visitorId, $idSite )
{
return $this->getLastVisitsForVisitor($visitorId, $idSite, $limit = 1);
}
/*
* @return Piwik_DataTable
*/
public function getLastVisitsForVisitor( $visitorId, $idSite, $limit = 10 )
{
Piwik::checkUserHasViewAccess($idSite);
$visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId, $limit);
$table = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
return $table;
}
/*
* @return Piwik_DataTable
*/
public function getLastVisits( $idSite, $limit = 10, $minIdVisit = false )
{
Piwik::checkUserHasViewAccess($idSite);
$visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit, $minIdVisit);
$table = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
return $table;
}
/*
* @return Piwik_DataTable
*/
public function getLastVisitsDetails( $idSite, $limit = 1000, $minIdVisit = false )
{
Piwik::checkUserHasViewAccess($idSite);
$visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit, $minIdVisit);
$dataTable = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
return $dataTable;
}
/*
* @return Piwik_DataTable
*/
public function getUsersInLastXMin( $idSite, $minutes = 30 )
{
Piwik::checkUserHasViewAccess($idSite);
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes, $days = 0, self::TYPE_FETCH_VISITS);
return $visitorData;
}
/*
* @return Piwik_DataTable
*/
public function getUsersInLastXDays( $idSite, $days = 10 )
{
Piwik::checkUserHasViewAccess($idSite);
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days, self::TYPE_FETCH_VISITS);
return $visitorData;
}
/*
* @return array
*/
public function getPageImpressionsInLastXDays($idSite, $days = 10)
{
Piwik::checkUserHasViewAccess($idSite);
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days, self::TYPE_FETCH_PAGEVIEWS);
return $visitorData;
}
/*
* @return array
*/
public function getPageImpressionsInLastXMin($idSite, $minutes = 30)
{
Piwik::checkUserHasViewAccess($idSite);
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes, $days = 0, self::TYPE_FETCH_PAGEVIEWS);
return $visitorData;
}
/*
* @return Piwik_DataTable
*/
private function getCleanedVisitorsFromDetails($visitorDetails, $idSite)
{
$table = new Piwik_DataTable();
foreach($visitorDetails as $visitorDetail)
{
$this->cleanVisitorDetails($visitorDetail);
$visitor = new Piwik_Live_Visitor($visitorDetail);
$visitorDetailsArray = $visitor->getAllVisitorDetails();
$site = new Piwik_Site($idSite);
$timezone = $site->getTimezone();
$dateTimeVisit = Piwik_Date::factory($visitorDetailsArray['firstActionTimestamp'], $timezone);
$visitorDetailsArray['serverDatePretty'] = $dateTimeVisit->getLocalized('%shortDay% %day% %shortMonth%');
$visitorDetailsArray['serverTimePretty'] = $dateTimeVisit->getLocalized('%time%');
// get Detail - 100 single SQL Statements - Performance Issue
$idvisit = $visitorDetailsArray['idVisit'];
$sql = "
SELECT DISTINCT " .Piwik_Common::prefixTable('log_action').".name AS pageUrl
FROM " .Piwik_Common::prefixTable('log_link_visit_action')."
INNER JOIN " .Piwik_Common::prefixTable('log_action')."
ON " .Piwik_Common::prefixTable('log_link_visit_action').".idaction_url = " .Piwik_Common::prefixTable('log_action').".idaction
WHERE " .Piwik_Common::prefixTable('log_link_visit_action').".idvisit = $idvisit;
";
$visitorDetailsArray['actionDetails'] = Piwik_FetchAll($sql);
$sql = "
SELECT DISTINCT " .Piwik_Common::prefixTable('log_action').".name AS pageUrl
FROM " .Piwik_Common::prefixTable('log_link_visit_action')."
INNER JOIN " .Piwik_Common::prefixTable('log_action')."
ON " .Piwik_Common::prefixTable('log_link_visit_action').".idaction_name = " .Piwik_Common::prefixTable('log_action').".idaction
WHERE " .Piwik_Common::prefixTable('log_link_visit_action').".idvisit = $idvisit;
";
$visitorDetailsArray['actionDetailsTitle'] = Piwik_FetchAll($sql);
$table->addRowFromArray( array(Piwik_DataTable_Row::COLUMNS => $visitorDetailsArray));
}
return $table;
}
/*
* @return array
*/
private function loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit = null, $minIdVisit = false )
{
$where = $whereBind = array();
$where[] = Piwik_Common::prefixTable('log_visit') . ".idsite = ? ";
$whereBind[] = $idSite;
if(!empty($visitorId))
{
$where[] = Piwik_Common::prefixTable('log_visit') . ".visitor_idcookie = ? ";
$whereBind[] = $visitorId;
}
if(!empty($minIdVisit))
{
$where[] = Piwik_Common::prefixTable('log_visit') . ".idvisit > ? ";
$whereBind[] = $minIdVisit;
}
$sqlWhere = "";
if(count($where) > 0)
{
$sqlWhere = " WHERE " . join(' AND ', $where);
}
$sql = "SELECT " . Piwik_Common::prefixTable('log_visit') . ".* ,
" . Piwik_Common::prefixTable ( 'goal' ) . ".match_attribute
FROM " . Piwik_Common::prefixTable('log_visit') . "
LEFT JOIN ".Piwik_Common::prefixTable('log_conversion')."
ON " . Piwik_Common::prefixTable('log_visit') . ".idvisit = " . Piwik_Common::prefixTable('log_conversion') . ".idvisit
LEFT JOIN ".Piwik_Common::prefixTable('goal')."
ON (" . Piwik_Common::prefixTable('goal') . ".idsite = " . Piwik_Common::prefixTable('log_visit') . ".idsite
AND " . Piwik_Common::prefixTable('goal') . ".idgoal = " . Piwik_Common::prefixTable('log_conversion') . ".idgoal)
AND " . Piwik_Common::prefixTable('goal') . ".deleted = 0
$sqlWhere
ORDER BY idsite,idvisit DESC
LIMIT $limit";
return Piwik_FetchAll($sql, $whereBind);
}
/**
* Load last Visitors PAGES or DETAILS in MINUTES or DAYS from database
*
* @param int $idSite
* @param int $minutes
* @param int $days
* @param int $type self::TYPE_FETCH_VISITS or self::TYPE_FETCH_PAGEVIEWS
*
* @return mixed
*/
private function loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days = 0, $type = false )
{
$where = $whereBind = array();
$where[] = " " . Piwik_Common::prefixTable('log_visit') . ".idsite = ? ";
$whereBind[] = $idSite;
if($minutes != 0)
{
$timeLimit = mktime(date("H"), date("i") - $minutes, 0, date("m"), date("d"), date("Y"));
$where[] = " visit_last_action_time > '".date('Y-m-d H:i:s',$timeLimit)."'";
}
if($days != 0)
{
$timeLimit = mktime(0, 0, 0, date("m"), date("d") - $days + 1, date("Y"));
$where[] = " visit_last_action_time > '".date('Y-m-d H:i:s', $timeLimit)."'";
}
$sqlWhere = "";
if(count($where) > 0)
{
$sqlWhere = " WHERE " . join(' AND ', $where);
}
// Details
if($type == self::TYPE_FETCH_VISITS)
{
$sql = "SELECT " . Piwik_Common::prefixTable('log_visit') . ".idvisit
FROM " . Piwik_Common::prefixTable('log_visit') . "
$sqlWhere
ORDER BY idsite,idvisit DESC";
}
// Pages
elseif($type == self::TYPE_FETCH_PAGEVIEWS)
{
$sql = "SELECT " . Piwik_Common::prefixTable('log_link_visit_action') . ".idaction_url
FROM " . Piwik_Common::prefixTable('log_link_visit_action') . "
INNER JOIN " . Piwik_Common::prefixTable('log_visit') . "
ON " . Piwik_Common::prefixTable('log_visit') . ".idvisit = " . Piwik_Common::prefixTable('log_link_visit_action') . ".idvisit
$sqlWhere";
}
else
{
// no $type is set --> ERROR
throw new Exception("type parameter is not properly set.");
}
// return $sql by fetching
return Piwik_FetchAll($sql, $whereBind);
}
/**
* Removes fields that are not meant to be displayed (md5 config hash)
* Or that the user should only access if he is super user (cookie, IP)
*
* @return void
*/
private function cleanVisitorDetails( &$visitorDetails )
{
$toUnset = array('config_md5config');
if(!Piwik::isUserIsSuperUser())
{
$toUnset[] = 'visitor_idcookie';
$toUnset[] = 'location_ip';
}
foreach($toUnset as $keyName)
{
if(isset($visitorDetails[$keyName]))
{
unset($visitorDetails[$keyName]);
}
}
}
}
+184
View File
@@ -0,0 +1,184 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Controller.php 2080 2010-04-12 07:34:46Z matt $
*
* @category Piwik_Plugins
* @package Piwik_Live
*/
/**
* @package Piwik_Live
*/
class Piwik_Live_Controller extends Piwik_Controller
{
function __construct()
{
parent::__construct();
$this->idSite = Piwik_Common::getRequestVar('idSite');
$this->minIdVisit = Piwik_Common::getRequestVar('minIdVisit', 0, 'int');
}
function index()
{
$this->widget(true);
}
public function widget($fetch = false)
{
$view = Piwik_View::factory('index');
$view->idSite = Piwik_Common::getRequestVar('idSite');
$view->visitorsCountHalfHour = $this->getUsersInLastXMin(30);
$view->visitorsCountToday = $this->getUsersInLastXDays(1);
$view->pisHalfhour = $this->getPageImpressionsInLastXMin(30);
$view->pisToday = $this->getPageImpressionsInLastXDays(1);
$view->visitors = $this->getLastVisitsStart($fetch = true);
echo $view->render();
}
public function getLastVisitsDetails($fetch = false)
{
$view = Piwik_ViewDataTable::factory('');
$view->init( $this->pluginName,
__FUNCTION__,
'Live.getLastVisitsDetails',
'getPagesFromVisitId');
// All colomns in DB which could be shown
//'ip', 'idVisit', 'countActions', 'isVisitorReturning', 'country', 'countryFlag', 'continent', 'provider', 'providerUrl', 'idSite',
//'serverDate', 'visitLength', 'visitLengthPretty', 'firstActionTimestamp', 'lastActionTimestamp', 'refererType', 'refererName',
//'keywords', 'refererUrl', 'searchEngineUrl', 'searchEngineIcon', 'operatingSystem', 'operatingSystemShortName', 'operatingSystemIcon',
//'browserFamily', 'browserFamilyDescription', 'browser', 'browserIcon', 'screen', 'resolution', 'screenIcon', 'plugins', 'lastActionDateTime',
//'serverDatePretty', 'serverTimePretty', 'actionDetails'
$view->setColumnsToDisplay(array(
'idVisit',
'serverDatePretty',
'serverTimePretty',
'ip',
'countActions',
'visitLengthPretty',
'keywords',
'refererUrl',
'operatingSystemShortName',
'browser',
'screen',
'resolution',
'plugins',
));
$view->setColumnsTranslations(array(
'idVisit' => Piwik_Translate(''),
'serverDatePretty' => Piwik_Translate('Live_Date'),
'serverTimePretty' => Piwik_Translate('Live_Time'),
'ip' => 'IP',
'countActions' => Piwik_Translate('VisitorInterest_ColumnPagesPerVisit'),
'visitLengthPretty' => Piwik_Translate('VisitorInterest_ColumnVisitDuration'),
'keywords' => Piwik_Translate('Referers_ColumnKeyword'),
'refererUrl' => Piwik_Translate('Live_Referrer_URL'),
'operatingSystemShortName' => Piwik_Translate('UserSettings_ColumnOperatingSystem'),
'browser' => Piwik_Translate('UserSettings_ColumnBrowser'),
'screen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen'),
'resolution' => Piwik_Translate('UserSettings_ColumnResolution'),
'plugins' => Piwik_Translate('UserSettings_ColumnPlugin'),
));
$view->disableSort();
$view->setLimit(10);
$view->disableExcludeLowPopulation();
$view->setSortedColumn('idVisit', 'ASC');
$view->disableSearchBox();
// "Include low population" link won't be displayed under this table
$view->disableExcludeLowPopulation();
// disable the tag cloud, pie charts, bar chart icons
$view->disableShowAllViewsIcons();
// disable the button "show more datas"
$view->disableShowAllColumns();
return $this->renderView($view, $fetch);
}
function getPagesFromVisitId( $fetch = false)
{
$view = Piwik_ViewDataTable::factory('');
$view->init( $this->pluginName,
__FUNCTION__,
'Live.getLastVisitsForVisitor',
'getPagesFromVisitId');
return $this->renderView($view, $fetch);
}
public function getLastVisitsStart($fetch = false)
{
$view = Piwik_View::factory('lastVisits');
$view->idSite = Piwik_Common::getRequestVar('idSite');
$view->visitors = $this->getLastVisits(10);
$rendered = $view->render($fetch);
if($fetch)
{
return $rendered;
}
echo $rendered;
}
public function getLastVisits($limit = 10)
{
$api = new Piwik_API_Request("method=Live.getLastVisits&idSite=$this->idSite&limit=$limit&format=php&serialize=0&disable_generic_filters=1");
$visitors = $api->process();
return $visitors;
}
public function getUsersInLastXMin($minutes = 30) {
$api = new Piwik_API_Request("method=Live.getUsersInLastXMin&idSite=".$this->idSite."&minutes=".$minutes."&format=php&serialize=0&disable_generic_filters=1");
$visitors_halfhour = $api->process();
return count($visitors_halfhour);
}
public function getUsersInLastXDays($days = 1) {
$api = new Piwik_API_Request("method=Live.getUsersInLastXDays&idSite=$this->idSite&days=$days&format=php&serialize=0&disable_generic_filters=1");
$visitors_today = $api->process();
return count($visitors_today);
}
public function getPageImpressionsInLastXMin($minutes = 30) {
$api = new Piwik_API_Request("method=Live.getPageImpressionsInLastXMin&idSite=$this->idSite&minutes=$minutes&format=php&serialize=0&disable_generic_filters=1");
$pis_halfhour = $api->process();
return count($pis_halfhour);
}
public function getPageImpressionsInLastXDays($days = 1) {
$api = new Piwik_API_Request("method=Live.getPageImpressionsInLastXDays&idSite=$this->idSite&days=$days&format=php&serialize=0&disable_generic_filters=1");
$pis_today = $api->process();
return count($pis_today);
}
public function ajaxTotalVisitors($fetch = false)
{
$view = Piwik_View::factory('totalVisits');
$view->idSite = Piwik_Common::getRequestVar('idSite');
$view->visitorsCountHalfHour = $this->getUsersInLastXMin(30);
$view->visitorsCountToday = $this->getUsersInLastXDays(1);
$view->pisHalfhour = $this->getPageImpressionsInLastXMin(30);
$view->pisToday = $this->getPageImpressionsInLastXDays(1);
$rendered = $view->render($fetch);
if($fetch)
{
return $rendered;
}
echo $rendered;
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Live.php 2264 2010-06-03 16:53:43Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Live
*/
/**
*
* @package Piwik_Live
*/
class Piwik_Live extends Piwik_Plugin
{
public function getInformation()
{
return array(
'description' => Piwik_Translate('Live_PluginDescription'),
'author' => 'Piwik',
'author_homepage' => 'http://piwik.org/',
'version' => Piwik_Version::VERSION,
);
}
function getListHooksRegistered()
{
return array(
'template_css_import' => 'css',
'WidgetsList.add' => 'addWidget',
'Menu.add' => 'addMenu',
);
}
function css()
{
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"themes/default/styles.css\" />\n";
}
function addMenu()
{
Piwik_AddMenu('General_Visitors', 'Live_VisitorLog', array('module' => 'Live', 'action' => 'getLastVisitsDetails'));
}
public function addWidget() {
Piwik_AddWidget('Live!', 'Live Visitors!', 'Live', 'widget');
}
}
+327
View File
@@ -0,0 +1,327 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Visitor.php 2147 2010-05-06 18:50:38Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Live
*/
/**
* @see plugins/Referers/functions.php
* @see plugins/UserCountry/functions.php
* @see plugins/UserSettings/functions.php
* @see plugins/Provider/functions.php
*/
require_once PIWIK_INCLUDE_PATH . '/plugins/Referers/functions.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/UserSettings/functions.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/Provider/functions.php';
/**
*
* @package Piwik_Live
*/
class Piwik_Live_Visitor
{
function __construct($visitorRawData)
{
$this->details = $visitorRawData;
}
function getAllVisitorDetails()
{
return array(
'ip' => $this->getIp(),
'idVisit' => $this->getIdVisit(),
'countActions' => $this->getNumberOfActions(),
'isVisitorReturning' => $this->isVisitorReturning(),
'country' => $this->getCountryName(),
'countryFlag' => $this->getCountryFlag(),
'continent' => $this->getContinent(),
'provider' => $this->getProvider(),
'providerUrl' => $this->getProviderUrl(),
'idSite' => $this->getIdSite(),
'serverDate' => $this->getServerDate(),
'visitLength' => $this->getVisitLength(),
'visitLengthPretty' => $this->getVisitLengthPretty(),
'firstActionTimestamp' => $this->getTimestampFirstAction(),
'lastActionTimestamp' => $this->getTimestampLastAction(),
'refererType' => $this->getRefererType(),
'refererName' => $this->getRefererTypeName(),
'keywords' => $this->getKeywords(),
'refererUrl' => $this->getRefererUrl(),
'refererName' => $this->getRefererName(),
'searchEngineUrl' => $this->getSearchEngineUrl(),
'searchEngineIcon' => $this->getSearchEngineIcon(),
'operatingSystem' => $this->getOperatingSystem(),
'operatingSystemShortName' => $this->getOperatingSystemShortName(),
'operatingSystemIcon' => $this->getOperatingSystemIcon(),
'browserFamily' => $this->getBrowserFamily(),
'browserFamilyDescription' => $this->getBrowserFamilyDescription(),
'browser' => $this->getBrowser(),
'browserIcon' => $this->getBrowserIcon(),
'screen' => $this->getScreenType(),
'resolution' => $this->getResolution(),
'screenIcon' => $this->getScreenTypeIcon(),
'plugins' => $this->getPlugins(),
'lastActionDateTime' => $this->getDateTimeLastAction(),
'isVisitorGoalConverted' => $this->isVisitorGoalConverted(),
'goalIcon' => $this->getGoalIcon(),
'goalType' => $this->getGoalType(),
);
}
function getServerDate()
{
return date('Y-m-d', strtotime($this->details['visit_last_action_time']));
}
function getIp()
{
if(isset($this->details['location_ip']))
{
return long2ip($this->details['location_ip']);
}
return false;
}
function getIdVisit()
{
return $this->details['idvisit'];
}
function getIdSite()
{
return $this->details['idsite'];
}
function getNumberOfActions()
{
return $this->details['visit_total_actions'];
}
function getVisitLength()
{
return $this->details['visit_total_time'];
}
function getVisitLengthPretty()
{
return Piwik::getPrettyTimeFromSeconds($this->details['visit_total_time']);
}
function isVisitorReturning()
{
return $this->details['visitor_returning'];
}
function getTimestampFirstAction()
{
return strtotime($this->details['visit_first_action_time']);
}
function getTimestampLastAction()
{
return strtotime($this->details['visit_last_action_time']);
}
function getCountryName()
{
return Piwik_CountryTranslate($this->details['location_country']);
}
function getCountryFlag()
{
return Piwik_getFlagFromCode($this->details['location_country']);
}
function getContinent()
{
return Piwik_ContinentTranslate($this->details['location_continent']);
}
function getRefererType()
{
$map = array(
Piwik_Common::REFERER_TYPE_SEARCH_ENGINE => 'searchEngine',
Piwik_Common::REFERER_TYPE_WEBSITE => 'website',
Piwik_Common::REFERER_TYPE_DIRECT_ENTRY => 'directEntry',
Piwik_Common::REFERER_TYPE_CAMPAIGN => 'campaign',
);
if(isset($map[$this->details['referer_type']]))
{
return $map[$this->details['referer_type']];
}
return $map[Piwik_Common::REFERER_TYPE_DIRECT_ENTRY];
}
function getRefererTypeName()
{
return Piwik_getRefererTypeLabel($this->details['referer_type']);
}
function getKeywords()
{
return $this->details['referer_keyword'];
}
function getRefererUrl()
{
return $this->details['referer_url'];
}
function getRefererName()
{
return $this->details['referer_name'];
}
function getSearchEngineUrl()
{
if($this->getRefererType() == 'searchEngine'
&& !empty($this->details['referer_name']))
{
return Piwik_getSearchEngineUrlFromName($this->details['referer_name']);
}
return null;
}
function getSearchEngineIcon()
{
$searchEngineUrl = $this->getSearchEngineUrl();
if( !is_null($searchEngineUrl) )
{
return Piwik_getSearchEngineLogoFromUrl($searchEngineUrl);
}
return null;
}
function getPlugins()
{
$plugins = array(
'config_pdf',
'config_flash',
'config_java',
'config_director',
'config_quicktime',
'config_realplayer',
'config_windowsmedia',
'config_gears',
'config_silverlight',
);
$return = array();
foreach($plugins as $plugin)
{
if($this->details[$plugin] == 1)
{
$pluginShortName = substr($plugin, 7);
$return[] = $pluginShortName;
}
}
return implode(", ", $return);
}
function getOperatingSystem()
{
return Piwik_getOSLabel($this->details['config_os']);
}
function getOperatingSystemShortName()
{
return Piwik_getOSShortLabel($this->details['config_os']);
}
function getOperatingSystemIcon()
{
return Piwik_getOSLogo($this->details['config_os']);
}
function getBrowserFamilyDescription()
{
return Piwik_getBrowserTypeLabel($this->getBrowserFamily());
}
function getBrowserFamily()
{
return Piwik_getBrowserFamily($this->details['config_browser_name']);
}
function getBrowser()
{
return Piwik_getBrowserLabel($this->details['config_browser_name'] . ";" . $this->details['config_browser_version']);
}
function getBrowserIcon()
{
return Piwik_getBrowsersLogo($this->details['config_browser_name'] . ";" . $this->details['config_browser_version']);
}
function getScreenType()
{
return Piwik_getScreenTypeFromResolution($this->details['config_resolution']);
}
function getResolution()
{
return $this->details['config_resolution'];
}
function getScreenTypeIcon()
{
return Piwik_getScreensLogo($this->getScreenType());
}
function getProvider()
{
return Piwik_getHostnameName($this->details['location_provider']);
}
function getProviderUrl()
{
return Piwik_getHostnameUrl($this->details['location_provider']);
}
function getDateTimeLastAction()
{
return date('Y-m-d H:i:s', strtotime($this->details['visit_last_action_time']));
}
function isVisitorGoalConverted()
{
return $this->details['visit_goal_converted'];
}
function getGoalType()
{
if(isset($this->details['match_attribute'])){
return $this->details['match_attribute'];
}
return false;
}
function getGoalIcon()
{
if(isset($this->details['match_attribute'])){
$goalicon = "";
switch ($this->details['match_attribute']) {
case "url":
$goalicon = "plugins/Live/templates/images/goal.png";
break;
case "file":
$goalicon = "plugins/Live/templates/images/download.png";
break;
case "external_website":
$goalicon = "plugins/Live/templates/images/outboundlink.png";
break;
}
return $goalicon;
}
return false;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

@@ -0,0 +1,183 @@
{literal}
<script type="text/javascript" src="plugins/Live/templates/scripts/spy.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
if($('#_spyTmp').size() == 0) {
$('#visitsLive > div:gt(2)').fadeEachDown(); // initial fade
$('#visitsLive').spy({
limit: 10,
ajax: 'index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=getLastVisitsStart',
fadeLast: 2,
isDupe: check_for_dupe,
timeout: 8000,
customParameterName: 'minIdVisit',
customParameterValueCallback: lastIdVisit,
fadeInSpeed: 600
});
}
});
// first I'm ensuring that 'last' has been initialised (with last.constructor == Object),
// then prev.html() == last.html() will return true if the HTML is the same, or false,
// if I have a different entry.
function check_for_dupe(prev, last)
{
if (last.constructor == Object) {
return (prev.html() == last.html());
}
else {
return 0;
}
}
function lastIdVisit()
{
updateTotalVisits();
updateVisitBox();
return $('#visitsLive > div:lt(2) .idvisit').html();
}
var pauseImage = "plugins/Live/templates/images/pause.gif";
var pauseDisabledImage = "plugins/Live/templates/images/pause_disabled.gif";
var playImage = "plugins/Live/templates/images/play.gif";
var playDisabledImage = "plugins/Live/templates/images/play_disabled.gif";
function onClickPause()
{
$('#pauseImage').attr('src', pauseImage);
$('#playImage').attr('src', playDisabledImage);
return pauseSpy();
}
function onClickPlay()
{
$('#playImage').attr('src', playImage);
$('#pauseImage').attr('src', pauseDisabledImage);
return playSpy();
}
// updates the numbers of total visits in startbox
function updateTotalVisits()
{
$("#visitsTotal").load("index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=ajaxTotalVisitors");
}
// updates the visit table, to refresh the already presented visotors pages
function updateVisitBox()
{
$("#visitsLive").load("index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=getLastVisitsStart");
}
/* TOOLTIP */
$('#visitsLive label').tooltip({
track: true,
delay: 0,
showURL: false,
showBody: " - ",
fade: 250
});
</script>
<style>
#visitsLive {
text-align:left;
font-size:90%;
}
#visitsLive .datetime, #visitsLive .country, #visitsLive .referer, #visitsLive .settings, #visitsLive .returning , #visitsLive .countActions{
border-bottom:1px solid #C1DAD7;
border-right:1px solid #C1DAD7;
padding:5px 5px 5px 12px;
}
#visitsLive .datetime {
background:#D4E3ED url(plugins/CoreHome/templates/images/bg_header.jpg) repeat-x scroll 0 0;
border-top:1px solid #C1DAD7;
color:#6D929B;
margin:0;
text-align:left;
}
#visitsLive .country {
color:#4F6B72;
background:#FFFFFF url(plugins/CoreHome/templates/images/bullet1.gif) no-repeat scroll 0 0;
}
#visitsLive .referer {
background:#F9FAFA none repeat scroll 0 0;
color:#797268;
}
#visitsLive .pagesTitle {
display:block;
float:left;
padding-top: 3px;
}
#visitsLive .countActions {
background:#FFFFFF none repeat scroll 0 0;
color:#4F6B72;
}
#visitsLive .settings {
background:#FFFFFF none repeat scroll 0 0;
color:#4F6B72;
}
#visitsLive .returning {
background:#F9FAFA none repeat scroll 0 0;
color:#797268;
}
#visitsLive .visit {
}
#visitsLive .alt {
}
#visitsLive .actions {
background:#F9FAFA none repeat scroll 0 0;
color:#797268;
padding:0px 5px 0px 12px;
}
</style>
{/literal}
<div id="visitsTotal">
<table class="dataTable" cellspacing="0">
<thead>
<tr>
<th id="label" class="sortable label" style="cursor: auto;">
<div id="thDIV">Period<div></th>
<th id="label" class="sortable label" style="cursor: auto;">
<div id="thDIV">Visits<div></th>
<th id="label" class="sortable label" style="cursor: auto;">
<div id="thDIV">PageViews<div></th>
</tr>
</thead>
<tbody>
<tr>
<tr class="">
<td class="columnodd">Today</td>
<td class="columnodd">{$visitorsCountToday}</td>
<td class="columnodd">{$pisToday}</td>
</tr>
<tr class="">
<td class="columnodd">Last 30 minutes</td>
<td class="columnodd">{$visitorsCountHalfHour}</td>
<td class="columnodd">{$pisHalfhour}</td>
</tr>
</tbody>
</table>
</div>
<div id='visitsLive'>
{$visitors}
</div>
<div>
<a href="javascript:void(0);" onclick="onClickPause();"><img id="pauseImage" border="0" src="plugins/Live/templates/images/pause_disabled.gif" /></a>
<a href="javascript:void(0);" onclick="onClickPlay();"><img id="playImage" border="0" src="plugins/Live/templates/images/play.gif" /></a>
</div>
@@ -0,0 +1,35 @@
{foreach from=$visitors item=visitor}
<div id="{$visitor.idVisit}" class="visit{if $visitor.idVisit % 2} alt{/if}">
<div style="display:none" class="idvisit">{$visitor.idVisit}</div>
<div class="datetime">
{$visitor.serverDatePretty} - {$visitor.serverTimePretty}
&nbsp;<img src="{$visitor.countryFlag}" title="{$visitor.country}, Provider {$visitor.provider}" />
&nbsp;<img src="{$visitor.browserIcon}" title="{$visitor.browser} with plugins {$visitor.plugins} enabled" />
&nbsp;<img src="{$visitor.operatingSystemIcon}" title="{$visitor.operatingSystem}, {$visitor.resolution}" />
&nbsp;{if $visitor.isVisitorGoalConverted}<img src="{$visitor.goalIcon}" title="{$visitor.goalType}" />{/if}
{if $visitor.isVisitorReturning}&nbsp;<img src="plugins/Live/templates/images/returningVisitor.gif" title="Returning Visitor" />{/if}
&nbsp;<label id="" title="IP: {$visitor.ip} - Duration: {$visitor.visitLengthPretty}">more...</label>
</div>
<!--<div class="settings"></div>-->
<div class="referer">
{if $visitor.refererType != 'directEntry'}from <a href="{$visitor.refererUrl}" target="_blank">{if !empty($visitor.searchEngineIcon)}<img src="{$visitor.searchEngineIcon}" /> {/if}{$visitor.refererName}</a>
{if !empty($visitor.keywords)}"{$visitor.keywords}"{/if}
{/if}
{if $visitor.refererType == 'directEntry'}Direct entry{/if}
</div>
<div id="{$visitor.idVisit}_actions" class="settings">
<span class="pagesTitle">Pages:</span>&nbsp;
{php} $col = 0; {/php}
{foreach from=$visitor.actionDetails item=action}
{php}
$col++;
if ($col>=9)
{
$col=0;
}
{/php}
<a href="{$action.pageUrl}" target="_blank"><img align="middle" src="plugins/Live/templates/images/file{php} echo $col; {/php}.png" title="{$action.pageUrl}" /></a>
{/foreach}
</div>
</div>
{/foreach}
@@ -0,0 +1,154 @@
/*
jQuery Plugin spy (leftlogic.com/info/articles/jquery_spy2)
(c) 2006 Remy Sharp (leftlogic.com)
$Id: spy.js 1868 2010-02-23 22:47:29Z vipsoft $
*/
var spyRunning = 1;
$.fn.spy = function(settings) {
var spy = this;
spy.epoch = new Date(1970, 0, 1);
spy.last = '';
spy.parsing = 0;
spy.waitTimer = 0;
spy.json = null;
if (!settings.ajax) {
alert("An AJAX/AJAH URL must be set for the spy to work.");
return;
}
spy.attachHolder = function() {
// not mad on this, but the only way to parse HTML collections
if (o.method == 'html')
$('body').append('<div style="display: none!important;" id="_spyTmp"></div>');
}
// returns true for 'no dupe', and false for 'dupe found'
// latest = is latest ajax return value (raw)
// last = is previous ajax return value (raw)
// note that comparing latest and last if they're JSON objects
// always returns false, so you need to implement it manually.
spy.isDupe = function(latest, last) {
if ((last.constructor == Object) && (o.method == 'html'))
return (latest.html() == last.html());
else if (last.constructor == String)
return (latest == last);
else
return 0;
}
spy.parse = function(e, r) {
spy.parsing = 1; // flag to stop pull via ajax
if (o.method == 'html') {
$('div#_spyTmp').html(r); // add contents to hidden div
} else if (o.method == 'json') {
eval('spy.json = ' + r); // convert text to json
}
if ((o.method == 'json' && spy.json.constructor == Array) || o.method == 'html') {
if (spy.parseItem(e)) {
spy.waitTimer = window.setInterval(function() {
if (spyRunning) {
if (!spy.parseItem(e)) {
spy.parsing = 0;
clearInterval(spy.waitTimer);
}
}
}, o.pushTimeout);
} else {
spy.parsing = 0;
}
} else if (o.method == 'json') { // we just have 1
eval('spy.json = ' + r)
spy.addItem(e, spy.json);
spy.parsing = 0;
}
}
// returns true if there's more to parse
spy.parseItem = function(e) {
if (o.method == 'html') {
// note: pre jq-1.0 doesn't return the object
var i = $('div#_spyTmp').find('div:first').remove();
if (i.size() > 0) {
i.hide();
spy.addItem(e, i);
}
return ($('div#_spyTmp').find('div').size() != 0);
} else {
if (spy.json.length) {
var i = spy.json.shift();
spy.addItem(e, i);
}
return (spy.json.length != 0);
}
}
spy.addItem = function(e, i) {
if (! o.isDupe.call(this, i, spy.last)) {
spy.last = i; // note i is a pointer - so when it gets modified, so does spy.last
$('#' + e.id + ' > div:gt(' + (o.limit - 2) + ')').remove();
$('#' + e.id + ' > div:gt(' + (o.limit - o.fadeLast - 2) + ')').fadeEachDown();
o.push.call(e, i);
$('#' + e.id + ' > div:first').fadeIn(o.fadeInSpeed);
}
}
spy.push = function(r) {
$('#' + this.id).prepend(r);
}
var o = {
limit: (settings.limit || 10),
ajax: settings.ajax,
timeout: (settings.timeout || 3000),
pushTimeout: (settings.pushTimeout || settings.timeout || 3000),
method: (settings.method || 'html').toLowerCase(),
push: (settings.push || spy.push),
fadeInSpeed: (settings.fadeInSpeed || 'slow'), // 1400 = crawl
customParameterName: settings.customParameterName,
customParameterValueCallback: settings.customParameterValueCallback,
isDupe: (settings.isDupe || spy.isDupe)
};
spy.attachHolder();
return this.each(function() {
var e = this;
var lr = ''; // last ajax return
var parameters = {};
spy.ajaxTimer = window.setInterval(function() {
if (spyRunning && (!spy.parsing)) {
var customParameterValue = o.customParameterValueCallback.call();
parameters[o.customParameterName] = customParameterValue;
$.get(o.ajax, parameters, function(r) {
spy.parse(e, r);
});
}
}, o.timeout);
});
};
$.fn.fadeEachDown = function() {
var s = this.size()+5;
return this.each(function(i) {
var o = 1 - (s == 1 ? 0.5 : 0.85/s*(i+1));
var e = this.style;
if (window.ActiveXObject)
e.filter = "alpha(opacity=" + o*100 + ")";
e.opacity = o;
});
};
function pauseSpy() {
spyRunning = 0; return false;
}
function playSpy() {
spyRunning = 1; return false;
}
@@ -0,0 +1,26 @@
<div id="visitsTotal">
<table class="dataTable" cellspacing="0">
<thead>
<tr>
<th id="label" class="sortable label" style="cursor: auto;">
<div id="thDIV">{'Live_Date'|translate}</div></th>
<th id="label" class="sortable label" style="cursor: auto;">
<div id="thDIV">{'General_ColumnNbVisits'|translate}</div></th>
<th id="label" class="sortable label" style="cursor: auto;">
<div id="thDIV">{'General_ColumnPageviews'|translate}</div></th>
</tr>
</thead>
<tbody>
<tr class="">
<td class="columnodd">{'General_Today'|translate}</td>
<td class="columnodd">{$visitorsCountToday}</td>
<td class="columnodd">{$pisToday}</td>
</tr>
<tr class="">
<td class="columnodd">{'Live_Last30Minutes'|translate}</td>
<td class="columnodd">{$visitorsCountHalfHour}</td>
<td class="columnodd">{$pisHalfhour}</td>
</tr>
</tbody>
</table>
</div>
+68
View File
@@ -0,0 +1,68 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Auth.php 2265 2010-06-03 17:46:05Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Login
*/
/**
*
* @package Piwik_Login
*/
class Piwik_Login_Auth implements Piwik_Auth
{
protected $login = null;
protected $token_auth = null;
public function getName()
{
return 'Login';
}
public function authenticate()
{
$rootLogin = Zend_Registry::get('config')->superuser->login;
$rootPassword = Zend_Registry::get('config')->superuser->password;
$rootToken = Piwik_UsersManager_API::getInstance()->getTokenAuth($rootLogin, $rootPassword);
if($this->login == $rootLogin
&& $this->token_auth == $rootToken)
{
return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $this->login, $this->token_auth );
}
if($this->token_auth === $rootToken)
{
return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $rootLogin, $rootToken );
}
$login = Piwik_FetchOne(
'SELECT login FROM '.Piwik_Common::prefixTable('user').' WHERE token_auth = ?',
array($this->token_auth)
);
if($login !== false)
{
if(is_null($this->login)
|| $this->login == $login)
{
return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, $this->token_auth );
}
}
return new Piwik_Auth_Result( Piwik_Auth_Result::FAILURE, $this->login, $this->token_auth );
}
public function setLogin($login)
{
$this->login = $login;
}
public function setTokenAuth($token_auth)
{
$this->token_auth = $token_auth;
}
}
@@ -0,0 +1,415 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Controller.php 2258 2010-06-02 14:50:18Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Login
*/
/**
* Login controller
*
* @package Piwik_Login
*/
class Piwik_Login_Controller extends Piwik_Controller
{
/**
* Get referer to redirect to upon successful login.
* Remembers referer URL even if navigation is: login form -> reset password -> login form
*
* @returns string
*/
static public function getRefererToRedirect()
{
// retrieve any previously saved referer
$ns = new Zend_Session_Namespace('Piwik_Login.referer');
$referer = $ns->referer;
if(empty($referer))
{
// if the referer contains module=Login, Installation, or CoreUpdater, we instead redirect to the doc root
$referer = Piwik_Url::getLocalReferer();
if(empty($referer) || preg_match('/module=(Login|Installation|CoreUpdater)/', $referer))
{
$referer = 'index.php';
}
$ns->referer = $referer;
$ns->setExpirationSeconds(300, 'referer');
}
else if(!Piwik_Url::isLocalUrl($referer))
{
$referer = 'index.php';
}
return $referer;
}
/**
* Default action
*
* @param none
* @return void
*/
function index()
{
$this->login();
}
/**
* Login form
*
* @param string $messageNoAccess Access error message
* @param string $currentUrl Current URL
* @return void
*/
function login($messageNoAccess = null)
{
$urlToRedirect = self::getRefererToRedirect();
$form = new Piwik_Login_Form();
if($form->validate())
{
$nonce = $form->getSubmitValue('form_nonce');
if(Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce))
{
$login = $form->getSubmitValue('form_login');
$password = $form->getSubmitValue('form_password');
$md5Password = md5($password);
try {
$this->authenticateAndRedirect($login, $md5Password, $urlToRedirect);
} catch(Exception $e) {
$messageNoAccess = $e->getMessage();
}
}
else
{
$messageNoAccess = Piwik_Translate('Login_InvalidNonceOrReferer');
}
}
$view = Piwik_View::factory('login');
$view->AccessErrorString = $messageNoAccess;
$view->nonce = Piwik_Nonce::getNonce('Piwik_Login.login');
$view->linkTitle = Piwik::getRandomTitle();
$view->addForm( $form );
$view->subTemplate = 'genericForm.tpl';
echo $view->render();
}
/**
* Form-less login
*
* @param none
* @return void
*/
function logme()
{
$password = Piwik_Common::getRequestVar('password', null, 'string');
if(strlen($password) != 32)
{
throw new Exception(Piwik_TranslateException('Login_ExceptionPasswordMD5HashExpected'));
}
$login = Piwik_Common::getRequestVar('login', null, 'string');
if($login == Zend_Registry::get('config')->superuser->login)
{
throw new Exception(Piwik_TranslateException('Login_ExceptionInvalidSuperUserAuthenticationMethod', array("logme")));
}
$currentUrl = 'index.php';
$urlToRedirect = Piwik_Common::getRequestVar('url', $currentUrl, 'string');
$urlToRedirect = htmlspecialchars_decode($urlToRedirect);
$this->authenticateAndRedirect($login, $password, $urlToRedirect);
}
/**
* Authenticate user and password. Redirect if successful.
*
* @param string $login (user name)
* @param string $md5Password (md5 hash of password)
* @param string $urlToRedirect (URL to redirect to, if successfully authenticated)
* @return string (failure message if unable to authenticate)
*/
protected function authenticateAndRedirect($login, $md5Password, $urlToRedirect)
{
$info = array( 'login' => $login,
'md5Password' => $md5Password,
);
Piwik_PostEvent('Login.initSession', $info);
Piwik_Url::redirectToUrl($urlToRedirect);
}
/**
* Lost password form. Email password reset information.
*
* @param none
* @return void
*/
function lostPassword()
{
$messageNoAccess = null;
$urlToRedirect = self::getRefererToRedirect();
$form = new Piwik_Login_PasswordForm();
if($form->validate())
{
$loginMail = $form->getSubmitValue('form_login');
$messageNoAccess = $this->lostPasswordFormValidated($loginMail);
}
$view = Piwik_View::factory('lostPassword');
$view->AccessErrorString = $messageNoAccess;
$view->linkTitle = Piwik::getRandomTitle();
$view->addForm( $form );
$view->subTemplate = 'genericForm.tpl';
echo $view->render();
}
/**
* Validate user (by username or email address).
*
* @param string $loginMail (user name or email address)
* @param string $urlToRedirect (URL to redirect to, if successfully validated)
* @return string (failure message if unable to validate)
*/
protected function lostPasswordFormValidated($loginMail)
{
$user = self::getUserInformation($loginMail);
if( $user === null )
{
return Piwik_Translate('Login_InvalidUsernameEmail');
}
$view = Piwik_View::factory('passwordsent');
$login = $user['login'];
$email = $user['email'];
// construct a password reset token from user information
$resetToken = self::generatePasswordResetToken($user);
$ip = Piwik_Common::getIpString();
$url = Piwik_Url::getCurrentUrlWithoutQueryString() . "?module=Login&action=resetPassword&token=$resetToken";
// send email with new password
try
{
$mail = new Piwik_Mail();
$mail->addTo($email, $login);
$mail->setSubject(Piwik_Translate('Login_MailTopicPasswordRecovery'));
$mail->setBodyText(
str_replace(
'\n',
"\n",
sprintf(Piwik_Translate('Login_MailPasswordRecoveryBody'), $login, $ip, $url, $resetToken)
) . "\n"
);
$piwikHost = $_SERVER['HTTP_HOST'];
if(strlen($piwikHost) == 0)
{
$piwikHost = 'piwik.org';
}
$fromEmailName = Zend_Registry::get('config')->General->login_password_recovery_email_name;
$fromEmailAddress = Zend_Registry::get('config')->General->login_password_recovery_email_address;
$fromEmailAddress = str_replace('{DOMAIN}', $piwikHost, $fromEmailAddress);
$mail->setFrom($fromEmailAddress, $fromEmailName);
@$mail->send();
}
catch(Exception $e)
{
$view->ErrorString = $e->getMessage();
}
$view->linkTitle = Piwik::getRandomTitle();
echo $view->render();
exit;
}
/**
* Reset password form. Enter new password here.
*
* @param none
* @return void
*/
function resetPassword()
{
$messageNoAccess = null;
$urlToRedirect = self::getRefererToRedirect();
$form = new Piwik_Login_ResetPasswordForm();
if($form->validate())
{
$loginMail = $form->getSubmitValue('form_login');
$token = $form->getSubmitValue('form_token');
$password = $form->getSubmitValue('form_password');
$messageNoAccess = $this->resetPasswordFormValidated($loginMail, $token, $password);
}
$view = Piwik_View::factory('resetPassword');
$view->AccessErrorString = $messageNoAccess;
$view->linkTitle = Piwik::getRandomTitle();
$view->addForm( $form );
$view->subTemplate = 'genericForm.tpl';
echo $view->render();
}
/**
* Validate password reset request. If successful, set new password and redirect.
*
* @param string $loginMail (user name or email address)
* @param string $token (password reset token)
* @param array of string $newPassword (new password)
* @param string $urlToRedirect (URL to redirect to, if successfully validated)
* @return string (failure message)
*/
protected function resetPasswordFormValidated($loginMail, $token, $password)
{
$user = self::getUserInformation($loginMail);
if( $user === null )
{
return Piwik_Translate('Login_InvalidUsernameEmail');
}
if(!self::isValidToken($token, $user))
{
return Piwik_Translate('Login_InvalidOrExpiredToken');
}
try
{
if( $user['email'] == Zend_Registry::get('config')->superuser->email )
{
$user['password'] = md5($password);
Zend_Registry::get('config')->superuser = $user;
}
else
{
Piwik_UsersManager_API::getInstance()->updateUser($user['login'], $password);
}
}
catch(Exception $e)
{
$view->ErrorString = $e->getMessage();
}
$view = Piwik_View::factory('passwordchanged');
$view->linkTitle = Piwik::getRandomTitle();
echo $view->render();
exit;
}
/**
* Get user information
*
* @param string $loginMail (user login or email address)
* @return array ("login" => '...', "email" => '...', "password" => '...') or null, if user not found
*/
protected function getUserInformation($loginMail)
{
Piwik::setUserIsSuperUser();
$user = null;
if( $loginMail == Zend_Registry::get('config')->superuser->email
|| $loginMail == Zend_Registry::get('config')->superuser->login )
{
$user = array(
'login' => Zend_Registry::get('config')->superuser->login,
'email' => Zend_Registry::get('config')->superuser->email,
'password' => Zend_Registry::get('config')->superuser->password,
);
}
else if( Piwik_UsersManager_API::getInstance()->userExists($loginMail) )
{
$user = Piwik_UsersManager_API::getInstance()->getUser($loginMail);
}
else if( Piwik_UsersManager_API::getInstance()->userEmailExists($loginMail) )
{
$user = Piwik_UsersManager_API::getInstance()->getUserByEmail($loginMail);
}
return $user;
}
/**
* Generate a password reset token. Expires in (roughly) 24 hours.
*
* @param array (user information)
* @param int $timestamp (Unix timestamp)
* @return string (generated token)
*/
protected function generatePasswordResetToken($user, $timestamp = null)
{
/*
* Piwik does not stored the generated password reset token.
* This avoids a database schema change and SQL queries to store, retrieve, and purge (expired) tokens.
*/
if(!$timestamp)
{
$timestamp = time() + 24*60*60; /* +24 hrs */
}
$expiry = strftime('%Y%m%d%H', $timestamp);
$token = md5($expiry . $user['login'] . $user['email'] . $user['password']);
return $token;
}
/**
* Validate token.
*
* @param string $token
* @param array $user (user information)
* @return bool (true if valid, false otherwise)
*/
protected function isValidToken($token, $user)
{
$now = time();
// token valid for 24 hrs (give or take, due to the coarse granularity in our strftime format string)
for($i = 0; $i <= 24; $i++)
{
$generatedToken = self::generatePasswordResetToken($user, $now + $i*60*60);
if($generatedToken == $token)
{
return true;
}
}
// fails if token is invalid, expired, password already changed, other user information has changed, ...
return false;
}
/**
* Clear session information
*
* @param none
* @return void
*/
static public function clearSession()
{
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
$cookie = new Piwik_Cookie($authCookieName);
$cookie->delete();
Zend_Session::expireSessionCookie();
}
/**
* Logout current user
*
* @param none
* @return void
*/
public function logout()
{
self::clearSession();
Piwik::redirectToModule('CoreHome');
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Form.php 2036 2010-04-01 21:08:24Z matt $
*
* @category Piwik_Plugins
* @package Piwik_Login
*/
/**
*
* @package Piwik_Login
*/
class Piwik_Login_Form extends Piwik_Form
{
function __construct()
{
parent::__construct();
// reset
$this->updateAttributes('id="loginform" name="loginform"');
}
function init()
{
$formElements = array(
array('text', 'form_login'),
array('password', 'form_password'),
array('hidden', 'form_nonce'),
);
$this->addElements( $formElements );
$formRules = array(
array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('General_Username')), 'required'),
array('form_password', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Password')), 'required'),
);
$this->addRules( $formRules );
$this->addElement('submit', 'submit');
}
}
+115
View File
@@ -0,0 +1,115 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Login.php 2264 2010-06-03 16:53:43Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Login
*/
/**
*
* @package Piwik_Login
*/
class Piwik_Login extends Piwik_Plugin
{
public function getInformation()
{
$info = array(
'description' => Piwik_Translate('Login_PluginDescription'),
'author' => 'Piwik',
'author_homepage' => 'http://piwik.org/',
'version' => Piwik_Version::VERSION,
);
return $info;
}
function getListHooksRegistered()
{
$hooks = array(
'FrontController.initAuthenticationObject' => 'initAuthenticationObject',
'FrontController.NoAccessException' => 'noAccess',
'API.Request.authenticate' => 'ApiRequestAuthenticate',
'Login.initSession' => 'initSession',
);
return $hooks;
}
function noAccess( $notification )
{
$exception = $notification->getNotificationObject();
$exceptionMessage = $exception->getMessage();
$controller = new Piwik_Login_Controller();
$controller->login($exceptionMessage);
}
function ApiRequestAuthenticate($notification)
{
$tokenAuth = $notification->getNotificationObject();
Zend_Registry::get('auth')->setLogin($login = null);
Zend_Registry::get('auth')->setTokenAuth($tokenAuth);
}
function initAuthenticationObject($notification)
{
$auth = new Piwik_Login_Auth();
Zend_Registry::set('auth', $auth);
$action = Piwik::getAction();
if(Piwik::getModule() === 'API'
&& (empty($action) || $action == 'index'))
{
return;
}
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
$authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
$authCookiePath = Zend_Registry::get('config')->General->login_cookie_path;
$authCookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath);
$defaultLogin = 'anonymous';
$defaultTokenAuth = 'anonymous';
if($authCookie->isCookieFound())
{
$defaultLogin = $authCookie->get('login');
$defaultTokenAuth = $authCookie->get('token_auth');
}
$auth->setLogin($defaultLogin);
$auth->setTokenAuth($defaultTokenAuth);
}
function initSession($notification)
{
$info = $notification->getNotificationObject();
$login = $info['login'];
$md5Password = $info['md5Password'];
$tokenAuth = Piwik_UsersManager_API::getInstance()->getTokenAuth($login, $md5Password);
$auth = Zend_Registry::get('auth');
$auth->setLogin($login);
$auth->setTokenAuth($tokenAuth);
$authResult = $auth->authenticate();
if(!$authResult->isValid())
{
throw new Exception(Piwik_Translate('Login_LoginPasswordNotCorrect'));
}
$ns = new Zend_Session_Namespace('Piwik_Login.referer');
unset($ns->referer);
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
$authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
$authCookiePath = Zend_Registry::get('config')->General->login_cookie_path;
$cookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath);
$cookie->set('login', $login);
$cookie->set('token_auth', $authResult->getTokenAuth());
$cookie->save();
Zend_Session::regenerateId();
}
}
@@ -0,0 +1,40 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: PasswordForm.php 1736 2009-12-26 21:48:30Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Login
*/
/**
*
* @package Piwik_Login
*/
class Piwik_Login_PasswordForm extends Piwik_Form
{
function __construct()
{
parent::__construct();
// reset
$this->updateAttributes('id="lostpasswordform" name="lostpasswordform"');
}
function init()
{
$formElements = array(
array('text', 'form_login'),
);
$this->addElements( $formElements );
$formRules = array(
array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_LoginOrEmail')), 'required'),
);
$this->addRules( $formRules );
$this->addElement('submit', 'submit');
}
}
@@ -0,0 +1,54 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: ResetPasswordForm.php 2036 2010-04-01 21:08:24Z matt $
*
* @category Piwik_Plugins
* @package Piwik_Login
*/
/**
*
* @package Piwik_Login
*/
class Piwik_Login_ResetPasswordForm extends Piwik_Form
{
function __construct()
{
parent::__construct();
// reset
$this->updateAttributes('id="resetpasswordform" name="resetpasswordform"');
}
function init()
{
$resetToken = Piwik_Common::getRequestVar('token', '', 'string');
$formElements = array(
array('text', 'form_login'),
array('password', 'form_password'),
array('password', 'form_password_bis'),
array('text', 'form_token'),
);
$this->addElements( $formElements );
$defaults = array(
'form_token' => $resetToken,
);
$this->setDefaults($defaults);
$formRules = array(
array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('General_Username')), 'required'),
array('form_password', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Password')), 'required'),
array('form_password_bis', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_PasswordRepeat')), 'required'),
array('form_token', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_PasswordResetToken')), 'required'),
array('form_password', Piwik_Translate( 'Login_PasswordsDoNotMatch'), 'fieldHaveSameValue', 'form_password_bis'),
);
$this->addRules( $formRules );
$this->addElement('submit', 'submit');
}
}
@@ -0,0 +1,33 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head>
<title>Piwik &rsaquo; {'Login_LogIn'|translate}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
<link rel="stylesheet" type="text/css" href="plugins/Login/templates/login.css" media="screen" />
{postEvent name="template_css_import"}
{literal}
<script type="text/javascript">
function focusit() {
var formLogin = document.getElementById('form_login');
if(formLogin)
{
formLogin.focus();
}
}
window.onload = focusit;
</script>
{/literal}
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
{postEvent name="template_js_import"}
</head>
<body class="login">
<!-- shamelessly taken from wordpress 2.5 - thank you guys!!! -->
<div id="logo">
<a href="http://piwik.org" title="{$linkTitle}"><span class="h1"><span style="color: rgb(245, 223, 114);">P</span><span style="color: rgb(241, 175, 108);">i</span><span style="color: rgb(241, 117, 117);">w</span><span style="color: rgb(155, 106, 58);">i</span><span style="color: rgb(107, 50, 11);">k</span> <span class="description"># {'General_OpenSourceWebAnalytics'|translate}</span></span></a>
</div>
@@ -0,0 +1,151 @@
/* shamelessly taken from wordpress 2.5 - thank you guys!!! */
* {
margin: 0;
padding: 0;
}
body {
font: 12px "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana,
sans-serif;
}
form {
margin-left: 8px;
padding: 16px 16px 40px 16px;
font-weight: bold;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
form .forgetmenot {
font-weight: normal;
float: left;
margin-bottom: 0;
}
#login form .submit input {
font-family: "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana,
sans-serif;
padding: 3px 5px;
border: none;
font-size: 13px;
border-width: 1px;
border-style: solid;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
cursor: default;
text-decoration: none;
margin-top: -6px;
}
form .submit {
float: right;
}
form p {
margin-bottom: 24px;
}
.updated,.login #login_error,.login .message {
background-color: #ffffe0;
border-color: #e6db55;
}
#login {
width: 292px;
margin: 7em auto;
margin-top: 20px;
}
#login_error,.message {
margin: 0 0 16px 8px;
border-width: 1px;
border-style: solid;
padding: 12px;
}
#nav {
margin: 0 0 0 8px;
padding: 16px;
}
#form_password,#form_login,#user_email,#form_token {
font-size: 20px;
width: 97%;
padding: 3px;
margin-right: 6px;
}
#login form input {
color: #555;
}
.login form {
background-color: #eaf3fa;
}
#login form .submit input {
background-color: #cee1ef !important;
}
#login #login_error {
background-color: #ffebe8;
border-color: #c00;
}
#login form .submit input {
background-color: #e5e5e5;
color: #246;
border-color: #80b5d0;
}
#login form .submit input:hover {
color: #d54e21;
}
#login form .submit input:hover {
border-color: #328ab2;
}
.login #login_error {
background-color: #ffffe0;
border-color: #e6db55;
}
.login #nav a {
color: #777;
}
body.login {
border-top-color: #464646;
}
#login form input {
color: #555;
}
a {
text-decoration: none;
}
#logo {
margin-left: 38%;
margin-top: 100px;
}
#logo .h1 {
font-family: Georgia, "Times New Roman", Times, serif;
font-weight: normal;
color: #136F8B;
font-size: 45pt;
text-transform: none;
}
#logo .description {
font-family: Georgia, "Times New Roman", Times, serif;
font-weight: normal;
color: #879dbd;
font-size: 19pt;
}
@@ -0,0 +1,43 @@
{include file="Login/templates/header.tpl"}
<div id="login">
{if $form_data.errors}
<div id="login_error">
{foreach from=$form_data.errors item=data}
<strong>{'General_Error'|translate}</strong>: {$data}<br />
{/foreach}
</div>
{/if}
{if $AccessErrorString}
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
{/if}
<form {$form_data.attributes}>
<p>
<label>{'General_Username'|translate}:<br />
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" />
<input type="hidden" name="form_nonce" id="form_nonce" value="{$nonce}" /></label>
</p>
<p>
<label>{'Login_Password'|translate}:<br />
<input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label>
</p>
{*
<p class="forgetmenot"><label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="90" /> Remember Me</label></p>
*}
<p class="submit">
<input type="submit" value="{'Login_LogIn'|translate}" tabindex="100" />
</p>
</form>
<p id="nav">
<a href="index.php?module=Login&amp;action=lostPassword" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
</p>
</div>
</body>
</html>
@@ -0,0 +1,38 @@
{include file="Login/templates/header.tpl"}
<div id="login">
{if $form_data.errors}
<div id="login_error">
{foreach from=$form_data.errors item=data}
<strong>{'General_Error'|translate}</strong>: {$data}<br />
{/foreach}
</div>
{/if}
{if $AccessErrorString}
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
{/if}
<p class="message">
{'Login_PasswordReminder'|translate}
</p>
<form {$form_data.attributes}>
<p>
<label>{'Login_LoginOrEmail'|translate}:<br />
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
</p>
<p class="submit">
<input type="submit" value="{'Login_RemindPassword'|translate}" tabindex="100" />
</p>
</form>
<p id="nav">
<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
</p>
</div>
</body>
</html>
@@ -0,0 +1,22 @@
{include file="Login/templates/header.tpl"}
<div id="login">
{if isset($ErrorString)}
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$ErrorString}<br />
{'Login_ContactAdmin'|translate}
</div>
{else}
<p class="message">
{'Login_PasswordSuccessfullyChanged'|translate}
</p>
{/if}
<p id="nav">
<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
</p>
</div>
</body>
</html>
@@ -0,0 +1,22 @@
{include file="Login/templates/header.tpl"}
<div id="login">
{if isset($ErrorString)}
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$ErrorString}<br />
{'Login_ContactAdmin'|translate}
</div>
{else}
<p class="message">
{'Login_PasswordSent'|translate}
</p>
{/if}
<p id="nav">
<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
</p>
</div>
</body>
</html>
@@ -0,0 +1,50 @@
{include file="Login/templates/header.tpl"}
<div id="login">
{if $form_data.errors}
<div id="login_error">
{foreach from=$form_data.errors item=data}
<strong>{'General_Error'|translate}</strong>: {$data}<br />
{/foreach}
</div>
{/if}
{if $AccessErrorString}
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
{/if}
<form {$form_data.attributes}>
<p>
<label>{'Login_LoginOrEmail'|translate}:<br />
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
</p>
<p>
<label>{'Login_Password'|translate}:<br />
<input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label>
</p>
<p>
<label>{'Login_PasswordRepeat'|translate}:<br />
<input type="password" name="form_password_bis" id="form_password" class="input" value="" size="20" tabindex="30" /></label>
</p>
<p>
<label>{'Login_PasswordResetToken'|translate}:<br />
<input type="text" name="form_token" id="form_token" class="input" value="{$form_data.form_token.value}" size="20" tabindex="40" /></label>
</p>
<p class="submit">
<input type="submit" value="{'Login_ChangePassword'|translate}" tabindex="100" />
</p>
</form>
<p id="nav">
<a href="index.php?module=Login&amp;action=lostPassword" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
</p>
</div>
</body>
</html>