From 171d362ecf65f78618d2fcf72cf815da5aca7a2d Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Sat, 10 Jul 2010 04:25:56 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Piwik=20=E5=88=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=BA=93=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@475 a2543c7e-f6e9-4f8a-8bff-1ffc34733512 --- oss/piwik/trunk/plugins/Live/API.php | 299 +++++++++++++ oss/piwik/trunk/plugins/Live/Controller.php | 184 ++++++++ oss/piwik/trunk/plugins/Live/Live.php | 52 +++ oss/piwik/trunk/plugins/Live/Visitor.php | 327 ++++++++++++++ .../Live/templates/images/download.png | Bin 0 -> 734 bytes .../plugins/Live/templates/images/file0.png | Bin 0 -> 535 bytes .../plugins/Live/templates/images/file1.png | Bin 0 -> 683 bytes .../plugins/Live/templates/images/file2.png | Bin 0 -> 632 bytes .../plugins/Live/templates/images/file3.png | Bin 0 -> 661 bytes .../plugins/Live/templates/images/file4.png | Bin 0 -> 596 bytes .../plugins/Live/templates/images/file5.png | Bin 0 -> 653 bytes .../plugins/Live/templates/images/file6.png | Bin 0 -> 654 bytes .../plugins/Live/templates/images/file7.png | Bin 0 -> 637 bytes .../plugins/Live/templates/images/file8.png | Bin 0 -> 574 bytes .../plugins/Live/templates/images/file9.png | Bin 0 -> 566 bytes .../plugins/Live/templates/images/goal.png | Bin 0 -> 672 bytes .../Live/templates/images/outboundlink.png | Bin 0 -> 799 bytes .../plugins/Live/templates/images/pause.gif | Bin 0 -> 669 bytes .../Live/templates/images/pause_disabled.gif | Bin 0 -> 619 bytes .../plugins/Live/templates/images/play.gif | Bin 0 -> 666 bytes .../Live/templates/images/play_disabled.gif | Bin 0 -> 407 bytes .../templates/images/returningVisitor.gif | Bin 0 -> 995 bytes .../trunk/plugins/Live/templates/index.tpl | 183 ++++++++ .../plugins/Live/templates/lastVisits.tpl | 35 ++ .../plugins/Live/templates/scripts/spy.js | 154 +++++++ .../plugins/Live/templates/totalVisits.tpl | 26 ++ oss/piwik/trunk/plugins/Login/Auth.php | 68 +++ oss/piwik/trunk/plugins/Login/Controller.php | 415 ++++++++++++++++++ oss/piwik/trunk/plugins/Login/Form.php | 43 ++ oss/piwik/trunk/plugins/Login/Login.php | 115 +++++ .../trunk/plugins/Login/PasswordForm.php | 40 ++ .../trunk/plugins/Login/ResetPasswordForm.php | 54 +++ .../trunk/plugins/Login/templates/header.tpl | 33 ++ .../trunk/plugins/Login/templates/login.css | 151 +++++++ .../trunk/plugins/Login/templates/login.tpl | 43 ++ .../plugins/Login/templates/lostPassword.tpl | 38 ++ .../Login/templates/passwordchanged.tpl | 22 + .../plugins/Login/templates/passwordsent.tpl | 22 + .../plugins/Login/templates/resetPassword.tpl | 50 +++ 39 files changed, 2354 insertions(+) create mode 100644 oss/piwik/trunk/plugins/Live/API.php create mode 100644 oss/piwik/trunk/plugins/Live/Controller.php create mode 100644 oss/piwik/trunk/plugins/Live/Live.php create mode 100644 oss/piwik/trunk/plugins/Live/Visitor.php create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/download.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file0.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file1.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file2.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file3.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file4.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file5.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file6.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file7.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file8.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/file9.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/goal.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/outboundlink.png create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/pause.gif create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/pause_disabled.gif create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/play.gif create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/play_disabled.gif create mode 100644 oss/piwik/trunk/plugins/Live/templates/images/returningVisitor.gif create mode 100644 oss/piwik/trunk/plugins/Live/templates/index.tpl create mode 100644 oss/piwik/trunk/plugins/Live/templates/lastVisits.tpl create mode 100644 oss/piwik/trunk/plugins/Live/templates/scripts/spy.js create mode 100644 oss/piwik/trunk/plugins/Live/templates/totalVisits.tpl create mode 100644 oss/piwik/trunk/plugins/Login/Auth.php create mode 100644 oss/piwik/trunk/plugins/Login/Controller.php create mode 100644 oss/piwik/trunk/plugins/Login/Form.php create mode 100644 oss/piwik/trunk/plugins/Login/Login.php create mode 100644 oss/piwik/trunk/plugins/Login/PasswordForm.php create mode 100644 oss/piwik/trunk/plugins/Login/ResetPasswordForm.php create mode 100644 oss/piwik/trunk/plugins/Login/templates/header.tpl create mode 100644 oss/piwik/trunk/plugins/Login/templates/login.css create mode 100644 oss/piwik/trunk/plugins/Login/templates/login.tpl create mode 100644 oss/piwik/trunk/plugins/Login/templates/lostPassword.tpl create mode 100644 oss/piwik/trunk/plugins/Login/templates/passwordchanged.tpl create mode 100644 oss/piwik/trunk/plugins/Login/templates/passwordsent.tpl create mode 100644 oss/piwik/trunk/plugins/Login/templates/resetPassword.tpl diff --git a/oss/piwik/trunk/plugins/Live/API.php b/oss/piwik/trunk/plugins/Live/API.php new file mode 100644 index 00000000..d134e4fa --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/API.php @@ -0,0 +1,299 @@ +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]); + } + } + } + +} diff --git a/oss/piwik/trunk/plugins/Live/Controller.php b/oss/piwik/trunk/plugins/Live/Controller.php new file mode 100644 index 00000000..23cb310d --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/Controller.php @@ -0,0 +1,184 @@ +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; + } +} diff --git a/oss/piwik/trunk/plugins/Live/Live.php b/oss/piwik/trunk/plugins/Live/Live.php new file mode 100644 index 00000000..b958705f --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/Live.php @@ -0,0 +1,52 @@ + 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 "\n"; + } + + function addMenu() + { + Piwik_AddMenu('General_Visitors', 'Live_VisitorLog', array('module' => 'Live', 'action' => 'getLastVisitsDetails')); + } + + public function addWidget() { + Piwik_AddWidget('Live!', 'Live Visitors!', 'Live', 'widget'); + } + +} diff --git a/oss/piwik/trunk/plugins/Live/Visitor.php b/oss/piwik/trunk/plugins/Live/Visitor.php new file mode 100644 index 00000000..4002d789 --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/Visitor.php @@ -0,0 +1,327 @@ +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; + } +} diff --git a/oss/piwik/trunk/plugins/Live/templates/images/download.png b/oss/piwik/trunk/plugins/Live/templates/images/download.png new file mode 100644 index 0000000000000000000000000000000000000000..1920b1bb2230d3ee4f67c0c2fdc51405432449b0 GIT binary patch literal 734 zcmV<40wMj0P)Uj3N}7+QYz(bv8o z_x<$T0&O*DyvfPA=iYNZ_nULBaOLSX{<0?SPGyu@J;LkqZj<8jNlCK4-317ufYWO7 zI4rs>7_Qfu;4!v&3^0ubqA=>Pv=2T;fa7KiXMewFhT~;b5U~wYzT4K<_^Dp zb(Hgo+)M}HyIwD#+^6(kyK!r>(DEWI?fIxFX^c$`O$_!4c)zfu`8F#Fg3zgv)X6(t zKp3vH^oCLST+JoNvzb*Z23<(tOur26#aqqM8*{QOmjqGl0`mDh6sHQ6)!GNGAhBW- zWTUc{8@Zg%h%}kn^Ou@i*XJZEPGcW~)>o?8Y}X0X)6<6&AS%(JON00lUc{EG+!mAS zeLk?LVLTj)H%mG3J5s?eeBVbHh9^&fCrn}&ds3>j(@4JKXBnxnelF610RNnVLQTBR zJrB}C9cj7V)8NjQ|H_3U5BXRM`J1z|vkz2N%{ug1Y}+DpNG^YtcRfZHhhqLrWtECo9#T_gMQj5g+d{*yu7?du=BaxrM3#j z+}{+~Zvw3R_^@UeMxs)wWOyI=%~`TxQZN>a#m4a;%k#XCq+pe{)n5V(09KY!`^#Ai QPXGV_07*qoM6N<$f`MLDGXMYp literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/file0.png b/oss/piwik/trunk/plugins/Live/templates/images/file0.png new file mode 100644 index 0000000000000000000000000000000000000000..2c6ce30fe3b8523dd3f5515a33f26d153cb28a33 GIT binary patch literal 535 zcmV+y0_gpTP)Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH?1KNQk*#H0msYygZR5;7c zl)-MoFbszOcvY!DhzW5V+GR(yBUjEmEzhvM#deuEQq)Qal)7CS?~tqo)RJl1VOCWo zYW&6iYg^gl5seuGV-Q8{J4yUHWS1wL!xhVz_EW#n#m+f9pCs}AZea|Ve;kp!-&zp) zK$v}Y4f=TK`Ivpwm)g-4Sl-^GuI2L+%wUGK^6}v*?s0KB z+>MAN%T$uU7-{4`7p_qtkeaiq@)|h`bG_Mkv4{Y`T6%s~kB_%f12eS7=>%q+PS6@e z?Z0CN5t!?jmz${pvftzWzS$~3>Ka+51_P;U7=xlvgMnIqBRoA_D}7$*TFZPM=>EI)+P=QZ zeh;lN9Cj2(9IMgjZne5fUtLT{W<-%34#9b-CX=>-J3!3<>gmjOR5r(YLBBP^AKCu{ ZeE~6Z1I?Id=tKYj002ovPDHLkV1mSO=$rrm literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/file1.png b/oss/piwik/trunk/plugins/Live/templates/images/file1.png new file mode 100644 index 0000000000000000000000000000000000000000..074e57705801f57b4fec99647f38c52fdc7452c5 GIT binary patch literal 683 zcmV;c0#yBpP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#00007bV*G`2iXV# z2s8x4eXX?s00JvXL_t(I%dJ$sQrticmb6~mWC%AT1(VFs@&+`#0tHXVJ5ccyR1~!7 z5}*l}Ic%?Y^(n=gJKtenilD-?Kk_GipH^b1(wmto0VJ~ia#0w-B7+Ar%~&zsu!s?j zu?#TPe680ph&@h_OC7`Eq`4K+e}i{yaQn zrA*a;Oxa>&5i*+*+qv%fxi~sP-w$!h5`E9kv2z zy{U4Z3L;w#WHwY_A2l;#c2$KCwCkiS?cKv;5%j&3rK_s>USlSrPp79`6bFZg+0RB| zGjl#nt5tb?JWtKcfbUmVziw~ia;a_W>Uv9ZGlU>@%|-F;@^Y=$5N13fb6dsba!rb5 zcVOj1zgU>6l;tMhF;Es;ywANhIlyxFuHB}9=7-i!L3TYSGWrh_`XKu-puemam<9%O R@ihPd002ovPDHLkV1lT~EQPx#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH*Ct(`g#{d8V3Q0skR5;7c zR6TDKK@i=Y*}Joy6j1;nXowJq79sHyX!sR0{1AQyE&l^5sx(xTDJ($)3IxmdwKMaU zVjbH#9AAVenBsJIyZdI|+c)Das=JINNCwZee$pf)fiK97McDqx2d-cVphlNVd*aG+ zPVSkUb2JGVnx{oxLZ>&aC>fFg3h%vBb8u*4n3c(}hQ1j!rtcr;&HSf>qX{QV=yY~+ zboa%hB*^umQ_tiJ8fZ6U{_XvlwW>|jMQ?RXh99S2vQkh>f?O9m9jG=GyZyQ-kEe*X z%2Tq|;tS%fW0~nbYB{tPPYwzy*jhm+pWl42TKJ&wM9#Sc+<*Dx=;^(E)T|X@!X&h)FwKgKq zf_7Y}C1cNd+XzsEM2IB=;GFZ$Z_05A3C>CIAwougCR{e!w&*J=Ee(ywo_fTJ$_bYv zK#va}a23K~nUzjR8?njfpSp~_Q=a^3j*3dI!pW;=gQoS{ z6Vh6t!2Nl%zV$qt23_Wvs#`OtPx#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH+5x2W|9{>OXCrLy>R5;7c zls#|MKoEv!XFq)BB+#591Of^QdKwx^Bt$_$L4{KBWB4OTbW}izL`?w&4QUYyoPb=; zXRkdwJ4><2#rVQqgeZ6mYwdUU*_rX~sIF!>k+8%d+T!wQ$3|GtAZ(K9zvKmdmas61 zIkDF0H#={xEdqcYn~Zj)$yV@u-iTt57=%Mo3Q&v0B+R276N4<#=K^VqA734O`&3Cx zZp);YsOH_9JGUNP6_y-t@T@JO!9neYnSXfkg=(gn{UNpUATjN~ndV9{iLm6jg6Bci zhQ*#9eBYj2;VvHAg>L5o4Z7a4oawsMvf3)3R!m|?ni{4iK6~Gt0B z8+Rt_Qfs(sX4D)K)m;DR+IeuLHV#dpg%j1REmF-dpT1w08UW1N>7>4VYCB|->ZdP8 zE(YPqdHlKB2e`Km6r>BW0{}@8l_sB#BlWD6>7uvjy!RySh8mHy4Oc-304%yZ$g=1< zZVFT8{WgH2@Pdx=xC7s}I`9H9P|&EO@CK0Qh3ATe47$}H8WU?}^0W;gmcT*+l7m;E zmR5q4AjQN8$PzYyEV@p76xL`&h6fK3vt?J}9fEetYlSJtW;<6prBjwtm_K@6Ty&Fl zAYpm9cmMVCx3hLi(mEWi9uA8|Vaf-O?+z}l>UT(L*f^YjZI`zx_ol%u(-tpW8Zk+3 vRcC-QYuU-p?t}*W)BXthYa#q2{ePfeJQj5#^~Ri}00000NkvXXu0mjf@s}fq literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/file4.png b/oss/piwik/trunk/plugins/Live/templates/images/file4.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c277981ed8eb88ec33c8251040d3a52e065ce6 GIT binary patch literal 596 zcmV-a0;~OrP)Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH-J4Y?z3IG5B=1D|BR5;7c zl);J=F%X86bdu=?*>%{1E9gyp071bQ@UR!((2FnNLGa)s2!bHu(Ua^7i%jcur;@6Q zhnmgyW}I#j57wbcx{@zdf2yKmBz0v(nJ71nE?@7BjMb9a=|nbEEKIq$X3R_{vRU?c zZ)E?fHR6hqXFz(Ink;3?TJO$B2lB^(_)#GM@08VFp3D^f0`CN_>_ zj3Ua`8UO;ImoL7IBXwOP+U1;|JUw~v@YY;v5O^4H*b)TZ{={)4=S|aSXAPzdKux0| z@atD!=TcKj^_z5i?XKO{Ao7nM+tx6v7Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH;A7V8(ng9R-A4x<(R5;7c zl)Y{gK@7)j&wge14hlXLK$J)bB+{heE$HZ>vm_x zHpL{%-U7D~qQJ#!?HT=S|7XV7I1iWRRGnx{IDB(MPBlh^Ig7?lj0glY2mraEfG&&)OD)S)D{`U^lvN4A0suhCaxIRW=zzXjYlQE!VM*S_1&LKG|gV2bYzs$hvpS$T-!GFaFO~D}X1v zK-@OHC;)hs2&t2cdtZ8wfL0_SsyuUD&1fWjS9;H)0ANUXq^lwH)<#JZw#|UJuH0p| z$wd|b6?L}9DCV}A0r|4zrV(o?Nq#-hA@0j^2BhBcW&`ZmI{*M29jgk6udGvZligh?XD@$o@M!XAaXcX#=7i`=XPxTLQMa8b1oyMViWH*Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH<0BEHqpa1{@AW1|)R5;7c zl)Y{gK@7(|G)SqC=xC_vsOfko9s=bJ@&c4dhyo!Rgi_>+B$vDF zjpxHQ#lYsY`Pc|i;9@m1-u$g0gv`Cya9%285n zVUT4vH|6KfQ~)rxqk?X5TwEmKt`Q~8Ni(ZhFaQYvlKKfYNppw36UdqB)AH*P%>}f! zj#XHBZ}i~h>^Uo!cu9gY6&mbmXM5m}i_dEbo@t$Z;E*MMS$!``MM)%s%3 z!^yOounIv005p~)qQM4nQ-OihijhPMCMnm}u_TiC{^tkJ)ZiG61progwew*;N& zk%Wu9Ugp*_ou^gH-WhZTYwK9qGoeAxbZ~rlTWSDsMDtxYyL8(sOJ3%-!Eu(H^!NH( z`(q%r6|ai~r6_?@Id9opFi}!%oo8C)ivbYj(6VRcqJ3F(r67r8tpOl~H~`A0wAfnR z)OA@h*-%@Tmtg>u&ggt^6*P^Ey9(;g(-{qbBudLZDMyn4z=FASfwGE+(BMd-41lny z)|v7tRnw6~?qBg5^D?Aq#HJbmJ%09Ng3ZqMv?wj08!czhAn)>7TIT&*BVy%ukKP;{ zA0E+skuPS|*45^?kM}0nynXn(cWKS$g!D|cbtmb(t9q|}ySCVM+fh;(Ro8$DtD9uk oc0fUQuiXgxYqRi=?EeG(0(*dOajzv8FaQ7m07*qoM6N<$f;`A6`~Uy| literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/file7.png b/oss/piwik/trunk/plugins/Live/templates/images/file7.png new file mode 100644 index 0000000000000000000000000000000000000000..8559758b56c7b2c7e4c7a4c4e12f0e1e845db4c4 GIT binary patch literal 637 zcmV-@0)qXCP)Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muKJ6$(Bj#sB~U4@pEpR5;7c zl(CKzK@5gHp4r{oK!WZLq@#!sItkHJTyxJs$Aj?@@Dfy1M?r;zXmTfk1W7K*PR3(< zC`MUr5-tmf0vD?t&+NDMZ;wsj6>LnCs4}8!pUzgA1dWA0!>xs}T?(SpBqF3q{tT3V zj_3fu*(#$8SLZF3Z~)}CK*|cNNeq}A10^oqK$TncZ-EfqWcFd!+$2zoWlEw+Mn`8) zPcJk{j+Z4MIy81iJKO<(`Tm~NlX&7)l(lHQx&4@x%3|fXSi(*P+>Y3{>#s+}P?PY+ zlfOY%cNOSKEnAdej8SEaB`1m+-hF;e;!9f_V*wx~Ie&P0HhO+2HP#S#xsD4G@8g`f zvBn`fhovTo;?YHh~C^Z0>`RjY-NxMu~sK#|%6s}f{qMYBqEkE_77I-PjZBMaM z_7krRAZu_~MfN_ z=d9$g+y}M(<*YBFNJ`vDilPJnrc>4gnhRIhI+FH)s@eti%P9?pZvS*qVzc1EkgD4C zfX<(dOFI}JA7`Z#q;|`IL1XoiG&DUO$-6)Zgr&;00000NkvXXu0mjf&V3ft literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/file8.png b/oss/piwik/trunk/plugins/Live/templates/images/file8.png new file mode 100644 index 0000000000000000000000000000000000000000..515bd791d7b0a489b86e420b0fce71b1f8256c60 GIT binary patch literal 574 zcmV-E0>S->P)Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH>vk54AZz=)}+PF9Q*hO9kWm}G^Ml?;qT1%OO@bpIlg@^dQ^ z3RD0G0#pFVo4~nH9?{PM5moNKceVl$m;{%)DlTXB2gv$*rA$;{9BCIu;9dI->ZI)2 zNDWZh?nkebP$28;lJZEkvDn3bhOm%K0st~f9TfNQ*q%7aMujM=U2UkPBASyCJ>IIVT*3Heu)_`KG7_JB43Mj?bWCDt0 zjy0Luay!wQlqKuy2LfQnJOH63YAL&KCqV97so5I`)lgTWa^*k+;Mz=pimhC452tfl zEFhVq1!}XqX^{CnB#>wPd&n1CO@MOii&>UzXq*AZAOy~H>l2`qlKZyUD#oSMjCRSn z*J+Lk!pZ`FR#}{O5kioejp5&z=JPbp-sQ`2Rq^0S)sqfx>a=q5uE@ M07*qoM6N<$f*5E2hyVZp literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/file9.png b/oss/piwik/trunk/plugins/Live/templates/images/file9.png new file mode 100644 index 0000000000000000000000000000000000000000..c06ec15bdb8305c6999af595e06fceffb50c31e5 GIT binary patch literal 566 zcmV-60?GY}P)Px#32;bRa{vGi!~g&e!~vBn4jTXf00(qQO+^RU2muH=HogRccmMza$Vo&&R5;7c zlud5bKoEsLcYACsi%1MoB4EQNNJuQ$AuhlHH~<&p5;+KqY_dREW~3;HKaJxtwyVo5 zy2pc^89PEOcnhoB?S8KJ^s1t+UeiMzDwufpj8oKMEOUqlJAYxorIkG@w|KE&mX!sG})D zGF8I*+vhoHt_l`(j>zup@F8+FHVswJ5H%(3W}D`C;H!yo73u(*+c~0Q#q#uE?9|~J zY(jZ6OLRr`BZT`d`u9Gx6GV+@;%zefk`a0(Z$y)6q9n~|N{SWv32ikdT4a~0s+5S;z2cI1z`db+O5&l1--*67~3441R5;6} z(_KtbVHgK+*KHTwb z3U8KEr|M6CKHF5d&eQVNxr*Xd#pN8o{Cp0%jbBO9Pl3P2cIMh>fmjREstPwbsR%UAN&a~0&W97_+{w2 zzK;Pe5g_}Da_b3Y$=5(~fG&DU3P+ZQ@qA?rj`(8?e(XnAv>p1lR%ogzEDpDzrF16) z>>$A2s?J^XXy3bIMu@`YByICjm?Ii^mmGBZV2)~`4mZPIM`5A2nrR066HnGEYA&=F z{ItC{p*~!JTj5FqSfV=gCp=^dW8^+e7-xWNN zxg9h5B6J9LGr&<6$h%weF5k=nw=Wx9Cml;Jj>-7nQg?!GIQQV{9x_4d_iwmJ{{Z)# z5>8sc{Dg*|7C@Q@mHF%nZwj!Ba~VLi89@E#6*A|x)Vtp=Lby^Yqxhx(0000#yLz&Ndx##4AnMLxFXBZ(g%HuJ zXi&qdfM(p}?71_;z-a>z1OY)1kR%Cdn$l{uaL%E% z20$r|G3H}0Xl>|O*#nSQ0Qr2LFbv7%a)e>nxm#-iK?Fn;rO}H#*uEVR!P*eOn08KU zEzY@4ZV^E#g$TGTkl0Q5yTko z96r1hp-s`2)|%YZ6svCDq_A@*KN&-G|2`-NL;2>{ay<)mpM1>)Xl?vJ194<}C>UEMz1(#)? z2-^S9HcD2kVCu*bayPCMH=C^7umK&0EG{h2Qi}O%6`Yd}!S|+-h9S4NY{31bkNg24I=4Iksz%a>Tzznj;k653ieJ|1K8_%QpT zsQ-%yp65||Q^JNmza1DLpU)yz5Kkbm-p{$%*@Oz8Th_`>gu&CBehx;5n=4n*f;C^bvfq< dg5VDz{U1L){aup)rDXsB002ovPDHLkV1hluXGs76 literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/pause.gif b/oss/piwik/trunk/plugins/Live/templates/images/pause.gif new file mode 100644 index 0000000000000000000000000000000000000000..5954f9f5457992b0c72d30ad6978faf185827390 GIT binary patch literal 669 zcmV;O0%H9~Nk%w1VG;lm0OkMy{{H{>`1_)xrQzl5?ezcI-sb4<`ODAM*W2Oo_51Dd z_fmntQGmWtfW2v$)@hj4(&G5f-}Tz+|K9BXxWm%h=Jm_fd)Ec z-stt)Gs^@@2Ri1y1>Zn^7`xX`P<;<@AUib^ZM%V_Vf1o^7Z*s zgu_yU!BT_3RE5K0l+M+vf7wE$j`dK$L;g_=I{8r zz{a<|!`R;B=U zo`XId2my3wDPLuDXh~H*g9JThvL;6c24GmY2Rx8;6CF`>CNK`gE;L_sTpJUDI43J* z1}zU*SuZpt2`XJUf;Vq-B?c}vMn(%WCPr*(H|=n9Ca_d9GK7H)6GNWJ=|>007${DR zys$weL<1Q|QWWvRj@gF+0EWz%5hRF=7zWl{0J4n^0SHVKKr>;Y0n9le0E6#f@C^*Ue*O9d3_gRwCouT<@#6oTSr{1@To`mf4hO{v1N(^v&Zg#; z*0%PJRz5KW4NWCUflgr+X+dsoAvq24c3}-ZPCgM)eojF>$u5D%nS=AF=ipN5Wz{1A{dH{{!Z) literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/play.gif b/oss/piwik/trunk/plugins/Live/templates/images/play.gif new file mode 100644 index 0000000000000000000000000000000000000000..87eded433b3b139fa910ffe4b75aecf3a42fa6df GIT binary patch literal 666 zcmaLU+e=dc0D$ph&9*EGwq7KY7HBhXS!<;Zi()oI!b<~%vP3kKZm{(#Yx5EjWeFiZ zNGLu8nWm98(vD7T%jKAJ*R!iTySnSycD8e-J7Ir7zvu7myIxa$sl1g6PyrVJq|-zq znHn7%w>$lT7-6uujLx_xgsmwxI>;W0rvi}#uV2RNTdfx^)C=b~wvtL~+~^}Leqv6# z0lDI98plt$R-uKBFrqg5lm?f@6Nj9L!4cMPg|xPS)r*?o(8tMH2`KX;_;v(?Z0=Aj z6^!D(5E?~sB#t%qNE^h94Pubjw=yB~Ov$}petQ)TVnH3)bQ6CpQH2>%!J7M#o5FB#&6W%ap_eA9DnhReMhWazZE&iFp)dq{@!z{Oa@MdrfnciU9%bM4e!XTzsyH!x7v*P7|?C7q*jE zN=nK&SF_ICVTqVe_<7`}=F-x`7wDXaT}=N|em?T@N2d*3K1#m{hsWC56odKN9*~jT z&&@j3qAg3E1%v~1dhQU=um}zxs`{p)1FiCX6_>k*7zLTa7sVIftL&}4q-=mu)!od` vJ93~!eB}X!26G3Gon*Y40)4bMl*VNWcWj*e`sQ0|aaWA-uKC(?0I2*6KP!n4 literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/play_disabled.gif b/oss/piwik/trunk/plugins/Live/templates/images/play_disabled.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef69513d6947a03d439362a7eecee3dea37d4064 GIT binary patch literal 407 zcmZ?wbhEHb6k-r!xXQqA=+L2q2M--MaB%xW$_ zMyyH-F0#DbqJ_-NhLTczB04T=>_VdA64urX+A@-yrY`F2!qX+K8Cis7`^;Sw1bFME ztX9g(2`K8jh{>@@Nz2#>%gHNn=&HN$Y6!8)$_gJd1$f0PVVQH)(=K162Pe%r807xg>GXMYp literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/images/returningVisitor.gif b/oss/piwik/trunk/plugins/Live/templates/images/returningVisitor.gif new file mode 100644 index 0000000000000000000000000000000000000000..bc71867e555f8982450c073f875a5e2e0becc07a GIT binary patch literal 995 zcmZ?wbhEHb6krfw_|CwPnAjGPHecR$zLLvoMaShXAzku5N8}wAD7mdsa$P0kvBxxF zze2!fRhz6S^ER(O@#pZh&)1%OyYlEu)QW%6YyP+F{+hVyU&8kP$=m+VxcEPD=f9+# z|1$Rf%RTB=Rm{ad%C zb?(TXu%~3f7Zx@!o zJG=bVnbq?ngxbCNXGaK44i-$a7Cc+2dag#}Vy))vIQiwdCM&9aS62I-m{a&W&QUTH@m#}+r9V;?fBZg1xp=;T75+G97Ky;B)#>7Cq-+` zO47}CRqFEKpWrPp%}=n_NifEkf5-Hi>E8Uk9zxN^qV0A(|NsAI7zMNp0mYvzj0_B2 z3_2i7KzV|J;{bywr;Nvj1qYoQ8F-yiCM;NB5OU2}ODmll$XxKTKonNuLlWSw- z;`H0~ z&AWk1L`}d`>B;e439X literal 0 HcmV?d00001 diff --git a/oss/piwik/trunk/plugins/Live/templates/index.tpl b/oss/piwik/trunk/plugins/Live/templates/index.tpl new file mode 100644 index 00000000..617dc916 --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/templates/index.tpl @@ -0,0 +1,183 @@ +{literal} + + + + + +{/literal} + +
+ + + + + + + + + + + + + + + + + + + + + +
+
Period
+
Visits
+
PageViews
Today{$visitorsCountToday}{$pisToday}
Last 30 minutes{$visitorsCountHalfHour}{$pisHalfhour}
+
+ +
+{$visitors} +
+ +
+ + +
diff --git a/oss/piwik/trunk/plugins/Live/templates/lastVisits.tpl b/oss/piwik/trunk/plugins/Live/templates/lastVisits.tpl new file mode 100644 index 00000000..e67ab5ec --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/templates/lastVisits.tpl @@ -0,0 +1,35 @@ +{foreach from=$visitors item=visitor} +
+ +
+ {$visitor.serverDatePretty} - {$visitor.serverTimePretty} +   +   +   +  {if $visitor.isVisitorGoalConverted}{/if} + {if $visitor.isVisitorReturning} {/if} +   +
+ +
+ {if $visitor.refererType != 'directEntry'}from {if !empty($visitor.searchEngineIcon)} {/if}{$visitor.refererName} + {if !empty($visitor.keywords)}"{$visitor.keywords}"{/if} + {/if} + {if $visitor.refererType == 'directEntry'}Direct entry{/if} +
+
+ Pages:  + {php} $col = 0; {/php} + {foreach from=$visitor.actionDetails item=action} + {php} + $col++; + if ($col>=9) + { + $col=0; + } + {/php} + + {/foreach} +
+
+{/foreach} diff --git a/oss/piwik/trunk/plugins/Live/templates/scripts/spy.js b/oss/piwik/trunk/plugins/Live/templates/scripts/spy.js new file mode 100644 index 00000000..0a3c3b39 --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/templates/scripts/spy.js @@ -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('
'); + } + + // 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; +} + + + diff --git a/oss/piwik/trunk/plugins/Live/templates/totalVisits.tpl b/oss/piwik/trunk/plugins/Live/templates/totalVisits.tpl new file mode 100644 index 00000000..a7294d78 --- /dev/null +++ b/oss/piwik/trunk/plugins/Live/templates/totalVisits.tpl @@ -0,0 +1,26 @@ +
+ + + + + + + + + + + + + + + + + + + + +
+
{'Live_Date'|translate}
+
{'General_ColumnNbVisits'|translate}
+
{'General_ColumnPageviews'|translate}
{'General_Today'|translate}{$visitorsCountToday}{$pisToday}
{'Live_Last30Minutes'|translate}{$visitorsCountHalfHour}{$pisHalfhour}
+
diff --git a/oss/piwik/trunk/plugins/Login/Auth.php b/oss/piwik/trunk/plugins/Login/Auth.php new file mode 100644 index 00000000..8dd80969 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/Auth.php @@ -0,0 +1,68 @@ +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; + } +} diff --git a/oss/piwik/trunk/plugins/Login/Controller.php b/oss/piwik/trunk/plugins/Login/Controller.php new file mode 100644 index 00000000..4bccff5c --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/Controller.php @@ -0,0 +1,415 @@ + 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'); + } +} diff --git a/oss/piwik/trunk/plugins/Login/Form.php b/oss/piwik/trunk/plugins/Login/Form.php new file mode 100644 index 00000000..8cf2563f --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/Form.php @@ -0,0 +1,43 @@ +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'); + } +} diff --git a/oss/piwik/trunk/plugins/Login/Login.php b/oss/piwik/trunk/plugins/Login/Login.php new file mode 100644 index 00000000..e54dc6f6 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/Login.php @@ -0,0 +1,115 @@ + 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(); + } +} diff --git a/oss/piwik/trunk/plugins/Login/PasswordForm.php b/oss/piwik/trunk/plugins/Login/PasswordForm.php new file mode 100644 index 00000000..c1e3fc96 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/PasswordForm.php @@ -0,0 +1,40 @@ +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'); + } +} diff --git a/oss/piwik/trunk/plugins/Login/ResetPasswordForm.php b/oss/piwik/trunk/plugins/Login/ResetPasswordForm.php new file mode 100644 index 00000000..7f828858 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/ResetPasswordForm.php @@ -0,0 +1,54 @@ +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'); + } +} diff --git a/oss/piwik/trunk/plugins/Login/templates/header.tpl b/oss/piwik/trunk/plugins/Login/templates/header.tpl new file mode 100644 index 00000000..b1cb4b4a --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/header.tpl @@ -0,0 +1,33 @@ + + + + Piwik › {'Login_LogIn'|translate} + + + + + {postEvent name="template_css_import"} + + {literal} + + {/literal} + + {postEvent name="template_js_import"} + + + + + + diff --git a/oss/piwik/trunk/plugins/Login/templates/login.css b/oss/piwik/trunk/plugins/Login/templates/login.css new file mode 100644 index 00000000..af9a89ae --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/login.css @@ -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; +} diff --git a/oss/piwik/trunk/plugins/Login/templates/login.tpl b/oss/piwik/trunk/plugins/Login/templates/login.tpl new file mode 100644 index 00000000..f837ada5 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/login.tpl @@ -0,0 +1,43 @@ +{include file="Login/templates/header.tpl"} + +
+ +{if $form_data.errors} +
+ {foreach from=$form_data.errors item=data} + {'General_Error'|translate}: {$data}
+ {/foreach} +
+{/if} + +{if $AccessErrorString} +
{'General_Error'|translate}: {$AccessErrorString}
+{/if} + +
+

