/** * Audit Log * @param string $entity * @param int $entityId * @param string $message * @param string|object|array $object */ public static function audit($entity, $entityId, $message, $object) { \Debug::Audit(sprintf('Audit Trail message recorded for %s with id %d. Message: %s', $entity, $entityId, $message)); if (self::$_auditLogStatement == null) { $dbh = \PDOConnect::newConnection(); self::$_auditLogStatement = $dbh->prepare(' INSERT INTO `auditlog` (logDate, userId, entity, message, entityId, objectAfter) VALUES (:logDate, :userId, :entity, :message, :entityId, :objectAfter) '); } // If we aren't a string then encode if (!is_string($object)) { $object = json_encode($object); } self::$_auditLogStatement->execute(array('logDate' => time(), 'userId' => \Kit::GetParam('userid', _SESSION, _INT, 0), 'entity' => $entity, 'message' => $message, 'entityId' => $entityId, 'objectAfter' => $object)); }
/** * Does the cache have the specified key * @param string $key The Key * @return boolean True or False */ public static function has($key) { // Load the key self::load($key); if (isset(self::$_data[$key]) && self::$_data[$key] != null) { // If the key has expired remove it if (self::$_data[$key]['expires'] < time()) { Debug::Audit($key . ' Expired: ' . self::$_data[$key]['expires']); // Remove it self::remove($key); return false; } Debug::Audit($key . ' present and in date'); return true; } Debug::Audit($key . ' not present'); return false; }
private function request($latitude, $longitude, $time = null, $options = array()) { $request_url = self::API_ENDPOINT . '[APIKEY]' . '/' . $latitude . ',' . $longitude . (is_null($time) ? '' : ',' . $time); if (!empty($options)) { $request_url .= '?' . http_build_query($options); } \Debug::Audit('Calling API with: ' . $request_url); $request_url = str_replace('[APIKEY]', $this->api_key, $request_url); $httpOptions = array(CURLOPT_TIMEOUT => 20, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_USERAGENT => 'Xibo Digital Signage', CURLOPT_HEADER => false, CURLINFO_HEADER_OUT => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_URL => $request_url); // Proxy support if (\Config::GetSetting('PROXY_HOST') != '' && !\Config::isProxyException($request_url)) { $httpOptions[CURLOPT_PROXY] = \Config::GetSetting('PROXY_HOST'); $httpOptions[CURLOPT_PROXYPORT] = \Config::GetSetting('PROXY_PORT'); if (\Config::GetSetting('PROXY_AUTH') != '') { $httpOptions[CURLOPT_PROXYUSERPWD] = \Config::GetSetting('PROXY_AUTH'); } } $curl = curl_init(); curl_setopt_array($curl, $httpOptions); $result = curl_exec($curl); // Get the response headers $outHeaders = curl_getinfo($curl); if ($outHeaders['http_code'] == 0) { // Unable to connect \Debug::Error('Unable to reach Forecast API. No Host Found (HTTP Code 0). Curl Error = ' . curl_error($curl)); return false; } else { if ($outHeaders['http_code'] != 200) { \Debug::Error('ForecastIO API returned ' . $outHeaders['http_code'] . ' status. Unable to proceed. Headers = ' . var_export($outHeaders, true)); // See if we can parse the error. $body = json_decode($result); \Debug::Error('ForecastIO Error: ' . (isset($body->errors[0]) ? $body->errors[0]->message : 'Unknown Error')); return false; } } // Parse out header and body $body = json_decode($result); return $body; }
/** * PHONE_HOME if required */ private function PhoneHome() { if (Config::GetSetting('PHONE_HOME') == 'On') { // Find out when we last PHONED_HOME :D // If it's been > 28 days since last PHONE_HOME then if (Config::GetSetting('PHONE_HOME_DATE') < time() - 60 * 60 * 24 * 28) { try { $dbh = PDOConnect::init(); // Retrieve number of displays $sth = $dbh->prepare('SELECT COUNT(*) AS Cnt FROM `display` WHERE `licensed` = 1'); $sth->execute(); $PHONE_HOME_CLIENTS = $sth->fetchColumn(); // Retrieve version number $PHONE_HOME_VERSION = Config::Version('app_ver'); $PHONE_HOME_URL = Config::GetSetting('PHONE_HOME_URL') . "?id=" . urlencode(Config::GetSetting('PHONE_HOME_KEY')) . "&version=" . urlencode($PHONE_HOME_VERSION) . "&numClients=" . urlencode($PHONE_HOME_CLIENTS); if ($this->isAuditing == 1) { Debug::LogEntry("audit", "PHONE_HOME_URL " . $PHONE_HOME_URL, "xmds", "RequiredFiles"); } // Set PHONE_HOME_TIME to NOW. $sth = $dbh->prepare('UPDATE `setting` SET `value` = :time WHERE `setting`.`setting` = :setting LIMIT 1'); $sth->execute(array('time' => time(), 'setting' => 'PHONE_HOME_DATE')); @file_get_contents($PHONE_HOME_URL); if ($this->isAuditing == 1) { Debug::Audit("PHONE_HOME [OUT]", $this->displayId); } } catch (Exception $e) { Debug::Error($e->getMessage(), $this->displayId); return false; } } } }
/** * Logs in a specific user * @param int $userId * @return bool */ function LoginServices($userId) { try { $dbh = PDOConnect::init(); $sth = $dbh->prepare('SELECT UserName, usertypeid, homepage FROM user WHERE userID = :userId AND Retired = 0'); $sth->execute(array('userId' => $userId)); if (!($results = $sth->fetch())) { return false; } $this->userid = $userId; $this->userName = Kit::ValidateParam($results['UserName'], _USERNAME); $this->usertypeid = Kit::ValidateParam($results['usertypeid'], _INT); $this->homePage = Kit::ValidateParam($results['homepage'], _WORD); return true; } catch (Exception $e) { Debug::Audit($e->getMessage()); return false; } }
public function LoadDefault() { Debug::Audit('Load Default ' . $this->type); try { $dbh = PDOConnect::init(); // Load the config from disk $this->loadFromFile(); // See if we have a default for this player type $sth = $dbh->prepare('SELECT * FROM `displayprofile` WHERE `type` = :type AND isdefault = 1'); $sth->execute(array('type' => $this->type)); if (!($row = $sth->fetch())) { // We don't so we should stick with the global default Debug::Audit('Fall back to global default'); } else { // We do, so we should overwrite the global default with our stored preferences $this->name = Kit::ValidateParam($row['name'], _STRING); $this->type = Kit::ValidateParam($row['type'], _STRING); $this->isDefault = Kit::ValidateParam($row['isdefault'], _INT); $this->userId = Kit::ValidateParam($row['userid'], _INT); // Load the client settings into an array $config = Kit::ValidateParam($row['config'], _HTMLSTRING); $config = $config == '' ? array() : json_decode($config, true); // We have an array of settings that we must use to overwrite the values in our global config for ($i = 0; $i < count($this->config); $i++) { // Does this setting exist in our store? for ($j = 0; $j < count($config); $j++) { if ($config[$j]['name'] == $this->config[$i]['name']) { $this->config[$i]['value'] = $config[$j]['value']; break; } } } $this->isNew = false; } return true; } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage()); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } }
/** * Data Set Results * @param <type> $dataSetId * @param <type> $columnIds * @param <type> $filter * @param <type> $ordering * @param <type> $lowerLimit * @param <type> $upperLimit * @return <type> */ public function DataSetResults($dataSetId, $columnIds, $filter = '', $ordering = '', $lowerLimit = 0, $upperLimit = 0, $displayId = 0) { $blackList = array(';', 'INSERT', 'UPDATE', 'SELECT', 'DELETE', 'TRUNCATE', 'TABLE', 'FROM', 'WHERE'); try { $dbh = PDOConnect::init(); $params = array('dataSetId' => $dataSetId); $selectSQL = ''; $outserSelect = ''; $finalSelect = ''; $results = array(); $headings = array(); $allowedOrderCols = array(); $filter = str_replace($blackList, '', $filter); $filter = str_replace('[DisplayId]', $displayId, $filter); $columns = explode(',', $columnIds); // Get the Latitude and Longitude ( might be used in a formula ) if ($displayId == 0) { $defaultLat = Config::GetSetting('DEFAULT_LAT'); $defaultLong = Config::GetSetting('DEFAULT_LONG'); $displayGeoLocation = "GEOMFROMTEXT('POINT(" . $defaultLat . " " . $defaultLong . ")')"; } else { $displayGeoLocation = sprintf("(SELECT GeoLocation FROM `display` WHERE DisplayID = %d)", $displayId); } // Get all columns for the cross tab $sth = $dbh->prepare('SELECT DataSetColumnID, Heading, DataSetColumnTypeID, Formula, DataTypeID FROM datasetcolumn WHERE DataSetID = :dataSetId'); $sth->execute(array('dataSetId' => $dataSetId)); $allColumns = $sth->fetchAll(); foreach ($allColumns as $col) { $heading = $col; $heading['Text'] = $heading['Heading']; $allowedOrderCols[] = $heading['Heading']; $formula = str_replace($blackList, '', htmlspecialchars_decode($col['Formula'], ENT_QUOTES)); // Is this column a formula column or a value column? if ($col['DataSetColumnTypeID'] == 2) { // Formula $formula = str_replace('[DisplayGeoLocation]', $displayGeoLocation, $formula); $formula = str_replace('[DisplayId]', $displayId, $formula); $heading['Heading'] = $formula . ' AS \'' . $heading['Heading'] . '\''; } else { // Value $selectSQL .= sprintf("MAX(CASE WHEN DataSetColumnID = %d THEN `Value` ELSE null END) AS '%s', ", $col['DataSetColumnID'], $heading['Heading']); } $headings[] = $heading; } // Build our select statement including formulas foreach ($headings as $heading) { if ($heading['DataSetColumnTypeID'] == 2) { // This is a formula, so the heading has been morphed into some SQL to run $outserSelect .= ' ' . $heading['Heading'] . ','; } else { $outserSelect .= sprintf(' `%s`,', $heading['Heading']); } } $outserSelect = rtrim($outserSelect, ','); // For each heading, put it in the correct order (according to $columns) foreach ($columns as $visibleColumn) { foreach ($headings as $heading) { if ($heading['DataSetColumnID'] == $visibleColumn) { $finalSelect .= sprintf(' `%s`,', $heading['Text']); $results['Columns'][] = $heading; } } } $finalSelect = rtrim($finalSelect, ','); // We are ready to build the select and from part of the SQL $SQL = "SELECT {$finalSelect} "; $SQL .= " FROM ( "; $SQL .= " SELECT {$outserSelect} ,"; $SQL .= " RowNumber "; $SQL .= " FROM ( "; $SQL .= " SELECT {$selectSQL} "; $SQL .= " RowNumber "; $SQL .= " FROM ("; $SQL .= " SELECT datasetcolumn.DataSetColumnID, datasetdata.RowNumber, datasetdata.`Value` "; $SQL .= " FROM datasetdata "; $SQL .= " INNER JOIN datasetcolumn "; $SQL .= " ON datasetcolumn.DataSetColumnID = datasetdata.DataSetColumnID "; $SQL .= " WHERE datasetcolumn.DataSetID = :dataSetId "; $SQL .= " ) datasetdatainner "; $SQL .= " GROUP BY RowNumber "; $SQL .= " ) datasetdata "; if ($filter != '') { $SQL .= ' WHERE ' . $filter; } $SQL .= ' ) finalselect '; if ($ordering != '') { $order = ' ORDER BY '; $ordering = explode(',', $ordering); foreach ($ordering as $orderPair) { // Sanitize the clause $sanitized = str_replace(' ASC', '', str_replace(' DESC', '', $orderPair)); // Check allowable if (!in_array($sanitized, $allowedOrderCols)) { Debug::Info('Disallowed column: ' . $sanitized); continue; } // Substitute if (strripos($orderPair, ' DESC')) { $order .= sprintf(' `%s` DESC,', $sanitized); } else { if (strripos($orderPair, ' ASC')) { $order .= sprintf(' `%s` ASC,', $sanitized); } else { $order .= sprintf(' `%s`,', $sanitized); } } } $SQL .= trim($order, ','); } else { $SQL .= " ORDER BY RowNumber "; } if ($lowerLimit != 0 || $upperLimit != 0) { // Lower limit should be 0 based if ($lowerLimit != 0) { $lowerLimit = $lowerLimit - 1; } // Upper limit should be the distance between upper and lower $upperLimit = $upperLimit - $lowerLimit; // Substitute in $SQL .= sprintf(' LIMIT %d, %d ', $lowerLimit, $upperLimit); } Debug::Audit($SQL . ' ' . var_export($params, true)); $sth = $dbh->prepare($SQL); //$sth->debugDumpParams(); $sth->execute($params); $results['Rows'] = $sth->fetchAll(); return $results; } catch (Exception $e) { Debug::Error($e->getMessage()); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } }
/** * Delete unused media for user * @param int $userId * @return bool */ public function deleteUnusedForUser($userId) { foreach (Media::entriesUnusedForUser($userId) as $item) { Debug::Audit('Deleting unused media: ' . $item['mediaId']); if (!$this->Delete($item['mediaId'])) { return false; } } return true; }
/** * Replace media in all layouts. * @param <type> $oldMediaId * @param <type> $newMediaId */ private function ReplaceMediaInAllLayouts($replaceInLayouts, $replaceBackgroundImages, $oldMediaId, $newMediaId) { $count = 0; Debug::LogEntry('audit', sprintf('Replacing mediaid %s with mediaid %s in all layouts', $oldMediaId, $newMediaId), 'module', 'ReplaceMediaInAllLayouts'); try { $dbh = PDOConnect::init(); // Some update statements to use $sth = $dbh->prepare('SELECT lklayoutmediaid, regionid FROM lklayoutmedia WHERE mediaid = :media_id AND layoutid = :layout_id'); $sth_update = $dbh->prepare('UPDATE lklayoutmedia SET mediaid = :media_id WHERE lklayoutmediaid = :lklayoutmediaid'); // Loop through a list of layouts this user has access to foreach ($this->user->LayoutList() as $layout) { $layoutId = $layout['layoutid']; // Does this layout use the old media id? $sth->execute(array('media_id' => $oldMediaId, 'layout_id' => $layoutId)); $results = $sth->fetchAll(); if (count($results) <= 0) { continue; } Debug::LogEntry('audit', sprintf('%d linked media items for layoutid %d', count($results), $layoutId), 'module', 'ReplaceMediaInAllLayouts'); // Create a region object for later use (new one each time) $layout = new Layout(); $region = new region($this->db); // Loop through each media link for this layout foreach ($results as $row) { // Get the LKID of the link between this layout and this media.. could be more than one? $lkId = $row['lklayoutmediaid']; $regionId = $row['regionid']; if ($regionId == 'background') { Debug::Audit('Replacing background image'); if (!$replaceBackgroundImages) { continue; } // Straight swap this background image node. if (!$layout->EditBackgroundImage($layoutId, $newMediaId)) { return false; } } else { if (!$replaceInLayouts) { continue; } // Get the Type of this media if (!($type = $region->GetMediaNodeType($layoutId, '', '', $lkId))) { continue; } // Create a new media node use it to swap the nodes over Debug::LogEntry('audit', 'Creating new module with MediaID: ' . $newMediaId . ' LayoutID: ' . $layoutId . ' and RegionID: ' . $regionId, 'region', 'ReplaceMediaInAllLayouts'); try { $module = ModuleFactory::createForMedia($type, $newMediaId, $this->db, $this->user); } catch (Exception $e) { Debug::Error($e->getMessage()); return false; } // Sets the URI field if (!$module->SetRegionInformation($layoutId, $regionId)) { return false; } // Get the media xml string to use in the swap. $mediaXmlString = $module->AsXml(); // Swap the nodes if (!$region->SwapMedia($layoutId, $regionId, $lkId, $oldMediaId, $newMediaId, $mediaXmlString)) { return false; } } // Update the LKID with the new media id $sth_update->execute(array('media_id' => $newMediaId, 'lklayoutmediaid' => $row['lklayoutmediaid'])); $count++; } } } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage()); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } Debug::LogEntry('audit', sprintf('Replaced media in %d layouts', $count), 'module', 'ReplaceMediaInAllLayouts'); }
/** * Edits an event * @return */ public function EditEvent() { // Check the token if (!Kit::CheckToken(Kit::GetParam('token_id', _POST, _STRING))) { trigger_error(__('Sorry the form has expired. Please refresh.'), E_USER_ERROR); } $db =& $this->db; $user =& $this->user; $response = new ResponseManager(); $eventId = Kit::GetParam('EventID', _POST, _INT, 0); $campaignId = Kit::GetParam('CampaignID', _POST, _INT, 0); $fromDT = Kit::GetParam('starttime', _POST, _STRING); $toDT = Kit::GetParam('endtime', _POST, _STRING); $displayGroupIDs = Kit::GetParam('DisplayGroupIDs', _POST, _ARRAY); $isPriority = Kit::GetParam('is_priority', _POST, _CHECKBOX); $repeatType = Kit::GetParam('rec_type', _POST, _STRING); $repeatInterval = Kit::GetParam('rec_detail', _POST, _INT); $repeatToDt = Kit::GetParam('rec_range', _POST, _STRING); $displayOrder = Kit::GetParam('DisplayOrder', _POST, _INT); $isNextButton = Kit::GetParam('next', _GET, _BOOL, false); // Convert our ISO strings $fromDT = DateManager::getTimestampFromString($fromDT); $toDT = DateManager::getTimestampFromString($toDT); if ($repeatToDt != '') { $repeatToDt = DateManager::getTimestampFromString($repeatToDt); } Debug::Audit('Times received are: FromDt=' . $fromDT . '. ToDt=' . $toDT . '. RepeatToDt=' . $repeatToDt); // Validate layout if ($campaignId == 0) { trigger_error(__("No layout selected"), E_USER_ERROR); } // check that at least one display has been selected if ($displayGroupIDs == '') { trigger_error(__("No displays selected"), E_USER_ERROR); } // validate the dates if ($toDT < $fromDT) { trigger_error(__('Can not have an end time earlier than your start time'), E_USER_ERROR); } // Check recurrence dT is in the future or empty if ($repeatToDt != '' && $repeatToDt < time() - 86400) { trigger_error(__("Your repeat until date is in the past. Cannot schedule events to repeat in to the past"), E_USER_ERROR); } // Ready to do the edit $scheduleObject = new Schedule($db); if (!$scheduleObject->Edit($eventId, $displayGroupIDs, $fromDT, $toDT, $campaignId, $repeatType, $repeatInterval, $repeatToDt, $isPriority, $this->user->userid, $displayOrder)) { trigger_error($scheduleObject->GetErrorMessage(), E_USER_ERROR); } $response->SetFormSubmitResponse(__("The Event has been Modified.")); $response->callBack = 'CallGenerateCalendar'; $response->Respond(); }
protected function getTwitterFeed($displayId = 0, $isPreview = true) { if (!extension_loaded('curl')) { trigger_error(__('cURL extension is required for Twitter')); return false; } // Do we need to add a geoCode? $geoCode = ''; $distance = $this->GetOption('tweetDistance'); if ($distance != 0) { // Use the display ID or the default. if ($displayId != 0) { // Look up the lat/long $display = new Display(); $display->displayId = $displayId; $display->Load(); $defaultLat = $display->latitude; $defaultLong = $display->longitude; } else { $defaultLat = Config::GetSetting('DEFAULT_LAT'); $defaultLong = Config::GetSetting('DEFAULT_LONG'); } // Built the geoCode string. $geoCode = implode(',', array($defaultLat, $defaultLong, $distance)) . 'mi'; } // Connect to twitter and get the twitter feed. $key = md5($this->GetOption('searchTerm') . $this->GetOption('resultType') . $this->GetOption('tweetCount', 15) . $geoCode); if (!Cache::has($key) || Cache::get($key) == '') { Debug::Audit('Querying API for ' . $this->GetOption('searchTerm')); // We need to search for it if (!($token = $this->getToken())) { return false; } // We have the token, make a tweet if (!($data = $this->searchApi($token, $this->GetOption('searchTerm'), $this->GetOption('resultType'), $geoCode, $this->GetOption('tweetCount', 15)))) { return false; } // Cache it Cache::put($key, $data, $this->GetSetting('cachePeriod')); } else { Debug::Audit('Served from Cache'); $data = Cache::get($key); } Debug::Audit(var_export(json_encode($data), true)); // Get the template $template = $this->GetRawNode('template'); // Parse the text template $matches = ''; preg_match_all('/\\[.*?\\]/', $template, $matches); // Build an array to return $return = array(); // Media Object to get profile images $media = new Media(); $layout = new Layout(); // Expiry time for any media that is downloaded $expires = time() + $this->GetSetting('cachePeriodImages') * 60 * 60; // Remove URL setting $removeUrls = $this->GetOption('removeUrls', 1); // If we have nothing to show, display a no tweets message. if (count($data->statuses) <= 0) { // Create ourselves an empty tweet so that the rest of the code can continue as normal $user = new stdClass(); $user->name = ''; $user->screen_name = ''; $user->profile_image_url = ''; $tweet = new stdClass(); $tweet->text = $this->GetOption('noTweetsMessage', __('There are no tweets to display')); $tweet->created_at = date("Y-m-d H:i:s"); $tweet->user = $user; // Append to our statuses $data->statuses[] = $tweet; } // This should return the formatted items. foreach ($data->statuses as $tweet) { // Substitute for all matches in the template $rowString = $template; foreach ($matches[0] as $sub) { // Always clear the stored template replacement $replace = ''; // Maybe make this more generic? switch ($sub) { case '[Tweet]': // Get the tweet text to operate on $tweetText = $tweet->text; // Replace URLs with their display_url before removal if (isset($tweet->entities->urls)) { foreach ($tweet->entities->urls as $url) { $tweetText = str_replace($url->url, $url->display_url, $tweetText); } } // Handle URL removal if requested if ($removeUrls == 1) { $tweetText = preg_replace("((https?|ftp|gopher|telnet|file|notes|ms-help):((\\/\\/)|(\\\\))+[\\w\\d:#\\@%\\/;\$()~_?\\+-=\\\\.&]*)", '', $tweetText); } $replace = emoji_unified_to_html($tweetText); break; case '[User]': $replace = $tweet->user->name; break; case '[ScreenName]': $replace = $tweet->user->screen_name; break; case '[Date]': $replace = date($this->GetOption('dateFormat', Config::GetSetting('DATE_FORMAT')), DateManager::getDateFromGregorianString($tweet->created_at)); break; case '[ProfileImage]': // Grab the profile image if ($tweet->user->profile_image_url != '') { $file = $media->addModuleFileFromUrl($tweet->user->profile_image_url, 'twitter_' . $tweet->user->id, $expires); // Tag this layout with this file $layout->AddLk($this->layoutid, 'module', $file['mediaId']); $replace = $isPreview ? '<img src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $file['mediaId'] . '" />' : '<img src="' . $file['storedAs'] . '" />'; } break; case '[Photo]': // See if there are any photos associated with this tweet. if (isset($tweet->entities->media) && count($tweet->entities->media) > 0) { // Only take the first one $photoUrl = $tweet->entities->media[0]->media_url; if ($photoUrl != '') { $file = $media->addModuleFileFromUrl($photoUrl, 'twitter_photo_' . $tweet->user->id . '_' . $tweet->entities->media[0]->id_str, $expires); $replace = $isPreview ? '<img src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $file['mediaId'] . '" />' : '<img src="' . $file['storedAs'] . '" />'; // Tag this layout with this file $layout->AddLk($this->layoutid, 'module', $file['mediaId']); } } break; default: $replace = ''; } $rowString = str_replace($sub, $replace, $rowString); } // Substitute the replacement we have found (it might be '') $return[] = $rowString; } // Return the data array return $return; }
public function TidyLibrary($tidyOldRevisions, $cleanUnusedFiles) { // Also run a script to tidy up orphaned media in the library $library = Config::GetSetting('LIBRARY_LOCATION'); $library = rtrim($library, '/') . '/'; $mediaObject = new Media(); Debug::Audit('Library Location: ' . $library); // Dump the files in the temp folder foreach (scandir($library . 'temp') as $item) { if ($item == '.' || $item == '..') { continue; } Debug::Audit('Deleting temp file: ' . $item); unlink($library . 'temp' . DIRECTORY_SEPARATOR . $item); } $media = array(); $unusedMedia = array(); $unusedRevisions = array(); // Run a query to get an array containing all of the media in the library try { $dbh = PDOConnect::init(); $sth = $dbh->prepare(' SELECT media.mediaid, media.storedAs, media.type, media.isedited, SUM(CASE WHEN IFNULL(lklayoutmedia.lklayoutmediaid, 0) = 0 THEN 0 ELSE 1 END) AS UsedInLayoutCount, SUM(CASE WHEN IFNULL(lkmediadisplaygroup.id, 0) = 0 THEN 0 ELSE 1 END) AS UsedInDisplayCount FROM `media` LEFT OUTER JOIN `lklayoutmedia` ON lklayoutmedia.mediaid = media.mediaid LEFT OUTER JOIN `lkmediadisplaygroup` ON lkmediadisplaygroup.mediaid = media.mediaid GROUP BY media.mediaid, media.storedAs, media.type, media.isedited '); $sth->execute(array()); foreach ($sth->fetchAll() as $row) { $media[$row['storedAs']] = $row; // Ignore any module files or fonts if ($row['type'] == 'module' || $row['type'] == 'font') { continue; } // Collect media revisions that aren't used if ($tidyOldRevisions && $row['UsedInLayoutCount'] <= 0 && $row['UsedInDisplayCount'] <= 0 && $row['isedited'] > 0) { $unusedRevisions[$row['storedAs']] = $row; } else { if ($cleanUnusedFiles && $row['UsedInLayoutCount'] <= 0 && $row['UsedInDisplayCount'] <= 0) { $unusedMedia[$row['storedAs']] = $row; } } } } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage()); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } //Debug::Audit(var_export($media, true)); //Debug::Audit(var_export($unusedMedia, true)); // Get a list of all media files foreach (scandir($library) as $file) { if ($file == '.' || $file == '..') { continue; } if (is_dir($library . $file)) { continue; } // Ignore thumbnails if (strstr($file, 'tn_') || strstr($file, 'bg_')) { continue; } // Is this file in the system anywhere? if (!array_key_exists($file, $media)) { // Totally missing Debug::Audit('Deleting file: ' . $file); // If not, delete it $mediaObject->DeleteMediaFile($file); } else { if (array_key_exists($file, $unusedRevisions)) { // It exists but isn't being used any more Debug::Audit('Deleting unused revision media: ' . $media[$file]['mediaid']); $mediaObject->Delete($media[$file]['mediaid']); } else { if (array_key_exists($file, $unusedMedia)) { // It exists but isn't being used any more Debug::Audit('Deleting unused media: ' . $media[$file]['mediaid']); $mediaObject->Delete($media[$file]['mediaid']); } } } } return true; }
/** * Should the host be considered a proxy exception * @param $host * @return bool */ public static function isProxyException($host) { $proxyException = Config::GetSetting('PROXY_EXCEPTIONS'); Debug::Audit($host . ' in ' . $proxyException . '. Pos = ' . stripos($host, $proxyException)); return $proxyException != '' && stripos($host, $proxyException) > -1; }
/** * Exchange request token and secret for an access token and * secret, to sign API calls. * * @returns array("oauth_token" => "the-access-token", * "oauth_token_secret" => "the-access-secret", * "user_id" => "9436992", * "screen_name" => "abraham") */ function getAccessToken($Twitteroauth_verifier) { $parameters = array(); $parameters['oauth_verifier'] = $Twitteroauth_verifier; $request = $this->TwitteroAuthRequest($this->accessTokenURL(), 'GET', $parameters); $token = TwitterOAuthUtil::parse_parameters($request); Debug::Audit(var_export($token, true)); $this->token = new TwitterOAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); return $token; }
/** * Assess each Display to correctly set the logged in flag based on last accessed time * @return */ public static function ValidateDisplays() { // Maintain an array of timed out displays $timedOutDisplays = array(); try { $dbh = PDOConnect::init(); $statObject = new Stat(); // Get a list of all displays and there last accessed / alert time out value $sth = $dbh->prepare('SELECT displayid, display, lastaccessed, alert_timeout, client_type, displayprofileid, email_alert, loggedin FROM display'); $sthUpdate = $dbh->prepare('UPDATE display SET loggedin = 0 WHERE displayid = :displayid'); $sth->execute(array()); // Get the global time out (overrides the alert time out on the display if 0) $globalTimeout = Config::GetSetting('MAINTENANCE_ALERT_TOUT') * 60; $displays = $sth->fetchAll(); foreach ($displays as $row) { $displayid = Kit::ValidateParam($row['displayid'], _INT); $lastAccessed = Kit::ValidateParam($row['lastaccessed'], _INT); $alertTimeout = Kit::ValidateParam($row['alert_timeout'], _INT); $clientType = Kit::ValidateParam($row['client_type'], _WORD); $loggedIn = Kit::ValidateParam($row['loggedin'], _INT); // Get the config object if ($alertTimeout == 0 && $clientType != '') { $displayProfileId = empty($row['displayprofileid']) ? 0 : Kit::ValidateParam($row['displayprofileid'], _INT); $display = new Display(); $display->displayId = $displayid; $display->displayProfileId = $displayProfileId; $display->clientType = $clientType; $timeoutToTestAgainst = $display->GetSetting('collectInterval', $globalTimeout); } else { $timeoutToTestAgainst = $globalTimeout; } // Store the time out to test against $row['timeout'] = $timeoutToTestAgainst; $timeOut = $lastAccessed + $timeoutToTestAgainst; // If the last time we accessed is less than now minus the time out if ($timeOut < time()) { Debug::Audit('Timed out display. Last Accessed: ' . date('Y-m-d h:i:s', $lastAccessed) . '. Time out: ' . date('Y-m-d h:i:s', $timeOut)); // If this is the first switch (i.e. the row was logged in before) if ($loggedIn == 1) { // Update the display and set it as logged out $sthUpdate->execute(array('displayid' => $displayid)); // Log the down event $statObject->displayDown($displayid, $lastAccessed); } // Store this row $timedOutDisplays[] = $row; } } return $timedOutDisplays; } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__); return false; } }
/** * Store the media inventory for a client * @param string $version * @param string $serverKey * @param string $hardwareKey * @param string $inventory * @return bool * @throws SoapFault */ public function MediaInventory($version, $serverKey, $hardwareKey, $inventory) { // Sanitize $serverKey = Kit::ValidateParam($serverKey, _STRING); $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); $inventory = Kit::ValidateParam($inventory, _HTMLSTRING); // Check the serverKey matches if ($serverKey != Config::GetSetting('SERVER_KEY')) { throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); } // Make sure we are sticking to our bandwidth limit if (!$this->CheckBandwidth()) { throw new SoapFault('Receiver', "Bandwidth Limit exceeded"); } // Auth this request... if (!$this->AuthDisplay($hardwareKey)) { throw new SoapFault('Receiver', 'This display client is not licensed'); } if ($this->isAuditing == 1) { Debug::Audit($inventory, 'xmds', $this->displayId); } // Check that the $inventory contains something if ($inventory == '') { throw new SoapFault('Receiver', 'Inventory Cannot be Empty'); } // Load the XML into a DOMDocument $document = new DOMDocument("1.0"); $document->loadXML($inventory); // Assume we are complete (but we are getting some) $mediaInventoryComplete = 1; $xpath = new DOMXPath($document); $fileNodes = $xpath->query("//file"); foreach ($fileNodes as $node) { $mediaId = $node->getAttribute('id'); $complete = $node->getAttribute('complete'); $md5 = $node->getAttribute('md5'); $lastChecked = $node->getAttribute('lastChecked'); // TODO: Check the MD5? // If this item is a 0 then set not complete if ($complete == 0) { $mediaInventoryComplete = 2; } } // Touch the display record $displayObject = new Display(); $displayObject->Touch($this->displayId, array('mediaInventoryStatus' => $mediaInventoryComplete, 'mediaInventoryXml' => $inventory)); $this->LogBandwidth($this->displayId, Bandwidth::$MEDIAINVENTORY, strlen($inventory)); return true; }
/** * GetResource * Return the rendered resource to be used by the client (or a preview) * for displaying this content. * @param integer $displayId If this comes from a real client, this will be the display id. * @return string */ public function GetResource($displayId = 0) { // Load in the template $template = file_get_contents('modules/preview/HtmlTemplate.html'); $isPreview = Kit::GetParam('preview', _REQUEST, _WORD, 'false') == 'true'; // Replace the View Port Width? if ($isPreview) { $template = str_replace('[[ViewPortWidth]]', $this->width, $template); } // Information from the Module $duration = $this->duration; // Generate a JSON string of items. if (!($items = $this->getYql($displayId, $isPreview))) { return ''; } // Run through each item and substitute with the template $itemTemplate = $this->GetRawNode('template'); $renderedItems = array(); foreach ($items as $item) { $renderedItems[] = $this->makeSubstitutions($item, $itemTemplate); } Debug::Audit('Items: ' . var_export($items, true)); Debug::Audit('Rendered items: ' . var_export($renderedItems, true)); $options = array('type' => $this->type, 'fx' => $this->GetOption('effect', 'none'), 'speed' => $this->GetOption('speed', 500), 'duration' => $duration, 'durationIsPerItem' => $this->GetOption('durationIsPerItem', 0) == 1, 'numItems' => count($renderedItems), 'itemsPerPage' => 1, 'originalWidth' => $this->width, 'originalHeight' => $this->height, 'previewWidth' => Kit::GetParam('width', _GET, _DOUBLE, 0), 'previewHeight' => Kit::GetParam('height', _GET, _DOUBLE, 0), 'scaleOverride' => Kit::GetParam('scale_override', _GET, _DOUBLE, 0)); // Replace the control meta with our data from twitter $controlMeta = '<!-- NUMITEMS=' . count($items) . ' -->' . PHP_EOL . '<!-- DURATION=' . ($this->GetOption('durationIsPerItem', 0) == 0 ? $duration : $duration * count($items)) . ' -->'; $template = str_replace('<!--[[[CONTROLMETA]]]-->', $controlMeta, $template); // Replace the head content $headContent = ''; // Add the CSS if it isn't empty $css = $this->GetRawNode('styleSheet'); if ($css != '') { $headContent .= '<style type="text/css">' . $css . '</style>'; } $backgroundColor = $this->GetOption('backgroundColor'); if ($backgroundColor != '') { $headContent .= '<style type="text/css">body, .page, .item { background-color: ' . $backgroundColor . ' }</style>'; } // Add our fonts.css file $headContent .= '<link href="' . ($isPreview ? 'modules/preview/' : '') . 'fonts.css" rel="stylesheet" media="screen">'; $headContent .= '<link href="' . ($isPreview ? 'modules/theme/twitter/' : '') . 'emoji.css" rel="stylesheet" media="screen">'; $headContent .= '<style type="text/css">' . file_get_contents(Theme::ItemPath('css/client.css')) . '</style>'; // Replace the Head Content with our generated javascript $template = str_replace('<!--[[[HEADCONTENT]]]-->', $headContent, $template); // Add some scripts to the JavaScript Content $javaScriptContent = '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/vendor/' : '') . 'jquery-1.11.1.min.js"></script>'; // Need the cycle plugin? if ($this->GetSetting('effect') != 'none') { $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/vendor/' : '') . 'jquery-cycle-2.1.6.min.js"></script>'; } // Need the marquee plugin? if (stripos($this->GetSetting('effect'), 'marquee') !== false) { $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/vendor/' : '') . 'jquery.marquee.min.js"></script>'; } $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/' : '') . 'xibo-layout-scaler.js"></script>'; $javaScriptContent .= '<script type="text/javascript" src="' . ($isPreview ? 'modules/preview/' : '') . 'xibo-text-render.js"></script>'; $javaScriptContent .= '<script type="text/javascript">'; $javaScriptContent .= ' var options = ' . json_encode($options) . ';'; $javaScriptContent .= ' var items = ' . Kit::jsonEncode($renderedItems) . ';'; $javaScriptContent .= ' $(document).ready(function() { '; $javaScriptContent .= ' $("body").xiboLayoutScaler(options); $("#content").xiboTextRender(options, items); '; $javaScriptContent .= ' }); '; $javaScriptContent .= '</script>'; // Replace the Head Content with our generated javascript $template = str_replace('<!--[[[JAVASCRIPTCONTENT]]]-->', $javaScriptContent, $template); // Replace the Body Content with our generated text $template = str_replace('<!--[[[BODYCONTENT]]]-->', '', $template); return $template; }
/** * Shows the TimeLine */ public function TimelineList() { $db =& $this->db; $user =& $this->user; $user->SetPref('timeLineView', 'list'); $response = new ResponseManager(); $response->html = ''; $layoutId = Kit::GetParam('layoutid', _GET, _INT); $regionId = Kit::GetParam('regionid', _REQUEST, _STRING); // Make sure we have permission to edit this region Kit::ClassLoader('region'); $region = new region($db); $ownerId = $region->GetOwnerId($layoutId, $regionId); $regionAuth = $this->user->RegionAssignmentAuth($ownerId, $layoutId, $regionId, true); if (!$regionAuth->edit) { trigger_error(__('You do not have permissions to edit this region'), E_USER_ERROR); } $response->html .= '<div class="container-fluid">'; $response->html .= '<div class="row">'; // Set the theme module buttons $this->ThemeSetModuleButtons($layoutId, $regionId); $response->html .= Theme::RenderReturn('layout_designer_form_timeline'); // Load the XML for this layout and region, we need to get the media nodes. // These form the time line and go in the right column // Generate an ID for the list (this is passed into the reorder function) $timeListMediaListId = uniqid('timelineMediaList_'); $response->html .= '<div class="col-md-10">'; $response->html .= '<div id="timelineControl" class="timelineColumn" layoutid="' . $layoutId . '" regionid="' . $regionId . '">'; $response->html .= ' <div class="timelineMediaVerticalList">'; $response->html .= ' <ul id="' . $timeListMediaListId . '" class="timelineSortableListOfMedia">'; // How are we going to colour the bars, my media type or my permissions $timeBarColouring = Config::GetSetting('REGION_OPTIONS_COLOURING'); // Create a layout object $region = new Region($db); foreach ($region->GetMediaNodeList($layoutId, $regionId) as $mediaNode) { // Put this node vertically in the region time line $mediaId = $mediaNode->getAttribute('id'); $lkId = $mediaNode->getAttribute('lkid'); $mediaType = $mediaNode->getAttribute('type'); $mediaDuration = $mediaNode->getAttribute('duration'); $ownerId = $mediaNode->getAttribute('userId'); // Permissions for this assignment $auth = $user->MediaAssignmentAuth($ownerId, $layoutId, $regionId, $mediaId, true); // Skip over media assignments that we do not have permission to see if (!$auth->view) { continue; } Debug::LogEntry('audit', sprintf('Permission Granted to View MediaID: %s', $mediaId), 'layout', 'TimeLine'); // Create a media module to handle all the complex stuff try { $tmpModule = ModuleFactory::load($mediaType, $layoutId, $regionId, $mediaId, $lkId, $this->db, $this->user); } catch (Exception $e) { Debug::Audit('Caught exception from Module Create'); trigger_error($e->getMessage(), E_USER_ERROR); } $mediaName = $tmpModule->GetName(); $transitionIn = $tmpModule->GetTransition('in'); $transitionOut = $tmpModule->GetTransition('out'); // Colouring for the media block if ($timeBarColouring == 'Permissions') { $mediaBlockColouringClass = 'timelineMediaItemColouring_' . ($auth->edit ? 'enabled' : 'disabled'); } else { $mediaBlockColouringClass = 'timelineMediaItemColouringDefault timelineMediaItemColouring_' . $mediaType; } // Create the list item $response->html .= '<li class="timelineMediaListItem" mediaid="' . $mediaId . '" lkid="' . $lkId . '">'; // In transition $response->html .= ' <div class="timelineMediaInTransition">'; if ($transitionIn != 'None') { $response->html .= '<span>' . $transitionIn . '</span>'; } $response->html .= ' </div>'; // Media Bar $response->html .= ' <div class="timelineMediaItem">'; $response->html .= ' <ul class="timelineMediaItemLinks">'; // Create some links if ($auth->edit) { $response->html .= '<li><a class="XiboFormButton timelineMediaBarLink" href="index.php?p=module&mod=' . $mediaType . '&q=Exec&method=EditForm&layoutid=' . $layoutId . '®ionid=' . $regionId . '&mediaid=' . $mediaId . '&lkid=' . $lkId . '" title="' . __('Click to edit this media') . '">' . __('Edit') . '</a></li>'; } if ($auth->del) { $response->html .= '<li><a class="XiboFormButton timelineMediaBarLink" href="index.php?p=module&mod=' . $mediaType . '&q=Exec&method=DeleteForm&layoutid=' . $layoutId . '®ionid=' . $regionId . '&mediaid=' . $mediaId . '&lkid=' . $lkId . '" title="' . __('Click to delete this media') . '">' . __('Delete') . '</a></li>'; } if ($auth->modifyPermissions) { $response->html .= '<li><a class="XiboFormButton timelineMediaBarLink" href="index.php?p=module&mod=' . $mediaType . '&q=Exec&method=PermissionsForm&layoutid=' . $layoutId . '®ionid=' . $regionId . '&mediaid=' . $mediaId . '&lkid=' . $lkId . '" title="Click to change permissions for this media">' . __('Permissions') . '</a></li>'; } if (count($this->user->TransitionAuth('in')) > 0) { $response->html .= '<li><a class="XiboFormButton timelineMediaBarLink" href="index.php?p=module&mod=' . $mediaType . '&q=Exec&method=TransitionEditForm&type=in&layoutid=' . $layoutId . '®ionid=' . $regionId . '&mediaid=' . $mediaId . '&lkid=' . $lkId . '" title="' . __('Click to edit this transition') . '">' . __('In Transition') . '</a></li>'; } if (count($this->user->TransitionAuth('out')) > 0) { $response->html .= '<li><a class="XiboFormButton timelineMediaBarLink" href="index.php?p=module&mod=' . $mediaType . '&q=Exec&method=TransitionEditForm&type=out&layoutid=' . $layoutId . '®ionid=' . $regionId . '&mediaid=' . $mediaId . '&lkid=' . $lkId . '" title="' . __('Click to edit this transition') . '">' . __('Out Transition') . '</a></li>'; } $response->html .= ' </ul>'; // Put the media name in $response->html .= ' <div class="timelineMediaDetails ' . $mediaBlockColouringClass . '">'; $response->html .= ' <h3>' . sprintf('%s (%d seconds)', $mediaName == '' ? __($tmpModule->displayType) : $mediaName, $mediaDuration) . '</h3>'; $response->html .= ' </div>'; // Put the media hover preview in $mediaHoverPreview = $tmpModule->HoverPreview(); $response->html .= ' <div class="timelineMediaPreview">' . $mediaHoverPreview . '</div>'; // End the time line media item $response->html .= ' </div>'; // Out transition $response->html .= ' <div class="timelineMediaOutTransition">'; if ($transitionOut != 'None') { $response->html .= '<span>' . $transitionOut . '</span>'; } $response->html .= ' </div>'; // End of this media item $response->html .= '</li>'; } $response->html .= ' </ul>'; $response->html .= ' </div>'; // Output a div to contain the preview for this media item $response->html .= ' <div id="timelinePreview"></div>'; $response->html .= ' </div>'; $response->html .= '</div>'; $response->html .= '</div>'; $response->html .= '</div>'; // Finish constructing the response $response->callBack = 'LoadTimeLineCallback'; $response->dialogClass = 'modal-big'; $response->dialogTitle = __('Region Timeline'); $response->dialogSize = true; $response->dialogWidth = '1000px'; $response->dialogHeight = '550px'; $response->focusInFirstInput = false; // Add some buttons $response->AddButton(__('Save Order'), 'XiboTimelineSaveOrder("' . $timeListMediaListId . '","' . $layoutId . '","' . $regionId . '")'); $response->AddButton(__('Switch to Grid'), 'XiboSwapDialog("index.php?p=timeline&q=TimelineGrid&layoutid=' . $layoutId . '®ionid=' . $regionId . '")'); $response->AddButton(__('Help'), 'XiboHelpRender("' . HelpManager::Link('Layout', 'RegionOptions') . '")'); $response->AddButton(__('Close'), 'XiboDialogClose()'); $response->Respond(); }
/** * Loads templates for this module */ public function loadTemplates() { // Scan the folder for template files foreach (glob('modules/theme/forecastio/*.template.json') as $template) { // Read the contents, json_decode and add to the array $this->settings['templates'][] = json_decode(file_get_contents($template), true); } Debug::Audit(count($this->settings['templates'])); }
/** * Shows the stats grid */ public function StatsGrid() { $db =& $this->db; $user =& $this->user; $response = new ResponseManager(); $fromDt = DateManager::getIsoDateFromString(Kit::GetParam('fromdt', _POST, _STRING)); $toDt = DateManager::getIsoDateFromString(Kit::GetParam('todt', _POST, _STRING)); $displayId = Kit::GetParam('displayid', _POST, _INT); $mediaId = Kit::GetParam('mediaid', _POST, _INT); // What if the fromdt and todt are exactly the same? // in this case assume an entire day from midnight on the fromdt to midnight on the todt (i.e. add a day to the todt) if ($fromDt == $toDt) { $toDt = date("Y-m-d", strtotime($toDt) + 86399); } Debug::Audit('Converted Times received are: FromDt=' . $fromDt . '. ToDt=' . $toDt); // Get an array of display id this user has access to. $displays = $this->user->DisplayList(); $display_ids = array(); foreach ($displays as $display) { $display_ids[] = $display['displayid']; } if (count($display_ids) <= 0) { trigger_error(__('No displays with View permissions'), E_USER_ERROR); } // 3 grids showing different stats. // Layouts Ran $SQL = 'SELECT display.Display, layout.Layout, COUNT(StatID) AS NumberPlays, SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration, MIN(start) AS MinStart, MAX(end) AS MaxEnd '; $SQL .= ' FROM stat '; $SQL .= ' INNER JOIN layout ON layout.LayoutID = stat.LayoutID '; $SQL .= ' INNER JOIN display ON stat.DisplayID = display.DisplayID '; $SQL .= " WHERE stat.type = 'layout' "; $SQL .= sprintf(" AND stat.end > '%s' ", $fromDt); $SQL .= sprintf(" AND stat.start <= '%s' ", $toDt); $SQL .= ' AND stat.displayID IN (' . implode(',', $display_ids) . ') '; if ($displayId != 0) { $SQL .= sprintf(" AND stat.displayID = %d ", $displayId); } $SQL .= 'GROUP BY display.Display, layout.Layout '; $SQL .= 'ORDER BY display.Display, layout.Layout'; // Log Debug::sql($SQL); if (!($results = $this->db->query($SQL))) { trigger_error($db->error()); trigger_error(__('Unable to get Layouts Shown'), E_USER_ERROR); } $cols = array(array('name' => 'Display', 'title' => __('Display')), array('name' => 'Layout', 'title' => __('Layout')), array('name' => 'NumberPlays', 'title' => __('Number of Plays')), array('name' => 'DurationSec', 'title' => __('Total Duration (s)')), array('name' => 'Duration', 'title' => __('Total Duration')), array('name' => 'MinStart', 'title' => __('First Shown')), array('name' => 'MaxEnd', 'title' => __('Last Shown'))); Theme::Set('table_cols', $cols); $rows = array(); while ($row = $db->get_assoc_row($results)) { $row['Display'] = Kit::ValidateParam($row['Display'], _STRING); $row['Layout'] = Kit::ValidateParam($row['Layout'], _STRING); $row['NumberPlays'] = Kit::ValidateParam($row['NumberPlays'], _INT); $row['DurationSec'] = Kit::ValidateParam($row['Duration'], _INT); $row['Duration'] = sec2hms(Kit::ValidateParam($row['Duration'], _INT)); $row['MinStart'] = DateManager::getLocalDate(strtotime(Kit::ValidateParam($row['MinStart'], _STRING))); $row['MaxEnd'] = DateManager::getLocalDate(strtotime(Kit::ValidateParam($row['MaxEnd'], _STRING))); $rows[] = $row; } Theme::Set('table_rows', $rows); Theme::Set('table_layouts_shown', Theme::RenderReturn('table_render')); // Media Ran $SQL = 'SELECT display.Display, media.Name, COUNT(StatID) AS NumberPlays, SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration, MIN(start) AS MinStart, MAX(end) AS MaxEnd '; $SQL .= ' FROM stat '; $SQL .= ' INNER JOIN display ON stat.DisplayID = display.DisplayID '; $SQL .= ' INNER JOIN media ON media.MediaID = stat.MediaID '; $SQL .= " WHERE stat.type = 'media' "; $SQL .= sprintf(" AND stat.end > '%s' ", $fromDt); $SQL .= sprintf(" AND stat.start <= '%s' ", $toDt); $SQL .= ' AND stat.displayID IN (' . implode(',', $display_ids) . ') '; if ($mediaId != 0) { $SQL .= sprintf(" AND media.MediaID = %d ", $mediaId); } if ($displayId != 0) { $SQL .= sprintf(" AND stat.displayID = %d ", $displayId); } $SQL .= 'GROUP BY display.Display, media.Name '; $SQL .= 'ORDER BY display.Display, media.Name'; if (!($results = $this->db->query($SQL))) { trigger_error($db->error()); trigger_error(__('Unable to get Library Media Ran'), E_USER_ERROR); } $cols = array(array('name' => 'Display', 'title' => __('Display')), array('name' => 'Media', 'title' => __('Media')), array('name' => 'NumberPlays', 'title' => __('Number of Plays')), array('name' => 'DurationSec', 'title' => __('Total Duration (s)')), array('name' => 'Duration', 'title' => __('Total Duration')), array('name' => 'MinStart', 'title' => __('First Shown')), array('name' => 'MaxEnd', 'title' => __('Last Shown'))); Theme::Set('table_cols', $cols); $rows = array(); while ($row = $db->get_assoc_row($results)) { $row['Display'] = Kit::ValidateParam($row['Display'], _STRING); $row['Media'] = Kit::ValidateParam($row['Name'], _STRING); $row['NumberPlays'] = Kit::ValidateParam($row['NumberPlays'], _INT); $row['DurationSec'] = Kit::ValidateParam($row['Duration'], _INT); $row['Duration'] = sec2hms(Kit::ValidateParam($row['Duration'], _INT)); $row['MinStart'] = DateManager::getLocalDate(strtotime(Kit::ValidateParam($row['MinStart'], _STRING))); $row['MaxEnd'] = DateManager::getLocalDate(strtotime(Kit::ValidateParam($row['MaxEnd'], _STRING))); $rows[] = $row; } Theme::Set('table_rows', $rows); Theme::Set('table_media_shown', Theme::RenderReturn('table_render')); // Media on Layouts Ran $SQL = "SELECT display.Display, layout.Layout, IFNULL(media.Name, 'Text/Rss/Webpage') AS Name, COUNT(StatID) AS NumberPlays, SUM(TIME_TO_SEC(TIMEDIFF(end, start))) AS Duration, MIN(start) AS MinStart, MAX(end) AS MaxEnd "; $SQL .= ' FROM stat '; $SQL .= ' INNER JOIN display ON stat.DisplayID = display.DisplayID '; $SQL .= ' INNER JOIN layout ON layout.LayoutID = stat.LayoutID '; $SQL .= ' LEFT OUTER JOIN media ON media.MediaID = stat.MediaID '; $SQL .= " WHERE stat.type = 'media' "; $SQL .= sprintf(" AND stat.end > '%s' ", $fromDt); $SQL .= sprintf(" AND stat.start <= '%s' ", $toDt); $SQL .= ' AND stat.displayID IN (' . implode(',', $display_ids) . ') '; if ($mediaId != 0) { $SQL .= sprintf(" AND media.MediaID = %d ", $mediaId); } if ($displayId != 0) { $SQL .= sprintf(" AND stat.displayID = %d ", $displayId); } $SQL .= "GROUP BY display.Display, layout.Layout, IFNULL(media.Name, 'Text/Rss/Webpage') "; $SQL .= "ORDER BY display.Display, layout.Layout, IFNULL(media.Name, 'Text/Rss/Webpage')"; if (!($results = $this->db->query($SQL))) { trigger_error($db->error()); trigger_error(__('Unable to get Library Media Ran'), E_USER_ERROR); } $cols = array(array('name' => 'Display', 'title' => __('Display')), array('name' => 'Layout', 'title' => __('Layout')), array('name' => 'Media', 'title' => __('Media')), array('name' => 'NumberPlays', 'title' => __('Number of Plays')), array('name' => 'DurationSec', 'title' => __('Total Duration (s)')), array('name' => 'Duration', 'title' => __('Total Duration')), array('name' => 'MinStart', 'title' => __('First Shown')), array('name' => 'MaxEnd', 'title' => __('Last Shown'))); Theme::Set('table_cols', $cols); $rows = array(); while ($row = $db->get_assoc_row($results)) { $row['Display'] = Kit::ValidateParam($row['Display'], _STRING); $row['Layout'] = Kit::ValidateParam($row['Layout'], _STRING); $row['Media'] = Kit::ValidateParam($row['Name'], _STRING); $row['NumberPlays'] = Kit::ValidateParam($row['NumberPlays'], _INT); $row['DurationSec'] = Kit::ValidateParam($row['Duration'], _INT); $row['Duration'] = sec2hms(Kit::ValidateParam($row['Duration'], _INT)); $row['MinStart'] = DateManager::getLocalDate(strtotime(Kit::ValidateParam($row['MinStart'], _STRING))); $row['MaxEnd'] = DateManager::getLocalDate(strtotime(Kit::ValidateParam($row['MaxEnd'], _STRING))); $rows[] = $row; } Theme::Set('table_rows', $rows); Theme::Set('table_media_on_layouts_shown', Theme::RenderReturn('table_render')); $output = Theme::RenderReturn('stats_page_grid'); $response->SetGridResponse($output); $response->paging = false; $response->Respond(); }
/** * Json Encode, handling and logging errors * http://stackoverflow.com/questions/10199017/how-to-solve-json-error-utf8-error-in-php-json-decode * @param mixed $mixed The item to encode * @return mixed The Encoded Item */ public static function jsonEncode($mixed) { if (version_compare(PHP_VERSION, '5.4.0') >= 0) { $encoded = json_encode($mixed, JSON_PRETTY_PRINT); } else { $encoded = json_encode($mixed); } switch (json_last_error()) { case JSON_ERROR_NONE: return $encoded; case JSON_ERROR_DEPTH: Debug::Audit('Maximum stack depth exceeded'); return false; case JSON_ERROR_STATE_MISMATCH: Debug::Audit('Underflow or the modes mismatch'); return false; case JSON_ERROR_CTRL_CHAR: Debug::Audit('Unexpected control character found'); return false; case JSON_ERROR_SYNTAX: Debug::Audit('Syntax error, malformed JSON'); return false; case JSON_ERROR_UTF8: $clean = Kit::utf8ize($mixed); return Kit::jsonEncode($clean); default: Debug::Audit('Unknown error'); return false; } }
header('HTTP/1.0 404 Not Found'); } else { // Issue magic packet // Send via Apache X-Sendfile header? if ($sendFileMode == 'Apache') { Debug::LogEntry('audit', 'HTTP GetFile request redirecting to ' . Config::GetSetting('LIBRARY_LOCATION') . $file['storedAs'], 'services'); header('X-Sendfile: ' . Config::GetSetting('LIBRARY_LOCATION') . $file['storedAs']); } else { if ($sendFileMode == 'Nginx') { header('X-Accel-Redirect: /download/' . $file['storedAs']); } else { header('HTTP/1.0 404 Not Found'); } } // Debug Debug::Audit('File request via magic packet. ' . $file['storedAs'], $file['displayId']); // Log bandwidth $bandwidth = new Bandwidth(); $bandwidth->Log($file['displayId'], 4, $file['size']); } exit; } try { $wsdl = 'lib/service/service_v' . $version . '.wsdl'; if (!file_exists($wsdl)) { $serviceResponse->ErrorServerError('Your client is not the correct version to communicate with this CMS.'); } $soap = new SoapServer($wsdl); //$soap = new SoapServer($wsdl, array('cache_wsdl' => WSDL_CACHE_NONE)); $soap->setClass('XMDSSoap' . $version); $soap->handle();
/** * Import a Folder of ZIP files * @param [string] $folder The folder to import */ public function importFolder($folder) { Debug::Audit('Importing folder: ' . $folder); if (is_dir($folder)) { // Get a list of files foreach (array_diff(scandir($folder), array('..', '.')) as $file) { Debug::Audit('Found file: ' . $file); if (stripos($file, '.zip')) { $this->Import($folder . DIRECTORY_SEPARATOR . $file, NULL, 1, false, false, true, false); } } } }
/** * Deletes an Xibo User Group * @param int $userGroupId * @return bool */ public function Delete($userGroupId) { Debug::Audit('IN: ' . $userGroupId); try { $dbh = PDOConnect::init(); $params = array('groupid' => $userGroupId); // Delete all permissions $sth = $dbh->prepare('DELETE FROM `lkcampaigngroup` WHERE GroupID = :groupid'); $sth->execute($params); $sth = $dbh->prepare('DELETE FROM `lkdatasetgroup` WHERE GroupID = :groupid'); $sth->execute($params); $sth = $dbh->prepare('DELETE FROM `lkdisplaygroupgroup` WHERE GroupID = :groupid'); $sth->execute($params); $sth = $dbh->prepare('DELETE FROM `lklayoutmediagroup` WHERE GroupID = :groupid'); $sth->execute($params); $sth = $dbh->prepare('DELETE FROM `lklayoutregiongroup` WHERE GroupID = :groupid'); $sth->execute($params); $sth = $dbh->prepare('DELETE FROM `lkmediagroup` WHERE GroupID = :groupid'); $sth->execute($params); // Remove linked users $sth = $dbh->prepare('DELETE FROM `lkusergroup` WHERE GroupID = :groupid'); $sth->execute($params); // Delete all menu links $sth = $dbh->prepare('DELETE FROM `lkmenuitemgroup` WHERE GroupID = :groupid'); $sth->execute($params); // Delete all page links $sth = $dbh->prepare('DELETE FROM `lkpagegroup` WHERE GroupID = :groupid'); $sth->execute($params); // Delete the user group $sth = $dbh->prepare('DELETE FROM `group` WHERE GroupID = :groupid'); $sth->execute($params); return true; } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage()); if (!$this->IsError()) { return $this->SetError(25015, __('Unable to delete User Group.')); } return false; } }
/** * Get Resource */ public function GetResource($displayId = 0) { $proportional = Kit::GetParam('proportional', _GET, _BOOL, true); $thumb = Kit::GetParam('thumb', _GET, _BOOL, false); $dynamic = isset($_REQUEST['dynamic']); $file = $this->storedAs; $width = intval(Kit::GetParam('width', _REQUEST, _DOUBLE, 80)); $height = intval(Kit::GetParam('height', _REQUEST, _DOUBLE, 80)); // File upload directory.. get this from the settings object $library = Config::GetSetting("LIBRARY_LOCATION"); $fileName = $library . $file; Debug::Audit(sprintf('Image Request %dx%d %s. Thumb: %s', $width, $height, $fileName, $thumb)); // If we are a thumb request then output the cached thumbnail if ($thumb) { $fileName = $library . sprintf('tn_%dx%d_%s', $width, $height, $file); // If the thumbnail doesn't exist then create one if (!file_exists($fileName)) { Debug::LogEntry('audit', 'File doesnt exist, creating a thumbnail for ' . $fileName); if (!($info = getimagesize($library . $file))) { die($library . $file . ' is not an image'); } ResizeImage($library . $file, $fileName, $width, $height, $proportional, 'file'); } } // Get the info for this new temporary file if (!($info = getimagesize($fileName))) { $fileName = 'theme/default/img/forms/filenotfound.png'; $this->ReturnFile($fileName); exit; } if ($dynamic && !$thumb && $info[2]) { $width = intval(Kit::GetParam('width', _REQUEST, _DOUBLE, 80)); $height = intval(Kit::GetParam('height', _REQUEST, _DOUBLE, 80)); // dynamically create an image of the correct size - used for previews ResizeImage($fileName, '', $width, $height, $proportional, 'browser'); exit; } if (!file_exists($fileName)) { //not sure Debug::LogEntry('audit', "Cant find: {$uid}", 'module', 'GetResource'); $fileName = 'theme/default/img/forms/filenotfound.png'; } $this->ReturnFile($fileName); exit; }
private function GetDataSetItems($displayId, $isPreview, $text) { $db =& $this->db; // Extra fields for data sets $dataSetId = $this->GetOption('datasetid'); $upperLimit = $this->GetOption('upperLimit'); $lowerLimit = $this->GetOption('lowerLimit'); $filter = $this->GetOption('filter'); $ordering = $this->GetOption('ordering'); Debug::LogEntry('audit', 'Then template for each row is: ' . $text); // Set an expiry time for the media $media = new Media(); $layout = new Layout(); $expires = time() + $this->GetOption('updateInterval', 3600) * 60; // Combine the column id's with the dataset data $matches = ''; preg_match_all('/\\[(.*?)\\]/', $text, $matches); $columnIds = array(); foreach ($matches[1] as $match) { // Get the column id's we are interested in Debug::LogEntry('audit', 'Matched column: ' . $match); $col = explode('|', $match); $columnIds[] = $col[1]; } // Get the dataset results $dataSet = new DataSet($db); if (!($dataSetResults = $dataSet->DataSetResults($dataSetId, implode(',', $columnIds), $filter, $ordering, $lowerLimit, $upperLimit, $displayId))) { return; } // Create an array of header|datatypeid pairs $columnMap = array(); foreach ($dataSetResults['Columns'] as $col) { $columnMap[$col['Text']] = $col; } Debug::Audit(var_export($columnMap, true)); $items = array(); foreach ($dataSetResults['Rows'] as $row) { // For each row, substitute into our template $rowString = $text; foreach ($matches[1] as $sub) { // Pick the appropriate column out $subs = explode('|', $sub); // The column header $header = $subs[0]; $replace = $row[$header]; // Check in the columns array to see if this is a special one if ($columnMap[$header]['DataTypeID'] == 4) { // Download the image, alter the replace to wrap in an image tag $file = $media->addModuleFileFromUrl(str_replace(' ', '%20', htmlspecialchars_decode($replace)), 'ticker_dataset_' . md5($dataSetId . $columnMap[$header]['DataSetColumnID'] . $replace), $expires); // Tag this layout with this file $layout->AddLk($this->layoutid, 'module', $file['mediaId']); $replace = $isPreview ? '<img src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $file['mediaId'] . '" />' : '<img src="' . $file['storedAs'] . '" />'; } $rowString = str_replace('[' . $sub . ']', $replace, $rowString); } $items[] = $rowString; } return $items; }
public function displayUp($displayId) { try { $dbh = PDOConnect::init(); Debug::Audit('Display Up: ' . $displayId); $sth = $dbh->prepare('UPDATE `stat` SET end = :toDt WHERE displayId = :displayId AND end IS NULL AND type = :type'); $sth->execute(array('toDt' => date('Y-m-d H:i:s'), 'type' => 'displaydown', 'displayId' => $displayId)); return true; } catch (Exception $e) { Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__); if (!$this->IsError()) { $this->SetError(1, __('Unknown Error')); } return false; } }
/** * Sets the Members of a group */ public function SetMembers() { $db =& $this->db; $response = new ResponseManager(); $groupObject = new UserGroup($db); $groupId = Kit::GetParam('GroupID', _REQUEST, _INT); $users = Kit::GetParam('UserID', _POST, _ARRAY, array()); // We will receive a list of users from the UI which are in the "assign column" at the time the form is // submitted. // We want to go through and unlink any users that are NOT in that list, but that the current user has access // to edit. // We want to add any users that are in that list (but aren't already assigned) // All users that this session has access to if (!($allUsers = $this->user->userList())) { trigger_error(__('Error getting all users'), E_USER_ERROR); } // Convert to an array of ID's for convenience $allUserIds = array_map(function ($array) { return $array['userid']; }, $allUsers); // Users in group $usersAssigned = UserData::entries(null, array('groupIds' => array($groupId))); Debug::Audit('All userIds we want to assign: ' . var_export($users, true)); Debug::Audit('All userIds we have access to: ' . var_export($allUserIds, true)); foreach ($usersAssigned as $user) { /* @var Userdata $user */ // Did this session have permission to do anything to this user? // If not, move on if (!in_array($user->userId, $allUserIds)) { continue; } Debug::Audit('Logged in user has permission to make changes to this assigned user ' . $user->userId); // Is this user in the provided list of users? if (in_array($user->userId, $users)) { // This user is already assigned, so we remove it from the $users array Debug::Audit('This user is already assigned ' . $user->userId); if (($key = array_search($user->userId, $users)) !== false) { unset($users[$key]); } } else { Debug::Audit('This user is assigned, but not in the list of assignments ' . $user->userId); // It isn't therefore needs to be removed if (!$groupObject->Unlink($groupId, $user->userId)) { trigger_error($groupObject->GetErrorMessage(), E_USER_ERROR); } } } Debug::Audit('All userIds we want to assign after sorting: ' . var_export($users, true)); // Add any users that are still missing after tha assignment process foreach ($users as $userId) { Debug::Audit('User was missing, linking them: ' . $userId); // Add any that are missing if (!$groupObject->Link($groupId, $userId)) { trigger_error($groupObject->GetErrorMessage(), E_USER_ERROR); } } $response->SetFormSubmitResponse(__('Group membership set'), false); $response->Respond(); }