@copyright Copyright (C) 2015. All Rights Reserved
@license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
A sermon distributor that links to Dropbox.
/-----------------------------------------------------------------------------------------------------------------------------*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* Sermondistributor component helper
*/
abstract class SermondistributorHelper
{
/**
* The Global Site Event Method.
**/
public static function globalEvent($document)
{
self::loadExternalUpdateAjax($document);
}
/**
* Load the External Update Ajax to page
**/
public static function loadExternalUpdateAjax($document)
{
$update = self::getNextUpdateValues(); // id, target, type
if ($update)
{
$document->addScriptDeclaration("
jQuery(window).load(function() {
checkExternalListing(".$update.");
});
function checkExternalListing(id, target, type) {
checkExternalListing_server(id, target, type).done(function(result) {
// good it is done
});
}
function checkExternalListing_server(id, target, type) {
var getUrl = '".JURI::root()."index.php?option=com_sermondistributor&task=ajax.autoUpdateLocalListingExternal&format=json';
if(target > 0 && type > 0 && id > 0){
var request = 'token=".JSession::getFormToken()."&target='+target+'&listing='+id+'&type='+type;
}
return jQuery.ajax({
type: 'GET',
url: getUrl,
dataType: 'jsonp',
data: request,
jsonp: 'callback'
});
}");
}
}
/**
* The external source links auto
**/
protected static $links_externalsource_auto;
/**
* The external source links manual
**/
protected static $links_externalsource_manual;
/**
* The external source selection auto
**/
protected static $select_externalsource_auto;
/**
* The external source selection manual
**/
protected static $select_externalsource_manual;
/**
* The user notice info File Name
**/
protected static $usernotice = false;
/**
* The update error info File Name
**/
protected static $updateerror = false;
/**
* The update last File path
**/
protected static $updatelast = false;
/**
* The update errors
**/
protected static $updateErrors = array();
/**
* prepare base64 string for url
**/
public static function base64_urlencode($string, $encode = false)
{
if ($encode)
{
$string = base64_encode($string);
}
return str_replace(array('+', '/'), array('-', '_'), $string);
}
/**
* prepare base64 string form url
**/
public static function base64_urldecode($string, $decode = false)
{
$string = str_replace(array('-', '_'), array('+', '/'), $string);
if ($decode)
{
$string = base64_decode($string);
}
return $string;
}
/**
* get Download links of a sermon
**/
public static function getDownloadLinks(&$sermon)
{
$links = array();
// Get local key
$localkey = self::getLocalKey();
// decrypt the urls
$safe = new FOFEncryptAes($localkey, 128);
// internal download url
$keyCounter = new stdClass;
$keyCounter->sermon = $sermon->id;
if ($sermon->preacher)
{
$keyCounter->preacher = $sermon->preacher;
}
if ($sermon->series)
{
$keyCounter->series = $sermon->series;
}
$keyCounterRAW = $safe->encryptString(json_encode($keyCounter));
$keyCounter = self::base64_urlencode($keyCounterRAW);
$token = JSession::getFormToken();
$downloadURL = JURI::root().'index.php?option=com_sermondistributor&task=download.file&key='.$keyCounter.'&token='.$token;
// check if local .htaccess should be set
$setHtaccess = false;
$onclick = ' onclick="sermonCounter(\''.$keyCounterRAW.'\',\'FILENAME\');"';
// check what source of our link
switch ($sermon->source)
{
case 1:
// local file get local folder and check if outside root (if not then allow direct)
$localFolder = JComponentHelper::getParams('com_sermondistributor')->get('localfolder', JPATH_ROOT.'/images').'/';
// should we allow direct downloads
$allowDirect = false;
if (2 == $sermon->link_type && strpos($localFolder, JPATH_ROOT) !== false)
{
$allowDirect = true;
$localFolderURL = JURI::root().str_replace(JPATH_ROOT, '', $localFolder);
// insure no double // is in the URL
$localFolderURL = str_replace('//', '/', $localFolderURL);
$localFolderURL = str_replace(':/', '://', $localFolderURL);
}
// insure no double // is in the path name
$localFolder = str_replace('//', '/', $localFolder);
$localFolder = str_replace(':/', '://', $localFolder);
if (self::checkArray($sermon->local_files))
{
foreach($sermon->local_files as $key)
{
if (1 == $sermon->link_type || !$allowDirect)
{
// get the file name use the same method as the auto
$filename = self::getDownloadFileName($sermon,$key,'local');
$lockedFolderPath = $safe->encryptString($localFolder.$key);
$sermon->download_links[$filename] = $downloadURL.'&link='.self::base64_urlencode($lockedFolderPath).'&filename='.$filename;
$sermon->onclick[$filename] = '';
}
elseif (2 == $sermon->link_type && $allowDirect)
{
$filename = $key;
$sermon->download_links[$filename] = $localFolderURL.$key;
$sermon->onclick[$filename] = str_replace('FILENAME', $filename, $onclick);
$setHtaccess = true;
}
}
}
break;
case 2:
// Dropbox get global dropbox switch
$addToButton = JComponentHelper::getParams('com_sermondistributor')->get('add_to_button', 0);
if (1 == $sermon->build)
{
if (self::checkArray($sermon->manual_files))
{
// manual dropbox
foreach($sermon->manual_files as $key)
{
// get the link
$dropURL = self::getExternalSourceLink('manual',1,$key);
if (1 == $sermon->link_type && $dropURL)
{
// get the file name use the same method as the auto
$filename = self::getDownloadFileName($sermon,$key,'dropbox_manual');
// should we encrypt string this string
if ('localKey34fdWEkl' == $localkey || (base64_encode(base64_decode($dropURL, true)) !== $dropURL)) // hmmm no global key has been set
{
$dropURL = $safe->encryptString($dropURL);
}
$sermon->download_links[$filename] = $downloadURL.'&link='.self::base64_urlencode($dropURL).'&filename='.$filename;
$sermon->onclick[$filename] = '';
}
elseif (2 == $sermon->link_type && $dropURL)
{
$filename = str_replace('VDM_pLeK_h0uEr/', '', $key);
if ('localKey34fdWEkl' == $localkey) // hmmm no global key has been set (so don't decrypt)
{
$sermon->download_links[$filename] = $dropURL;
}
else
{
$sermon->download_links[$filename] = rtrim($safe->decryptString($dropURL), "\0");
}
$sermon->onclick[$filename] = str_replace('FILENAME', $filename, $onclick);
}
// build dropbox switch if needed
if (1 == $addToButton && $dropURL)
{
if ('localKey34fdWEkl' == $localkey) // hmmm no global key has been set (so don't decrypt)
{
$sermon->dropbox_buttons[$filename] = str_replace('?dl=1', '?dl=0', $dropURL);
}
else
{
$sermon->dropbox_buttons[$filename] = str_replace('?dl=1', '?dl=0', rtrim($safe->decryptString($dropURL), "\0"));
}
$sermon->onclick_drobox[$filename] = str_replace('FILENAME', $filename, $onclick);
}
}
}
}
elseif (2 == $sermon->build)
{
if (self::checkArray($sermon->auto_sermons))
{
// automatic dropbox
foreach($sermon->auto_sermons as $filename => $key)
{
// get the link
$dropURL = self::getExternalSourceLink('auto',1,$key);
if (1 == $sermon->link_type && $dropURL)
{
// should we encrypt string this string
if ('localKey34fdWEkl' == $localkey || (base64_encode(base64_decode($dropURL, true)) !== $dropURL)) // hmmm no global key has been set
{
$dropURL = $safe->encryptString($dropURL);
}
// get the file name (use the same method as the auto
$sermon->download_links[$filename] = $downloadURL.'&link='.self::base64_urlencode($dropURL).'&filename='.$filename;
$sermon->onclick[$filename] = '';
}
elseif (2 == $sermon->link_type && $dropURL)
{
if ('localKey34fdWEkl' == $localkey) // hmmm no global key has been set (so don't decrypt)
{
$sermon->download_links[$filename] = $dropURL;
}
else
{
$sermon->download_links[$filename] = rtrim($safe->decryptString($dropURL), "\0");
}
$sermon->onclick[$filename] = str_replace('FILENAME', $filename, $onclick);
}
// build dropbox switch if needed
if (1 == $addToButton && $dropURL)
{
if ('localKey34fdWEkl' == $localkey) // hmmm no global key has been set (so don't decrypt)
{
$sermon->dropbox_buttons[$filename] = str_replace('?dl=1', '?dl=0', $dropURL);
}
else
{
$sermon->dropbox_buttons[$filename] = str_replace('?dl=1', '?dl=0', rtrim($safe->decryptString($dropURL), "\0"));
}
$sermon->onclick_drobox[$filename] = str_replace('FILENAME', $filename, $onclick);
}
}
}
}
break;
case 3:
// url get the file name use the same method as the auto
$filename = self::getDownloadFileName($sermon,$sermon->url,'url');
if (1 == $sermon->link_type)
{
$lockedURL = $safe->encryptString($sermon->url);
$sermon->download_links[$filename] = $downloadURL.'&link='.self::base64_urlencode($lockedURL).'&filename='.$filename;
$sermon->onclick[$filename] = '';
}
elseif (2 == $sermon->link_type)
{
$sermon->download_links[$filename] = $sermon->url;
$sermon->onclick[$filename] = str_replace('FILENAME', $filename, $onclick);
}
break;
}
// remove the values no longer needed
unset($sermon->local_files);
unset($sermon->manual_files);
unset($sermon->auto_sermons);
unset($sermon->url);
// should we set the local .htaccess for the download folder
if ($setHtaccess)
{
// TODO we may need to add this latter to enforce download of files.
}
return true;
}
protected static function getNextUpdateValues()
{
// get actual update values
$updates = self::getExternalListingUpdateKeys();
// get last update
$updatePath = self::getFilePath('update', 'last', 'vDm', '.txt', JPATH_COMPONENT_ADMINISTRATOR);
if (($lastUpdate = @file_get_contents($updatePath)) !== FALSE && self::checkArray($updates))
{
// now check what is next
$lastKey = array_search($lastUpdate, $updates);
if (!is_null($lastKey))
{
$nextKey = $lastKey + 1;
if (isset($updates[$nextKey]))
{
self::saveFile($updates[$nextKey],$updatePath);
return $updates[$nextKey];
}
}
}
// rest and start with the first key
if (self::checkArray($updates))
{
// save the first set
$start = reset($updates);
self::saveFile($start,$updatePath);
return $start;
}
return false;
}
protected static function saveFile($data,$path_filename)
{
if (self::checkString($data))
{
$fp = fopen($path_filename, 'w');
fwrite($fp, $data);
fclose($fp);
return true;
}
return false;
}
public static function getExternalListingUpdateKeys($id = null, $updateMethod = 2, $returnType = 1)
{
// first check if this file already has statistics
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('id','sharedurl','folder','permissiontype','dropboxoptions','build')));
$query->from($db->quoteName('#__sermondistributor_external_source'));
if ($updateMethod && is_numeric($updateMethod))
{
$query->where($db->quoteName('update_method') . ' = '. (int) $updateMethod);
}
if ($id && is_numeric($id))
{
$query->where($db->quoteName('id') . ' = '. (int) $id);
}
elseif ($id && self::checkArray($id))
{
$ids = implode(',', array_map( 'intval', $id));
$query->where($db->quoteName('id') . ' IN (' . $ids . ')');
}
$query->where($db->quoteName('published') . ' = 1');
$db->setQuery($query);
$db->execute();
if ($db->getNumRows())
{
$results = $db->loadObjectList();
$updates = array();
foreach ($results as $result)
{
if ('full' == $result->permissiontype)
{
// load folder or urls
switch ($result->dropboxoptions)
{
case 1: // sharedurl
if (self::checkJson($result->sharedurl))
{
$targets = json_decode($result->sharedurl)->tsharedurl;
}
break;
case 2: // folders
if (self::checkJson($result->folder))
{
$targets = json_decode($result->folder)->tfolder;
}
break;
}
if (self::checkArray($targets))
{
foreach ($targets as $key => $value)
{
$nr = $key + 1;
// id, target, type
if (1 == $returnType)
{
$updates[] = $result->id . ', '. $nr . ', ' . $result->build;
}
else // only return the targets
{
$updates[] = $nr;
}
}
}
}
else
{
// id, target, type
if (1 == $returnType)
{
$updates[] = $result->id . ', 1, '. $result->build;
}
else // only return the targets
{
$updates[] = 1;
}
}
}
return $updates;
}
return false;
}
public static function getExternalSourceLink($type, $return = 7, $get = false, $target = 'links')
{
// make sure all defaults are set
$found = self::checkExternalSourceLocalListing($type, $target);
if ($found)
{
switch($return)
{
case 1:
// return a link
if (isset(self::${$target.'_externalsource_'.$type}[$get]))
{
return self::${$target.'_externalsource_'.$type}[$get];
}
break;
case 2:
// return all links
return self::${$target.'_externalsource_'.$type};
break;
default :
// just confirm that it is set
return true;
break;
}
}
return false;
}
public static function countDownload($counter,$filename)
{
// Get local key
$localkey = self::getLocalKey();
$opener = new FOFEncryptAes($localkey, 128);
$counter = json_decode(rtrim($opener->decryptString($counter), "\0"));
if (self::checkObject($counter))
{
$counter->filename = $filename;
// set the date object
$date = JFactory::getDate();
// first check if this file already has statistics
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('id','counter')));
$query->from($db->quoteName('#__sermondistributor_statistic'));
$query->where($db->quoteName('sermon') . ' = '. (int) $counter->sermon);
$query->where($db->quoteName('filename') . ' = '. $db->quote($counter->filename));
$db->setQuery($query);
$db->execute();
if ($db->getNumRows())
{
$statistic = $db->loadObject();
// already has an entry
$statistic->counter++;
$statistic->modified = $date->toSql();
// update the entry
return $db->updateObject('#__sermondistributor_statistic', $statistic, 'id');
}
else
{
// set a new entry
$counter->counter = 1;
$counter->published = 1;
$counter->created = $date->toSql();
$counter->access = 1;
$counter->version = 1;
// set a new entry
$done = $db->insertObject('#__sermondistributor_statistic', $counter);
// if done return last used id
if ($done)
{
$newId = $db->insertid();
// make sure the access of asset is set
return self::setAsset($newId,'statistic');
}
}
}
return false;
}
protected static function getDownloadFileName(&$sermon,$file,$type)
{
// first get file name and file type
$file = str_replace('VDM_pLeK_h0uEr/', '', $file);
$fileType = pathinfo($file, PATHINFO_EXTENSION);
if ($fileType)
{
$file = str_replace('.'.$fileType, '', $file);
}
else
{
$fileType = 'error';
}
// now build download name
$downloadName = array();
// build the Download File Name - first add the preacher name if set
if ($sermon->preacher)
{
$downloadName[] = self::safeString($sermon->preacher_name,'U');
}
// add the series name if set
if ($sermon->series)
{
$downloadName[] = self::safeString($sermon->series_name,'F');
}
// add the category name if set
if ($sermon->catid && self::checkString($sermon->category))
{
$downloadName[] = self::safeString($sermon->category, 'F');
}
if ('dropbox_manual' == $type || 'local' == $type)
{
// add the main file name
$downloadName[] = self::safeString($sermon->name,'F');
$downloadName[] = self::safeString($file,'F');
}
else
{
$downloadName[] = self::safeString($sermon->name,'F');
if ('error' == $fileType || strpos('?', $fileType) !== false || strpos('&', $fileType) !== false )
{
$fileType = 'mp3'; // TODO we don't know the url filetype (setting to mp3 but this could be wrong)
}
}
// now build the download file name
return implode('__', $downloadName).'.'.$fileType;
}
/**
* check External Source Local Listing (do we have the files)
**/
public static function checkExternalSourceLocalListing($type, $get = 'links')
{
// get the local links
if (isset(self::${$get.'_externalsource_'.$type}) && self::checkArray(self::${$get.'_externalsource_'.$type}))
{
// return true we have links loaded
return true;
}
else
{
$target = array('links' => 'url', 'select' => 'name');
$build = array( 'auto' => 2, 'manual' => 1);
if (isset($build[$type]))
{
// load the links from the database
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
$query->select($db->quoteName(array('key', $target[$get])));
$query->from($db->quoteName('#__sermondistributor_local_listing'));
$query->where($db->quoteName('build') . ' = '. (int) $build[$type]);
$query->where($db->quoteName('published') . ' = 1'); // TODO we can now limit the links to access groups
// Reset the query using our newly populated query object.
$db->setQuery($query);
$db->execute();
if ($db->getNumRows())
{
self::${$get.'_externalsource_'.$type} = $db->loadAssocList('key', $target[$get]);
// return true we have links loaded
return true;
}
}
}
return false;
}
public static function getFilePath($type, $name = 'listing', $key = 'vDm', $fileType = '.json', $PATH = JPATH_COMPONENT_SITE)
{
if (!isset(self::${$type.$name}[$key]) || !self::checkString(self::${$type.$name}[$key]))
{
// Get local key
$localkey = self::getLocalKey();
// check the key
$keyMD5 = '';
if ('vDm' != $key)
{
$keyMD5 = $key;
}
// set the name
$fileName = md5($type.$name.$localkey.$keyMD5);
// set file path
self::${$type.$name}[$key] = $PATH.'/helpers/'.$fileName.$fileType;
}
if (isset(self::${$type.$name}[$key]) && self::checkString(self::${$type.$name}[$key]))
{
// return the path
return self::${$type.$name}[$key];
}
return '';
}
/**
* get the localkey
**/
protected static $localkey = array();
public static function getLocalKey($type = 'basic_key')
{
if (!isset(self::$localkey[$type]))
{
// get the main key
self::$localkey[$type] = JComponentHelper::getParams('com_sermondistributor')->get($type, 'localKey34fdWEkl');
}
return self::$localkey[$type];
}
public static function updateExternalSource($id, $target = 0, $type = false, $force = false, $sleutel = null)
{
$source = self::getVar('external_source', (int) $id, 'id', 'externalsources');
if (1 == $source) // Dropbox is the source
{
// load the file
JLoader::import('dropboxupdater', JPATH_COMPONENT_SITE.'/helpers');
// update types
$types = array('manual','auto');
// okay now update this type
if (self::checkString($type) && in_array($type,$types))
{
$dropbox = new Dropboxupdater();
if ($dropbox->update($id, $target, $type, $force, $sleutel))
{
return true;
}
self::setUpdateError($id, $dropbox->getErrors());
return false;
}
}
self::setUpdateError($id, array(JText::_('COM_SERMONDISTRIBUTOR_THE_EXTERNAL_SOURCE_COULD_NOT_BE_FOUND')));
return false;
}
public static function getSourceStatus($id)
{
// fist get errors if any is found
$errors = array();
if ($targets = self::getExternalListingUpdateKeys($id, null, 1))
{
foreach ($targets as $target)
{
$key = preg_replace('/[ ,]+/', '', trim($target));
if ($error = self::getUpdateError(0, $key))
{
$errors[] = $error;
}
}
}
// check when was the last update
$updateInfo = self::updateInfo($id);
if (!$updateInfo)
{
$errors[] = JText::_('COM_SERMONDISTRIBUTOR_THIS_SOURCE_HAS_NO_LOCAL_LISTING_SET');
}
// build the return string
if (isset($updateInfo['last']) || self::checkArray($errors))
{
$body = array();
// great we have source status
if (isset($updateInfo['last']))
{
$body[] = '