+ +

+ +

+ +

+ {* +

+ *} +

+ +

+
+ + + +
+ + + diff --git a/oss/piwik/trunk/plugins/Login/templates/lostPassword.tpl b/oss/piwik/trunk/plugins/Login/templates/lostPassword.tpl new file mode 100644 index 00000000..7e3e8fbe --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/lostPassword.tpl @@ -0,0 +1,38 @@ +{include file="Login/templates/header.tpl"} + +
+ +{if $form_data.errors} +
+ {foreach from=$form_data.errors item=data} + {'General_Error'|translate}: {$data}
+ {/foreach} +
+{/if} + +{if $AccessErrorString} +
{'General_Error'|translate}: {$AccessErrorString}
+{/if} + +

+{'Login_PasswordReminder'|translate} +

+ +
+

+ +

+

+ +

+
+ + + +
+ + + diff --git a/oss/piwik/trunk/plugins/Login/templates/passwordchanged.tpl b/oss/piwik/trunk/plugins/Login/templates/passwordchanged.tpl new file mode 100644 index 00000000..5337abc2 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/passwordchanged.tpl @@ -0,0 +1,22 @@ +{include file="Login/templates/header.tpl"} + +
+ +{if isset($ErrorString)} +
{'General_Error'|translate}: {$ErrorString}
+ {'Login_ContactAdmin'|translate} +
+{else} +

