Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560 [2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85 [3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50 [4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13 [5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
| Server IP : 94.177.8.99 / Your IP : 216.73.217.165 Web Server : Apache/2.4.58 (Ubuntu) System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/hopeinstoughton_cdn1/include/ |
Upload File : |
<?php
class MediaSource {
private $db;
private $data;
private $basename;
private $mmitem;
private $media;
const ARIES = 1;
const HOSTZ = 2;
const CHURCH = 3;
const BACKUP1 = 4; // Home
// 256bit key, generated using https://csfieldguide.org.nz/en/interactives/rsa-key-generator/
const KEY_PRIVATE = <<<BLOCK
-----BEGIN RSA PRIVATE KEY-----
MIGqAgEAAiEAz/aF1DSTz4duSmvTKItkZE/8sxfnQhUl4rks26KbgwECAwEAAQIg
RIgr8BNnhmNOAC5qRpkw+pmYu66OvdZmvUhXrHGqfHUCEQDr58xGtxKWAlk+otdO
bK8PAhEA4a1nyqbkxT7T2Lc3ghqs7wIRALlyU/x3KC4ylHOP0Y++EnMCEG2fyUpE
ld5GrauZHGqjwJsCECC4AJInN24VvWe5ealG/bs=
-----END RSA PRIVATE KEY-----
BLOCK;
const KEY_PUBLIC = <<<BLOCK
-----BEGIN RSA PUBLIC KEY-----
MCgCIQDP9oXUNJPPh25Ka9Moi2RkT/yzF+dCFSXiuSzbopuDAQIDAQAB
-----END RSA PUBLIC KEY-----
BLOCK;
public function __construct() {
$this->data = NULL;
$this->media = NULL;
}
public function Db() {
if (func_num_args()) {
$this->db = func_get_arg(0);
return $this;
}
return $this->db;
}
public function BaseFilename() { // filename without path or extension
if (func_num_args()) {
$this->basename = func_get_arg(0);
return $this;
}
return $this->basename;
}
public function MmItem() { // mm_item object from the database. must have `mi_id` property
if (func_num_args()) {
$this->mmitem = func_get_arg(0);
return $this;
}
return $this->mmitem;
}
public function Media() { // items from the mm_media table
if (func_num_args()) {
$this->media = func_get_arg(0);
return $this;
}
return $this->media;
}
public function Load() {
$rows = $this->db->get_results('select ms_id,ms_name,ms_url,ms_path,ms_mountfile from `mm_source` order by ms_id');
$this->data = [];
foreach($rows as $row) {
$id = $row->ms_id;
$this->data[$id] = $row;
}
}
public function generateDownloadLink($target, $downloadname, $action = 'file') {
if ($this->data === NULL) $this->Load();
$p = strrpos($downloadname, '.');
$ext = substr($downloadname, $p + 1);
$base = substr($downloadname, 0, $p);
if ($base == '') $downloadname = '';
$id = $this->mmitem->mi_id;
$auth = $this->generateAuth($ext);
$link = $this->data[$target]->ms_url . '/' . $action . '/' . $auth;
if ($downloadname != '') $link .= '/' . $downloadname;
return $link;
}
// save file to filesystem
// get file info
public function getListing() {
if ($this->data === NULL) $this->Load();
$hasVTT = 0;
$hasJPG = 0;
foreach($this->media as $item) {
switch($item->mm_type) {
case 'vtt':
$hasVTT = 1;
break;
case 'jpg':
$hasJPG = 1;
break;
}
}
$rows = [];
foreach($this->media as $item) {
$ext = $item->mm_type;
$source_id = $item->mm_source;
$source_info = $this->data[$source_id];
if ($ext == 'mp3' && isset($item->mm_other->ext)) {
$ext = $item->mm_other->ext;
}
$base = ($ext == 'vtt' || $ext == 'xml' || $ext == 'html' || $ext == 'zip') ? $this->mmitem->mi_id : $this->basename;
$node = [
'i_type' => $ext,
'i_filename' => $base . '.' . $ext,
'source' => $source_id,
// 'name' => $source_info->ms_name,
'base' => $source_info->ms_path,
'url' => $source_info->ms_url,
'i_filesize' => static::formatBytes($item->mm_filesize),
'i_dimension'=> $item->mm_framesize,
'i_location' => $source_info->ms_name,
'i_flags' => '',
'auth' => $this->generateAuth($ext),
];
$duration = (int) $item->mm_duration;
if ($duration > 3599) {
$hours = floor($duration / 3600);
$duration %= 3600;
$duration = sprintf('%d:%02d:%02d', $hours, floor($duration / 60), $duration % 60);
} elseif ($duration) {
$duration = sprintf('%02d:%02d', floor($duration / 60), $duration % 60);
} else {
$duration = '';
}
$node['i_duration'] = $duration;
if ($ext == 'mp3' || $ext == 'm4a') {
$node['present_vtt'] = $hasVTT;
$node['info'] = (array) $item->mm_other;
unset($node['info']['bitrate'], $node['info']['frequency']);
}
if ($ext == 'mp4') {
$node['present_jpg'] = $hasJPG;
}
$rows[] = $node;
}
return $rows;
}
public function determineBestServer($serverbitmap, $asURL = FALSE) {
if ($this->data === NULL) $this->Load();
if ($serverbitmap & (1 << self::ARIES)) {
return self::ARIES; // Alcor is the best
}
// if ($asURL && $serverbitmap & (1 << self::HOSTZ)) {
// return self::HOSTZ; // Hostz, if present should be primary source for downloads
// }
foreach($this->data as $key => $value) {
$mask = 1 << $key;
if ($serverbitmap & $mask) {
if (!$asURL) { // if the media is not mounted, ignore it
$specialfile = $this->data[$key]->ms_path . '/' . $this->data[$key]->ms_mountfile;
if (!file_exists($specialfile)) continue;
}
return $key;
}
}
return NULL; // not present anywhere :(
}
public function getDestination($target, $filename) {
if ($this->data === NULL) $this->Load();
$targetdir = $this->data[$target]->ms_path . '/' . substr($filename, 0, 1);
if (!is_dir($targetdir)) {
mkdir($targetdir, 0777, TRUE);
}
return $targetdir . '/' . $filename;
}
public function getHost($target) {
if ($this->data === NULL) $this->Load();
return $this->data[$target]->ms_url;
}
private function _getOldMoorestownFolder($src) {
if ($src == 3) return '/mnt/church/av/moorestown'; // mp3. should use ms_path
if ($src == 1) return '/var/www/hopeinstoughton_www/av/moorestown-vtt';
die('unknown location ' . $src);
}
// copy a file from a source server to a target
// filename does not contain path
// sources is a bitmap of servers containing the requested file
// target is a ms_id
// datatype is used to determine where the source file is located
public function CopyFile($filename, $sources, $target, $datatype = NULL) {
if ($this->data === NULL) $this->Load();
$src = $this->determineBestServer($sources);
if ($datatype == 'mt' && ($src == 3 || $src == 1)) {
$sourcefile = $this->_getOldMoorestownFolder($src) . '/' . $filename;
} else {
echo('unable to determine source path (' . $src . ') for ' . $filename . "<br>\n");
return FALSE;
}
$destfile = $this->getDestination($target, $filename); // this will create folders if needed
if (!file_exists($destfile)) {
copy($sourcefile, $destfile); // server-to-server transfer
@chmod($destfile, 0666);
return 1; // not existing, copied
}
return 2; // exists, so not copied
}
private function _encryptPayload($privatekey, $payload) {
$key = openssl_pkey_get_private($privatekey);
// encrypt
$det = openssl_pkey_get_details($key);
$blocksize = intval(($det['bits'] - 88) / 8);
$output = '';
foreach(str_split($payload, $blocksize) as $chunk) {
$encrypted = '';
$j = openssl_private_encrypt($chunk, $encrypted, $key, OPENSSL_PKCS1_PADDING );
if ($j === FALSE) return FALSE; // failed to encrypt - bad key
$output .= $encrypted;
}
return base64_encode($output);
}
// 256bit key can encrypt blocks of 21 bytes
// requires Id() set
// payload: 3byte ext, 4byte exp, remaining = identifier
public function generateAuth($ext, $ttl = 3600) {
if (empty($this->mmitem->mi_id)) die('id not specified');
$id = substr($this->mmitem->mi_id, 0, 14);
$exp = time() - 1630000000;
$payload = pack('A3Va14', $ext, $exp + $ttl, $id);
$encrypted = $this->_encryptPayload(self::KEY_PRIVATE, $payload);
$encrypted = str_replace(['+', '/'], ['-', '_'], $encrypted);
return $encrypted;
}
private function _decryptPayload($private_key, $data) {
$key = openssl_pkey_get_private($private_key);
$info = openssl_pkey_get_details($key);
$pub = $info['key'];
$key = openssl_pkey_get_public($pub);
$blocksize = ceil(($info['bits']) / 8);
$output = '';
foreach(str_split($data, $blocksize) as $block) {
$decrypted = '';
if (!openssl_public_decrypt($block, $decrypted, $key)) {
return FALSE; // not using this key
}
$output .= $decrypted;
}
return $output;
}
public function decodeAuth($payload) {
$payload = base64_decode(str_replace(['-', '_'], ['+', '/'], $payload));
$data = $this->_decryptPayload(self::KEY_PRIVATE, $payload);
$result = new StdClass;
$result->valid = !empty($data);
$result->expired = TRUE;
if ($result->valid) {
$info = unpack('A3ext/Vexp/a14id', $data);
$result->id = trim($info['id']);
$result->expiry = $info['exp'] + 1630000000;
$result->ext = trim($info['ext']);
$result->expired = time() > $result->expiry;
}
return $result;
}
static
public function formatBytes($bytes, $precision = 2) {
$units = array('B', 'KiB', 'MiB', 'GiB', 'TiB');
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
}