+ {'Login_PasswordSuccessfullyChanged'|translate} +

+{/if} + + + +
+ + + diff --git a/oss/piwik/trunk/plugins/Login/templates/passwordsent.tpl b/oss/piwik/trunk/plugins/Login/templates/passwordsent.tpl new file mode 100644 index 00000000..7529c57f --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/passwordsent.tpl @@ -0,0 +1,22 @@ +{include file="Login/templates/header.tpl"} + +
+ +{if isset($ErrorString)} +
{'General_Error'|translate}: {$ErrorString}
+ {'Login_ContactAdmin'|translate} +
+{else} +

+ {'Login_PasswordSent'|translate} +

+{/if} + + + +
+ + + diff --git a/oss/piwik/trunk/plugins/Login/templates/resetPassword.tpl b/oss/piwik/trunk/plugins/Login/templates/resetPassword.tpl new file mode 100644 index 00000000..49644b21 --- /dev/null +++ b/oss/piwik/trunk/plugins/Login/templates/resetPassword.tpl @@ -0,0 +1,50 @@ +{include file="Login/templates/header.tpl"} + +
+ +{if $form_data.errors} +
+ {foreach from=$form_data.errors item=data} + {'General_Error'|translate}: {$data}
+ {/foreach} +
+{/if} + +{if $AccessErrorString} +
{'General_Error'|translate}: {$AccessErrorString}
+{/if} + +
+

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+ +

+
+ + + +
+ + +