mirror of
https://codeberg.org/streams/streams.git
synced 2024-09-20 14:35:16 +00:00
Merge branch 'dev' of /home/macgirvin/./streams into dev
This commit is contained in:
commit
550c3414ec
755 changed files with 110032 additions and 105775 deletions
|
@ -5,5 +5,5 @@ self.addEventListener('install', function(e) {
|
|||
|
||||
self.addEventListener('fetch', function(e) {
|
||||
// nothing here yet
|
||||
return;
|
||||
|
||||
});
|
||||
|
|
|
@ -12,153 +12,158 @@ namespace Zotlabs\Access;
|
|||
* and @ref ::Zotlabs::Lib::Permcat "Permcat"s individual content ACLs are evaluated.
|
||||
* These answer the question "Can Joe view *this* album/photo?".
|
||||
*/
|
||||
class AccessControl {
|
||||
/**
|
||||
* @brief Allow contacts
|
||||
* @var string
|
||||
*/
|
||||
private $allow_cid;
|
||||
/**
|
||||
* @brief Allow groups
|
||||
* @var string
|
||||
*/
|
||||
private $allow_gid;
|
||||
/**
|
||||
* @brief Deny contacts
|
||||
* @var string
|
||||
*/
|
||||
private $deny_cid;
|
||||
/**
|
||||
* @brief Deny groups
|
||||
* @var string
|
||||
*/
|
||||
private $deny_gid;
|
||||
/**
|
||||
* @brief Indicates if we are using the default constructor values or
|
||||
* values that have been set explicitly.
|
||||
* @var boolean
|
||||
*/
|
||||
private $explicit;
|
||||
class AccessControl
|
||||
{
|
||||
/**
|
||||
* @brief Allow contacts
|
||||
* @var string
|
||||
*/
|
||||
private $allow_cid;
|
||||
/**
|
||||
* @brief Allow groups
|
||||
* @var string
|
||||
*/
|
||||
private $allow_gid;
|
||||
/**
|
||||
* @brief Deny contacts
|
||||
* @var string
|
||||
*/
|
||||
private $deny_cid;
|
||||
/**
|
||||
* @brief Deny groups
|
||||
* @var string
|
||||
*/
|
||||
private $deny_gid;
|
||||
/**
|
||||
* @brief Indicates if we are using the default constructor values or
|
||||
* values that have been set explicitly.
|
||||
* @var bool
|
||||
*/
|
||||
private $explicit;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Constructor for AccessList class.
|
||||
*
|
||||
* @note The array to pass to the constructor is different from the array
|
||||
* that you provide to the set() or set_from_array() functions.
|
||||
*
|
||||
* @param array $channel A channel array, where these entries are evaluated:
|
||||
* * \e string \b channel_allow_cid => string of allowed cids
|
||||
* * \e string \b channel_allow_gid => string of allowed gids
|
||||
* * \e string \b channel_deny_cid => string of denied cids
|
||||
* * \e string \b channel_deny_gid => string of denied gids
|
||||
*/
|
||||
function __construct($channel) {
|
||||
if($channel) {
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
$this->deny_gid = $channel['channel_deny_gid'];
|
||||
}
|
||||
else {
|
||||
$this->allow_cid = '';
|
||||
$this->allow_gid = '';
|
||||
$this->deny_cid = '';
|
||||
$this->deny_gid = '';
|
||||
}
|
||||
/**
|
||||
* @brief Constructor for AccessList class.
|
||||
*
|
||||
* @note The array to pass to the constructor is different from the array
|
||||
* that you provide to the set() or set_from_array() functions.
|
||||
*
|
||||
* @param array $channel A channel array, where these entries are evaluated:
|
||||
* * \e string \b channel_allow_cid => string of allowed cids
|
||||
* * \e string \b channel_allow_gid => string of allowed gids
|
||||
* * \e string \b channel_deny_cid => string of denied cids
|
||||
* * \e string \b channel_deny_gid => string of denied gids
|
||||
*/
|
||||
public function __construct($channel)
|
||||
{
|
||||
if ($channel) {
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
$this->deny_gid = $channel['channel_deny_gid'];
|
||||
} else {
|
||||
$this->allow_cid = '';
|
||||
$this->allow_gid = '';
|
||||
$this->deny_cid = '';
|
||||
$this->deny_gid = '';
|
||||
}
|
||||
|
||||
$this->explicit = false;
|
||||
}
|
||||
$this->explicit = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get if we are using the default constructor values
|
||||
* or values that have been set explicitly.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function get_explicit() {
|
||||
return $this->explicit;
|
||||
}
|
||||
/**
|
||||
* @brief Get if we are using the default constructor values
|
||||
* or values that have been set explicitly.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_explicit()
|
||||
{
|
||||
return $this->explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set access list from strings such as those in already
|
||||
* existing stored data items.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set_from_array().
|
||||
*
|
||||
* @param array $arr
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set($arr, $explicit = true) {
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
$this->deny_gid = $arr['deny_gid'];
|
||||
/**
|
||||
* @brief Set access list from strings such as those in already
|
||||
* existing stored data items.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set_from_array().
|
||||
*
|
||||
* @param array $arr
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
* @param bool $explicit (optional) default true
|
||||
*/
|
||||
public function set($arr, $explicit = true)
|
||||
{
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
$this->deny_gid = $arr['deny_gid'];
|
||||
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return an array consisting of the current access list components
|
||||
* where the elements are directly storable.
|
||||
*
|
||||
* @return array An associative array with:
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
*/
|
||||
function get() {
|
||||
return [
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
'deny_cid' => $this->deny_cid,
|
||||
'deny_gid' => $this->deny_gid,
|
||||
];
|
||||
}
|
||||
/**
|
||||
* @brief Return an array consisting of the current access list components
|
||||
* where the elements are directly storable.
|
||||
*
|
||||
* @return array An associative array with:
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return [
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
'deny_cid' => $this->deny_cid,
|
||||
'deny_gid' => $this->deny_gid,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set access list components from arrays, such as those provided by
|
||||
* acl_selector().
|
||||
*
|
||||
* For convenience, a string (or non-array) input is assumed to be a
|
||||
* comma-separated list and auto-converted into an array.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set().
|
||||
*
|
||||
* @param array $arr An associative array with:
|
||||
* * \e array|string \b contact_allow => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_allow => array with gids or comma-seperated string
|
||||
* * \e array|string \b contact_deny => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_deny => array with gids or comma-seperated string
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set_from_array($arr, $explicit = true) {
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',', $arr['contact_allow']));
|
||||
$this->allow_gid = perms2str((is_array($arr['group_allow']))
|
||||
? $arr['group_allow'] : explode(',', $arr['group_allow']));
|
||||
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
|
||||
? $arr['contact_deny'] : explode(',', $arr['contact_deny']));
|
||||
$this->deny_gid = perms2str((is_array($arr['group_deny']))
|
||||
? $arr['group_deny'] : explode(',', $arr['group_deny']));
|
||||
/**
|
||||
* @brief Set access list components from arrays, such as those provided by
|
||||
* acl_selector().
|
||||
*
|
||||
* For convenience, a string (or non-array) input is assumed to be a
|
||||
* comma-separated list and auto-converted into an array.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set().
|
||||
*
|
||||
* @param array $arr An associative array with:
|
||||
* * \e array|string \b contact_allow => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_allow => array with gids or comma-seperated string
|
||||
* * \e array|string \b contact_deny => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_deny => array with gids or comma-seperated string
|
||||
* @param bool $explicit (optional) default true
|
||||
*/
|
||||
public function set_from_array($arr, $explicit = true)
|
||||
{
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',', $arr['contact_allow']));
|
||||
$this->allow_gid = perms2str((is_array($arr['group_allow']))
|
||||
? $arr['group_allow'] : explode(',', $arr['group_allow']));
|
||||
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
|
||||
? $arr['contact_deny'] : explode(',', $arr['contact_deny']));
|
||||
$this->deny_gid = perms2str((is_array($arr['group_deny']))
|
||||
? $arr['group_deny'] : explode(',', $arr['group_deny']));
|
||||
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if any access lists component is set.
|
||||
*
|
||||
* @return boolean Return true if any of allow_* deny_* values is set.
|
||||
*/
|
||||
function is_private() {
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if any access lists component is set.
|
||||
*
|
||||
* @return bool Return true if any of allow_* deny_* values is set.
|
||||
*/
|
||||
public function is_private()
|
||||
{
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,78 +26,83 @@ use Zotlabs\Lib\PConfig;
|
|||
*
|
||||
* @see Permissions
|
||||
*/
|
||||
class PermissionLimits {
|
||||
class PermissionLimits
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Get standard permission limits.
|
||||
*
|
||||
* Viewing permissions and post_comments permission are set to 'anybody',
|
||||
* other permissions are set to 'those I allow'.
|
||||
*
|
||||
* The list of permissions comes from Permissions::Perms().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function Std_Limits() {
|
||||
$limits = [];
|
||||
$perms = Permissions::Perms();
|
||||
/**
|
||||
* @brief Get standard permission limits.
|
||||
*
|
||||
* Viewing permissions and post_comments permission are set to 'anybody',
|
||||
* other permissions are set to 'those I allow'.
|
||||
*
|
||||
* The list of permissions comes from Permissions::Perms().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function Std_Limits()
|
||||
{
|
||||
$limits = [];
|
||||
$perms = Permissions::Perms();
|
||||
|
||||
foreach($perms as $k => $v) {
|
||||
if(strstr($k, 'view'))
|
||||
$limits[$k] = PERMS_PUBLIC;
|
||||
else
|
||||
$limits[$k] = PERMS_SPECIFIC;
|
||||
}
|
||||
foreach ($perms as $k => $v) {
|
||||
if (strstr($k, 'view')) {
|
||||
$limits[$k] = PERMS_PUBLIC;
|
||||
} else {
|
||||
$limits[$k] = PERMS_SPECIFIC;
|
||||
}
|
||||
}
|
||||
|
||||
return $limits;
|
||||
}
|
||||
return $limits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a permission limit for a channel.
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @param string $perm
|
||||
* @param int $perm_limit one of PERMS_* constants
|
||||
*/
|
||||
static public function Set($channel_id, $perm, $perm_limit) {
|
||||
PConfig::Set($channel_id, 'perm_limits', $perm, $perm_limit);
|
||||
}
|
||||
/**
|
||||
* @brief Sets a permission limit for a channel.
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @param string $perm
|
||||
* @param int $perm_limit one of PERMS_* constants
|
||||
*/
|
||||
public static function Set($channel_id, $perm, $perm_limit)
|
||||
{
|
||||
PConfig::Set($channel_id, 'perm_limits', $perm, $perm_limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a channel's permission limits.
|
||||
*
|
||||
* Return a channel's permission limits from PConfig. If $perm is set just
|
||||
* return this permission limit, if not set, return an array with all
|
||||
* permission limits.
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @param string $perm (optional)
|
||||
* @return
|
||||
* * \b false if no perm_limits set for this channel
|
||||
* * \b int if $perm is set, return one of PERMS_* constants for this permission, default 0
|
||||
* * \b array with all permission limits, if $perm is not set
|
||||
*/
|
||||
static public function Get($channel_id, $perm = '') {
|
||||
/**
|
||||
* @brief Get a channel's permission limits.
|
||||
*
|
||||
* Return a channel's permission limits from PConfig. If $perm is set just
|
||||
* return this permission limit, if not set, return an array with all
|
||||
* permission limits.
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @param string $perm (optional)
|
||||
* @return
|
||||
* * \b false if no perm_limits set for this channel
|
||||
* * \b int if $perm is set, return one of PERMS_* constants for this permission, default 0
|
||||
* * \b array with all permission limits, if $perm is not set
|
||||
*/
|
||||
public static function Get($channel_id, $perm = '')
|
||||
{
|
||||
|
||||
if (! intval($channel_id)) {
|
||||
return false;
|
||||
}
|
||||
if (! intval($channel_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($perm) {
|
||||
$x = PConfig::Get($channel_id, 'perm_limits', $perm);
|
||||
if($x === false) {
|
||||
$a = [ 'channel_id' => $channel_id, 'permission' => $perm, 'value' => $x ];
|
||||
call_hooks('permission_limits_get',$a);
|
||||
return intval($a['value']);
|
||||
}
|
||||
return intval($x);
|
||||
}
|
||||
if ($perm) {
|
||||
$x = PConfig::Get($channel_id, 'perm_limits', $perm);
|
||||
if ($x === false) {
|
||||
$a = [ 'channel_id' => $channel_id, 'permission' => $perm, 'value' => $x ];
|
||||
call_hooks('permission_limits_get', $a);
|
||||
return intval($a['value']);
|
||||
}
|
||||
return intval($x);
|
||||
}
|
||||
|
||||
PConfig::Load($channel_id);
|
||||
if(array_key_exists($channel_id, App::$config) && array_key_exists('perm_limits', App::$config[$channel_id])) {
|
||||
return App::$config[$channel_id]['perm_limits'];
|
||||
}
|
||||
PConfig::Load($channel_id);
|
||||
if (array_key_exists($channel_id, App::$config) && array_key_exists('perm_limits', App::$config[$channel_id])) {
|
||||
return App::$config[$channel_id]['perm_limits'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -7,193 +7,146 @@ namespace Zotlabs\Access;
|
|||
*
|
||||
* @see Permissions
|
||||
*/
|
||||
class PermissionRoles {
|
||||
class PermissionRoles
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief PermissionRoles version.
|
||||
*
|
||||
* This must match the version in Permissions.php before permission updates can run.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 3;
|
||||
}
|
||||
/**
|
||||
* @brief PermissionRoles version.
|
||||
*
|
||||
* This must match the version in Permissions.php before permission updates can run.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
public static function version()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
static function role_perms($role) {
|
||||
public static function role_perms($role)
|
||||
{
|
||||
|
||||
$ret = [];
|
||||
$ret = [];
|
||||
|
||||
$ret['role'] = $role;
|
||||
$ret['role'] = $role;
|
||||
|
||||
switch($role) {
|
||||
case 'social':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'send_stream', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
break;
|
||||
switch ($role) {
|
||||
case 'social':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = true;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'send_stream', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
break;
|
||||
|
||||
case 'social_restricted':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_storage',
|
||||
'view_pages', 'send_stream', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
break;
|
||||
case 'social_restricted':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_storage',
|
||||
'view_pages', 'send_stream', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
break;
|
||||
|
||||
case 'forum':
|
||||
$ret['perms_auto'] = true;
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'write_storage',
|
||||
'view_pages', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
case 'forum':
|
||||
$ret['perms_auto'] = true;
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'write_storage',
|
||||
'view_pages', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
|
||||
case 'forum_moderated':
|
||||
$ret['perms_auto'] = true;
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'post_mail', 'post_wall', 'post_comments', 'moderated'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
case 'forum_moderated':
|
||||
$ret['perms_auto'] = true;
|
||||
$ret['default_collection'] = false;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
'view_pages', 'post_mail', 'post_wall', 'post_comments', 'moderated'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['channel_type'] = 'group';
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'forum_restricted':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'write_storage',
|
||||
'view_pages', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
$ret['channel_type'] = 'group';
|
||||
break;
|
||||
case 'forum_restricted':
|
||||
$ret['perms_auto'] = false;
|
||||
$ret['default_collection'] = true;
|
||||
$ret['directory_publish'] = true;
|
||||
$ret['online'] = false;
|
||||
$ret['perms_connect'] = [
|
||||
'view_stream', 'view_profile', 'view_contacts', 'view_storage', 'write_storage',
|
||||
'view_pages', 'post_mail', 'post_wall', 'post_comments'
|
||||
];
|
||||
$ret['limits'] = PermissionLimits::Std_Limits();
|
||||
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
$ret['channel_type'] = 'group';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// case 'collection':
|
||||
// $ret['perms_auto'] = true;
|
||||
// $ret['default_collection'] = false;
|
||||
// $ret['directory_publish'] = true;
|
||||
// $ret['online'] = false;
|
||||
// $ret['perms_connect'] = [
|
||||
// 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
// 'view_pages', 'post_mail', 'post_comments'
|
||||
// ];
|
||||
// $ret['limits'] = PermissionLimits::Std_Limits();
|
||||
// $ret['channel_type'] = 'collection';
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case 'collection_restricted':
|
||||
// $ret['perms_auto'] = false;
|
||||
// $ret['default_collection'] = true;
|
||||
// $ret['directory_publish'] = true;
|
||||
// $ret['online'] = false;
|
||||
// $ret['perms_connect'] = [
|
||||
// 'view_stream', 'view_profile', 'view_storage',
|
||||
// 'view_pages', 'post_mail', 'post_comments'
|
||||
// ];
|
||||
// $ret['limits'] = PermissionLimits::Std_Limits();
|
||||
// $ret['limits']['view_contacts'] = PERMS_SPECIFIC;
|
||||
// $ret['channel_type'] = 'collection';
|
||||
// break;
|
||||
//
|
||||
// case 'feed':
|
||||
// $ret['perms_auto'] = true;
|
||||
// $ret['default_collection'] = false;
|
||||
// $ret['directory_publish'] = true;
|
||||
// $ret['online'] = false;
|
||||
// $ret['perms_connect'] = [
|
||||
// 'view_stream', 'view_profile', 'view_contacts', 'view_storage',
|
||||
// 'view_pages', 'send_stream', 'post_wall', 'post_mail', 'post_comments',
|
||||
// 'republish'
|
||||
// ];
|
||||
// $ret['limits'] = PermissionLimits::Std_Limits();
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case 'repository':
|
||||
// //Legacy settings to cover all channel_types previously in Libzot.php
|
||||
// $ret['channel_type'] = 'group';
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$x = get_config('system', 'role_perms');
|
||||
// let system settings over-ride any or all
|
||||
if ($x && is_array($x) && array_key_exists($role, $x)) {
|
||||
$ret = array_merge($ret, $x[$role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hooks get_role_perms
|
||||
* * \e array
|
||||
*/
|
||||
$x = ['role' => $role, 'result' => $ret];
|
||||
|
||||
call_hooks('get_role_perms', $x);
|
||||
|
||||
return $x['result'];
|
||||
}
|
||||
|
||||
|
||||
$x = get_config('system','role_perms');
|
||||
// let system settings over-ride any or all
|
||||
if($x && is_array($x) && array_key_exists($role,$x))
|
||||
$ret = array_merge($ret,$x[$role]);
|
||||
/**
|
||||
* @brief Array with translated role names and grouping.
|
||||
*
|
||||
* Return an associative array with grouped role names that can be used
|
||||
* to create select groups like in \e field_select_grouped.tpl.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function roles()
|
||||
{
|
||||
$roles = [
|
||||
t('Social Networking') => [
|
||||
'social' => t('Social - Normal'),
|
||||
'social_restricted' => t('Social - Restricted')
|
||||
],
|
||||
|
||||
/**
|
||||
* @hooks get_role_perms
|
||||
* * \e array
|
||||
*/
|
||||
$x = [ 'role' => $role, 'result' => $ret ];
|
||||
t('Community Group') => [
|
||||
'forum' => t('Group - Normal'),
|
||||
'forum_restricted' => t('Group - Restricted'),
|
||||
'forum_moderated' => t('Group - Moderated')
|
||||
],
|
||||
];
|
||||
|
||||
call_hooks('get_role_perms', $x);
|
||||
call_hooks('list_permission_roles', $roles);
|
||||
|
||||
return $x['result'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Array with translated role names and grouping.
|
||||
*
|
||||
* Return an associative array with grouped role names that can be used
|
||||
* to create select groups like in \e field_select_grouped.tpl.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function roles() {
|
||||
$roles = [
|
||||
t('Social Networking') => [
|
||||
'social' => t('Social - Normal'),
|
||||
'social_restricted' => t('Social - Restricted')
|
||||
],
|
||||
|
||||
t('Community Group') => [
|
||||
'forum' => t('Group - Normal'),
|
||||
'forum_restricted' => t('Group - Restricted'),
|
||||
'forum_moderated' => t('Group - Moderated')
|
||||
],
|
||||
|
||||
// t('Collection') => [
|
||||
// 'collection' => t('Collection - Normal'),
|
||||
// 'collection_restricted' => t('Collection - Restricted')
|
||||
// ]
|
||||
|
||||
];
|
||||
|
||||
call_hooks('list_permission_roles',$roles);
|
||||
|
||||
return $roles;
|
||||
}
|
||||
return $roles;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,252 +31,266 @@ use Zotlabs\Lib as Zlib;
|
|||
* something different for a specific permission within the given role.
|
||||
*
|
||||
*/
|
||||
class Permissions {
|
||||
class Permissions
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Permissions version.
|
||||
*
|
||||
* This must match the version in PermissionRoles.php before permission updates can run.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
static public function version() {
|
||||
return 3;
|
||||
}
|
||||
/**
|
||||
* @brief Permissions version.
|
||||
*
|
||||
* This must match the version in PermissionRoles.php before permission updates can run.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
public static function version()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return an array with Permissions.
|
||||
*
|
||||
* @param string $filter (optional) only passed to hook permissions_list
|
||||
* @return array Associative array with permissions and short description.
|
||||
*/
|
||||
static public function Perms($filter = '') {
|
||||
/**
|
||||
* @brief Return an array with Permissions.
|
||||
*
|
||||
* @param string $filter (optional) only passed to hook permissions_list
|
||||
* @return array Associative array with permissions and short description.
|
||||
*/
|
||||
public static function Perms($filter = '')
|
||||
{
|
||||
|
||||
$perms = [
|
||||
'view_stream' => t('Grant viewing access to and delivery of your channel stream and posts'),
|
||||
'view_profile' => t('Grant viewing access to your default channel profile'),
|
||||
'view_contacts' => t('Grant viewing access to your address book (connections)'),
|
||||
'view_storage' => t('Grant viewing access to your file storage and photos'),
|
||||
'post_wall' => t('Grant permission to post on your channel (wall) page'),
|
||||
'post_mail' => t('Accept delivery of direct messages and personal mail'),
|
||||
'send_stream' => t('Accept delivery of their posts and all comments to their posts'),
|
||||
'post_comments' => t('Accept delivery of their comments and likes on your posts'),
|
||||
'write_storage' => t('Grant upload permissions to your file storage and photos'),
|
||||
'republish' => t('Grant permission to republish/mirror your posts'),
|
||||
'moderated' => t('Accept comments and wall posts only after approval (moderation)'),
|
||||
'delegate' => t('Grant channel administration (delegation) permission')
|
||||
];
|
||||
$perms = [
|
||||
'view_stream' => t('Grant viewing access to and delivery of your channel stream and posts'),
|
||||
'view_profile' => t('Grant viewing access to your default channel profile'),
|
||||
'view_contacts' => t('Grant viewing access to your address book (connections)'),
|
||||
'view_storage' => t('Grant viewing access to your file storage and photos'),
|
||||
'post_wall' => t('Grant permission to post on your channel (wall) page'),
|
||||
'post_mail' => t('Accept delivery of direct messages and personal mail'),
|
||||
'send_stream' => t('Accept delivery of their posts and all comments to their posts'),
|
||||
'post_comments' => t('Accept delivery of their comments and likes on your posts'),
|
||||
'write_storage' => t('Grant upload permissions to your file storage and photos'),
|
||||
'republish' => t('Grant permission to republish/mirror your posts'),
|
||||
'moderated' => t('Accept comments and wall posts only after approval (moderation)'),
|
||||
'delegate' => t('Grant channel administration (delegation) permission')
|
||||
];
|
||||
|
||||
$x = [
|
||||
'permissions' => $perms,
|
||||
'filter' => $filter
|
||||
];
|
||||
/**
|
||||
* @hooks permissions_list
|
||||
* * \e array \b permissions
|
||||
* * \e string \b filter
|
||||
*/
|
||||
call_hooks('permissions_list', $x);
|
||||
$x = [
|
||||
'permissions' => $perms,
|
||||
'filter' => $filter
|
||||
];
|
||||
/**
|
||||
* @hooks permissions_list
|
||||
* * \e array \b permissions
|
||||
* * \e string \b filter
|
||||
*/
|
||||
call_hooks('permissions_list', $x);
|
||||
|
||||
return($x['permissions']);
|
||||
}
|
||||
return($x['permissions']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perms from the above list that are blocked from anonymous observers.
|
||||
*
|
||||
* e.g. you must be authenticated.
|
||||
*
|
||||
* @return array Associative array with permissions and short description.
|
||||
*/
|
||||
static public function BlockedAnonPerms() {
|
||||
/**
|
||||
* @brief Perms from the above list that are blocked from anonymous observers.
|
||||
*
|
||||
* e.g. you must be authenticated.
|
||||
*
|
||||
* @return array Associative array with permissions and short description.
|
||||
*/
|
||||
public static function BlockedAnonPerms()
|
||||
{
|
||||
|
||||
$res = [];
|
||||
$perms = PermissionLimits::Std_limits();
|
||||
foreach($perms as $perm => $limit) {
|
||||
if($limit != PERMS_PUBLIC) {
|
||||
$res[] = $perm;
|
||||
}
|
||||
}
|
||||
$res = [];
|
||||
$perms = PermissionLimits::Std_limits();
|
||||
foreach ($perms as $perm => $limit) {
|
||||
if ($limit != PERMS_PUBLIC) {
|
||||
$res[] = $perm;
|
||||
}
|
||||
}
|
||||
|
||||
$x = ['permissions' => $res];
|
||||
/**
|
||||
* @hooks write_perms
|
||||
* * \e array \b permissions
|
||||
*/
|
||||
call_hooks('write_perms', $x);
|
||||
$x = ['permissions' => $res];
|
||||
/**
|
||||
* @hooks write_perms
|
||||
* * \e array \b permissions
|
||||
*/
|
||||
call_hooks('write_perms', $x);
|
||||
|
||||
return($x['permissions']);
|
||||
}
|
||||
return($x['permissions']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts indexed perms array to associative perms array.
|
||||
*
|
||||
* Converts [ 0 => 'view_stream', ... ]
|
||||
* to [ 'view_stream' => 1 ] for any permissions in $arr;
|
||||
* Undeclared permissions which exist in Perms() are added and set to 0.
|
||||
*
|
||||
* @param array $arr
|
||||
* @return array
|
||||
*/
|
||||
static public function FilledPerms($arr) {
|
||||
if(is_null($arr) || (! is_array($arr))) {
|
||||
btlogger('FilledPerms: ' . print_r($arr,true));
|
||||
$arr = [];
|
||||
}
|
||||
/**
|
||||
* @brief Converts indexed perms array to associative perms array.
|
||||
*
|
||||
* Converts [ 0 => 'view_stream', ... ]
|
||||
* to [ 'view_stream' => 1 ] for any permissions in $arr;
|
||||
* Undeclared permissions which exist in Perms() are added and set to 0.
|
||||
*
|
||||
* @param array $arr
|
||||
* @return array
|
||||
*/
|
||||
public static function FilledPerms($arr)
|
||||
{
|
||||
if (is_null($arr) || (! is_array($arr))) {
|
||||
btlogger('FilledPerms: ' . print_r($arr, true));
|
||||
$arr = [];
|
||||
}
|
||||
|
||||
$everything = self::Perms();
|
||||
$ret = [];
|
||||
foreach($everything as $k => $v) {
|
||||
if(in_array($k, $arr))
|
||||
$ret[$k] = 1;
|
||||
else
|
||||
$ret[$k] = 0;
|
||||
}
|
||||
$everything = self::Perms();
|
||||
$ret = [];
|
||||
foreach ($everything as $k => $v) {
|
||||
if (in_array($k, $arr)) {
|
||||
$ret[$k] = 1;
|
||||
} else {
|
||||
$ret[$k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert perms array to indexed array.
|
||||
*
|
||||
* Converts [ 'view_stream' => 1 ] for any permissions in $arr
|
||||
* to [ 0 => ['name' => 'view_stream', 'value' => 1], ... ]
|
||||
*
|
||||
* @param array $arr associative perms array 'view_stream' => 1
|
||||
* @return array Indexed array with elements that look like
|
||||
* * \e string \b name the perm name (e.g. view_stream)
|
||||
* * \e int \b value the value of the perm (e.g. 1)
|
||||
*/
|
||||
static public function OPerms($arr) {
|
||||
$ret = [];
|
||||
if($arr) {
|
||||
foreach($arr as $k => $v) {
|
||||
$ret[] = [ 'name' => $k, 'value' => $v ];
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
/**
|
||||
* @brief Convert perms array to indexed array.
|
||||
*
|
||||
* Converts [ 'view_stream' => 1 ] for any permissions in $arr
|
||||
* to [ 0 => ['name' => 'view_stream', 'value' => 1], ... ]
|
||||
*
|
||||
* @param array $arr associative perms array 'view_stream' => 1
|
||||
* @return array Indexed array with elements that look like
|
||||
* * \e string \b name the perm name (e.g. view_stream)
|
||||
* * \e int \b value the value of the perm (e.g. 1)
|
||||
*/
|
||||
public static function OPerms($arr)
|
||||
{
|
||||
$ret = [];
|
||||
if ($arr) {
|
||||
foreach ($arr as $k => $v) {
|
||||
$ret[] = [ 'name' => $k, 'value' => $v ];
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @return boolean|array
|
||||
*/
|
||||
static public function FilledAutoperms($channel_id) {
|
||||
if(! intval(get_pconfig($channel_id,'system','autoperms')))
|
||||
return false;
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $channel_id
|
||||
* @return bool|array
|
||||
*/
|
||||
public static function FilledAutoperms($channel_id)
|
||||
{
|
||||
if (! intval(get_pconfig($channel_id, 'system', 'autoperms'))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$arr = [];
|
||||
$r = q("select * from pconfig where uid = %d and cat = 'autoperms'",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$arr[$rr['k']] = intval($rr['v']);
|
||||
}
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
$arr = [];
|
||||
$r = q(
|
||||
"select * from pconfig where uid = %d and cat = 'autoperms'",
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$arr[$rr['k']] = intval($rr['v']);
|
||||
}
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares that all Permissions from $p1 exist also in $p2.
|
||||
*
|
||||
* @param array $p1 The perms that have to exist in $p2
|
||||
* @param array $p2 The perms to compare against
|
||||
* @return boolean true if all perms from $p1 exist also in $p2
|
||||
*/
|
||||
static public function PermsCompare($p1, $p2) {
|
||||
foreach($p1 as $k => $v) {
|
||||
if(! array_key_exists($k, $p2))
|
||||
return false;
|
||||
/**
|
||||
* @brief Compares that all Permissions from $p1 exist also in $p2.
|
||||
*
|
||||
* @param array $p1 The perms that have to exist in $p2
|
||||
* @param array $p2 The perms to compare against
|
||||
* @return bool true if all perms from $p1 exist also in $p2
|
||||
*/
|
||||
public static function PermsCompare($p1, $p2)
|
||||
{
|
||||
foreach ($p1 as $k => $v) {
|
||||
if (! array_key_exists($k, $p2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if($p1[$k] != $p2[$k])
|
||||
return false;
|
||||
}
|
||||
if ($p1[$k] != $p2[$k]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $channel_id A channel id
|
||||
* @return array Associative array with
|
||||
* * \e array \b perms Permission array
|
||||
* * \e int \b automatic 0 or 1
|
||||
*/
|
||||
static public function connect_perms($channel_id) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $channel_id A channel id
|
||||
* @return array Associative array with
|
||||
* * \e array \b perms Permission array
|
||||
* * \e int \b automatic 0 or 1
|
||||
*/
|
||||
public static function connect_perms($channel_id)
|
||||
{
|
||||
|
||||
$my_perms = [];
|
||||
$permcat = null;
|
||||
$automatic = 0;
|
||||
$my_perms = [];
|
||||
$permcat = null;
|
||||
$automatic = 0;
|
||||
|
||||
// If a default permcat exists, use that
|
||||
// If a default permcat exists, use that
|
||||
|
||||
$pc = ((feature_enabled($channel_id,'permcats')) ? get_pconfig($channel_id,'system','default_permcat') : 'default');
|
||||
if(! in_array($pc, [ '','default' ])) {
|
||||
$pcp = new Zlib\Permcat($channel_id);
|
||||
$permcat = $pcp->fetch($pc);
|
||||
if($permcat && $permcat['perms']) {
|
||||
foreach($permcat['perms'] as $p) {
|
||||
$my_perms[$p['name']] = $p['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$pc = ((feature_enabled($channel_id, 'permcats')) ? get_pconfig($channel_id, 'system', 'default_permcat') : 'default');
|
||||
if (! in_array($pc, [ '','default' ])) {
|
||||
$pcp = new Zlib\Permcat($channel_id);
|
||||
$permcat = $pcp->fetch($pc);
|
||||
if ($permcat && $permcat['perms']) {
|
||||
foreach ($permcat['perms'] as $p) {
|
||||
$my_perms[$p['name']] = $p['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$automatic = intval(get_pconfig($channel_id,'system','autoperms'));
|
||||
$automatic = intval(get_pconfig($channel_id, 'system', 'autoperms'));
|
||||
|
||||
// look up the permission role to see if it specified auto-connect
|
||||
// and if there was no permcat or a default permcat, set the perms
|
||||
// from the role
|
||||
// look up the permission role to see if it specified auto-connect
|
||||
// and if there was no permcat or a default permcat, set the perms
|
||||
// from the role
|
||||
|
||||
$role = get_pconfig($channel_id,'system','permissions_role');
|
||||
if($role) {
|
||||
$xx = PermissionRoles::role_perms($role);
|
||||
$role = get_pconfig($channel_id, 'system', 'permissions_role');
|
||||
if ($role) {
|
||||
$xx = PermissionRoles::role_perms($role);
|
||||
|
||||
if((! $my_perms) && ($xx['perms_connect'])) {
|
||||
$default_perms = $xx['perms_connect'];
|
||||
$my_perms = Permissions::FilledPerms($default_perms);
|
||||
}
|
||||
}
|
||||
if ((! $my_perms) && ($xx['perms_connect'])) {
|
||||
$default_perms = $xx['perms_connect'];
|
||||
$my_perms = Permissions::FilledPerms($default_perms);
|
||||
}
|
||||
}
|
||||
|
||||
// If we reached this point without having any permission information,
|
||||
// it is likely a custom permissions role. First see if there are any
|
||||
// automatic permissions.
|
||||
// If we reached this point without having any permission information,
|
||||
// it is likely a custom permissions role. First see if there are any
|
||||
// automatic permissions.
|
||||
|
||||
if(! $my_perms) {
|
||||
$m = Permissions::FilledAutoperms($channel_id);
|
||||
if($m) {
|
||||
$my_perms = $m;
|
||||
}
|
||||
}
|
||||
if (! $my_perms) {
|
||||
$m = Permissions::FilledAutoperms($channel_id);
|
||||
if ($m) {
|
||||
$my_perms = $m;
|
||||
}
|
||||
}
|
||||
|
||||
// If we reached this point with no permissions, the channel is using
|
||||
// custom perms but they are not automatic. They will be stored in abconfig with
|
||||
// the channel's channel_hash (the 'self' connection).
|
||||
// If we reached this point with no permissions, the channel is using
|
||||
// custom perms but they are not automatic. They will be stored in abconfig with
|
||||
// the channel's channel_hash (the 'self' connection).
|
||||
|
||||
if(! $my_perms) {
|
||||
$c = channelx_by_n($channel_id);
|
||||
if($c) {
|
||||
$my_perms = Permissions::FilledPerms(explode(',',get_abconfig($channel_id,$c['channel_hash'],'system','my_perms',EMPTY_STR)));
|
||||
}
|
||||
}
|
||||
if (! $my_perms) {
|
||||
$c = channelx_by_n($channel_id);
|
||||
if ($c) {
|
||||
$my_perms = Permissions::FilledPerms(explode(',', get_abconfig($channel_id, $c['channel_hash'], 'system', 'my_perms', EMPTY_STR)));
|
||||
}
|
||||
}
|
||||
|
||||
return ( [ 'perms' => $my_perms, 'automatic' => $automatic ] );
|
||||
}
|
||||
return ( [ 'perms' => $my_perms, 'automatic' => $automatic ] );
|
||||
}
|
||||
|
||||
|
||||
static public function serialise($p) {
|
||||
$n = [];
|
||||
if($p) {
|
||||
foreach($p as $k => $v) {
|
||||
if(intval($v)) {
|
||||
$n[] = $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(',',$n);
|
||||
}
|
||||
|
||||
public static function serialise($p)
|
||||
{
|
||||
$n = [];
|
||||
if ($p) {
|
||||
foreach ($p as $k => $v) {
|
||||
if (intval($v)) {
|
||||
$n[] = $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(',', $n);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Addon
|
||||
{
|
||||
|
||||
class Addon {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
call_hooks('daemon_addon',$argv);
|
||||
|
||||
}
|
||||
call_hooks('daemon_addon', $argv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +1,54 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/photos.php');
|
||||
|
||||
class CacheThumb {
|
||||
class CacheThumb
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
if (! $argc == 2) {
|
||||
return;
|
||||
}
|
||||
if (! $argc == 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$path = 'cache/img/' . substr($argv[1],0,2) . '/' . $argv[1];
|
||||
$path = 'cache/img/' . substr($argv[1], 0, 2) . '/' . $argv[1];
|
||||
|
||||
$is = getimagesize($path);
|
||||
$is = getimagesize($path);
|
||||
|
||||
if (! $is) {
|
||||
return;
|
||||
}
|
||||
if (! $is) {
|
||||
return;
|
||||
}
|
||||
|
||||
$width = $is[0];
|
||||
$height = $is[1];
|
||||
$width = $is[0];
|
||||
$height = $is[1];
|
||||
|
||||
$max_thumb = get_config('system','max_cache_thumbnail',1024);
|
||||
$max_thumb = get_config('system', 'max_cache_thumbnail', 1024);
|
||||
|
||||
if ($width > $max_thumb || $height > $max_thumb) {
|
||||
$imagick_path = get_config('system','imagick_convert_path');
|
||||
if ($imagick_path && @file_exists($imagick_path)) {
|
||||
$tmp_name = $path . '-001';
|
||||
$newsize = photo_calculate_scale(array_merge($is,['max' => $max_thumb]));
|
||||
$cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $path) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name);
|
||||
if ($width > $max_thumb || $height > $max_thumb) {
|
||||
$imagick_path = get_config('system', 'imagick_convert_path');
|
||||
if ($imagick_path && @file_exists($imagick_path)) {
|
||||
$tmp_name = $path . '-001';
|
||||
$newsize = photo_calculate_scale(array_merge($is, ['max' => $max_thumb]));
|
||||
$cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $path) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name);
|
||||
|
||||
for ($x = 0; $x < 4; $x ++) {
|
||||
exec($cmd);
|
||||
if (file_exists($tmp_name)) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for ($x = 0; $x < 4; $x++) {
|
||||
exec($cmd);
|
||||
if (file_exists($tmp_name)) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! file_exists($tmp_name)) {
|
||||
return;
|
||||
}
|
||||
@rename($tmp_name,$path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! file_exists($tmp_name)) {
|
||||
return;
|
||||
}
|
||||
@rename($tmp_name, $path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,33 +2,34 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Cache_embeds
|
||||
{
|
||||
|
||||
class Cache_embeds {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
if (! $argc == 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $argc == 2) {
|
||||
return;
|
||||
}
|
||||
$c = q(
|
||||
"select body, html, created from item where id = %d ",
|
||||
dbesc(intval($argv[1]))
|
||||
);
|
||||
|
||||
$c = q("select body, html, created from item where id = %d ",
|
||||
dbesc(intval($argv[1]))
|
||||
);
|
||||
if (! $c) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $c) {
|
||||
return;
|
||||
}
|
||||
$item = array_shift($c);
|
||||
|
||||
$item = array_shift($c);
|
||||
$cache_expire = intval(get_config('system', 'default_expire_days'));
|
||||
if ($cache_expire <= 0) {
|
||||
$cache_expire = 60;
|
||||
}
|
||||
$cache_enable = ((($cache_expire) && ($item['created'] < datetime_convert('UTC', 'UTC', 'now - ' . $cache_expire . ' days'))) ? false : true);
|
||||
|
||||
$cache_expire = intval(get_config('system', 'default_expire_days'));
|
||||
if ($cache_expire <= 0) {
|
||||
$cache_expire = 60;
|
||||
}
|
||||
$cache_enable = ((($cache_expire) && ($item['created'] < datetime_convert('UTC','UTC', 'now - ' . $cache_expire . ' days'))) ? false : true);
|
||||
|
||||
$s = bbcode($item['body']);
|
||||
$s = sslify($s, $cache_enable);
|
||||
|
||||
}
|
||||
$s = bbcode($item['body']);
|
||||
$s = sslify($s, $cache_enable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@ namespace Zotlabs\Daemon;
|
|||
|
||||
use Zotlabs\Lib\Img_cache;
|
||||
|
||||
class Cache_image {
|
||||
class Cache_image
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
cli_startup();
|
||||
logger('caching: ' . $argv[1] . ' to ' . $argv[2]);
|
||||
if ($argc === 3) {
|
||||
Img_cache::url_to_cache($argv[1],$argv[2]);
|
||||
}
|
||||
|
||||
}
|
||||
cli_startup();
|
||||
logger('caching: ' . $argv[1] . ' to ' . $argv[2]);
|
||||
if ($argc === 3) {
|
||||
Img_cache::url_to_cache($argv[1], $argv[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,32 +2,35 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Channel_purge
|
||||
{
|
||||
|
||||
class Channel_purge {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
cli_startup();
|
||||
|
||||
cli_startup();
|
||||
$channel_id = intval($argv[1]);
|
||||
|
||||
$channel_id = intval($argv[1]);
|
||||
$channel = q(
|
||||
"select * from channel where channel_id = %d and channel_removed = 1",
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
$channel = q("select * from channel where channel_id = %d and channel_removed = 1",
|
||||
intval($channel_id)
|
||||
);
|
||||
if (! $channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
$r = q("select id from item where uid = %d and item_deleted = 0 limit 1000",
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
drop_item($rv['id'],false);
|
||||
}
|
||||
}
|
||||
} while ($r);
|
||||
}
|
||||
do {
|
||||
$r = q(
|
||||
"select id from item where uid = %d and item_deleted = 0 limit 1000",
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
drop_item($rv['id'], false);
|
||||
}
|
||||
}
|
||||
} while ($r);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +1,66 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
|
||||
class Checksites {
|
||||
class Checksites
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
logger('checksites: start');
|
||||
logger('checksites: start');
|
||||
|
||||
if(($argc > 1) && ($argv[1]))
|
||||
$site_id = $argv[1];
|
||||
if (($argc > 1) && ($argv[1])) {
|
||||
$site_id = $argv[1];
|
||||
}
|
||||
|
||||
if($site_id)
|
||||
$sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
|
||||
if ($site_id) {
|
||||
$sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
|
||||
}
|
||||
|
||||
$days = intval(get_config('system','sitecheckdays'));
|
||||
if($days < 1)
|
||||
$days = 30;
|
||||
$days = intval(get_config('system', 'sitecheckdays'));
|
||||
if ($days < 1) {
|
||||
$days = 30;
|
||||
}
|
||||
|
||||
$r = q("select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
|
||||
db_utcnow(), db_quoteinterval($days . ' DAY'),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
$r = q(
|
||||
"select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval($days . ' DAY'),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($r as $rr) {
|
||||
if(! strcasecmp($rr['site_url'],z_root()))
|
||||
continue;
|
||||
foreach ($r as $rr) {
|
||||
if (! strcasecmp($rr['site_url'], z_root())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$x = ping_site($rr['site_url']);
|
||||
if($x['success']) {
|
||||
logger('checksites: ' . $rr['site_url']);
|
||||
q("update site set site_update = '%s' where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($rr['site_url'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
logger('marking dead site: ' . $x['message']);
|
||||
q("update site set site_dead = 1 where site_url = '%s' ",
|
||||
dbesc($rr['site_url'])
|
||||
);
|
||||
}
|
||||
}
|
||||
$x = ping_site($rr['site_url']);
|
||||
if ($x['success']) {
|
||||
logger('checksites: ' . $rr['site_url']);
|
||||
q(
|
||||
"update site set site_update = '%s' where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($rr['site_url'])
|
||||
);
|
||||
} else {
|
||||
logger('marking dead site: ' . $x['message']);
|
||||
q(
|
||||
"update site set site_dead = 1 where site_url = '%s' ",
|
||||
dbesc($rr['site_url'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,52 +8,55 @@ require_once('include/cli_startup.php');
|
|||
require_once('include/attach.php');
|
||||
require_once('include/import.php');
|
||||
|
||||
class Content_importer {
|
||||
class Content_importer
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
cli_startup();
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
cli_startup();
|
||||
|
||||
$page = $argv[1];
|
||||
$since = $argv[2];
|
||||
$until = $argv[3];
|
||||
$channel_address = $argv[4];
|
||||
$hz_server = urldecode($argv[5]);
|
||||
$page = $argv[1];
|
||||
$since = $argv[2];
|
||||
$until = $argv[3];
|
||||
$channel_address = $argv[4];
|
||||
$hz_server = urldecode($argv[5]);
|
||||
|
||||
$m = parse_url($hz_server);
|
||||
$m = parse_url($hz_server);
|
||||
|
||||
$channel = channelx_by_nick($channel_address);
|
||||
if(! $channel) {
|
||||
logger('itemhelper: channel not found');
|
||||
killme();
|
||||
}
|
||||
$channel = channelx_by_nick($channel_address);
|
||||
if (! $channel) {
|
||||
logger('itemhelper: channel not found');
|
||||
killme();
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'X-API-Token' => random_string(),
|
||||
'X-API-Request' => $hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get /api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
];
|
||||
$headers = [
|
||||
'X-API-Token' => random_string(),
|
||||
'X-API-Request' => $hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get /api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page ,
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), true, 'sha512');
|
||||
|
||||
$x = z_fetch_url($hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page,false,$redirects,[ 'headers' => $headers ]);
|
||||
$x = z_fetch_url($hz_server . '/api/z/1.0/item/export_page?f=&zap_compat=1&since=' . urlencode($since) . '&until=' . urlencode($until) . '&page=' . $page, false, $redirects, [ 'headers' => $headers ]);
|
||||
|
||||
if(! $x['success']) {
|
||||
logger('no API response',LOGGER_DEBUG);
|
||||
killme();
|
||||
}
|
||||
if (! $x['success']) {
|
||||
logger('no API response', LOGGER_DEBUG);
|
||||
killme();
|
||||
}
|
||||
|
||||
$j = json_decode($x['body'],true);
|
||||
$j = json_decode($x['body'], true);
|
||||
|
||||
if (! $j) {
|
||||
killme();
|
||||
}
|
||||
if (! $j) {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(! ($j['item'] || count($j['item'])))
|
||||
killme();
|
||||
if (! ($j['item'] || count($j['item']))) {
|
||||
killme();
|
||||
}
|
||||
|
||||
import_items($channel,$j['item'],false,((array_key_exists('relocate',$j)) ? $j['relocate'] : null));
|
||||
import_items($channel, $j['item'], false, ((array_key_exists('relocate', $j)) ? $j['relocate'] : null));
|
||||
|
||||
killme();
|
||||
}
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,53 +6,56 @@ use Zotlabs\Lib\Activity;
|
|||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\ASCollection;
|
||||
|
||||
class Convo {
|
||||
class Convo
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
logger('convo invoked: ' . print_r($argv,true));
|
||||
logger('convo invoked: ' . print_r($argv, true));
|
||||
|
||||
if($argc != 4) {
|
||||
killme();
|
||||
}
|
||||
if ($argc != 4) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$id = $argv[1];
|
||||
$channel_id = intval($argv[2]);
|
||||
$contact_hash = $argv[3];
|
||||
$id = $argv[1];
|
||||
$channel_id = intval($argv[2]);
|
||||
$contact_hash = $argv[3];
|
||||
|
||||
$channel = channelx_by_n($channel_id);
|
||||
if (! $channel) {
|
||||
killme();
|
||||
}
|
||||
$channel = channelx_by_n($channel_id);
|
||||
if (! $channel) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
$r = q(
|
||||
"SELECT abook.*, xchan.* FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d and abook_xchan = '%s' LIMIT 1",
|
||||
intval($channel_id),
|
||||
dbesc($contact_hash)
|
||||
);
|
||||
if (! $r) {
|
||||
killme();
|
||||
}
|
||||
intval($channel_id),
|
||||
dbesc($contact_hash)
|
||||
);
|
||||
if (! $r) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$contact = array_shift($r);
|
||||
$contact = array_shift($r);
|
||||
|
||||
$obj = new ASCollection($id, $channel);
|
||||
$obj = new ASCollection($id, $channel);
|
||||
|
||||
$messages = $obj->get();
|
||||
$messages = $obj->get();
|
||||
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message,$channel);
|
||||
}
|
||||
// set client flag because comments will probably just be objects and not full blown activities
|
||||
// and that lets us use implied_create
|
||||
$AS = new ActivityStreams($message, null, true);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS,true);
|
||||
Activity::store($channel,$contact['abook_xchan'],$AS,$item,true,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $channel);
|
||||
}
|
||||
// set client flag because comments will probably just be objects and not full blown activities
|
||||
// and that lets us use implied_create
|
||||
$AS = new ActivityStreams($message, null, true);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS, true);
|
||||
Activity::store($channel, $contact['abook_xchan'], $AS, $item, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,201 +1,221 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Cron {
|
||||
class Cron
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
$maxsysload = intval(get_config('system','maxloadavg'));
|
||||
if($maxsysload < 1)
|
||||
$maxsysload = 50;
|
||||
if(function_exists('sys_getloadavg')) {
|
||||
$load = sys_getloadavg();
|
||||
if(intval($load[0]) > $maxsysload) {
|
||||
logger('system: load ' . $load . ' too high. Cron deferred to next scheduled run.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
$maxsysload = intval(get_config('system', 'maxloadavg'));
|
||||
if ($maxsysload < 1) {
|
||||
$maxsysload = 50;
|
||||
}
|
||||
if (function_exists('sys_getloadavg')) {
|
||||
$load = sys_getloadavg();
|
||||
if (intval($load[0]) > $maxsysload) {
|
||||
logger('system: load ' . $load . ' too high. Cron deferred to next scheduled run.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'cache/cron';
|
||||
if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (! get_config('system','override_cron_lockfile'))) {
|
||||
logger("cron: Already running");
|
||||
return;
|
||||
}
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'cache/cron';
|
||||
if (
|
||||
(file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (! get_config('system', 'override_cron_lockfile'))
|
||||
) {
|
||||
logger("cron: Already running");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
|
||||
file_put_contents($lockfile, $x);
|
||||
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
|
||||
file_put_contents($lockfile, $x);
|
||||
|
||||
logger('cron: start');
|
||||
logger('cron: start');
|
||||
|
||||
// run queue delivery process in the background
|
||||
// run queue delivery process in the background
|
||||
|
||||
Run::Summon( [ 'Queue' ] );
|
||||
Run::Summon([ 'Queue' ]);
|
||||
|
||||
Run::Summon( [ 'Poller' ] );
|
||||
Run::Summon([ 'Poller' ]);
|
||||
|
||||
// maintenance for mod sharedwithme - check for updated items and remove them
|
||||
// maintenance for mod sharedwithme - check for updated items and remove them
|
||||
|
||||
require_once('include/sharedwithme.php');
|
||||
apply_updates();
|
||||
require_once('include/sharedwithme.php');
|
||||
apply_updates();
|
||||
|
||||
// expire any expired items
|
||||
// expire any expired items
|
||||
|
||||
$r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
|
||||
$r = q(
|
||||
"select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
|
||||
and item_deleted = 0 ",
|
||||
db_utcnow()
|
||||
);
|
||||
if($r) {
|
||||
require_once('include/items.php');
|
||||
foreach($r as $rr) {
|
||||
drop_item($rr['id'],false,(($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
|
||||
if($rr['item_wall']) {
|
||||
// The notifier isn't normally invoked unless item_drop is interactive.
|
||||
Run::Summon( [ 'Notifier', 'drop', $rr['id'] ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
db_utcnow()
|
||||
);
|
||||
if ($r) {
|
||||
require_once('include/items.php');
|
||||
foreach ($r as $rr) {
|
||||
drop_item($rr['id'], false, (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
|
||||
if ($rr['item_wall']) {
|
||||
// The notifier isn't normally invoked unless item_drop is interactive.
|
||||
Run::Summon([ 'Notifier', 'drop', $rr['id'] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// delete expired access tokens
|
||||
// delete expired access tokens
|
||||
|
||||
$r = q("select atoken_id from atoken where atoken_expires > '%s' and atoken_expires < %s",
|
||||
dbesc(NULL_DATE),
|
||||
db_utcnow()
|
||||
);
|
||||
if($r) {
|
||||
require_once('include/security.php');
|
||||
foreach($r as $rr) {
|
||||
atoken_delete($rr['atoken_id']);
|
||||
}
|
||||
}
|
||||
$r = q(
|
||||
"select atoken_id from atoken where atoken_expires > '%s' and atoken_expires < %s",
|
||||
dbesc(NULL_DATE),
|
||||
db_utcnow()
|
||||
);
|
||||
if ($r) {
|
||||
require_once('include/security.php');
|
||||
foreach ($r as $rr) {
|
||||
atoken_delete($rr['atoken_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that every channel pings their directory occasionally.
|
||||
// Ensure that every channel pings their directory occasionally.
|
||||
|
||||
$r = q("select channel_id from channel where channel_dirdate < %s - INTERVAL %s and channel_removed = 0",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
Run::Summon( [ 'Directory', $rr['channel_id'], 'force' ] );
|
||||
if($interval)
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
}
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_dirdate < %s - INTERVAL %s and channel_removed = 0",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
Run::Summon([ 'Directory', $rr['channel_id'], 'force' ]);
|
||||
if ($interval) {
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// publish any applicable items that were set to be published in the future
|
||||
// (time travel posts). Restrict to items that have come of age in the last
|
||||
// couple of days to limit the query to something reasonable.
|
||||
// publish any applicable items that were set to be published in the future
|
||||
// (time travel posts). Restrict to items that have come of age in the last
|
||||
// couple of days to limit the query to something reasonable.
|
||||
|
||||
$r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
|
||||
db_utcnow(),
|
||||
dbesc(datetime_convert('UTC','UTC','now - 2 days'))
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$x = q("update item set item_delayed = 0 where id = %d",
|
||||
intval($rr['id'])
|
||||
);
|
||||
if($x) {
|
||||
$z = q("select * from item where id = %d",
|
||||
intval($message_id)
|
||||
);
|
||||
if($z) {
|
||||
xchan_query($z);
|
||||
$sync_item = fetch_post_tags($z);
|
||||
Libsync::build_sync_packet($sync_item[0]['uid'],
|
||||
[
|
||||
'item' => [ encode_item($sync_item[0],true) ]
|
||||
]
|
||||
);
|
||||
}
|
||||
Run::Summon( [ 'Notifier','wall-new',$rr['id'] ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
$r = q(
|
||||
"select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
|
||||
db_utcnow(),
|
||||
dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$x = q(
|
||||
"update item set item_delayed = 0 where id = %d",
|
||||
intval($rr['id'])
|
||||
);
|
||||
if ($x) {
|
||||
$z = q(
|
||||
"select * from item where id = %d",
|
||||
intval($message_id)
|
||||
);
|
||||
if ($z) {
|
||||
xchan_query($z);
|
||||
$sync_item = fetch_post_tags($z);
|
||||
Libsync::build_sync_packet(
|
||||
$sync_item[0]['uid'],
|
||||
[
|
||||
'item' => [ encode_item($sync_item[0], true) ]
|
||||
]
|
||||
);
|
||||
}
|
||||
Run::Summon([ 'Notifier','wall-new',$rr['id'] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once('include/attach.php');
|
||||
attach_upgrade();
|
||||
require_once('include/attach.php');
|
||||
attach_upgrade();
|
||||
|
||||
$abandon_days = intval(get_config('system','account_abandon_days'));
|
||||
if($abandon_days < 1)
|
||||
$abandon_days = 0;
|
||||
$abandon_days = intval(get_config('system', 'account_abandon_days'));
|
||||
if ($abandon_days < 1) {
|
||||
$abandon_days = 0;
|
||||
}
|
||||
|
||||
|
||||
// once daily run birthday_updates and then expire in background
|
||||
// once daily run birthday_updates and then expire in background
|
||||
|
||||
// FIXME: add birthday updates, both locally and for xprof for use
|
||||
// by directory servers
|
||||
// FIXME: add birthday updates, both locally and for xprof for use
|
||||
// by directory servers
|
||||
|
||||
$d1 = intval(get_config('system','last_expire_day'));
|
||||
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
|
||||
$d1 = intval(get_config('system', 'last_expire_day'));
|
||||
$d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd'));
|
||||
|
||||
// Allow somebody to staggger daily activities if they have more than one site on their server,
|
||||
// or if it happens at an inconvenient (busy) hour.
|
||||
// Allow somebody to staggger daily activities if they have more than one site on their server,
|
||||
// or if it happens at an inconvenient (busy) hour.
|
||||
|
||||
$h1 = intval(get_config('system','cron_hour'));
|
||||
$h2 = intval(datetime_convert('UTC','UTC','now','G'));
|
||||
$h1 = intval(get_config('system', 'cron_hour'));
|
||||
$h2 = intval(datetime_convert('UTC', 'UTC', 'now', 'G'));
|
||||
|
||||
|
||||
if(($d2 != $d1) && ($h1 == $h2)) {
|
||||
Run::Summon( [ 'Cron_daily' ] );
|
||||
}
|
||||
if (($d2 != $d1) && ($h1 == $h2)) {
|
||||
Run::Summon([ 'Cron_daily' ]);
|
||||
}
|
||||
|
||||
// update any photos which didn't get imported properly
|
||||
// This should be rare
|
||||
// update any photos which didn't get imported properly
|
||||
// This should be rare
|
||||
|
||||
$r = q("select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
|
||||
$r = q(
|
||||
"select xchan_photo_l, xchan_hash from xchan where xchan_photo_l != '' and xchan_photo_m = ''
|
||||
and xchan_photo_date < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 DAY')
|
||||
);
|
||||
if($r) {
|
||||
require_once('include/photo_factory.php');
|
||||
foreach($r as $rr) {
|
||||
$photos = import_remote_xchan_photo($rr['xchan_photo_l'],$rr['xchan_hash']);
|
||||
if ($photos) {
|
||||
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
require_once('include/photo_factory.php');
|
||||
foreach ($r as $rr) {
|
||||
$photos = import_remote_xchan_photo($rr['xchan_photo_l'], $rr['xchan_hash']);
|
||||
if ($photos) {
|
||||
$x = q(
|
||||
"update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
|
||||
where xchan_hash = '%s'",
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($rr['xchan_hash'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($rr['xchan_hash'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$generation = 0;
|
||||
$generation = 0;
|
||||
|
||||
$restart = false;
|
||||
$restart = false;
|
||||
|
||||
if(($argc > 1) && ($argv[1] == 'restart')) {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if(! $generation)
|
||||
return;
|
||||
}
|
||||
if (($argc > 1) && ($argv[1] == 'restart')) {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if (! $generation) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reload_plugins();
|
||||
reload_plugins();
|
||||
|
||||
$d = datetime_convert();
|
||||
$d = datetime_convert();
|
||||
|
||||
// TODO check to see if there are any cronhooks before wasting a process
|
||||
// TODO check to see if there are any cronhooks before wasting a process
|
||||
|
||||
if(! $restart)
|
||||
Run::Summon( [ 'Cronhooks' ] );
|
||||
if (! $restart) {
|
||||
Run::Summon([ 'Cronhooks' ]);
|
||||
}
|
||||
|
||||
set_config('system','lastcron',datetime_convert());
|
||||
set_config('system', 'lastcron', datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
@unlink($lockfile);
|
||||
//All done - clear the lockfile
|
||||
@unlink($lockfile);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,110 +1,122 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
class Cron_daily {
|
||||
class Cron_daily
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
logger('cron_daily: start');
|
||||
logger('cron_daily: start');
|
||||
|
||||
/**
|
||||
* Cron Daily
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Cron Daily
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// make sure our own site record is up to date
|
||||
Libzot::import_site(Libzot::site_info(true));
|
||||
// make sure our own site record is up to date
|
||||
Libzot::import_site(Libzot::site_info(true));
|
||||
|
||||
|
||||
// Fire off the Cron_weekly process if it's the correct day.
|
||||
// Fire off the Cron_weekly process if it's the correct day.
|
||||
|
||||
$d3 = intval(datetime_convert('UTC','UTC','now','N'));
|
||||
if ($d3 == 7) {
|
||||
Run::Summon( [ 'Cron_weekly' ] );
|
||||
}
|
||||
$d3 = intval(datetime_convert('UTC', 'UTC', 'now', 'N'));
|
||||
if ($d3 == 7) {
|
||||
Run::Summon([ 'Cron_weekly' ]);
|
||||
}
|
||||
|
||||
// once daily run birthday_updates and then expire in background
|
||||
// once daily run birthday_updates and then expire in background
|
||||
|
||||
// FIXME: add birthday updates, both locally and for xprof for use
|
||||
// by directory servers
|
||||
// FIXME: add birthday updates, both locally and for xprof for use
|
||||
// by directory servers
|
||||
|
||||
update_birthdays();
|
||||
update_birthdays();
|
||||
|
||||
// expire any read notifications over a month old
|
||||
// expire any read notifications over a month old
|
||||
|
||||
q("delete from notify where seen = 1 and created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('60 DAY')
|
||||
);
|
||||
q(
|
||||
"delete from notify where seen = 1 and created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('60 DAY')
|
||||
);
|
||||
|
||||
// expire any unread notifications over a year old
|
||||
// expire any unread notifications over a year old
|
||||
|
||||
q("delete from notify where seen = 0 and created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('1 YEAR')
|
||||
);
|
||||
q(
|
||||
"delete from notify where seen = 0 and created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 YEAR')
|
||||
);
|
||||
|
||||
|
||||
//update statistics in config
|
||||
require_once('include/statistics_fns.php');
|
||||
update_channels_total_stat();
|
||||
update_channels_active_halfyear_stat();
|
||||
update_channels_active_monthly_stat();
|
||||
update_local_posts_stat();
|
||||
update_local_comments_stat();
|
||||
//update statistics in config
|
||||
require_once('include/statistics_fns.php');
|
||||
update_channels_total_stat();
|
||||
update_channels_active_halfyear_stat();
|
||||
update_channels_active_monthly_stat();
|
||||
update_local_posts_stat();
|
||||
update_local_comments_stat();
|
||||
|
||||
|
||||
// expire old delivery reports
|
||||
// expire old delivery reports
|
||||
|
||||
$keep_reports = intval(get_config('system','expire_delivery_reports'));
|
||||
if($keep_reports === 0)
|
||||
$keep_reports = 10;
|
||||
$keep_reports = intval(get_config('system', 'expire_delivery_reports'));
|
||||
if ($keep_reports === 0) {
|
||||
$keep_reports = 10;
|
||||
}
|
||||
|
||||
q("delete from dreport where dreport_time < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval($keep_reports . ' DAY')
|
||||
);
|
||||
q(
|
||||
"delete from dreport where dreport_time < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval($keep_reports . ' DAY')
|
||||
);
|
||||
|
||||
// delete accounts that did not submit email verification within 3 days
|
||||
// delete accounts that did not submit email verification within 3 days
|
||||
|
||||
$r = q("select * from register where password = 'verify' and created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
q("DELETE FROM account WHERE account_id = %d",
|
||||
intval($rv['uid'])
|
||||
);
|
||||
$r = q(
|
||||
"select * from register where password = 'verify' and created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
q(
|
||||
"DELETE FROM account WHERE account_id = %d",
|
||||
intval($rv['uid'])
|
||||
);
|
||||
|
||||
q("DELETE FROM register WHERE id = %d",
|
||||
intval($rv['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
q(
|
||||
"DELETE FROM register WHERE id = %d",
|
||||
intval($rv['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// expire any expired accounts
|
||||
downgrade_accounts();
|
||||
// expire any expired accounts
|
||||
downgrade_accounts();
|
||||
|
||||
Run::Summon( [ 'Expire' ] );
|
||||
Run::Summon([ 'Expire' ]);
|
||||
|
||||
|
||||
// remove xchan photos that were stored in the DB ine earlier versions
|
||||
// and were migrated to filesystem storage.
|
||||
// eventually this will do nothing but waste cpu cycles checking to see if anything remains.
|
||||
// remove xchan photos that were stored in the DB ine earlier versions
|
||||
// and were migrated to filesystem storage.
|
||||
// eventually this will do nothing but waste cpu cycles checking to see if anything remains.
|
||||
|
||||
cleanup_xchan_photos();
|
||||
cleanup_xchan_photos();
|
||||
|
||||
remove_obsolete_hublocs();
|
||||
remove_obsolete_hublocs();
|
||||
|
||||
call_hooks('cron_daily',datetime_convert());
|
||||
call_hooks('cron_daily', datetime_convert());
|
||||
|
||||
set_config('system','last_expire_day',intval(datetime_convert('UTC','UTC','now','d')));
|
||||
set_config('system', 'last_expire_day', intval(datetime_convert('UTC', 'UTC', 'now', 'd')));
|
||||
|
||||
/**
|
||||
* End Cron Daily
|
||||
*/
|
||||
}
|
||||
/**
|
||||
* End Cron Daily
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,77 +2,83 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Cron_weekly {
|
||||
class Cron_weekly
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
/**
|
||||
* Cron Weekly
|
||||
*
|
||||
* Actions in the following block are executed once per day only on Sunday (once per week).
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Cron Weekly
|
||||
*
|
||||
* Actions in the following block are executed once per day only on Sunday (once per week).
|
||||
*
|
||||
*/
|
||||
|
||||
call_hooks('cron_weekly',datetime_convert());
|
||||
call_hooks('cron_weekly', datetime_convert());
|
||||
|
||||
z_check_cert();
|
||||
z_check_cert();
|
||||
|
||||
prune_hub_reinstalls();
|
||||
prune_hub_reinstalls();
|
||||
|
||||
mark_orphan_hubsxchans();
|
||||
mark_orphan_hubsxchans();
|
||||
|
||||
// Find channels that were removed in the last three weeks, but
|
||||
// haven't been finally cleaned up. These should be older than 10
|
||||
// days to ensure that "purgeall" messages have gone out or bounced
|
||||
// or timed out.
|
||||
// Find channels that were removed in the last three weeks, but
|
||||
// haven't been finally cleaned up. These should be older than 10
|
||||
// days to ensure that "purgeall" messages have gone out or bounced
|
||||
// or timed out.
|
||||
|
||||
$r = q("select channel_id from channel where channel_removed = 1 and
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_removed = 1 and
|
||||
channel_deleted > %s - INTERVAL %s and channel_deleted < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('21 DAY'),
|
||||
db_utcnow(), db_quoteinterval('10 DAY')
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
channel_remove_final($rv['channel_id']);
|
||||
}
|
||||
}
|
||||
db_utcnow(),
|
||||
db_quoteinterval('21 DAY'),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('10 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
channel_remove_final($rv['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// get rid of really old poco records
|
||||
// get rid of really old poco records
|
||||
|
||||
q("delete from xlink where xlink_updated < %s - INTERVAL %s and xlink_static = 0 ",
|
||||
db_utcnow(), db_quoteinterval('14 DAY')
|
||||
);
|
||||
q(
|
||||
"delete from xlink where xlink_updated < %s - INTERVAL %s and xlink_static = 0 ",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 DAY')
|
||||
);
|
||||
|
||||
// Check for dead sites
|
||||
Run::Summon( ['Checksites' ] );
|
||||
// Check for dead sites
|
||||
Run::Summon(['Checksites' ]);
|
||||
|
||||
|
||||
// clean up image cache - use site expiration or 60 days if not set or zero
|
||||
// clean up image cache - use site expiration or 60 days if not set or zero
|
||||
|
||||
$files = glob('cache/img/*/*');
|
||||
$expire_days = intval(get_config('system','default_expire_days'));
|
||||
if ($expire_days <= 0) {
|
||||
$expire_days = 60;
|
||||
}
|
||||
$now = time();
|
||||
$maxage = 86400 * $expire_days;
|
||||
if ($files) {
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
if ($now - filemtime($file) >= $maxage) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$files = glob('cache/img/*/*');
|
||||
$expire_days = intval(get_config('system', 'default_expire_days'));
|
||||
if ($expire_days <= 0) {
|
||||
$expire_days = 60;
|
||||
}
|
||||
$now = time();
|
||||
$maxage = 86400 * $expire_days;
|
||||
if ($files) {
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
if ($now - filemtime($file) >= $maxage) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update searchable doc indexes
|
||||
// update searchable doc indexes
|
||||
|
||||
Run::Summon( [ 'Importdoc'] );
|
||||
Run::Summon([ 'Importdoc']);
|
||||
|
||||
/**
|
||||
* End Cron Weekly
|
||||
*/
|
||||
|
||||
}
|
||||
/**
|
||||
* End Cron Weekly
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -1,17 +1,21 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Cronhooks {
|
||||
class Cronhooks
|
||||
{
|
||||
|
||||
static public function run($argc,$argv){
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
logger('cronhooks: start');
|
||||
logger('cronhooks: start');
|
||||
|
||||
$d = datetime_convert();
|
||||
$d = datetime_convert();
|
||||
|
||||
call_hooks('cron', $d);
|
||||
call_hooks('cron', $d);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,48 +8,53 @@ namespace Zotlabs\Daemon;
|
|||
|
||||
// Handles expiration of stale cookies currently by deleting them and rewriting the file.
|
||||
|
||||
class CurlAuth {
|
||||
use App;
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
class CurlAuth
|
||||
{
|
||||
|
||||
if($argc != 2)
|
||||
return;
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
\App::$session->start();
|
||||
if ($argc != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$_SESSION['authenticated'] = 1;
|
||||
$_SESSION['uid'] = $argv[1];
|
||||
App::$session->start();
|
||||
|
||||
$x = session_id();
|
||||
$_SESSION['authenticated'] = 1;
|
||||
$_SESSION['uid'] = $argv[1];
|
||||
|
||||
$f = 'cache/cookie_' . $argv[1];
|
||||
$c = 'cache/cookien_' . $argv[1];
|
||||
$x = session_id();
|
||||
|
||||
$e = file_exists($f);
|
||||
$f = 'cache/cookie_' . $argv[1];
|
||||
$c = 'cache/cookien_' . $argv[1];
|
||||
|
||||
$output = '';
|
||||
$e = file_exists($f);
|
||||
|
||||
if($e) {
|
||||
$lines = file($f);
|
||||
if($lines) {
|
||||
foreach($lines as $line) {
|
||||
if(strlen($line) > 0 && $line[0] != '#' && substr_count($line, "\t") == 6) {
|
||||
$tokens = explode("\t", $line);
|
||||
$tokens = array_map('trim', $tokens);
|
||||
if($tokens[4] > time()) {
|
||||
$output .= $line . "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
$output .= $line;
|
||||
}
|
||||
}
|
||||
}
|
||||
$t = time() + (24 * 3600);
|
||||
file_put_contents($f, $output . 'HttpOnly_' . \App::get_hostname() . "\tFALSE\t/\tTRUE\t$t\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0));
|
||||
$output = '';
|
||||
|
||||
file_put_contents($c,$x);
|
||||
if ($e) {
|
||||
$lines = file($f);
|
||||
if ($lines) {
|
||||
foreach ($lines as $line) {
|
||||
if (strlen($line) > 0 && $line[0] != '#' && substr_count($line, "\t") == 6) {
|
||||
$tokens = explode("\t", $line);
|
||||
$tokens = array_map('trim', $tokens);
|
||||
if ($tokens[4] > time()) {
|
||||
$output .= $line . "\n";
|
||||
}
|
||||
} else {
|
||||
$output .= $line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$t = time() + (24 * 3600);
|
||||
file_put_contents($f, $output . 'HttpOnly_' . App::get_hostname() . "\tFALSE\t/\tTRUE\t$t\tPHPSESSID\t" . $x, (($e) ? FILE_APPEND : 0));
|
||||
|
||||
return;
|
||||
}
|
||||
file_put_contents($c, $x);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +1,36 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
class Deliver
|
||||
{
|
||||
|
||||
class Deliver {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
if ($argc < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($argc < 2)
|
||||
return;
|
||||
logger('deliver: invoked: ' . print_r($argv, true), LOGGER_DATA);
|
||||
|
||||
logger('deliver: invoked: ' . print_r($argv,true), LOGGER_DATA);
|
||||
for ($x = 1; $x < $argc; $x++) {
|
||||
if (! $argv[$x]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for($x = 1; $x < $argc; $x ++) {
|
||||
|
||||
if(! $argv[$x])
|
||||
continue;
|
||||
|
||||
$r = q("select * from outq where outq_hash = '%s' limit 1",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
if($r) {
|
||||
Queue::deliver($r[0],true);
|
||||
}
|
||||
}
|
||||
}
|
||||
$r = q(
|
||||
"select * from outq where outq_hash = '%s' limit 1",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
if ($r) {
|
||||
Queue::deliver($r[0], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,23 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Deliver_hooks
|
||||
{
|
||||
|
||||
class Deliver_hooks {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
if($argc < 2)
|
||||
return;
|
||||
if ($argc < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from item where id = '%d'",
|
||||
intval($argv[1])
|
||||
);
|
||||
if($r)
|
||||
call_hooks('notifier_normal',$r[0]);
|
||||
|
||||
}
|
||||
$r = q(
|
||||
"select * from item where id = '%d'",
|
||||
intval($argv[1])
|
||||
);
|
||||
if ($r) {
|
||||
call_hooks('notifier_normal', $r[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,18 +6,20 @@ namespace Zotlabs\Daemon;
|
|||
* Daemon to remove 'item' resources in the background from a removed connection
|
||||
*/
|
||||
|
||||
class Delxitems {
|
||||
class Delxitems
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
cli_startup();
|
||||
cli_startup();
|
||||
|
||||
if($argc != 3) {
|
||||
return;
|
||||
}
|
||||
if ($argc != 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove_abook_items($argv[1],$argv[2]);
|
||||
remove_abook_items($argv[1], $argv[2]);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,52 +2,52 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
|
||||
use Zotlabs\Lib\Libzot;;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
class Directory
|
||||
{
|
||||
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
class Directory {
|
||||
if ($argc < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
$force = false;
|
||||
$pushall = true;
|
||||
|
||||
if ($argc < 2) {
|
||||
return;
|
||||
}
|
||||
if ($argc > 2) {
|
||||
if ($argv[2] === 'force') {
|
||||
$force = true;
|
||||
}
|
||||
if ($argv[2] === 'nopush') {
|
||||
$pushall = false;
|
||||
}
|
||||
}
|
||||
|
||||
$force = false;
|
||||
$pushall = true;
|
||||
logger('directory update', LOGGER_DEBUG);
|
||||
|
||||
if ($argc > 2) {
|
||||
if ($argv[2] === 'force') {
|
||||
$force = true;
|
||||
}
|
||||
if ($argv[2] === 'nopush') {
|
||||
$pushall = false;
|
||||
}
|
||||
}
|
||||
$channel = channelx_by_n($argv[1]);
|
||||
if (! $channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger('directory update', LOGGER_DEBUG);
|
||||
// update the local directory - was optional, but now done regardless
|
||||
|
||||
$channel = channelx_by_n($argv[1]);
|
||||
if (! $channel) {
|
||||
return;
|
||||
}
|
||||
Libzotdir::local_dir_update($argv[1], $force);
|
||||
|
||||
// update the local directory - was optional, but now done regardless
|
||||
q(
|
||||
"update channel set channel_dirdate = '%s' where channel_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
Libzotdir::local_dir_update($argv[1],$force);
|
||||
|
||||
q("update channel set channel_dirdate = '%s' where channel_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
// Now update all the connections
|
||||
if ($pushall) {
|
||||
Run::Summon( [ 'Notifier','refresh_all',$channel['channel_id'] ] );
|
||||
}
|
||||
}
|
||||
// Now update all the connections
|
||||
if ($pushall) {
|
||||
Run::Summon([ 'Notifier','refresh_all',$channel['channel_id'] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,90 +2,94 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Expire
|
||||
{
|
||||
|
||||
class Expire {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv){
|
||||
cli_startup();
|
||||
|
||||
cli_startup();
|
||||
// perform final cleanup on previously delete items
|
||||
|
||||
// perform final cleanup on previously delete items
|
||||
$r = q(
|
||||
"select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('10 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
drop_item($rr['id'], false, DROPITEM_PHASE2);
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('10 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
drop_item($rr['id'], false, DROPITEM_PHASE2);
|
||||
}
|
||||
}
|
||||
// physically remove anything that has been deleted for more than two months
|
||||
/** @FIXME - this is a wretchedly inefficient query */
|
||||
|
||||
// physically remove anything that has been deleted for more than two months
|
||||
/** @FIXME - this is a wretchedly inefficient query */
|
||||
$r = q(
|
||||
"delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('36 DAY')
|
||||
);
|
||||
|
||||
$r = q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('36 DAY')
|
||||
);
|
||||
logger('expire: start', LOGGER_DEBUG);
|
||||
|
||||
logger('expire: start', LOGGER_DEBUG);
|
||||
$site_expire = intval(get_config('system', 'default_expire_days'));
|
||||
$commented_days = intval(get_config('system', 'active_expire_days'));
|
||||
|
||||
$site_expire = intval(get_config('system', 'default_expire_days'));
|
||||
$commented_days = intval(get_config('system','active_expire_days'));
|
||||
logger('site_expire: ' . $site_expire);
|
||||
|
||||
logger('site_expire: ' . $site_expire);
|
||||
$r = q("SELECT channel_id, channel_system, channel_address, channel_expire_days from channel where true");
|
||||
|
||||
$r = q("SELECT channel_id, channel_system, channel_address, channel_expire_days from channel where true");
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
// expire the sys channel separately
|
||||
if (intval($rr['channel_system'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
// service class default (if non-zero) over-rides the site default
|
||||
|
||||
// expire the sys channel separately
|
||||
if (intval($rr['channel_system']))
|
||||
continue;
|
||||
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
|
||||
if (intval($service_class_expire)) {
|
||||
$channel_expire = $service_class_expire;
|
||||
} else {
|
||||
$channel_expire = $site_expire;
|
||||
}
|
||||
|
||||
// service class default (if non-zero) over-rides the site default
|
||||
if (
|
||||
intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
|
||||
intval($rr['channel_expire_days'] == 0)
|
||||
) {
|
||||
$expire_days = $channel_expire;
|
||||
} else {
|
||||
$expire_days = $rr['channel_expire_days'];
|
||||
}
|
||||
|
||||
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
|
||||
if (intval($service_class_expire)) {
|
||||
$channel_expire = $service_class_expire;
|
||||
}
|
||||
else {
|
||||
$channel_expire = $site_expire;
|
||||
}
|
||||
// if the site or service class expiration is non-zero and less than person expiration, use that
|
||||
logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $expire_days, LOGGER_DEBUG);
|
||||
item_expire($rr['channel_id'], $expire_days, $commented_days);
|
||||
}
|
||||
}
|
||||
|
||||
if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) ||
|
||||
intval($rr['channel_expire_days'] == 0)) {
|
||||
$expire_days = $channel_expire;
|
||||
}
|
||||
else {
|
||||
$expire_days = $rr['channel_expire_days'];
|
||||
}
|
||||
$x = get_sys_channel();
|
||||
if ($x) {
|
||||
// this should probably just fetch the channel_expire_days from the sys channel,
|
||||
// but there's no convenient way to set it.
|
||||
|
||||
// if the site or service class expiration is non-zero and less than person expiration, use that
|
||||
logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $expire_days, LOGGER_DEBUG);
|
||||
item_expire($rr['channel_id'], $expire_days, $commented_days);
|
||||
}
|
||||
}
|
||||
$expire_days = get_config('system', 'sys_expire_days', 30);
|
||||
|
||||
$x = get_sys_channel();
|
||||
if ($x) {
|
||||
if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) {
|
||||
$expire_days = $site_expire;
|
||||
}
|
||||
|
||||
// this should probably just fetch the channel_expire_days from the sys channel,
|
||||
// but there's no convenient way to set it.
|
||||
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
|
||||
|
||||
$expire_days = get_config('system', 'sys_expire_days',30);
|
||||
if ($expire_days) {
|
||||
item_expire($x['channel_id'], $expire_days, $commented_days);
|
||||
}
|
||||
|
||||
if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) {
|
||||
$expire_days = $site_expire;
|
||||
}
|
||||
|
||||
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
|
||||
|
||||
if ($expire_days) {
|
||||
item_expire($x['channel_id'], $expire_days, $commented_days);
|
||||
}
|
||||
|
||||
logger('Expire: sys: done', LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
logger('Expire: sys: done', LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,43 +8,45 @@ require_once('include/cli_startup.php');
|
|||
require_once('include/attach.php');
|
||||
require_once('include/import.php');
|
||||
|
||||
class File_importer {
|
||||
class File_importer
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
cli_startup();
|
||||
cli_startup();
|
||||
|
||||
$attach_id = $argv[1];
|
||||
$channel_address = $argv[2];
|
||||
$hz_server = urldecode($argv[3]);
|
||||
$attach_id = $argv[1];
|
||||
$channel_address = $argv[2];
|
||||
$hz_server = urldecode($argv[3]);
|
||||
|
||||
$m = parse_url($hz_server);
|
||||
$m = parse_url($hz_server);
|
||||
|
||||
$channel = channelx_by_nick($channel_address);
|
||||
if(! $channel) {
|
||||
logger('filehelper: channel not found');
|
||||
killme();
|
||||
}
|
||||
$channel = channelx_by_nick($channel_address);
|
||||
if (! $channel) {
|
||||
logger('filehelper: channel not found');
|
||||
killme();
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'X-API-Token' => random_string(),
|
||||
'X-API-Request' => $hz_server . '/api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id,
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get /api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id,
|
||||
];
|
||||
$headers = [
|
||||
'X-API-Token' => random_string(),
|
||||
'X-API-Request' => $hz_server . '/api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id,
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'get /api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id,
|
||||
];
|
||||
|
||||
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),true,'sha512');
|
||||
$x = z_fetch_url($hz_server . '/api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id,false,$redirects,[ 'headers' => $headers ]);
|
||||
$headers = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), true, 'sha512');
|
||||
$x = z_fetch_url($hz_server . '/api/z/1.0/file/export?f=&zap_compat=1&file_id=' . $attach_id, false, $redirects, [ 'headers' => $headers ]);
|
||||
|
||||
if(! $x['success']) {
|
||||
logger('no API response',LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
if (! $x['success']) {
|
||||
logger('no API response', LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
$j = json_decode($x['body'],true);
|
||||
$j = json_decode($x['body'], true);
|
||||
|
||||
$r = sync_files($channel,[$j]);
|
||||
$r = sync_files($channel, [$j]);
|
||||
|
||||
killme();
|
||||
}
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
|
@ -8,55 +10,57 @@ use Zotlabs\Lib\Zotfinger;
|
|||
|
||||
// performs zot_finger on $argv[1], which is a hex_encoded webbie/reddress
|
||||
|
||||
class Gprobe {
|
||||
class Gprobe
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
|
||||
if ($argc != 2) {
|
||||
return;
|
||||
}
|
||||
if ($argc != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
$protocols = [];
|
||||
$url = hex2bin($argv[1]);
|
||||
$protocols = [];
|
||||
|
||||
if (! strpos($url,'@')) {
|
||||
return;
|
||||
}
|
||||
if (! strpos($url, '@')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from hubloc where hubloc_addr = '%s'",
|
||||
dbesc($url)
|
||||
);
|
||||
$r = q(
|
||||
"select * from hubloc where hubloc_addr = '%s'",
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
if ($rv['hubloc_network'] === 'activitypub') {
|
||||
$protocols[] = 'activitypub';
|
||||
continue;
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
if ($rv['hubloc_network'] === 'activitypub') {
|
||||
$protocols[] = 'activitypub';
|
||||
continue;
|
||||
}
|
||||
if ($rv['hubloc_network'] === 'nomad') {
|
||||
$protocols[] = 'nomad';
|
||||
$protocols[] = 'zot6';
|
||||
continue;
|
||||
}
|
||||
if ($rv['hubloc_network'] === 'zot6') {
|
||||
$protocols[] = 'zot6';
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (! in_array('zot6',$protocols)) {
|
||||
$href = Webfinger::zot_url(punify($url));
|
||||
if ($href) {
|
||||
$zf = Zotfinger::exec($href,$channel);
|
||||
if ($rv['hubloc_network'] === 'zot6') {
|
||||
$protocols[] = 'zot6';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid']) && isset($zf['data']) && $zf['data']) {
|
||||
$xc = Libzot::import_xchan($zf['data']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (! in_array('zot6', $protocols)) {
|
||||
$href = Webfinger::zot_url(punify($url));
|
||||
if ($href) {
|
||||
$zf = Zotfinger::exec($href, $channel);
|
||||
}
|
||||
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid']) && isset($zf['data']) && $zf['data']) {
|
||||
$xc = Libzot::import_xchan($zf['data']);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,50 +2,50 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Importdoc
|
||||
{
|
||||
|
||||
class Importdoc {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
require_once('include/help.php');
|
||||
|
||||
require_once('include/help.php');
|
||||
self::update_docs_dir('doc/*');
|
||||
}
|
||||
|
||||
self::update_docs_dir('doc/*');
|
||||
|
||||
}
|
||||
|
||||
static public function update_docs_dir($s) {
|
||||
$f = basename($s);
|
||||
$d = dirname($s);
|
||||
if($s === 'doc/html')
|
||||
return;
|
||||
$files = glob("$d/$f");
|
||||
if($files) {
|
||||
foreach($files as $fi) {
|
||||
if($fi === 'doc/html') {
|
||||
continue;
|
||||
}
|
||||
if(is_dir($fi)) {
|
||||
self::update_docs_dir("$fi/*");
|
||||
}
|
||||
else {
|
||||
// don't update media content
|
||||
if(strpos(z_mime_content_type($fi),'text') === 0) {
|
||||
store_doc_file($fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove old files that weren't updated (indicates they were most likely deleted).
|
||||
$i = q("select * from item where item_type = 5 and edited < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 DAY')
|
||||
);
|
||||
if ($i) {
|
||||
foreach ($i as $iv) {
|
||||
drop_item($iv['id'],false,DROPITEM_NORMAL,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static function update_docs_dir($s)
|
||||
{
|
||||
$f = basename($s);
|
||||
$d = dirname($s);
|
||||
if ($s === 'doc/html') {
|
||||
return;
|
||||
}
|
||||
$files = glob("$d/$f");
|
||||
if ($files) {
|
||||
foreach ($files as $fi) {
|
||||
if ($fi === 'doc/html') {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($fi)) {
|
||||
self::update_docs_dir("$fi/*");
|
||||
} else {
|
||||
// don't update media content
|
||||
if (strpos(z_mime_content_type($fi), 'text') === 0) {
|
||||
store_doc_file($fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove old files that weren't updated (indicates they were most likely deleted).
|
||||
$i = q(
|
||||
"select * from item where item_type = 5 and edited < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('14 DAY')
|
||||
);
|
||||
if ($i) {
|
||||
foreach ($i as $iv) {
|
||||
drop_item($iv['id'], false, DROPITEM_NORMAL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,49 +1,57 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Importfile {
|
||||
class Importfile
|
||||
{
|
||||
|
||||
static public function run($argc,$argv){
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
logger('Importfile: ' . print_r($argv,true));
|
||||
logger('Importfile: ' . print_r($argv, true));
|
||||
|
||||
if($argc < 3)
|
||||
return;
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = channelx_by_n($argv[1]);
|
||||
if(! $channel)
|
||||
return;
|
||||
$channel = channelx_by_n($argv[1]);
|
||||
if (! $channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
$srcfile = $argv[2];
|
||||
$folder = (($argc > 3) ? $argv[3] : '');
|
||||
$dstname = (($argc > 4) ? $argv[4] : '');
|
||||
$srcfile = $argv[2];
|
||||
$folder = (($argc > 3) ? $argv[3] : '');
|
||||
$dstname = (($argc > 4) ? $argv[4] : '');
|
||||
|
||||
$hash = random_string();
|
||||
$hash = random_string();
|
||||
|
||||
$arr = [
|
||||
'src' => $srcfile,
|
||||
'filename' => (($dstname) ? $dstname : basename($srcfile)),
|
||||
'hash' => $hash,
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid'],
|
||||
'preserve_original' => true,
|
||||
'replace' => true
|
||||
];
|
||||
$arr = [
|
||||
'src' => $srcfile,
|
||||
'filename' => (($dstname) ? $dstname : basename($srcfile)),
|
||||
'hash' => $hash,
|
||||
'allow_cid' => $channel['channel_allow_cid'],
|
||||
'allow_gid' => $channel['channel_allow_gid'],
|
||||
'deny_cid' => $channel['channel_deny_cid'],
|
||||
'deny_gid' => $channel['channel_deny_gid'],
|
||||
'preserve_original' => true,
|
||||
'replace' => true
|
||||
];
|
||||
|
||||
if($folder)
|
||||
$arr['folder'] = $folder;
|
||||
if ($folder) {
|
||||
$arr['folder'] = $folder;
|
||||
}
|
||||
|
||||
attach_store($channel,$channel['channel_hash'],'import',$arr);
|
||||
attach_store($channel, $channel['channel_hash'], 'import', $arr);
|
||||
|
||||
$sync = attach_export_data($channel,$hash);
|
||||
if($sync)
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||
$sync = attach_export_data($channel, $hash);
|
||||
if ($sync) {
|
||||
Libsync::build_sync_packet($channel['channel_id'], array('file' => array($sync)));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,75 +1,87 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzotdir;
|
||||
|
||||
class Onedirsync
|
||||
{
|
||||
|
||||
class Onedirsync {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
logger('onedirsync: start ' . intval($argv[1]));
|
||||
|
||||
logger('onedirsync: start ' . intval($argv[1]));
|
||||
if (($argc > 1) && (intval($argv[1]))) {
|
||||
$update_id = intval($argv[1]);
|
||||
}
|
||||
|
||||
if(($argc > 1) && (intval($argv[1])))
|
||||
$update_id = intval($argv[1]);
|
||||
if (! $update_id) {
|
||||
logger('onedirsync: no update');
|
||||
return;
|
||||
}
|
||||
|
||||
if(! $update_id) {
|
||||
logger('onedirsync: no update');
|
||||
$r = q(
|
||||
"select * from updates where ud_id = %d limit 1",
|
||||
intval($update_id)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (! $r[0]['ud_addr'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Have we probed this channel more recently than the other directory server
|
||||
// (where we received this update from) ?
|
||||
// If we have, we don't need to do anything except mark any older entries updated
|
||||
|
||||
$x = q(
|
||||
"select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
|
||||
dbesc($r[0]['ud_addr']),
|
||||
dbesc($r[0]['ud_date']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
if ($x) {
|
||||
$y = q(
|
||||
"update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($x[0]['ud_date'])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore doing an update if this ud_addr refers to a known dead hubloc
|
||||
|
||||
$h = q(
|
||||
"select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($r[0]['ud_addr'])
|
||||
);
|
||||
if (($h) && ($h[0]['hubloc_status'] & HUBLOC_OFFLINE)) {
|
||||
$y = q(
|
||||
"update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// we might have to pull this out some day, but for now update_directory_entry()
|
||||
// runs zot_finger() and is kind of zot specific
|
||||
|
||||
if ($h && in_array($h[0]['hubloc_network'],['nomad','zot6'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from updates where ud_id = %d limit 1",
|
||||
intval($update_id)
|
||||
);
|
||||
Libzotdir::update_directory_entry($r[0]);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
if(($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (! $r[0]['ud_addr']))
|
||||
return;
|
||||
|
||||
// Have we probed this channel more recently than the other directory server
|
||||
// (where we received this update from) ?
|
||||
// If we have, we don't need to do anything except mark any older entries updated
|
||||
|
||||
$x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d ) > 0 order by ud_date desc limit 1",
|
||||
dbesc($r[0]['ud_addr']),
|
||||
dbesc($r[0]['ud_date']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
if($x) {
|
||||
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($x[0]['ud_date'])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore doing an update if this ud_addr refers to a known dead hubloc
|
||||
|
||||
$h = q("select * from hubloc where hubloc_addr = '%s' limit 1",
|
||||
dbesc($r[0]['ud_addr'])
|
||||
);
|
||||
if(($h) && ($h[0]['hubloc_status'] & HUBLOC_OFFLINE)) {
|
||||
$y = q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($r[0]['ud_addr']),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// we might have to pull this out some day, but for now update_directory_entry()
|
||||
// runs zot_finger() and is kind of zot specific
|
||||
|
||||
if($h && in_array($h[0]['hubloc_network'],['nomad','zot6']))
|
||||
return;
|
||||
|
||||
Libzotdir::update_directory_entry($r[0]);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
|
@ -7,164 +9,171 @@ use Zotlabs\Lib\ActivityStreams;
|
|||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ASCollection;
|
||||
|
||||
|
||||
require_once('include/socgraph.php');
|
||||
|
||||
|
||||
class Onepoll {
|
||||
class Onepoll
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
logger('onepoll: start');
|
||||
logger('onepoll: start');
|
||||
|
||||
if(($argc > 1) && (intval($argv[1])))
|
||||
$contact_id = intval($argv[1]);
|
||||
if (($argc > 1) && (intval($argv[1]))) {
|
||||
$contact_id = intval($argv[1]);
|
||||
}
|
||||
|
||||
if(! $contact_id) {
|
||||
logger('onepoll: no contact');
|
||||
return;
|
||||
}
|
||||
if (! $contact_id) {
|
||||
logger('onepoll: no contact');
|
||||
return;
|
||||
}
|
||||
|
||||
$d = datetime_convert();
|
||||
$d = datetime_convert();
|
||||
|
||||
$contacts = q("SELECT abook.*, xchan.*, account.*
|
||||
$contacts = q(
|
||||
"SELECT abook.*, xchan.*, account.*
|
||||
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
|
||||
where abook_id = %d
|
||||
and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
|
||||
AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
|
||||
intval($contact_id),
|
||||
intval(ACCOUNT_OK),
|
||||
intval(ACCOUNT_UNVERIFIED)
|
||||
);
|
||||
intval($contact_id),
|
||||
intval(ACCOUNT_OK),
|
||||
intval(ACCOUNT_UNVERIFIED)
|
||||
);
|
||||
|
||||
if(! $contacts) {
|
||||
logger('onepoll: abook_id not found: ' . $contact_id);
|
||||
return;
|
||||
}
|
||||
if (! $contacts) {
|
||||
logger('onepoll: abook_id not found: ' . $contact_id);
|
||||
return;
|
||||
}
|
||||
|
||||
$contact = array_shift($contacts);
|
||||
$contact = array_shift($contacts);
|
||||
|
||||
$t = $contact['abook_updated'];
|
||||
$t = $contact['abook_updated'];
|
||||
|
||||
$importer_uid = $contact['abook_channel'];
|
||||
$importer_uid = $contact['abook_channel'];
|
||||
|
||||
$r = q("SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
|
||||
intval($importer_uid)
|
||||
);
|
||||
$r = q(
|
||||
"SELECT * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
|
||||
intval($importer_uid)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
$importer = $r[0];
|
||||
$importer = $r[0];
|
||||
|
||||
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
|
||||
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
|
||||
|
||||
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
|
||||
? datetime_convert('UTC','UTC','now - 7 days')
|
||||
: datetime_convert('UTC','UTC',$contact['abook_updated'] . ' - 2 days')
|
||||
);
|
||||
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
|
||||
? datetime_convert('UTC', 'UTC', 'now - 7 days')
|
||||
: datetime_convert('UTC', 'UTC', $contact['abook_updated'] . ' - 2 days')
|
||||
);
|
||||
|
||||
if(in_array($contact['xchan_network'],['nomad']['zot6'])) {
|
||||
if (in_array($contact['xchan_network'],['nomad']['zot6'])) {
|
||||
// update permissions
|
||||
|
||||
// update permissions
|
||||
$x = Libzot::refresh($contact, $importer);
|
||||
|
||||
$x = Libzot::refresh($contact,$importer);
|
||||
$responded = false;
|
||||
$updated = datetime_convert();
|
||||
$connected = datetime_convert();
|
||||
if (! $x) {
|
||||
// mark for death by not updating abook_connected, this is caught in include/poller.php
|
||||
q(
|
||||
"update abook set abook_updated = '%s' where abook_id = %d",
|
||||
dbesc($updated),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
} else {
|
||||
q(
|
||||
"update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d",
|
||||
dbesc($updated),
|
||||
dbesc($connected),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$responded = true;
|
||||
}
|
||||
|
||||
$responded = false;
|
||||
$updated = datetime_convert();
|
||||
$connected = datetime_convert();
|
||||
if(! $x) {
|
||||
// mark for death by not updating abook_connected, this is caught in include/poller.php
|
||||
q("update abook set abook_updated = '%s' where abook_id = %d",
|
||||
dbesc($updated),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d",
|
||||
dbesc($updated),
|
||||
dbesc($connected),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$responded = true;
|
||||
}
|
||||
if (! $responded) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $responded) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$fetch_feed = true;
|
||||
|
||||
$fetch_feed = true;
|
||||
// They haven't given us permission to see their stream
|
||||
|
||||
// They haven't given us permission to see their stream
|
||||
$can_view_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'their_perms', 'view_stream'));
|
||||
|
||||
$can_view_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'their_perms','view_stream'));
|
||||
if (! $can_view_stream) {
|
||||
$fetch_feed = false;
|
||||
}
|
||||
|
||||
if (! $can_view_stream) {
|
||||
$fetch_feed = false;
|
||||
}
|
||||
// we haven't given them permission to send us their stream
|
||||
|
||||
// we haven't given them permission to send us their stream
|
||||
$can_send_stream = intval(get_abconfig($importer_uid, $contact['abook_xchan'], 'my_perms', 'send_stream'));
|
||||
|
||||
$can_send_stream = intval(get_abconfig($importer_uid,$contact['abook_xchan'],'my_perms','send_stream'));
|
||||
if (! $can_send_stream) {
|
||||
$fetch_feed = false;
|
||||
}
|
||||
|
||||
if (! $can_send_stream) {
|
||||
$fetch_feed = false;
|
||||
}
|
||||
if ($contact['abook_created'] < datetime_convert('UTC', 'UTC', 'now - 1 week')) {
|
||||
$fetch_feed = false;
|
||||
}
|
||||
|
||||
if ($contact['abook_created'] < datetime_convert('UTC','UTC', 'now - 1 week')) {
|
||||
$fetch_feed = false;
|
||||
}
|
||||
// In previous releases there was a mechanism to fetch 'external' or public stream posts from a site
|
||||
// (as opposed to a channel). This mechanism was deprecated as there is no reliable/scalable method
|
||||
// for informing downstream publishers when/if the content has expired or been deleted.
|
||||
// We can use the ThreadListener interface to implement this on the owner's outbox, however this is still a
|
||||
// work in progress and may present scaling issues. Making this work correctly with third-party fetches is
|
||||
// prohibitive as deletion requests would need to be relayed over potentially hostile networks.
|
||||
|
||||
// In previous releases there was a mechanism to fetch 'external' or public stream posts from a site
|
||||
// (as opposed to a channel). This mechanism was deprecated as there is no reliable/scalable method
|
||||
// for informing downstream publishers when/if the content has expired or been deleted.
|
||||
// We can use the ThreadListener interface to implement this on the owner's outbox, however this is still a
|
||||
// work in progress and may present scaling issues. Making this work correctly with third-party fetches is
|
||||
// prohibitive as deletion requests would need to be relayed over potentially hostile networks.
|
||||
if ($fetch_feed) {
|
||||
$max = intval(get_config('system', 'max_imported_posts', 20));
|
||||
if (intval($max)) {
|
||||
$cl = get_xconfig($xchan, 'activitypub', 'collections');
|
||||
if (is_array($cl) && $cl) {
|
||||
$url = ((array_key_exists('outbox', $cl)) ? $cl['outbox'] : '');
|
||||
if ($url) {
|
||||
logger('fetching outbox');
|
||||
$url = $url . '?date_begin=' . urlencode($last_update);
|
||||
$obj = new ASCollection($url, $importer, 0, $max);
|
||||
$messages = $obj->get();
|
||||
if ($messages) {
|
||||
foreach ($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message, $importer);
|
||||
}
|
||||
if (is_array($message)) {
|
||||
$AS = new ActivityStreams($message, null, true);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS, true);
|
||||
if ($item) {
|
||||
Activity::store($importer, $contact['abook_xchan'], $AS, $item, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($fetch_feed) {
|
||||
$max = intval(get_config('system','max_imported_posts',20));
|
||||
if (intval($max)) {
|
||||
$cl = get_xconfig($xchan,'activitypub','collections');
|
||||
if (is_array($cl) && $cl) {
|
||||
$url = ((array_key_exists('outbox',$cl)) ? $cl['outbox'] : '');
|
||||
if ($url) {
|
||||
logger('fetching outbox');
|
||||
$url = $url . '?date_begin=' . urlencode($last_update);
|
||||
$obj = new ASCollection($url, $importer, 0, $max);
|
||||
$messages = $obj->get();
|
||||
if ($messages) {
|
||||
foreach($messages as $message) {
|
||||
if (is_string($message)) {
|
||||
$message = Activity::fetch($message,$importer);
|
||||
}
|
||||
if (is_array($message)) {
|
||||
$AS = new ActivityStreams($message,null,true);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS,true);
|
||||
if ($item) {
|
||||
Activity::store($importer,$contact['abook_xchan'],$AS, $item, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// update the poco details for this connection
|
||||
|
||||
// update the poco details for this connection
|
||||
|
||||
$r = q("SELECT xlink_id from xlink
|
||||
$r = q(
|
||||
"SELECT xlink_id from xlink
|
||||
where xlink_xchan = '%s' and xlink_updated > %s - INTERVAL %s and xlink_static = 0 limit 1",
|
||||
intval($contact['xchan_hash']),
|
||||
db_utcnow(), db_quoteinterval('7 DAY')
|
||||
);
|
||||
if(! $r) {
|
||||
poco_load($contact['xchan_hash'],$contact['xchan_connurl']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
intval($contact['xchan_hash']),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
);
|
||||
if (! $r) {
|
||||
poco_load($contact['xchan_hash'], $contact['xchan_connurl']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,79 +1,90 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Poller {
|
||||
class Poller
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
$maxsysload = intval(get_config('system','maxloadavg'));
|
||||
if($maxsysload < 1)
|
||||
$maxsysload = 50;
|
||||
if(function_exists('sys_getloadavg')) {
|
||||
$load = sys_getloadavg();
|
||||
if(intval($load[0]) > $maxsysload) {
|
||||
logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
$maxsysload = intval(get_config('system', 'maxloadavg'));
|
||||
if ($maxsysload < 1) {
|
||||
$maxsysload = 50;
|
||||
}
|
||||
if (function_exists('sys_getloadavg')) {
|
||||
$load = sys_getloadavg();
|
||||
if (intval($load[0]) > $maxsysload) {
|
||||
logger('system: load ' . $load . ' too high. Poller deferred to next scheduled run.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$interval = intval(get_config('system','poll_interval'));
|
||||
if(! $interval)
|
||||
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
|
||||
$interval = intval(get_config('system', 'poll_interval'));
|
||||
if (! $interval) {
|
||||
$interval = ((get_config('system', 'delivery_interval') === false) ? 3 : intval(get_config('system', 'delivery_interval')));
|
||||
}
|
||||
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'cache/poller';
|
||||
if((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (! get_config('system','override_poll_lockfile'))) {
|
||||
logger("poller: Already running");
|
||||
return;
|
||||
}
|
||||
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
|
||||
$lockfile = 'cache/poller';
|
||||
if (
|
||||
(file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
|
||||
&& (! get_config('system', 'override_poll_lockfile'))
|
||||
) {
|
||||
logger("poller: Already running");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a lockfile.
|
||||
file_put_contents($lockfile, EMPTY_STR);
|
||||
// Create a lockfile.
|
||||
file_put_contents($lockfile, EMPTY_STR);
|
||||
|
||||
logger('poller: start');
|
||||
logger('poller: start');
|
||||
|
||||
$manual_id = 0;
|
||||
$generation = 0;
|
||||
$manual_id = 0;
|
||||
$generation = 0;
|
||||
|
||||
$force = false;
|
||||
$restart = false;
|
||||
$force = false;
|
||||
$restart = false;
|
||||
|
||||
if(($argc > 1) && ($argv[1] == 'force'))
|
||||
$force = true;
|
||||
if (($argc > 1) && ($argv[1] == 'force')) {
|
||||
$force = true;
|
||||
}
|
||||
|
||||
if(($argc > 1) && ($argv[1] == 'restart')) {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if(! $generation)
|
||||
return;
|
||||
}
|
||||
if (($argc > 1) && ($argv[1] == 'restart')) {
|
||||
$restart = true;
|
||||
$generation = intval($argv[2]);
|
||||
if (! $generation) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(($argc > 1) && intval($argv[1])) {
|
||||
$manual_id = intval($argv[1]);
|
||||
$force = true;
|
||||
}
|
||||
if (($argc > 1) && intval($argv[1])) {
|
||||
$manual_id = intval($argv[1]);
|
||||
$force = true;
|
||||
}
|
||||
|
||||
|
||||
$sql_extra = (($manual_id) ? " AND abook_id = " . intval($manual_id) . " " : "");
|
||||
$sql_extra = (($manual_id) ? " AND abook_id = " . intval($manual_id) . " " : "");
|
||||
|
||||
reload_plugins();
|
||||
reload_plugins();
|
||||
|
||||
$d = datetime_convert();
|
||||
$d = datetime_convert();
|
||||
|
||||
// Only poll from those with suitable relationships
|
||||
// Only poll from those with suitable relationships
|
||||
|
||||
// $abandon_sql = (($abandon_days)
|
||||
// ? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days).' DAY'))
|
||||
// : ''
|
||||
// );
|
||||
// $abandon_sql = (($abandon_days)
|
||||
// ? sprintf(" AND account_lastlog > %s - INTERVAL %s ", db_utcnow(), db_quoteinterval(intval($abandon_days).' DAY'))
|
||||
// : ''
|
||||
// );
|
||||
|
||||
$abandon_sql = EMPTY_STR;
|
||||
$abandon_sql = EMPTY_STR;
|
||||
|
||||
$randfunc = db_getfunc('RAND');
|
||||
$randfunc = db_getfunc('RAND');
|
||||
|
||||
$contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
|
||||
$contacts = q(
|
||||
"SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
|
||||
abook.abook_channel, abook.abook_id, abook.abook_archived, abook.abook_pending,
|
||||
abook.abook_ignored, abook.abook_blocked,
|
||||
xchan.xchan_network,
|
||||
|
@ -83,109 +94,115 @@ class Poller {
|
|||
where abook_self = 0
|
||||
$sql_extra
|
||||
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
|
||||
intval(ACCOUNT_OK),
|
||||
intval(ACCOUNT_UNVERIFIED) // FIXME
|
||||
);
|
||||
intval(ACCOUNT_OK),
|
||||
intval(ACCOUNT_UNVERIFIED) // FIXME
|
||||
);
|
||||
|
||||
if($contacts) {
|
||||
if ($contacts) {
|
||||
foreach ($contacts as $contact) {
|
||||
$update = false;
|
||||
|
||||
foreach($contacts as $contact) {
|
||||
$t = $contact['abook_updated'];
|
||||
$c = $contact['abook_connected'];
|
||||
|
||||
$update = false;
|
||||
if (intval($contact['abook_feed'])) {
|
||||
$min = service_class_fetch($contact['abook_channel'], 'minimum_feedcheck_minutes');
|
||||
if (! $min) {
|
||||
$min = intval(get_config('system', 'minimum_feedcheck_minutes'));
|
||||
}
|
||||
if (! $min) {
|
||||
$min = 60;
|
||||
}
|
||||
$x = datetime_convert('UTC', 'UTC', "now - $min minutes");
|
||||
if ($c < $x) {
|
||||
Run::Summon([ 'Onepoll', $contact['abook_id'] ]);
|
||||
if ($interval) {
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$t = $contact['abook_updated'];
|
||||
$c = $contact['abook_connected'];
|
||||
|
||||
if(intval($contact['abook_feed'])) {
|
||||
$min = service_class_fetch($contact['abook_channel'],'minimum_feedcheck_minutes');
|
||||
if(! $min)
|
||||
$min = intval(get_config('system','minimum_feedcheck_minutes'));
|
||||
if(! $min)
|
||||
$min = 60;
|
||||
$x = datetime_convert('UTC','UTC',"now - $min minutes");
|
||||
if($c < $x) {
|
||||
Run::Summon( [ 'Onepoll', $contact['abook_id'] ] );
|
||||
if($interval)
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
if (! in_array($contact['xchan_network'],['nomad','zot6'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($c == $t) {
|
||||
if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 day")) {
|
||||
$update = true;
|
||||
}
|
||||
} else {
|
||||
// if we've never connected with them, start the mark for death countdown from now
|
||||
|
||||
if(! in_array($contact['xchan_network'],['nomad','zot6']))
|
||||
continue;
|
||||
if ($c <= NULL_DATE) {
|
||||
$r = q(
|
||||
"update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$c = datetime_convert();
|
||||
$update = true;
|
||||
}
|
||||
|
||||
if($c == $t) {
|
||||
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
|
||||
$update = true;
|
||||
}
|
||||
else {
|
||||
// He's dead, Jim
|
||||
|
||||
// if we've never connected with them, start the mark for death countdown from now
|
||||
if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 30 day")) > 0) {
|
||||
$r = q(
|
||||
"update abook set abook_archived = 1 where abook_id = %d",
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$update = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if($c <= NULL_DATE) {
|
||||
$r = q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$c = datetime_convert();
|
||||
$update = true;
|
||||
}
|
||||
if (intval($contact['abook_archived'])) {
|
||||
$update = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// He's dead, Jim
|
||||
// might be dead, so maybe don't poll quite so often
|
||||
|
||||
if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 30 day")) > 0) {
|
||||
$r = q("update abook set abook_archived = 1 where abook_id = %d",
|
||||
intval($contact['abook_id'])
|
||||
);
|
||||
$update = false;
|
||||
continue;
|
||||
}
|
||||
// recently deceased, so keep up the regular schedule for 3 days
|
||||
|
||||
if(intval($contact['abook_archived'])) {
|
||||
$update = false;
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
(strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $c . " + 3 day")) > 0)
|
||||
&& (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 1 day")) > 0)
|
||||
) {
|
||||
$update = true;
|
||||
}
|
||||
|
||||
// might be dead, so maybe don't poll quite so often
|
||||
// After that back off and put them on a morphine drip
|
||||
|
||||
// recently deceased, so keep up the regular schedule for 3 days
|
||||
if (strcmp(datetime_convert('UTC', 'UTC', 'now'), datetime_convert('UTC', 'UTC', $t . " + 2 day")) > 0) {
|
||||
$update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if((strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $c . " + 3 day")) > 0)
|
||||
&& (strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 1 day")) > 0))
|
||||
$update = true;
|
||||
if (intval($contact['abook_pending']) || intval($contact['abook_archived']) || intval($contact['abook_ignored']) || intval($contact['abook_blocked'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// After that back off and put them on a morphine drip
|
||||
if ((! $update) && (! $force)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strcmp(datetime_convert('UTC','UTC', 'now'),datetime_convert('UTC','UTC', $t . " + 2 day")) > 0) {
|
||||
$update = true;
|
||||
}
|
||||
Run::Summon([ 'Onepoll',$contact['abook_id'] ]);
|
||||
if ($interval) {
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// migrate a few photos - eventually we'll migrate them all but without killing somebody's site
|
||||
// trying to do them all at once
|
||||
|
||||
if(intval($contact['abook_pending']) || intval($contact['abook_archived']) || intval($contact['abook_ignored']) || intval($contact['abook_blocked']))
|
||||
continue;
|
||||
migrate_xchan_photos(5);
|
||||
|
||||
if((! $update) && (! $force))
|
||||
continue;
|
||||
set_config('system', 'lastpoll', datetime_convert());
|
||||
|
||||
Run::Summon( [ 'Onepoll',$contact['abook_id'] ] );
|
||||
if($interval)
|
||||
@time_sleep_until(microtime(true) + (float) $interval);
|
||||
//All done - clear the lockfile
|
||||
@unlink($lockfile);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// migrate a few photos - eventually we'll migrate them all but without killing somebody's site
|
||||
// trying to do them all at once
|
||||
|
||||
migrate_xchan_photos(5);
|
||||
|
||||
set_config('system','lastpoll',datetime_convert());
|
||||
|
||||
//All done - clear the lockfile
|
||||
@unlink($lockfile);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,82 +1,94 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib as Zlib;
|
||||
|
||||
class Queue
|
||||
{
|
||||
|
||||
class Queue {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
if ($argc > 1) {
|
||||
$queue_id = $argv[1];
|
||||
} else {
|
||||
$queue_id = EMPTY_STR;
|
||||
}
|
||||
|
||||
if($argc > 1)
|
||||
$queue_id = $argv[1];
|
||||
else
|
||||
$queue_id = EMPTY_STR;
|
||||
logger('queue: start');
|
||||
|
||||
logger('queue: start');
|
||||
// delete all queue items more than 3 days old
|
||||
// but first mark these sites dead if we haven't heard from them in a month
|
||||
|
||||
// delete all queue items more than 3 days old
|
||||
// but first mark these sites dead if we haven't heard from them in a month
|
||||
$r = q(
|
||||
"select outq_posturl from outq where outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$site_url = '';
|
||||
$h = parse_url($rr['outq_posturl']);
|
||||
$desturl = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||
q(
|
||||
"update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
|
||||
dbesc($desturl),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 MONTH')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('3 DAY')
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$site_url = '';
|
||||
$h = parse_url($rr['outq_posturl']);
|
||||
$desturl = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
|
||||
dbesc($desturl),
|
||||
db_utcnow(), db_quoteinterval('1 MONTH')
|
||||
);
|
||||
}
|
||||
}
|
||||
$r = q(
|
||||
"DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(),
|
||||
db_quoteinterval('3 DAY')
|
||||
);
|
||||
|
||||
$r = q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
|
||||
db_utcnow(), db_quoteinterval('3 DAY')
|
||||
);
|
||||
if ($queue_id) {
|
||||
$r = q(
|
||||
"SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
|
||||
dbesc($queue_id)
|
||||
);
|
||||
} else {
|
||||
// For the first 12 hours we'll try to deliver every 15 minutes
|
||||
// After that, we'll only attempt delivery once per hour.
|
||||
// This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
|
||||
// so that we don't start off a thousand deliveries for a couple of dead hubs.
|
||||
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
|
||||
// Other drivers will have to do something different here and may need their own query.
|
||||
|
||||
if($queue_id) {
|
||||
$r = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
|
||||
dbesc($queue_id)
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
// For the first 12 hours we'll try to deliver every 15 minutes
|
||||
// After that, we'll only attempt delivery once per hour.
|
||||
// This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
|
||||
// so that we don't start off a thousand deliveries for a couple of dead hubs.
|
||||
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
|
||||
// Other drivers will have to do something different here and may need their own query.
|
||||
|
||||
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
|
||||
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
|
||||
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
|
||||
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
|
||||
// or twice a day.
|
||||
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
|
||||
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
|
||||
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
|
||||
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
|
||||
// or twice a day.
|
||||
|
||||
$sqlrandfunc = db_getfunc('rand');
|
||||
|
||||
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||
db_utcnow()
|
||||
);
|
||||
while ($r) {
|
||||
foreach($r as $rv) {
|
||||
Zlib\Queue::deliver($rv);
|
||||
}
|
||||
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||
db_utcnow()
|
||||
);
|
||||
}
|
||||
}
|
||||
if(! $r)
|
||||
return;
|
||||
$r = q(
|
||||
"SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||
db_utcnow()
|
||||
);
|
||||
while ($r) {
|
||||
foreach ($r as $rv) {
|
||||
Zlib\Queue::deliver($rv);
|
||||
}
|
||||
$r = q(
|
||||
"SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||
db_utcnow()
|
||||
);
|
||||
}
|
||||
}
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($r as $rv) {
|
||||
Zlib\Queue::deliver($rv);
|
||||
}
|
||||
}
|
||||
foreach ($r as $rv) {
|
||||
Zlib\Queue::deliver($rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,74 +2,76 @@
|
|||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
if (array_search( __file__ , get_included_files()) === 0) {
|
||||
if (array_search(__file__, get_included_files()) === 0) {
|
||||
require_once('include/cli_startup.php');
|
||||
array_shift($argv);
|
||||
$argc = count($argv);
|
||||
|
||||
require_once('include/cli_startup.php');
|
||||
array_shift($argv);
|
||||
$argc = count($argv);
|
||||
|
||||
if ($argc) {
|
||||
Run::Release($argc,$argv);
|
||||
}
|
||||
return;
|
||||
if ($argc) {
|
||||
Run::Release($argc, $argv);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Run {
|
||||
class Run
|
||||
{
|
||||
|
||||
// These processes should be ignored by addons which enforce timeouts (e.g. queueworker)
|
||||
// as it could result in corrupt data. Please add additional long running tasks to this list as they arise.
|
||||
// Ideally the queueworker should probably be provided an allow list rather than a deny list as it will be easier
|
||||
// to maintain. This was a quick hack to fix truncation of very large synced files when the queueworker addon is installed.
|
||||
// These processes should be ignored by addons which enforce timeouts (e.g. queueworker)
|
||||
// as it could result in corrupt data. Please add additional long running tasks to this list as they arise.
|
||||
// Ideally the queueworker should probably be provided an allow list rather than a deny list as it will be easier
|
||||
// to maintain. This was a quick hack to fix truncation of very large synced files when the queueworker addon is installed.
|
||||
|
||||
public static $long_running = [ 'Addon', 'Channel_purge', 'Checksites', 'Content_importer', 'Convo',
|
||||
'Cron', 'Cron_daily', 'Cron_weekly', 'Delxitems', 'Expire', 'File_importer', 'Importfile'
|
||||
];
|
||||
public static $long_running = [ 'Addon', 'Channel_purge', 'Checksites', 'Content_importer', 'Convo',
|
||||
'Cron', 'Cron_daily', 'Cron_weekly', 'Delxitems', 'Expire', 'File_importer', 'Importfile'
|
||||
];
|
||||
|
||||
static public function Summon($arr) {
|
||||
if (file_exists('maintenance_lock') || file_exists('cache/maintenance_lock')) {
|
||||
return;
|
||||
}
|
||||
public static function Summon($arr)
|
||||
{
|
||||
if (file_exists('maintenance_lock') || file_exists('cache/maintenance_lock')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hookinfo = [
|
||||
'argv' => $arr,
|
||||
'long_running' => self::$long_running
|
||||
];
|
||||
$hookinfo = [
|
||||
'argv' => $arr,
|
||||
'long_running' => self::$long_running
|
||||
];
|
||||
|
||||
call_hooks('daemon_summon', $hookinfo);
|
||||
call_hooks('daemon_summon', $hookinfo);
|
||||
|
||||
$arr = $hookinfo['argv'];
|
||||
$argc = count($arr);
|
||||
$arr = $hookinfo['argv'];
|
||||
$argc = count($arr);
|
||||
|
||||
if ((! is_array($arr) || ($argc < 1))) {
|
||||
logger("Summon handled by hook.", LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
if ((! is_array($arr) || ($argc < 1))) {
|
||||
logger("Summon handled by hook.", LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
proc_run('php','Zotlabs/Daemon/Run.php',$arr);
|
||||
}
|
||||
proc_run('php', 'Zotlabs/Daemon/Run.php', $arr);
|
||||
}
|
||||
|
||||
static public function Release($argc,$argv) {
|
||||
cli_startup();
|
||||
public static function Release($argc, $argv)
|
||||
{
|
||||
cli_startup();
|
||||
|
||||
$hookinfo = [
|
||||
'argv' => $argv,
|
||||
'long_running' => self::$long_running
|
||||
];
|
||||
$hookinfo = [
|
||||
'argv' => $argv,
|
||||
'long_running' => self::$long_running
|
||||
];
|
||||
|
||||
call_hooks('daemon_release', $hookinfo);
|
||||
call_hooks('daemon_release', $hookinfo);
|
||||
|
||||
$argv = $hookinfo['argv'];
|
||||
$argc = count($argv);
|
||||
$argv = $hookinfo['argv'];
|
||||
$argc = count($argv);
|
||||
|
||||
if ((! is_array($argv) || ($argc < 1))) {
|
||||
logger("Release handled by hook.", LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
if ((! is_array($argv) || ($argc < 1))) {
|
||||
logger("Release handled by hook.", LOGGER_DEBUG);
|
||||
return;
|
||||
}
|
||||
|
||||
logger('Run: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc,$argv);
|
||||
}
|
||||
logger('Run: release: ' . print_r($argv, true), LOGGER_ALL, LOG_DEBUG);
|
||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||
$cls::run($argc, $argv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,79 +1,85 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Thumbnail
|
||||
{
|
||||
|
||||
class Thumbnail {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
if (! ($argc == 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! ($argc == 2)) {
|
||||
return;
|
||||
}
|
||||
$c = q(
|
||||
"select * from attach where hash = '%s' ",
|
||||
dbesc($argv[1])
|
||||
);
|
||||
|
||||
$c = q("select * from attach where hash = '%s' ",
|
||||
dbesc($argv[1])
|
||||
);
|
||||
if (! $c) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $c) {
|
||||
return;
|
||||
}
|
||||
$attach = $c[0];
|
||||
|
||||
$attach = $c[0];
|
||||
$preview_style = intval(get_config('system', 'thumbnail_security', 0));
|
||||
$preview_width = intval(get_config('system', 'thumbnail_width', 300));
|
||||
$preview_height = intval(get_config('system', 'thumbnail_height', 300));
|
||||
|
||||
$preview_style = intval(get_config('system','thumbnail_security',0));
|
||||
$preview_width = intval(get_config('system','thumbnail_width',300));
|
||||
$preview_height = intval(get_config('system','thumbnail_height',300));
|
||||
$p = [
|
||||
'attach' => $attach,
|
||||
'preview_style' => $preview_style,
|
||||
'preview_width' => $preview_width,
|
||||
'preview_height' => $preview_height,
|
||||
'thumbnail' => null
|
||||
];
|
||||
|
||||
$p = [
|
||||
'attach' => $attach,
|
||||
'preview_style' => $preview_style,
|
||||
'preview_width' => $preview_width,
|
||||
'preview_height' => $preview_height,
|
||||
'thumbnail' => null
|
||||
];
|
||||
/**
|
||||
* @hooks thumbnail
|
||||
* * \e array \b attach
|
||||
* * \e int \b preview_style
|
||||
* * \e int \b preview_width
|
||||
* * \e int \b preview_height
|
||||
* * \e string \b thumbnail
|
||||
*/
|
||||
|
||||
/**
|
||||
* @hooks thumbnail
|
||||
* * \e array \b attach
|
||||
* * \e int \b preview_style
|
||||
* * \e int \b preview_width
|
||||
* * \e int \b preview_height
|
||||
* * \e string \b thumbnail
|
||||
*/
|
||||
call_hooks('thumbnail', $p);
|
||||
if ($p['thumbnail']) {
|
||||
return;
|
||||
}
|
||||
|
||||
call_hooks('thumbnail',$p);
|
||||
if ($p['thumbnail']) {
|
||||
return;
|
||||
}
|
||||
$default_controller = null;
|
||||
|
||||
$default_controller = null;
|
||||
|
||||
$files = glob('Zotlabs/Thumbs/*.php');
|
||||
if ($files) {
|
||||
foreach ($files as $f) {
|
||||
$clsname = '\\Zotlabs\\Thumbs\\' . ucfirst(basename($f,'.php'));
|
||||
if (class_exists($clsname)) {
|
||||
$x = new $clsname();
|
||||
if (method_exists($x,'Match')) {
|
||||
$matched = $x->Match($attach['filetype']);
|
||||
if ($matched) {
|
||||
$x->Thumb($attach,$preview_style,$preview_width,$preview_height);
|
||||
}
|
||||
}
|
||||
if (method_exists($x,'MatchDefault')) {
|
||||
$default_matched = $x->MatchDefault(substr($attach['filetype'],0,strpos($attach['filetype'],'/')));
|
||||
if ($default_matched) {
|
||||
$default_controller = $x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($default_controller)
|
||||
&& ((! file_exists(dbunescbin($attach['content']) . '.thumb'))
|
||||
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))) {
|
||||
$default_controller->Thumb($attach,$preview_style,$preview_width,$preview_height);
|
||||
}
|
||||
}
|
||||
$files = glob('Zotlabs/Thumbs/*.php');
|
||||
if ($files) {
|
||||
foreach ($files as $f) {
|
||||
$clsname = '\\Zotlabs\\Thumbs\\' . ucfirst(basename($f, '.php'));
|
||||
if (class_exists($clsname)) {
|
||||
$x = new $clsname();
|
||||
if (method_exists($x, 'Match')) {
|
||||
$matched = $x->Match($attach['filetype']);
|
||||
if ($matched) {
|
||||
$x->Thumb($attach, $preview_style, $preview_width, $preview_height);
|
||||
}
|
||||
}
|
||||
if (method_exists($x, 'MatchDefault')) {
|
||||
$default_matched = $x->MatchDefault(substr($attach['filetype'], 0, strpos($attach['filetype'], '/')));
|
||||
if ($default_matched) {
|
||||
$default_controller = $x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
($default_controller)
|
||||
&& ((! file_exists(dbunescbin($attach['content']) . '.thumb'))
|
||||
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))
|
||||
) {
|
||||
$default_controller->Thumb($attach, $preview_style, $preview_width, $preview_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,39 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
class Xchan_photo
|
||||
{
|
||||
|
||||
class Xchan_photo {
|
||||
public static function run($argc, $argv)
|
||||
{
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
if ($argc != 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($argc != 3) {
|
||||
return;
|
||||
}
|
||||
$url = hex2bin($argv[1]);
|
||||
$xchan = hex2bin($argv[2]);
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
$xchan = hex2bin($argv[2]);
|
||||
// Some photo sources hang after connect and aren't caught by curl timeout
|
||||
|
||||
// Some photo sources hang after connect and aren't caught by curl timeout
|
||||
set_time_limit(90);
|
||||
|
||||
set_time_limit(90);
|
||||
$photos = import_remote_xchan_photo($url, $xchan);
|
||||
if ($photos) {
|
||||
$r = q(
|
||||
"update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
|
||||
dbescdate(datetime_convert()),
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($xchan)
|
||||
);
|
||||
}
|
||||
|
||||
$photos = import_remote_xchan_photo($url,$xchan);
|
||||
if ($photos) {
|
||||
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
|
||||
dbescdate(datetime_convert()),
|
||||
dbesc($photos[0]),
|
||||
dbesc($photos[1]),
|
||||
dbesc($photos[2]),
|
||||
dbesc($photos[3]),
|
||||
dbesc($xchan)
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,118 +8,129 @@ use App;
|
|||
* @brief Hook class.
|
||||
*
|
||||
*/
|
||||
class Hook {
|
||||
class Hook
|
||||
{
|
||||
|
||||
static public function register($hook,$file,$function,$version = 1,$priority = 0) {
|
||||
if (is_array($function)) {
|
||||
$function = serialize($function);
|
||||
}
|
||||
public static function register($hook, $file, $function, $version = 1, $priority = 0)
|
||||
{
|
||||
if (is_array($function)) {
|
||||
$function = serialize($function);
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM hook WHERE hook = '%s' AND file = '%s' AND fn = '%s' and priority = %d and hook_version = %d LIMIT 1",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function),
|
||||
intval($priority),
|
||||
intval($version)
|
||||
);
|
||||
if ($r) {
|
||||
return true;
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * FROM hook WHERE hook = '%s' AND file = '%s' AND fn = '%s' and priority = %d and hook_version = %d LIMIT 1",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function),
|
||||
intval($priority),
|
||||
intval($version)
|
||||
);
|
||||
if ($r) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// To aid in upgrade and transition, remove old settings for any registered hooks that match in all respects except
|
||||
// for priority or hook_version
|
||||
// To aid in upgrade and transition, remove old settings for any registered hooks that match in all respects except
|
||||
// for priority or hook_version
|
||||
|
||||
$r = q("DELETE FROM hook where hook = '%s' and file = '%s' and fn = '%s'",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function)
|
||||
);
|
||||
$r = q(
|
||||
"DELETE FROM hook where hook = '%s' and file = '%s' and fn = '%s'",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function)
|
||||
);
|
||||
|
||||
$r = q("INSERT INTO hook (hook, file, fn, priority, hook_version) VALUES ( '%s', '%s', '%s', %d, %d )",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function),
|
||||
intval($priority),
|
||||
intval($version)
|
||||
);
|
||||
$r = q(
|
||||
"INSERT INTO hook (hook, file, fn, priority, hook_version) VALUES ( '%s', '%s', '%s', %d, %d )",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function),
|
||||
intval($priority),
|
||||
intval($version)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
static public function register_array($file,$arr) {
|
||||
if ($arr) {
|
||||
foreach ($arr as $k => $v) {
|
||||
self::register($k,$file,$v);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static function register_array($file, $arr)
|
||||
{
|
||||
if ($arr) {
|
||||
foreach ($arr as $k => $v) {
|
||||
self::register($k, $file, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public function unregister($hook,$file,$function,$version = 1,$priority = 0) {
|
||||
if (is_array($function)) {
|
||||
$function = serialize($function);
|
||||
}
|
||||
$r = q("DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND fn = '%s' and priority = %d and hook_version = %d",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function),
|
||||
intval($priority),
|
||||
intval($version)
|
||||
);
|
||||
public static function unregister($hook, $file, $function, $version = 1, $priority = 0)
|
||||
{
|
||||
if (is_array($function)) {
|
||||
$function = serialize($function);
|
||||
}
|
||||
$r = q(
|
||||
"DELETE FROM hook WHERE hook = '%s' AND file = '%s' AND fn = '%s' and priority = %d and hook_version = %d",
|
||||
dbesc($hook),
|
||||
dbesc($file),
|
||||
dbesc($function),
|
||||
intval($priority),
|
||||
intval($version)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister all hooks with this file component.
|
||||
*
|
||||
* Useful for addon upgrades where you want to clean out old interfaces.
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
/**
|
||||
* @brief Unregister all hooks with this file component.
|
||||
*
|
||||
* Useful for addon upgrades where you want to clean out old interfaces.
|
||||
*
|
||||
* @param string $file
|
||||
*/
|
||||
|
||||
static public function unregister_by_file($file) {
|
||||
$r = q("DELETE FROM hook WHERE file = '%s' ",
|
||||
dbesc($file)
|
||||
);
|
||||
public static function unregister_by_file($file)
|
||||
{
|
||||
$r = q(
|
||||
"DELETE FROM hook WHERE file = '%s' ",
|
||||
dbesc($file)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a hook into a page request.
|
||||
*
|
||||
* Insert a short-lived hook into the running page request.
|
||||
* Hooks are normally persistent so that they can be called
|
||||
* across asynchronous processes such as delivery and poll
|
||||
* processes.
|
||||
*
|
||||
* insert_hook lets you attach a hook callback immediately
|
||||
* which will not persist beyond the life of this page request
|
||||
* or the current process.
|
||||
*
|
||||
* @param string $hook
|
||||
* name of hook to attach callback
|
||||
* @param string $fn
|
||||
* function name of callback handler
|
||||
* @param int $version
|
||||
* hook interface version, 0 uses two callback params, 1 uses one callback param
|
||||
* @param int $priority
|
||||
* currently not implemented in this function, would require the hook array to be resorted
|
||||
*/
|
||||
static public function insert($hook, $fn, $version = 0, $priority = 0) {
|
||||
if (is_array($fn)) {
|
||||
$fn = serialize($fn);
|
||||
}
|
||||
/**
|
||||
* @brief Inserts a hook into a page request.
|
||||
*
|
||||
* Insert a short-lived hook into the running page request.
|
||||
* Hooks are normally persistent so that they can be called
|
||||
* across asynchronous processes such as delivery and poll
|
||||
* processes.
|
||||
*
|
||||
* insert_hook lets you attach a hook callback immediately
|
||||
* which will not persist beyond the life of this page request
|
||||
* or the current process.
|
||||
*
|
||||
* @param string $hook
|
||||
* name of hook to attach callback
|
||||
* @param string $fn
|
||||
* function name of callback handler
|
||||
* @param int $version
|
||||
* hook interface version, 0 uses two callback params, 1 uses one callback param
|
||||
* @param int $priority
|
||||
* currently not implemented in this function, would require the hook array to be resorted
|
||||
*/
|
||||
public static function insert($hook, $fn, $version = 0, $priority = 0)
|
||||
{
|
||||
if (is_array($fn)) {
|
||||
$fn = serialize($fn);
|
||||
}
|
||||
|
||||
if (! is_array(App::$hooks)) {
|
||||
App::$hooks = [];
|
||||
}
|
||||
if (! is_array(App::$hooks)) {
|
||||
App::$hooks = [];
|
||||
}
|
||||
|
||||
if (! array_key_exists($hook, App::$hooks)) {
|
||||
App::$hooks[$hook] = [];
|
||||
}
|
||||
if (! array_key_exists($hook, App::$hooks)) {
|
||||
App::$hooks[$hook] = [];
|
||||
}
|
||||
|
||||
App::$hooks[$hook][] = [ '', $fn, $priority, $version ];
|
||||
}
|
||||
App::$hooks[$hook][] = [ '', $fn, $priority, $version ];
|
||||
}
|
||||
}
|
|
@ -2,47 +2,51 @@
|
|||
|
||||
namespace Zotlabs\Extend;
|
||||
|
||||
class Route
|
||||
{
|
||||
|
||||
class Route {
|
||||
public static function register($file, $modname)
|
||||
{
|
||||
$rt = self::get();
|
||||
$rt[] = [$file, $modname];
|
||||
self::set($rt);
|
||||
}
|
||||
|
||||
static function register($file,$modname) {
|
||||
$rt = self::get();
|
||||
$rt[] = [ $file, $modname ];
|
||||
self::set($rt);
|
||||
}
|
||||
public static function unregister($file, $modname)
|
||||
{
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file && $r[1] !== $modname) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
|
||||
static function unregister($file,$modname) {
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file && $r[1] !== $modname) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
public static function unregister_by_file($file)
|
||||
{
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
|
||||
static function unregister_by_file($file) {
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
public static function get()
|
||||
{
|
||||
return get_config('system', 'routes', []);
|
||||
}
|
||||
|
||||
static function get() {
|
||||
return get_config('system','routes',[]);
|
||||
}
|
||||
|
||||
static function set($r) {
|
||||
return set_config('system','routes',$r);
|
||||
}
|
||||
public static function set($r)
|
||||
{
|
||||
return set_config('system', 'routes', $r);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,46 +2,51 @@
|
|||
|
||||
namespace Zotlabs\Extend;
|
||||
|
||||
class Widget
|
||||
{
|
||||
|
||||
class Widget {
|
||||
public static function register($file, $widget)
|
||||
{
|
||||
$rt = self::get();
|
||||
$rt[] = [$file, $widget];
|
||||
self::set($rt);
|
||||
}
|
||||
|
||||
static function register($file,$widget) {
|
||||
$rt = self::get();
|
||||
$rt[] = [ $file, $widget ];
|
||||
self::set($rt);
|
||||
}
|
||||
public static function unregister($file, $widget)
|
||||
{
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file && $r[1] !== $widget) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
|
||||
static function unregister($file,$widget) {
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file && $r[1] !== $widget) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
public static function unregister_by_file($file)
|
||||
{
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
|
||||
static function unregister_by_file($file) {
|
||||
$rt = self::get();
|
||||
if ($rt) {
|
||||
$n = [];
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] !== $file) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
self::set($n);
|
||||
}
|
||||
}
|
||||
public static function get()
|
||||
{
|
||||
return get_config('system', 'widgets', []);
|
||||
}
|
||||
|
||||
static function get() {
|
||||
return get_config('system','widgets',[]);
|
||||
}
|
||||
|
||||
static function set($r) {
|
||||
return set_config('system','widgets',$r);
|
||||
}
|
||||
public static function set($r)
|
||||
{
|
||||
return set_config('system', 'widgets', $r);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,37 +8,38 @@ use OAuth2\Storage\Memory;
|
|||
use OAuth2\GrantType\ClientCredentials;
|
||||
use OAuth2\OpenID\GrantType\AuthorizationCode;
|
||||
|
||||
class OAuth2Server extends Server {
|
||||
class OAuth2Server extends Server
|
||||
{
|
||||
|
||||
public function __construct(OAuth2Storage $storage, $config = null) {
|
||||
public function __construct(OAuth2Storage $storage, $config = null)
|
||||
{
|
||||
|
||||
if (! is_array($config)) {
|
||||
$config = [
|
||||
// 'use_openid_connect' => true,
|
||||
'issuer' => System::get_site_name(),
|
||||
// 'use_jwt_access_tokens' => true,
|
||||
// 'enforce_state' => false
|
||||
];
|
||||
}
|
||||
if (! is_array($config)) {
|
||||
$config = [
|
||||
// 'use_openid_connect' => true,
|
||||
'issuer' => System::get_site_name(),
|
||||
// 'use_jwt_access_tokens' => true,
|
||||
// 'enforce_state' => false
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($storage, $config);
|
||||
parent::__construct($storage, $config);
|
||||
|
||||
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
|
||||
$this->addGrantType(new ClientCredentials($storage));
|
||||
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
|
||||
$this->addGrantType(new ClientCredentials($storage));
|
||||
|
||||
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
|
||||
// Need to use OpenID\GrantType to return id_token
|
||||
// (see:https://github.com/bshaffer/oauth2-server-php/issues/443)
|
||||
$this->addGrantType(new AuthorizationCode($storage));
|
||||
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
|
||||
// Need to use OpenID\GrantType to return id_token
|
||||
// (see:https://github.com/bshaffer/oauth2-server-php/issues/443)
|
||||
$this->addGrantType(new AuthorizationCode($storage));
|
||||
|
||||
$keyStorage = new Memory( [
|
||||
'keys' => [
|
||||
'public_key' => get_config('system', 'pubkey'),
|
||||
'private_key' => get_config('system', 'prvkey')
|
||||
]
|
||||
]);
|
||||
|
||||
$this->addStorage($keyStorage, 'public_key');
|
||||
}
|
||||
$keyStorage = new Memory([
|
||||
'keys' => [
|
||||
'public_key' => get_config('system', 'pubkey'),
|
||||
'private_key' => get_config('system', 'prvkey')
|
||||
]
|
||||
]);
|
||||
|
||||
$this->addStorage($keyStorage, 'public_key');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace Zotlabs\Identity;
|
||||
|
||||
use OAuth2\Storage\Pdo;
|
||||
|
||||
class OAuth2Storage extends \OAuth2\Storage\Pdo {
|
||||
class OAuth2Storage extends Pdo
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
|
@ -38,9 +40,8 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
|
|||
protected function checkPassword($user, $password)
|
||||
{
|
||||
|
||||
$x = account_verify_password($user,$password);
|
||||
return((array_key_exists('channel',$x) && ! empty($x['channel'])) ? true : false);
|
||||
|
||||
$x = account_verify_password($user, $password);
|
||||
return((array_key_exists('channel', $x) && ! empty($x['channel'])) ? true : false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,76 +51,79 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
|
|||
public function getUser($username)
|
||||
{
|
||||
|
||||
$x = channelx_by_n($username);
|
||||
if (! $x) {
|
||||
return false;
|
||||
}
|
||||
$x = channelx_by_n($username);
|
||||
if (! $x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$a = q("select * from account where account_id = %d",
|
||||
intval($x['channel_account_id'])
|
||||
);
|
||||
$a = q(
|
||||
"select * from account where account_id = %d",
|
||||
intval($x['channel_account_id'])
|
||||
);
|
||||
|
||||
$n = explode(' ', $x['channel_name']);
|
||||
$n = explode(' ', $x['channel_name']);
|
||||
|
||||
return( [
|
||||
'webfinger' => channel_reddress($x),
|
||||
'portable_id' => $x['channel_hash'],
|
||||
'email' => $a[0]['account_email'],
|
||||
'username' => $x['channel_address'],
|
||||
'user_id' => $x['channel_id'],
|
||||
'name' => $x['channel_name'],
|
||||
'firstName' => ((count($n) > 1) ? $n[1] : $n[0]),
|
||||
'lastName' => ((count($n) > 2) ? $n[count($n) - 1] : ''),
|
||||
'picture' => $x['xchan_photo_l']
|
||||
] );
|
||||
return( [
|
||||
'webfinger' => channel_reddress($x),
|
||||
'portable_id' => $x['channel_hash'],
|
||||
'email' => $a[0]['account_email'],
|
||||
'username' => $x['channel_address'],
|
||||
'user_id' => $x['channel_id'],
|
||||
'name' => $x['channel_name'],
|
||||
'firstName' => ((count($n) > 1) ? $n[1] : $n[0]),
|
||||
'lastName' => ((count($n) > 2) ? $n[count($n) - 1] : ''),
|
||||
'picture' => $x['xchan_photo_l']
|
||||
] );
|
||||
}
|
||||
|
||||
public function scopeExists($scope) {
|
||||
public function scopeExists($scope)
|
||||
{
|
||||
// Report that the scope is valid even if it's not.
|
||||
// We will only return a very small subset no matter what.
|
||||
// @TODO: Truly validate the scope
|
||||
// see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and
|
||||
// vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/Pdo.php
|
||||
// for more info.
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDefaultScope($client_id=null) {
|
||||
public function getDefaultScope($client_id = null)
|
||||
{
|
||||
// Do not REQUIRE a scope
|
||||
// see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and
|
||||
// for more info.
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getUserClaims ($user_id, $claims) {
|
||||
// Populate the CLAIMS requested (if any).
|
||||
// @TODO: create a more reasonable/comprehensive list.
|
||||
// @TODO: present claims on the AUTHORIZATION screen
|
||||
public function getUserClaims($user_id, $claims)
|
||||
{
|
||||
// Populate the CLAIMS requested (if any).
|
||||
// @TODO: create a more reasonable/comprehensive list.
|
||||
// @TODO: present claims on the AUTHORIZATION screen
|
||||
|
||||
$userClaims = [];
|
||||
$claims = explode (' ', trim($claims));
|
||||
$claims = explode(' ', trim($claims));
|
||||
$validclaims = [ "name", "preferred_username", "webfinger", "portable_id", "email", "picture", "firstName", "lastName" ];
|
||||
$claimsmap = [
|
||||
"webfinger" => 'webfinger',
|
||||
"portable_id" => 'portable_id',
|
||||
"name" => 'name',
|
||||
"email" => 'email',
|
||||
"preferred_username" => 'username',
|
||||
"picture" => 'picture',
|
||||
"given_name" => 'firstName',
|
||||
"family_name" => 'lastName'
|
||||
];
|
||||
"webfinger" => 'webfinger',
|
||||
"portable_id" => 'portable_id',
|
||||
"name" => 'name',
|
||||
"email" => 'email',
|
||||
"preferred_username" => 'username',
|
||||
"picture" => 'picture',
|
||||
"given_name" => 'firstName',
|
||||
"family_name" => 'lastName'
|
||||
];
|
||||
$userinfo = $this->getUser($user_id);
|
||||
foreach ($validclaims as $validclaim) {
|
||||
if (in_array($validclaim,$claims)) {
|
||||
$claimkey = $claimsmap[$validclaim];
|
||||
$userClaims[$validclaim] = $userinfo[$claimkey];
|
||||
}
|
||||
else {
|
||||
$userClaims[$validclaim] = $validclaim;
|
||||
if (in_array($validclaim, $claims)) {
|
||||
$claimkey = $claimsmap[$validclaim];
|
||||
$userClaims[$validclaim] = $userinfo[$claimkey];
|
||||
} else {
|
||||
$userClaims[$validclaim] = $validclaim;
|
||||
}
|
||||
}
|
||||
$userClaims["sub"]=$user_id;
|
||||
$userClaims["sub"] = $user_id;
|
||||
return $userClaims;
|
||||
}
|
||||
|
||||
|
@ -163,5 +167,4 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
|
|||
// if grant_types are not defined, then none are restricted
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Import;
|
||||
|
||||
use App;
|
||||
|
@ -11,353 +12,354 @@ use Zotlabs\Access\PermissionRoles;
|
|||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Run;
|
||||
|
||||
class Friendica
|
||||
{
|
||||
|
||||
class Friendica {
|
||||
private $data;
|
||||
private $settings;
|
||||
|
||||
private $data;
|
||||
private $settings;
|
||||
private $default_group = null;
|
||||
|
||||
private $default_group = null;
|
||||
|
||||
private $groups = null;
|
||||
private $members = null;
|
||||
private $contacts = null;
|
||||
|
||||
|
||||
function __construct($data, $settings) {
|
||||
$this->data = $data;
|
||||
$this->settings = $settings;
|
||||
$this->extract();
|
||||
}
|
||||
|
||||
function extract() {
|
||||
|
||||
// channel stuff
|
||||
|
||||
$channel = [
|
||||
'channel_name' => escape_tags($this->data['user']['username']),
|
||||
'channel_address' => escape_tags($this->data['user']['nickname']),
|
||||
'channel_guid' => escape_tags($this->data['user']['guid']),
|
||||
'channel_guid_sig' => Libzot::sign($this->data['user']['guid'],$this->data['user']['prvkey']),
|
||||
'channel_hash' => Libzot::make_xchan_hash($this->data['user']['guid'],$this->data['user']['pubkey']),
|
||||
'channel_prvkey' => $this->data['user']['prvkey'],
|
||||
'channel_pubkey' => $this->data['user']['pubkey'],
|
||||
'channel_pageflags' => PAGE_NORMAL,
|
||||
'channel_expire_days' => intval($this->data['user']['expire']),
|
||||
'channel_timezone' => escape_tags($this->data['user']['timezone']),
|
||||
'channel_location' => escape_tags($this->data['user']['default-location'])
|
||||
];
|
||||
|
||||
$account_id = $this->settings['account_id'];
|
||||
|
||||
$max_identities = account_service_class_fetch($account_id,'total_identities');
|
||||
|
||||
if ($max_identities !== false) {
|
||||
$r = q("select channel_id from channel where channel_account_id = %d and channel_removed = 0 ",
|
||||
intval($account_id)
|
||||
);
|
||||
if ($r && count($r) > $max_identities) {
|
||||
notice( sprintf( t('Your service plan only allows %d channels.'), $max_identities) . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// save channel or die
|
||||
|
||||
|
||||
$channel = import_channel($channel,$this->settings['account_id'],$this->settings['sieze'],$this->settings['newname']);
|
||||
if (! $channel) {
|
||||
logger('no channel');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// figure out channel permission roles
|
||||
|
||||
$permissions_role = 'social';
|
||||
|
||||
$pageflags = ((isset($this->data['user']['page-flags'])) ? intval($this->data['user']['page-flags']) : 0);
|
||||
|
||||
if ($pageflags === 2) {
|
||||
$permissions_role = 'forum';
|
||||
}
|
||||
if ($pageflags === 5) {
|
||||
$permissions_role = 'forum_restricted';
|
||||
}
|
||||
|
||||
if ($pageflags === 0 && isset($this->data['user']['allow_gid']) && $this->data['user']['allow_gid']) {
|
||||
$permissions_role = 'social_restricted';
|
||||
}
|
||||
|
||||
// Friendica folks only have PERMS_AUTHED and "just me"
|
||||
|
||||
$post_comments = (($pageflags === 1) ? 0 : PERMS_AUTHED);
|
||||
PermissionLimits::Set(local_channel(),'post_comments',$post_comments);
|
||||
|
||||
PConfig::Set($channel['channel_id'],'system','permissions_role',$permissions_role);
|
||||
PConfig::Set($channel['channel_id'],'system','use_browser_location', (string) intval($this->data['user']['allow_location']));
|
||||
|
||||
// find the self contact
|
||||
|
||||
$self_contact = null;
|
||||
|
||||
if (isset($this->data['contact']) && is_array($this->data['contact'])) {
|
||||
foreach ($this->data['contact'] as $contact) {
|
||||
if (isset($contact['self']) && intval($contact['self'])) {
|
||||
$self_contact = $contact;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_array($self_contact)) {
|
||||
logger('self contact not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a verified hub location pointing to this site.
|
||||
|
||||
$r = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $channel['channel_guid'],
|
||||
'hubloc_guid_sig' => $channel['channel_guid_sig'],
|
||||
'hubloc_id_url' => channel_url($channel),
|
||||
'hubloc_hash' => $channel['channel_hash'],
|
||||
'hubloc_addr' => channel_reddress($channel),
|
||||
'hubloc_primary' => 1,
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => Libzot::sign(z_root(),$channel['channel_prvkey']),
|
||||
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(),get_config('system','pubkey')),
|
||||
'hubloc_host' => App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/zot',
|
||||
'hubloc_sitekey' => get_config('system','pubkey'),
|
||||
'hubloc_network' => 'nomad',
|
||||
'hubloc_updated' => datetime_convert()
|
||||
]
|
||||
);
|
||||
if (! $r) {
|
||||
logger('Unable to store hub location');
|
||||
}
|
||||
|
||||
|
||||
if ($self_contact['avatar']) {
|
||||
$p = z_fetch_url($self_contact['avatar'],true);
|
||||
if ($p['success']) {
|
||||
$h = explode("\n",$p['header']);
|
||||
foreach ($h as $l) {
|
||||
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
|
||||
$hdrs[strtolower($k)] = $v;
|
||||
}
|
||||
if (array_key_exists('content-type', $hdrs)) {
|
||||
$phototype = $hdrs['content-type'];
|
||||
}
|
||||
else {
|
||||
$phototype = 'image/jpeg';
|
||||
}
|
||||
|
||||
import_channel_photo($p['body'],$phototype,$account_id,$channel['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
$newuid = $channel['channel_id'];
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $channel['channel_hash'],
|
||||
'xchan_guid' => $channel['channel_guid'],
|
||||
'xchan_guid_sig' => $channel['channel_guid_sig'],
|
||||
'xchan_pubkey' => $channel['channel_pubkey'],
|
||||
'xchan_photo_mimetype' => (($photo_type) ? $photo_type : 'image/png'),
|
||||
'xchan_photo_l' => z_root() . "/photo/profile/l/{$newuid}",
|
||||
'xchan_photo_m' => z_root() . "/photo/profile/m/{$newuid}",
|
||||
'xchan_photo_s' => z_root() . "/photo/profile/s/{$newuid}",
|
||||
'xchan_addr' => channel_reddress($channel),
|
||||
'xchan_url' => channel_url($channel),
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
|
||||
'xchan_name' => $channel['channel_name'],
|
||||
'xchan_network' => 'nomad',
|
||||
'xchan_updated' => datetime_convert(),
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert(),
|
||||
'xchan_system' => 0
|
||||
]
|
||||
);
|
||||
|
||||
$r = profile_store_lowlevel(
|
||||
[
|
||||
'aid' => intval($channel['channel_account_id']),
|
||||
'uid' => intval($newuid),
|
||||
'profile_guid' => new_uuid(),
|
||||
'profile_name' => t('Default Profile'),
|
||||
'is_default' => 1,
|
||||
'publish' => ((isset($this->data['profile']['publish'])) ? $this->data['profile']['publish'] : 1),
|
||||
'fullname' => $channel['channel_name'],
|
||||
'photo' => z_root() . "/photo/profile/l/{$newuid}",
|
||||
'thumb' => z_root() . "/photo/profile/m/{$newuid}",
|
||||
'homepage' => ((isset($this->data['profile']['homepage'])) ? $this->data['profile']['homepage'] : EMPTY_STR),
|
||||
]
|
||||
);
|
||||
|
||||
if($role_permissions) {
|
||||
$myperms = ((array_key_exists('perms_connect',$role_permissions)) ? $role_permissions['perms_connect'] : [] );
|
||||
}
|
||||
else {
|
||||
$x = PermissionRoles::role_perms('social');
|
||||
$myperms = $x['perms_connect'];
|
||||
}
|
||||
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
'abook_account' => intval($channel['channel_account_id']),
|
||||
'abook_channel' => intval($newuid),
|
||||
'abook_xchan' => $channel['channel_hash'],
|
||||
'abook_closeness' => 0,
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_self' => 1
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$x = Permissions::serialise(Permissions::FilledPerms($myperms));
|
||||
set_abconfig($newuid,$channel['channel_hash'],'system','my_perms',$x);
|
||||
|
||||
if(intval($channel['channel_account_id'])) {
|
||||
|
||||
// Save our permissions role so we can perhaps call it up and modify it later.
|
||||
|
||||
if($role_permissions) {
|
||||
if(array_key_exists('online',$role_permissions))
|
||||
set_pconfig($newuid,'system','hide_presence',1-intval($role_permissions['online']));
|
||||
if(array_key_exists('perms_auto',$role_permissions)) {
|
||||
$autoperms = intval($role_permissions['perms_auto']);
|
||||
set_pconfig($newuid,'system','autoperms',$autoperms);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a group with yourself as a member. This allows somebody to use it
|
||||
// right away as a default group for new contacts.
|
||||
|
||||
AccessList::add($newuid, t('Friends'));
|
||||
AccessList::member_add($newuid,t('Friends'),$ret['channel']['channel_hash']);
|
||||
|
||||
// if our role_permissions indicate that we're using a default collection ACL, add it.
|
||||
|
||||
if(is_array($role_permissions) && $role_permissions['default_collection']) {
|
||||
$r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
|
||||
intval($newuid),
|
||||
dbesc( t('Friends') )
|
||||
);
|
||||
if($r) {
|
||||
q("update channel set channel_default_group = '%s', channel_allow_gid = '%s' where channel_id = %d",
|
||||
dbesc($r[0]['hash']),
|
||||
dbesc('<' . $r[0]['hash'] . '>'),
|
||||
intval($newuid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set_pconfig($channel['channel_id'],'system','photo_path', '%Y/%Y-%m');
|
||||
set_pconfig($channel['channel_id'],'system','attach_path','%Y/%Y-%m');
|
||||
|
||||
|
||||
// auto-follow any of the hub's pre-configured channel choices.
|
||||
// Only do this if it's the first channel for this account;
|
||||
// otherwise it could get annoying. Don't make this list too big
|
||||
// or it will impact registration time.
|
||||
|
||||
$accts = get_config('system','auto_follow');
|
||||
if(($accts) && (! $total_identities)) {
|
||||
if(! is_array($accts))
|
||||
$accts = array($accts);
|
||||
|
||||
foreach($accts as $acct) {
|
||||
if(trim($acct)) {
|
||||
$f = connect_and_sync($channel,trim($acct));
|
||||
if($f['success']) {
|
||||
|
||||
$can_view_stream = their_perms_contains($channel['channel_id'],$f['abook']['abook_xchan'],'view_stream');
|
||||
|
||||
// If we can view their stream, pull in some posts
|
||||
|
||||
if(($can_view_stream) || ($f['abook']['xchan_network'] === 'rss')) {
|
||||
Run::Summon([ 'Onepoll',$f['abook']['abook_id'] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
call_hooks('create_identity', $newuid);
|
||||
}
|
||||
|
||||
$this->groups = ((isset($this->data['group'])) ? $this->data['group'] : null);
|
||||
$this->members = ((isset($this->data['group_member'])) ? $this->data['group_member'] : null);
|
||||
|
||||
// import contacts
|
||||
|
||||
if (isset($this->data['contact']) && is_array($this->data['contact'])) {
|
||||
foreach ($this->data['contact'] as $contact) {
|
||||
if (isset($contact['self']) && intval($contact['self'])) {
|
||||
continue;
|
||||
}
|
||||
logger('connecting: ' . $contact['url'], LOGGER_DEBUG);
|
||||
$result = Connect::connect($channel,(($contact['addr']) ? $contact['addr'] : $contact['url']));
|
||||
if ($result['success'] && isset($result['abook'])) {
|
||||
$contact['xchan_hash'] = $result['abook']['abook_xchan'];
|
||||
$this->contacts[] = $contact;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import pconfig
|
||||
// it is unlikely we can make use of these unless we recongise them.
|
||||
|
||||
if (isset($this->data['pconfig']) && is_array($this->data['pconfig'])) {
|
||||
foreach ($this->data['pconfig'] as $pc) {
|
||||
$entry = [
|
||||
'cat' => escape_tags(str_replace('.','__',$pc['cat'])),
|
||||
'k' => escape_tags(str_replace('.','__',$pc['k'])),
|
||||
'v' => ((preg_match('|^a:[0-9]+:{.*}$|s', $pc['v'])) ? serialise(unserialize($pc['v'])) : $pc['v']),
|
||||
];
|
||||
PConfig::Set($channel['channel_id'],$entry['cat'],$entry['k'],$entry['v']);
|
||||
}
|
||||
}
|
||||
|
||||
// The default 'Friends' group is already created and possibly populated.
|
||||
// So some of the following code is redundant in that regard.
|
||||
// Mostly this is used to create and populate any other groups.
|
||||
|
||||
if ($this->groups) {
|
||||
foreach ($this->groups as $group) {
|
||||
if (! intval($group['deleted'])) {
|
||||
AccessList::add($channel['channel_id'], $group['name'], intval($group['visible']));
|
||||
if ($this->members) {
|
||||
foreach ($this->members as $member) {
|
||||
if (intval($member['gid']) === intval(AccessList::byname($channel['channel_id'],$group['name']))) {
|
||||
$contact_id = $member['contact-id'];
|
||||
if ($this->contacts) {
|
||||
foreach ($this->contacts as $contact) {
|
||||
if (intval($contact['id']) === intval($contact_id)) {
|
||||
AccessList::member_add($channel['channel_id'],$group['name'],$contact['xchan_hash']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
change_channel($channel['channel_id']);
|
||||
notice( t('Import complete.') . EOL);
|
||||
|
||||
goaway(z_root() . '/stream' );
|
||||
|
||||
}
|
||||
private $groups = null;
|
||||
private $members = null;
|
||||
private $contacts = null;
|
||||
|
||||
|
||||
public function __construct($data, $settings)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->settings = $settings;
|
||||
$this->extract();
|
||||
}
|
||||
|
||||
public function extract()
|
||||
{
|
||||
|
||||
// channel stuff
|
||||
|
||||
$channel = [
|
||||
'channel_name' => escape_tags($this->data['user']['username']),
|
||||
'channel_address' => escape_tags($this->data['user']['nickname']),
|
||||
'channel_guid' => escape_tags($this->data['user']['guid']),
|
||||
'channel_guid_sig' => Libzot::sign($this->data['user']['guid'], $this->data['user']['prvkey']),
|
||||
'channel_hash' => Libzot::make_xchan_hash($this->data['user']['guid'], $this->data['user']['pubkey']),
|
||||
'channel_prvkey' => $this->data['user']['prvkey'],
|
||||
'channel_pubkey' => $this->data['user']['pubkey'],
|
||||
'channel_pageflags' => PAGE_NORMAL,
|
||||
'channel_expire_days' => intval($this->data['user']['expire']),
|
||||
'channel_timezone' => escape_tags($this->data['user']['timezone']),
|
||||
'channel_location' => escape_tags($this->data['user']['default-location'])
|
||||
];
|
||||
|
||||
$account_id = $this->settings['account_id'];
|
||||
|
||||
$max_identities = account_service_class_fetch($account_id, 'total_identities');
|
||||
|
||||
if ($max_identities !== false) {
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_account_id = %d and channel_removed = 0 ",
|
||||
intval($account_id)
|
||||
);
|
||||
if ($r && count($r) > $max_identities) {
|
||||
notice(sprintf(t('Your service plan only allows %d channels.'), $max_identities) . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// save channel or die
|
||||
|
||||
|
||||
$channel = import_channel($channel, $this->settings['account_id'], $this->settings['sieze'], $this->settings['newname']);
|
||||
if (!$channel) {
|
||||
logger('no channel');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// figure out channel permission roles
|
||||
|
||||
$permissions_role = 'social';
|
||||
|
||||
$pageflags = ((isset($this->data['user']['page-flags'])) ? intval($this->data['user']['page-flags']) : 0);
|
||||
|
||||
if ($pageflags === 2) {
|
||||
$permissions_role = 'forum';
|
||||
}
|
||||
if ($pageflags === 5) {
|
||||
$permissions_role = 'forum_restricted';
|
||||
}
|
||||
|
||||
if ($pageflags === 0 && isset($this->data['user']['allow_gid']) && $this->data['user']['allow_gid']) {
|
||||
$permissions_role = 'social_restricted';
|
||||
}
|
||||
|
||||
// Friendica folks only have PERMS_AUTHED and "just me"
|
||||
|
||||
$post_comments = (($pageflags === 1) ? 0 : PERMS_AUTHED);
|
||||
PermissionLimits::Set(local_channel(), 'post_comments', $post_comments);
|
||||
|
||||
PConfig::Set($channel['channel_id'], 'system', 'permissions_role', $permissions_role);
|
||||
PConfig::Set($channel['channel_id'], 'system', 'use_browser_location', (string)intval($this->data['user']['allow_location']));
|
||||
|
||||
// find the self contact
|
||||
|
||||
$self_contact = null;
|
||||
|
||||
if (isset($this->data['contact']) && is_array($this->data['contact'])) {
|
||||
foreach ($this->data['contact'] as $contact) {
|
||||
if (isset($contact['self']) && intval($contact['self'])) {
|
||||
$self_contact = $contact;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($self_contact)) {
|
||||
logger('self contact not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a verified hub location pointing to this site.
|
||||
|
||||
$r = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $channel['channel_guid'],
|
||||
'hubloc_guid_sig' => $channel['channel_guid_sig'],
|
||||
'hubloc_id_url' => channel_url($channel),
|
||||
'hubloc_hash' => $channel['channel_hash'],
|
||||
'hubloc_addr' => channel_reddress($channel),
|
||||
'hubloc_primary' => 1,
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => Libzot::sign(z_root(), $channel['channel_prvkey']),
|
||||
'hubloc_site_id' => Libzot::make_xchan_hash(z_root(), get_config('system', 'pubkey')),
|
||||
'hubloc_host' => App::get_hostname(),
|
||||
'hubloc_callback' => z_root() . '/zot',
|
||||
'hubloc_sitekey' => get_config('system', 'pubkey'),
|
||||
'hubloc_network' => 'nomad',
|
||||
'hubloc_updated' => datetime_convert()
|
||||
]
|
||||
);
|
||||
if (!$r) {
|
||||
logger('Unable to store hub location');
|
||||
}
|
||||
|
||||
|
||||
if ($self_contact['avatar']) {
|
||||
$p = z_fetch_url($self_contact['avatar'], true);
|
||||
if ($p['success']) {
|
||||
$h = explode("\n", $p['header']);
|
||||
foreach ($h as $l) {
|
||||
list($k, $v) = array_map("trim", explode(":", trim($l), 2));
|
||||
$hdrs[strtolower($k)] = $v;
|
||||
}
|
||||
if (array_key_exists('content-type', $hdrs)) {
|
||||
$phototype = $hdrs['content-type'];
|
||||
} else {
|
||||
$phototype = 'image/jpeg';
|
||||
}
|
||||
|
||||
import_channel_photo($p['body'], $phototype, $account_id, $channel['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
$newuid = $channel['channel_id'];
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $channel['channel_hash'],
|
||||
'xchan_guid' => $channel['channel_guid'],
|
||||
'xchan_guid_sig' => $channel['channel_guid_sig'],
|
||||
'xchan_pubkey' => $channel['channel_pubkey'],
|
||||
'xchan_photo_mimetype' => (($photo_type) ? $photo_type : 'image/png'),
|
||||
'xchan_photo_l' => z_root() . "/photo/profile/l/{$newuid}",
|
||||
'xchan_photo_m' => z_root() . "/photo/profile/m/{$newuid}",
|
||||
'xchan_photo_s' => z_root() . "/photo/profile/s/{$newuid}",
|
||||
'xchan_addr' => channel_reddress($channel),
|
||||
'xchan_url' => channel_url($channel),
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_connurl' => z_root() . '/poco/' . $channel['channel_address'],
|
||||
'xchan_name' => $channel['channel_name'],
|
||||
'xchan_network' => 'nomad',
|
||||
'xchan_updated' => datetime_convert(),
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert(),
|
||||
'xchan_system' => 0
|
||||
]
|
||||
);
|
||||
|
||||
$r = profile_store_lowlevel(
|
||||
[
|
||||
'aid' => intval($channel['channel_account_id']),
|
||||
'uid' => intval($newuid),
|
||||
'profile_guid' => new_uuid(),
|
||||
'profile_name' => t('Default Profile'),
|
||||
'is_default' => 1,
|
||||
'publish' => ((isset($this->data['profile']['publish'])) ? $this->data['profile']['publish'] : 1),
|
||||
'fullname' => $channel['channel_name'],
|
||||
'photo' => z_root() . "/photo/profile/l/{$newuid}",
|
||||
'thumb' => z_root() . "/photo/profile/m/{$newuid}",
|
||||
'homepage' => ((isset($this->data['profile']['homepage'])) ? $this->data['profile']['homepage'] : EMPTY_STR),
|
||||
]
|
||||
);
|
||||
|
||||
if ($role_permissions) {
|
||||
$myperms = ((array_key_exists('perms_connect', $role_permissions)) ? $role_permissions['perms_connect'] : []);
|
||||
} else {
|
||||
$x = PermissionRoles::role_perms('social');
|
||||
$myperms = $x['perms_connect'];
|
||||
}
|
||||
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
'abook_account' => intval($channel['channel_account_id']),
|
||||
'abook_channel' => intval($newuid),
|
||||
'abook_xchan' => $channel['channel_hash'],
|
||||
'abook_closeness' => 0,
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_self' => 1
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$x = Permissions::serialise(Permissions::FilledPerms($myperms));
|
||||
set_abconfig($newuid, $channel['channel_hash'], 'system', 'my_perms', $x);
|
||||
|
||||
if (intval($channel['channel_account_id'])) {
|
||||
// Save our permissions role so we can perhaps call it up and modify it later.
|
||||
|
||||
if ($role_permissions) {
|
||||
if (array_key_exists('online', $role_permissions)) {
|
||||
set_pconfig($newuid, 'system', 'hide_presence', 1 - intval($role_permissions['online']));
|
||||
}
|
||||
if (array_key_exists('perms_auto', $role_permissions)) {
|
||||
$autoperms = intval($role_permissions['perms_auto']);
|
||||
set_pconfig($newuid, 'system', 'autoperms', $autoperms);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a group with yourself as a member. This allows somebody to use it
|
||||
// right away as a default group for new contacts.
|
||||
|
||||
AccessList::add($newuid, t('Friends'));
|
||||
AccessList::member_add($newuid, t('Friends'), $ret['channel']['channel_hash']);
|
||||
|
||||
// if our role_permissions indicate that we're using a default collection ACL, add it.
|
||||
|
||||
if (is_array($role_permissions) && $role_permissions['default_collection']) {
|
||||
$r = q(
|
||||
"select hash from pgrp where uid = %d and gname = '%s' limit 1",
|
||||
intval($newuid),
|
||||
dbesc(t('Friends'))
|
||||
);
|
||||
if ($r) {
|
||||
q(
|
||||
"update channel set channel_default_group = '%s', channel_allow_gid = '%s' where channel_id = %d",
|
||||
dbesc($r[0]['hash']),
|
||||
dbesc('<' . $r[0]['hash'] . '>'),
|
||||
intval($newuid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set_pconfig($channel['channel_id'], 'system', 'photo_path', '%Y/%Y-%m');
|
||||
set_pconfig($channel['channel_id'], 'system', 'attach_path', '%Y/%Y-%m');
|
||||
|
||||
|
||||
// auto-follow any of the hub's pre-configured channel choices.
|
||||
// Only do this if it's the first channel for this account;
|
||||
// otherwise it could get annoying. Don't make this list too big
|
||||
// or it will impact registration time.
|
||||
|
||||
$accts = get_config('system', 'auto_follow');
|
||||
if (($accts) && (!$total_identities)) {
|
||||
if (!is_array($accts)) {
|
||||
$accts = array($accts);
|
||||
}
|
||||
|
||||
foreach ($accts as $acct) {
|
||||
if (trim($acct)) {
|
||||
$f = connect_and_sync($channel, trim($acct));
|
||||
if ($f['success']) {
|
||||
$can_view_stream = their_perms_contains($channel['channel_id'], $f['abook']['abook_xchan'], 'view_stream');
|
||||
|
||||
// If we can view their stream, pull in some posts
|
||||
|
||||
if (($can_view_stream) || ($f['abook']['xchan_network'] === 'rss')) {
|
||||
Run::Summon(['Onepoll', $f['abook']['abook_id']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
call_hooks('create_identity', $newuid);
|
||||
}
|
||||
|
||||
$this->groups = ((isset($this->data['group'])) ? $this->data['group'] : null);
|
||||
$this->members = ((isset($this->data['group_member'])) ? $this->data['group_member'] : null);
|
||||
|
||||
// import contacts
|
||||
|
||||
if (isset($this->data['contact']) && is_array($this->data['contact'])) {
|
||||
foreach ($this->data['contact'] as $contact) {
|
||||
if (isset($contact['self']) && intval($contact['self'])) {
|
||||
continue;
|
||||
}
|
||||
logger('connecting: ' . $contact['url'], LOGGER_DEBUG);
|
||||
$result = Connect::connect($channel, (($contact['addr']) ? $contact['addr'] : $contact['url']));
|
||||
if ($result['success'] && isset($result['abook'])) {
|
||||
$contact['xchan_hash'] = $result['abook']['abook_xchan'];
|
||||
$this->contacts[] = $contact;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import pconfig
|
||||
// it is unlikely we can make use of these unless we recongise them.
|
||||
|
||||
if (isset($this->data['pconfig']) && is_array($this->data['pconfig'])) {
|
||||
foreach ($this->data['pconfig'] as $pc) {
|
||||
$entry = [
|
||||
'cat' => escape_tags(str_replace('.', '__', $pc['cat'])),
|
||||
'k' => escape_tags(str_replace('.', '__', $pc['k'])),
|
||||
'v' => ((preg_match('|^a:[0-9]+:{.*}$|s', $pc['v'])) ? serialise(unserialize($pc['v'])) : $pc['v']),
|
||||
];
|
||||
PConfig::Set($channel['channel_id'], $entry['cat'], $entry['k'], $entry['v']);
|
||||
}
|
||||
}
|
||||
|
||||
// The default 'Friends' group is already created and possibly populated.
|
||||
// So some of the following code is redundant in that regard.
|
||||
// Mostly this is used to create and populate any other groups.
|
||||
|
||||
if ($this->groups) {
|
||||
foreach ($this->groups as $group) {
|
||||
if (!intval($group['deleted'])) {
|
||||
AccessList::add($channel['channel_id'], $group['name'], intval($group['visible']));
|
||||
if ($this->members) {
|
||||
foreach ($this->members as $member) {
|
||||
if (intval($member['gid']) === intval(AccessList::byname($channel['channel_id'], $group['name']))) {
|
||||
$contact_id = $member['contact-id'];
|
||||
if ($this->contacts) {
|
||||
foreach ($this->contacts as $contact) {
|
||||
if (intval($contact['id']) === intval($contact_id)) {
|
||||
AccessList::member_add($channel['channel_id'], $group['name'], $contact['xchan_hash']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
change_channel($channel['channel_id']);
|
||||
notice(t('Import complete.') . EOL);
|
||||
|
||||
goaway(z_root() . '/stream');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,22 +4,26 @@ namespace Zotlabs\Lib;
|
|||
|
||||
// account configuration storage is built on top of the under-utilised xconfig
|
||||
|
||||
class AConfig {
|
||||
class AConfig
|
||||
{
|
||||
|
||||
static public function Load($account_id) {
|
||||
return XConfig::Load('a_' . $account_id);
|
||||
}
|
||||
public static function Load($account_id)
|
||||
{
|
||||
return XConfig::Load('a_' . $account_id);
|
||||
}
|
||||
|
||||
static public function Get($account_id,$family,$key,$default = false) {
|
||||
return XConfig::Get('a_' . $account_id,$family,$key, $default);
|
||||
}
|
||||
public static function Get($account_id, $family, $key, $default = false)
|
||||
{
|
||||
return XConfig::Get('a_' . $account_id, $family, $key, $default);
|
||||
}
|
||||
|
||||
static public function Set($account_id,$family,$key,$value) {
|
||||
return XConfig::Set('a_' . $account_id,$family,$key,$value);
|
||||
}
|
||||
|
||||
static public function Delete($account_id,$family,$key) {
|
||||
return XConfig::Delete('a_' . $account_id,$family,$key);
|
||||
}
|
||||
public static function Set($account_id, $family, $key, $value)
|
||||
{
|
||||
return XConfig::Set('a_' . $account_id, $family, $key, $value);
|
||||
}
|
||||
|
||||
public static function Delete($account_id, $family, $key)
|
||||
{
|
||||
return XConfig::Delete('a_' . $account_id, $family, $key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,147 +12,140 @@ use Zotlabs\Lib\Activity;
|
|||
* An optional limit to the number of records returned may also be specified.
|
||||
* Use $class->get() to return an array of collection members.
|
||||
*/
|
||||
class ASCollection
|
||||
{
|
||||
|
||||
private $channel = null;
|
||||
private $nextpage = null;
|
||||
private $limit = 0;
|
||||
private $direction = 0; // 0 = forward, 1 = reverse
|
||||
private $data = [];
|
||||
private $history = [];
|
||||
|
||||
|
||||
public function __construct($obj, $channel = null, $direction = 0, $limit = 0)
|
||||
{
|
||||
|
||||
$this->channel = $channel;
|
||||
$this->direction = $direction;
|
||||
$this->limit = $limit;
|
||||
|
||||
class ASCollection {
|
||||
if (is_array($obj)) {
|
||||
$data = $obj;
|
||||
}
|
||||
|
||||
private $channel = null;
|
||||
private $nextpage = null;
|
||||
private $limit = 0;
|
||||
private $direction = 0; // 0 = forward, 1 = reverse
|
||||
private $data = [];
|
||||
private $history = [];
|
||||
if (is_string($obj)) {
|
||||
$data = Activity::fetch($obj, $channel);
|
||||
$this->history[] = $obj;
|
||||
}
|
||||
|
||||
if (!is_array($data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
function __construct($obj, $channel = null, $direction = 0, $limit = 0) {
|
||||
if (!in_array($data['type'], ['Collection', 'OrderedCollection'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->channel = $channel;
|
||||
$this->direction = $direction;
|
||||
$this->limit = $limit;
|
||||
if ($this->direction) {
|
||||
if (array_key_exists('last', $data) && $data['last']) {
|
||||
$this->nextpage = $data['last'];
|
||||
}
|
||||
} else {
|
||||
if (array_key_exists('first', $data) && $data['first']) {
|
||||
$this->nextpage = $data['first'];
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($obj)) {
|
||||
$data = $obj;
|
||||
}
|
||||
if (isset($data['items']) && is_array($data['items'])) {
|
||||
$this->data = (($this->direction) ? array_reverse($data['items']) : $data['items']);
|
||||
} elseif (isset($data['orderedItems']) && is_array($data['orderedItems'])) {
|
||||
$this->data = (($this->direction) ? array_reverse($data['orderedItems']) : $data['orderedItems']);
|
||||
}
|
||||
|
||||
if (is_string($obj)) {
|
||||
$data = Activity::fetch($obj,$channel);
|
||||
$this->history[] = $obj;
|
||||
}
|
||||
if ($limit) {
|
||||
if (count($this->data) > $limit) {
|
||||
$this->data = array_slice($this->data, 0, $limit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_array($data)) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
$x = $this->next();
|
||||
} while ($x);
|
||||
}
|
||||
|
||||
if (! in_array($data['type'], ['Collection','OrderedCollection'])) {
|
||||
return false;
|
||||
}
|
||||
public function get()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
if ($this->direction) {
|
||||
if (array_key_exists('last',$data) && $data['last']) {
|
||||
$this->nextpage = $data['last'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (array_key_exists('first',$data) && $data['first']) {
|
||||
$this->nextpage = $data['first'];
|
||||
}
|
||||
}
|
||||
public function next()
|
||||
{
|
||||
|
||||
if (isset($data['items']) && is_array($data['items'])) {
|
||||
$this->data = (($this->direction) ? array_reverse($data['items']) : $data['items']);
|
||||
}
|
||||
elseif (isset($data['orderedItems']) && is_array($data['orderedItems'])) {
|
||||
$this->data = (($this->direction) ? array_reverse($data['orderedItems']) : $data['orderedItems']);
|
||||
}
|
||||
if (!$this->nextpage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($limit) {
|
||||
if (count($this->data) > $limit) {
|
||||
$this->data = array_slice($this->data,0,$limit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (is_array($this->nextpage)) {
|
||||
$data = $this->nextpage;
|
||||
}
|
||||
|
||||
do {
|
||||
$x = $this->next();
|
||||
} while ($x);
|
||||
}
|
||||
if (is_string($this->nextpage)) {
|
||||
if (in_array($this->nextpage, $this->history)) {
|
||||
// recursion detected
|
||||
return false;
|
||||
}
|
||||
$data = Activity::fetch($this->nextpage, $this->channel);
|
||||
$this->history[] = $this->nextpage;
|
||||
}
|
||||
|
||||
function get() {
|
||||
return $this->data;
|
||||
}
|
||||
if (!is_array($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (!in_array($data['type'], ['CollectionPage', 'OrderedCollectionPage'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->nextpage) {
|
||||
return false;
|
||||
}
|
||||
$this->setnext($data);
|
||||
|
||||
if (is_array($this->nextpage)) {
|
||||
$data = $this->nextpage;
|
||||
}
|
||||
if (isset($data['items']) && is_array($data['items'])) {
|
||||
$this->data = array_merge($this->data, (($this->direction) ? array_reverse($data['items']) : $data['items']));
|
||||
} elseif (isset($data['orderedItems']) && is_array($data['orderedItems'])) {
|
||||
$this->data = array_merge($this->data, (($this->direction) ? array_reverse($data['orderedItems']) : $data['orderedItems']));
|
||||
}
|
||||
|
||||
if (is_string($this->nextpage)) {
|
||||
if (in_array($this->nextpage,$this->history)) {
|
||||
// recursion detected
|
||||
return false;
|
||||
}
|
||||
$data = Activity::fetch($this->nextpage,$this->channel);
|
||||
$this->history[] = $this->nextpage;
|
||||
}
|
||||
if ($limit) {
|
||||
if (count($this->data) > $limit) {
|
||||
$this->data = array_slice($this->data, 0, $limit);
|
||||
$this->nextpage = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_array($data)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! in_array($data['type'], ['CollectionPage','OrderedCollectionPage'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setnext($data);
|
||||
|
||||
if (isset($data['items']) && is_array($data['items'])) {
|
||||
$this->data = array_merge($this->data,(($this->direction) ? array_reverse($data['items']) : $data['items']));
|
||||
}
|
||||
elseif (isset($data['orderedItems']) && is_array($data['orderedItems'])) {
|
||||
$this->data = array_merge($this->data,(($this->direction) ? array_reverse($data['orderedItems']) : $data['orderedItems']));
|
||||
}
|
||||
|
||||
if ($limit) {
|
||||
if (count($this->data) > $limit) {
|
||||
$this->data = array_slice($this->data,0,$limit);
|
||||
$this->nextpage = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function setnext($data) {
|
||||
if ($this->direction) {
|
||||
if (array_key_exists('prev',$data) && $data['prev']) {
|
||||
$this->nextpage = $data['prev'];
|
||||
}
|
||||
elseif (array_key_exists('first',$data) && $data['first']) {
|
||||
$this->nextpage = $data['first'];
|
||||
}
|
||||
else {
|
||||
$this->nextpage = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (array_key_exists('next',$data) && $data['next']) {
|
||||
$this->nextpage = $data['next'];
|
||||
}
|
||||
elseif (array_key_exists('last',$data) && $data['last']) {
|
||||
$this->nextpage = $data['last'];
|
||||
}
|
||||
else {
|
||||
$this->nextpage = false;
|
||||
}
|
||||
}
|
||||
logger('nextpage: ' . $this->nextpage, LOGGER_DEBUG);
|
||||
}
|
||||
public function setnext($data)
|
||||
{
|
||||
if ($this->direction) {
|
||||
if (array_key_exists('prev', $data) && $data['prev']) {
|
||||
$this->nextpage = $data['prev'];
|
||||
} elseif (array_key_exists('first', $data) && $data['first']) {
|
||||
$this->nextpage = $data['first'];
|
||||
} else {
|
||||
$this->nextpage = false;
|
||||
}
|
||||
} else {
|
||||
if (array_key_exists('next', $data) && $data['next']) {
|
||||
$this->nextpage = $data['next'];
|
||||
} elseif (array_key_exists('last', $data) && $data['last']) {
|
||||
$this->nextpage = $data['last'];
|
||||
} else {
|
||||
$this->nextpage = false;
|
||||
}
|
||||
}
|
||||
logger('nextpage: ' . $this->nextpage, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,74 +2,83 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class AbConfig
|
||||
{
|
||||
|
||||
class AbConfig {
|
||||
|
||||
static public function Load($chan,$xhash,$family = '') {
|
||||
if($family)
|
||||
$where = sprintf(" and cat = '%s' ",dbesc($family));
|
||||
$r = q("select * from abconfig where chan = %d and xchan = '%s' $where",
|
||||
intval($chan),
|
||||
dbesc($xhash)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
public static function Load($chan, $xhash, $family = '')
|
||||
{
|
||||
if ($family) {
|
||||
$where = sprintf(" and cat = '%s' ", dbesc($family));
|
||||
}
|
||||
$r = q(
|
||||
"select * from abconfig where chan = %d and xchan = '%s' $where",
|
||||
intval($chan),
|
||||
dbesc($xhash)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static public function Get($chan,$xhash,$family,$key, $default = false) {
|
||||
$r = q("select * from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
if($r) {
|
||||
return unserialise($r[0]['v']);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
public static function Get($chan, $xhash, $family, $key, $default = false)
|
||||
{
|
||||
$r = q(
|
||||
"select * from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' limit 1",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
if ($r) {
|
||||
return unserialise($r[0]['v']);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
|
||||
static public function Set($chan,$xhash,$family,$key,$value) {
|
||||
public static function Set($chan, $xhash, $family, $key, $value)
|
||||
{
|
||||
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($chan,$xhash,$family,$key) === false) {
|
||||
$r = q("insert into abconfig ( chan, xchan, cat, k, v ) values ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("update abconfig set v = '%s' where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
dbesc($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
if (self::Get($chan, $xhash, $family, $key) === false) {
|
||||
$r = q(
|
||||
"insert into abconfig ( chan, xchan, cat, k, v ) values ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
} else {
|
||||
$r = q(
|
||||
"update abconfig set v = '%s' where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
dbesc($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
|
||||
if($r)
|
||||
return $value;
|
||||
return false;
|
||||
}
|
||||
if ($r) {
|
||||
return $value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static public function Delete($chan,$xhash,$family,$key) {
|
||||
public static function Delete($chan, $xhash, $family, $key)
|
||||
{
|
||||
|
||||
$r = q("delete from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
$r = q(
|
||||
"delete from abconfig where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
|
||||
intval($chan),
|
||||
dbesc($xhash),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,461 +4,489 @@ namespace Zotlabs\Lib;
|
|||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class AccessList
|
||||
{
|
||||
|
||||
class AccessList {
|
||||
public static function add($uid, $name, $public = 0)
|
||||
{
|
||||
|
||||
static function add($uid,$name,$public = 0) {
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = self::byname($uid, $name); // check for dups
|
||||
if ($r !== false) {
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a list which we once deleted
|
||||
// all the old members are gone, but the list remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead list, but old content which
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = self::byname($uid,$name); // check for dups
|
||||
if ($r !== false) {
|
||||
$z = q(
|
||||
"SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if (($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice(t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
|
||||
}
|
||||
$hash = self::by_id($uid, $r);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
// This could be a problem.
|
||||
// Let's assume we've just created a list which we once deleted
|
||||
// all the old members are gone, but the list remains so we don't break any security
|
||||
// access lists. What we're doing here is reviving the dead list, but old content which
|
||||
// was restricted to this list may now be seen by the new list members.
|
||||
$hash = new_uuid();
|
||||
|
||||
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||
intval($r)
|
||||
);
|
||||
if(($z) && $z[0]['deleted']) {
|
||||
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||
notice( t('A deleted list with this name was revived. Existing item permissions <strong>may</strong> apply to this list and any future members. If this is not what you intended, please create another list with a different name.') . EOL);
|
||||
}
|
||||
$hash = self::by_id($uid,$r);
|
||||
return $hash;
|
||||
}
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname, rule )
|
||||
$r = q(
|
||||
"INSERT INTO pgrp ( hash, uid, visible, gname, rule )
|
||||
VALUES( '%s', %d, %d, '%s', '' ) ",
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
intval($public),
|
||||
dbesc($name)
|
||||
);
|
||||
$ret = $r;
|
||||
}
|
||||
dbesc($hash),
|
||||
intval($uid),
|
||||
intval($public),
|
||||
dbesc($name)
|
||||
);
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return (($ret) ? $hash : $ret);
|
||||
}
|
||||
return (($ret) ? $hash : $ret);
|
||||
}
|
||||
|
||||
|
||||
static function remove($uid,$name) {
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
public static function remove($uid, $name)
|
||||
{
|
||||
$ret = false;
|
||||
if ($uid && $name) {
|
||||
$r = q(
|
||||
"SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
$group_id = $r[0]['id'];
|
||||
$group_hash = $r[0]['hash'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove group from default posting lists
|
||||
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$user_info = array_shift($r);
|
||||
$change = false;
|
||||
// remove group from default posting lists
|
||||
$r = q(
|
||||
"SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$user_info = array_shift($r);
|
||||
$change = false;
|
||||
|
||||
if ($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
}
|
||||
if ($user_info['channel_default_group'] == $group_hash) {
|
||||
$user_info['channel_default_group'] = '';
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||
$change = true;
|
||||
}
|
||||
if (strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||
$change = true;
|
||||
}
|
||||
|
||||
if ($change) {
|
||||
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
if ($change) {
|
||||
q(
|
||||
"UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||
WHERE channel_id = %d",
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
dbesc($user_info['channel_deny_gid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
intval($user_info['channel_default_group']),
|
||||
dbesc($user_info['channel_allow_gid']),
|
||||
dbesc($user_info['channel_deny_gid']),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// remove all members
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
|
||||
intval($uid),
|
||||
intval($group_id)
|
||||
);
|
||||
// remove all members
|
||||
$r = q(
|
||||
"DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
|
||||
intval($uid),
|
||||
intval($group_id)
|
||||
);
|
||||
|
||||
// remove group
|
||||
$r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
// remove group
|
||||
$r = q(
|
||||
"UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
|
||||
$ret = $r;
|
||||
$ret = $r;
|
||||
}
|
||||
|
||||
}
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
// returns the integer id of an access group owned by $uid and named $name
|
||||
// or false.
|
||||
|
||||
// returns the integer id of an access group owned by $uid and named $name
|
||||
// or false.
|
||||
public static function byname($uid, $name)
|
||||
{
|
||||
if (!($uid && $name)) {
|
||||
return false;
|
||||
}
|
||||
$r = q(
|
||||
"SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
return $r[0]['id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function byname($uid,$name) {
|
||||
if (! ($uid && $name)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT id FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
return $r[0]['id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static function by_id($uid, $id)
|
||||
{
|
||||
if (!($uid && $id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static function by_id($uid,$id) {
|
||||
if (! ($uid && $id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
|
||||
intval($uid),
|
||||
intval($id)
|
||||
);
|
||||
if ($r) {
|
||||
return array_shift($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * FROM pgrp WHERE uid = %d AND id = %d and deleted = 0",
|
||||
intval($uid),
|
||||
intval($id)
|
||||
);
|
||||
if ($r) {
|
||||
return array_shift($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static function rec_byhash($uid,$hash) {
|
||||
if (! ( $uid && $hash)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($hash)
|
||||
);
|
||||
if ($r) {
|
||||
return array_shift($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static function rec_byhash($uid, $hash)
|
||||
{
|
||||
if (!($uid && $hash)) {
|
||||
return false;
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
dbesc($hash)
|
||||
);
|
||||
if ($r) {
|
||||
return array_shift($r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function member_remove($uid,$name,$member) {
|
||||
$gid = self::byname($uid,$name);
|
||||
if (! $gid) {
|
||||
return false;
|
||||
}
|
||||
if (! ($uid && $gid && $member)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
public static function member_remove($uid, $name, $member)
|
||||
{
|
||||
$gid = self::byname($uid, $name);
|
||||
if (!$gid) {
|
||||
return false;
|
||||
}
|
||||
if (!($uid && $gid && $member)) {
|
||||
return false;
|
||||
}
|
||||
$r = q(
|
||||
"DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function member_add($uid,$name,$member,$gid = 0) {
|
||||
if (! $gid) {
|
||||
$gid = self::byname($uid,$name);
|
||||
}
|
||||
if (! ($gid && $uid && $member)) {
|
||||
return false;
|
||||
}
|
||||
public static function member_add($uid, $name, $member, $gid = 0)
|
||||
{
|
||||
if (!$gid) {
|
||||
$gid = self::byname($uid, $name);
|
||||
}
|
||||
if (!($gid && $uid && $member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if ($r) {
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
}
|
||||
else {
|
||||
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
$r = q(
|
||||
"SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
if ($r) {
|
||||
return true; // You might question this, but
|
||||
// we indicate success because the group member was in fact created
|
||||
// -- It was just created at another time
|
||||
} else {
|
||||
$r = q(
|
||||
"INSERT INTO pgrp_member (uid, gid, xchan)
|
||||
VALUES( %d, %d, '%s' ) ",
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
}
|
||||
Libsync::build_sync_packet($uid,null,true);
|
||||
return $r;
|
||||
}
|
||||
intval($uid),
|
||||
intval($gid),
|
||||
dbesc($member)
|
||||
);
|
||||
}
|
||||
Libsync::build_sync_packet($uid, null, true);
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
static function members($uid, $gid, $total = false, $start = 0, $records = 0) {
|
||||
$ret = [];
|
||||
if ($records) {
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($records), intval($start));
|
||||
}
|
||||
public static function members($uid, $gid, $total = false, $start = 0, $records = 0)
|
||||
{
|
||||
$ret = [];
|
||||
if ($records) {
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($records), intval($start));
|
||||
}
|
||||
|
||||
// process virtual groups
|
||||
if (strpos($gid,':') === 0) {
|
||||
$vg = substr($gid,1);
|
||||
switch ($vg) {
|
||||
case '1':
|
||||
$sql_extra = EMPTY_STR;
|
||||
break;
|
||||
case '2':
|
||||
// process virtual groups
|
||||
if (strpos($gid, ':') === 0) {
|
||||
$vg = substr($gid, 1);
|
||||
switch ($vg) {
|
||||
case '1':
|
||||
$sql_extra = EMPTY_STR;
|
||||
break;
|
||||
case '2':
|
||||
$sql_extra = " and xchan_network in ('nomad','zot6') ";
|
||||
break;
|
||||
case '3':
|
||||
$sql_extra = " and xchan_network = 'activitypub' ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ($total) {
|
||||
$r = q("SELECT count(*) FROM abook left join xchan on xchan_hash = abook_xchan WHERE abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql",
|
||||
intval($uid)
|
||||
);
|
||||
return ($r) ? $r[0]['total'] : false;
|
||||
}
|
||||
break;
|
||||
case '3':
|
||||
$sql_extra = " and xchan_network = 'activitypub' ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ($total) {
|
||||
$r = q(
|
||||
"SELECT count(*) FROM abook left join xchan on xchan_hash = abook_xchan WHERE abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql",
|
||||
intval($uid)
|
||||
);
|
||||
return ($r) ? $r[0]['total'] : false;
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan
|
||||
$r = q(
|
||||
"SELECT * FROM abook left join xchan on xchan_hash = abook_xchan
|
||||
WHERE abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 $sql_extra ORDER BY xchan_name ASC $pager_sql",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
for($x = 0; $x < count($r); $x ++) {
|
||||
$r[$x]['xchan'] = $r[$x]['abook_xchan'];
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
for ($x = 0; $x < count($r); $x++) {
|
||||
$r[$x]['xchan'] = $r[$x]['abook_xchan'];
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
if (intval($gid)) {
|
||||
if ($total) {
|
||||
$r = q("SELECT count(xchan) as total FROM pgrp_member
|
||||
if (intval($gid)) {
|
||||
if ($total) {
|
||||
$r = q(
|
||||
"SELECT count(xchan) as total FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0
|
||||
and abook_blocked = 0 and abook_pending = 0",
|
||||
intval($gid),
|
||||
intval($uid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
return $r[0]['total'];
|
||||
}
|
||||
}
|
||||
intval($gid),
|
||||
intval($uid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
return $r[0]['total'];
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pgrp_member
|
||||
$r = q(
|
||||
"SELECT * FROM pgrp_member
|
||||
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC $pager_sql",
|
||||
intval($gid),
|
||||
intval($uid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$ret = $r;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
intval($gid),
|
||||
intval($uid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$ret = $r;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function members_xchan($uid,$gid) {
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
public static function members_xchan($uid, $gid)
|
||||
{
|
||||
$ret = [];
|
||||
if (intval($gid)) {
|
||||
$r = q(
|
||||
"SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||
intval($gid),
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function select($uid,$group = '') {
|
||||
public static function select($uid, $group = '')
|
||||
{
|
||||
|
||||
$grps = [];
|
||||
$grps = [];
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = [ 'name' => '', 'hash' => '0', 'selected' => '' ];
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$grps[] = [ 'name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '') ];
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($uid)
|
||||
);
|
||||
$grps[] = ['name' => '', 'hash' => '0', 'selected' => ''];
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$grps[] = ['name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : '')];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_selection.tpl'), [
|
||||
'$label' => t('Add new connections to this access list'),
|
||||
'$groups' => $grps
|
||||
]);
|
||||
}
|
||||
return replace_macros(get_markup_template('group_selection.tpl'), [
|
||||
'$label' => t('Add new connections to this access list'),
|
||||
'$groups' => $grps
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
static function widget($every="connections",$each="lists",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||
public static function widget($every = "connections", $each = "lists", $edit = false, $group_id = 0, $cid = '', $mode = 1)
|
||||
{
|
||||
|
||||
$o = '';
|
||||
$o = '';
|
||||
|
||||
$groups = [];
|
||||
$groups = [];
|
||||
|
||||
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = [];
|
||||
if ($cid) {
|
||||
$member_of = self::containing(local_channel(),$cid);
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||
intval($_SESSION['uid'])
|
||||
);
|
||||
$member_of = [];
|
||||
if ($cid) {
|
||||
$member_of = self::containing(local_channel(), $cid);
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||
|
||||
if ($edit) {
|
||||
$groupedit = [ 'href' => "lists/".$rr['id'], 'title' => t('edit') ];
|
||||
}
|
||||
else {
|
||||
$groupedit = null;
|
||||
}
|
||||
if ($edit) {
|
||||
$groupedit = ['href' => "lists/" . $rr['id'], 'title' => t('edit')];
|
||||
} else {
|
||||
$groupedit = null;
|
||||
}
|
||||
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'],$member_of),
|
||||
];
|
||||
}
|
||||
}
|
||||
$groups[] = [
|
||||
'id' => $rr['id'],
|
||||
'enc_cid' => base64url_encode($cid),
|
||||
'cid' => $cid,
|
||||
'text' => $rr['gname'],
|
||||
'selected' => $selected,
|
||||
'href' => (($mode == 0) ? $each . '?f=&gid=' . $rr['id'] : $each . "/" . $rr['id']) . ((x($_GET, 'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET, 'order')) ? '&order=' . $_GET['order'] : ''),
|
||||
'edit' => $groupedit,
|
||||
'ismember' => in_array($rr['id'], $member_of),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('group_side.tpl'), [
|
||||
'$title' => t('Lists'),
|
||||
'$edittext' => t('Edit list'),
|
||||
'$createtext' => t('Create new list'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
]);
|
||||
|
||||
}
|
||||
return replace_macros(get_markup_template('group_side.tpl'), [
|
||||
'$title' => t('Lists'),
|
||||
'$edittext' => t('Edit list'),
|
||||
'$createtext' => t('Create new list'),
|
||||
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any access list') : ''),
|
||||
'$groups' => $groups,
|
||||
'$add' => t('add'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
static function expand($g) {
|
||||
if (! (is_array($g) && count($g))) {
|
||||
return [];
|
||||
}
|
||||
public static function expand($g)
|
||||
{
|
||||
if (!(is_array($g) && count($g))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$ret = [];
|
||||
$x = [];
|
||||
$ret = [];
|
||||
$x = [];
|
||||
|
||||
foreach ($g as $gv) {
|
||||
foreach ($g as $gv) {
|
||||
// virtual access lists
|
||||
// connections:abc is all the connection sof the channel with channel_hash abc
|
||||
// zot:abc is all of abc's zot6 connections
|
||||
// activitypub:abc is all of abc's activitypub connections
|
||||
|
||||
// virtual access lists
|
||||
// connections:abc is all the connection sof the channel with channel_hash abc
|
||||
// zot:abc is all of abc's zot6 connections
|
||||
// activitypub:abc is all of abc's activitypub connections
|
||||
|
||||
if (strpos($gv,'connections:') === 0 || strpos($gv,'zot:') === 0 || strpos($gv,'activitypub:') === 0) {
|
||||
$sql_extra = EMPTY_STR;
|
||||
$channel_hash = substr($gv,strpos($gv,':') + 1);
|
||||
if (strpos($gv,'zot:') === 0) {
|
||||
if (strpos($gv, 'connections:') === 0 || strpos($gv, 'zot:') === 0 || strpos($gv, 'activitypub:') === 0) {
|
||||
$sql_extra = EMPTY_STR;
|
||||
$channel_hash = substr($gv, strpos($gv, ':') + 1);
|
||||
if (strpos($gv, 'zot:') === 0) {
|
||||
$sql_extra = " and xchan_network in ('nomad','zot6') ";
|
||||
}
|
||||
if (strpos($gv,'activitypub:') === 0) {
|
||||
$sql_extra = " and xchan_network = 'activitypub' ";
|
||||
}
|
||||
$r = q("select channel_id from channel where channel_hash = '%s' ",
|
||||
dbesc($channel_hash)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$y = q("select abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 $sql_extra",
|
||||
intval($rv['channel_id'])
|
||||
);
|
||||
if ($y) {
|
||||
foreach ($y as $yv) {
|
||||
$ret[] = $yv['abook_xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strpos($gv, 'activitypub:') === 0) {
|
||||
$sql_extra = " and xchan_network = 'activitypub' ";
|
||||
}
|
||||
$r = q(
|
||||
"select channel_id from channel where channel_hash = '%s' ",
|
||||
dbesc($channel_hash)
|
||||
);
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$y = q(
|
||||
"select abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 $sql_extra",
|
||||
intval($rv['channel_id'])
|
||||
);
|
||||
if ($y) {
|
||||
foreach ($y as $yv) {
|
||||
$ret[] = $yv['abook_xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$x[] = $gv;
|
||||
}
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
stringify_array_elms($x,true);
|
||||
$groups = implode(',', $x);
|
||||
if ($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
if ($x) {
|
||||
stringify_array_elms($x, true);
|
||||
$groups = implode(',', $x);
|
||||
if ($groups) {
|
||||
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['xchan'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static function member_of($c) {
|
||||
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
public static function member_of($c)
|
||||
{
|
||||
$r = q(
|
||||
"SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id
|
||||
WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||
dbesc($c)
|
||||
);
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
static function containing($uid,$c) {
|
||||
public static function containing($uid, $c)
|
||||
{
|
||||
|
||||
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
dbesc($c)
|
||||
);
|
||||
$r = q(
|
||||
"SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||
intval($uid),
|
||||
dbesc($c)
|
||||
);
|
||||
|
||||
$ret = [];
|
||||
if ($r) {
|
||||
foreach ($r as $rv)
|
||||
$ret[] = $rv['gid'];
|
||||
}
|
||||
$ret = [];
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$ret[] = $rv['gid'];
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -4,463 +4,489 @@ namespace Zotlabs\Lib;
|
|||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
|
||||
/**
|
||||
* @brief ActivityStreams class.
|
||||
*
|
||||
* Parses an ActivityStream JSON string.
|
||||
*/
|
||||
class ActivityStreams
|
||||
{
|
||||
|
||||
class ActivityStreams {
|
||||
public $raw = null;
|
||||
public $data = null;
|
||||
public $hub = null;
|
||||
public $valid = false;
|
||||
public $deleted = false;
|
||||
public $id = '';
|
||||
public $parent_id = '';
|
||||
public $type = '';
|
||||
public $actor = null;
|
||||
public $obj = null;
|
||||
public $tgt = null;
|
||||
public $replyto = null;
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
public $implied_create = false;
|
||||
|
||||
public $raw = null;
|
||||
public $data = null;
|
||||
public $hub = null;
|
||||
public $valid = false;
|
||||
public $deleted = false;
|
||||
public $id = '';
|
||||
public $parent_id = '';
|
||||
public $type = '';
|
||||
public $actor = null;
|
||||
public $obj = null;
|
||||
public $tgt = null;
|
||||
public $replyto = null;
|
||||
public $origin = null;
|
||||
public $owner = null;
|
||||
public $signer = null;
|
||||
public $ldsig = null;
|
||||
public $sigok = false;
|
||||
public $recips = null;
|
||||
public $raw_recips = null;
|
||||
public $implied_create = false;
|
||||
/**
|
||||
* @brief Constructor for ActivityStreams.
|
||||
*
|
||||
* Takes a JSON string or previously decode activity array as parameter,
|
||||
* decodes it and sets up this object/activity, fetching any required attributes
|
||||
* which were only referenced by @id/URI.
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
public function __construct($string, $hub = null, $client = null)
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Constructor for ActivityStreams.
|
||||
*
|
||||
* Takes a JSON string or previously decode activity array as parameter,
|
||||
* decodes it and sets up this object/activity, fetching any required attributes
|
||||
* which were only referenced by @id/URI.
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
function __construct($string,$hub = null,$client = null) {
|
||||
$this->raw = $string;
|
||||
$this->hub = $hub;
|
||||
|
||||
$this->raw = $string;
|
||||
$this->hub = $hub;
|
||||
if (is_array($string)) {
|
||||
$this->data = $string;
|
||||
$this->raw = json_encode($string, JSON_UNESCAPED_SLASHES);
|
||||
} else {
|
||||
$this->data = json_decode($string, true);
|
||||
}
|
||||
|
||||
if (is_array($string)) {
|
||||
$this->data = $string;
|
||||
$this->raw = json_encode($string,JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
else {
|
||||
$this->data = json_decode($string, true);
|
||||
}
|
||||
if ($this->data) {
|
||||
// verify and unpack JSalmon signature if present
|
||||
// This will only be the case for Zot6 packets
|
||||
|
||||
if ($this->data) {
|
||||
if (is_array($this->data) && array_key_exists('signed', $this->data)) {
|
||||
$ret = JSalmon::verify($this->data);
|
||||
$tmp = JSalmon::unpack($this->data['data']);
|
||||
if ($ret && $ret['success']) {
|
||||
if ($ret['signer']) {
|
||||
logger('Unpacked: ' . json_encode($tmp, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOGGER_DATA, LOG_DEBUG);
|
||||
$saved = json_encode($this->data, JSON_UNESCAPED_SLASHES);
|
||||
$this->data = $tmp;
|
||||
$this->data['signer'] = $ret['signer'];
|
||||
$this->data['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$this->data['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
// This will only be the case for Zot6 packets
|
||||
// This indicates only that we have sucessfully decoded JSON.
|
||||
$this->valid = true;
|
||||
|
||||
if (is_array($this->data) && array_key_exists('signed',$this->data)) {
|
||||
$ret = JSalmon::verify($this->data);
|
||||
$tmp = JSalmon::unpack($this->data['data']);
|
||||
if ($ret && $ret['success']) {
|
||||
if ($ret['signer']) {
|
||||
logger('Unpacked: ' . json_encode($tmp,JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT),LOGGER_DATA,LOG_DEBUG);
|
||||
$saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
|
||||
$this->data = $tmp;
|
||||
$this->data['signer'] = $ret['signer'];
|
||||
$this->data['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$this->data['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Special handling for Mastodon "delete actor" activities which will often fail to verify
|
||||
// because the key cannot be fetched. We will catch this condition elsewhere.
|
||||
|
||||
// This indicates only that we have sucessfully decoded JSON.
|
||||
$this->valid = true;
|
||||
if (array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
|
||||
if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
|
||||
$this->deleted = $this->data['actor'];
|
||||
$this->valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling for Mastodon "delete actor" activities which will often fail to verify
|
||||
// because the key cannot be fetched. We will catch this condition elsewhere.
|
||||
// Attempt to assemble an Activity from what we were given.
|
||||
|
||||
if (array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
|
||||
if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
|
||||
$this->deleted = $this->data['actor'];
|
||||
$this->valid = false;
|
||||
}
|
||||
}
|
||||
if ($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor', '', '');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
$this->tgt = $this->get_compound_property('target');
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
$this->replyto = $this->get_property_obj('replyTo');
|
||||
|
||||
}
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if ($this->ldsig) {
|
||||
$this->signer = $this->get_compound_property('creator', $this->ldsig);
|
||||
if (
|
||||
$this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer)
|
||||
&& is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']
|
||||
) {
|
||||
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to assemble an Activity from what we were given.
|
||||
// Implied create activity required by C2S specification if no object is present
|
||||
|
||||
if ($this->is_valid()) {
|
||||
$this->id = $this->get_property_obj('id');
|
||||
$this->type = $this->get_primary_type();
|
||||
$this->actor = $this->get_actor('actor','','');
|
||||
$this->obj = $this->get_compound_property('object');
|
||||
$this->tgt = $this->get_compound_property('target');
|
||||
$this->origin = $this->get_compound_property('origin');
|
||||
$this->recips = $this->collect_recips();
|
||||
$this->replyto = $this->get_property_obj('replyTo');
|
||||
if (!$this->obj) {
|
||||
if (!$client) {
|
||||
$this->implied_create = true;
|
||||
}
|
||||
$this->obj = $this->data;
|
||||
$this->type = 'Create';
|
||||
if (!$this->actor) {
|
||||
$this->actor = $this->get_actor('attributedTo', $this->obj);
|
||||
}
|
||||
}
|
||||
|
||||
$this->ldsig = $this->get_compound_property('signature');
|
||||
if ($this->ldsig) {
|
||||
$this->signer = $this->get_compound_property('creator',$this->ldsig);
|
||||
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer)
|
||||
&& is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||
$this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
|
||||
}
|
||||
}
|
||||
// fetch recursive or embedded activities
|
||||
|
||||
// Implied create activity required by C2S specification if no object is present
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
|
||||
}
|
||||
|
||||
if (! $this->obj) {
|
||||
if (! $client) {
|
||||
$this->implied_create = true;
|
||||
}
|
||||
$this->obj = $this->data;
|
||||
$this->type = 'Create';
|
||||
if (! $this->actor) {
|
||||
$this->actor = $this->get_actor('attributedTo',$this->obj);
|
||||
}
|
||||
}
|
||||
// Enumerate and store actors in referenced objects
|
||||
|
||||
// fetch recursive or embedded activities
|
||||
if ($this->obj && is_array($this->obj) && $this->obj['actor']) {
|
||||
$this->obj['actor'] = $this->get_actor('actor', $this->obj);
|
||||
}
|
||||
if ($this->tgt && is_array($this->tgt) && $this->tgt['actor']) {
|
||||
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
|
||||
}
|
||||
|
||||
if ($this->obj && is_array($this->obj) && array_key_exists('object',$this->obj)) {
|
||||
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
|
||||
}
|
||||
// Determine if this is a followup or response activity
|
||||
|
||||
// Enumerate and store actors in referenced objects
|
||||
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||
|
||||
if ($this->obj && is_array($this->obj) && $this->obj['actor']) {
|
||||
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
|
||||
}
|
||||
if ($this->tgt && is_array($this->tgt) && $this->tgt['actor']) {
|
||||
$this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
|
||||
}
|
||||
if ((!$this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['inReplyTo'];
|
||||
}
|
||||
if ((!$this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if this is a followup or response activity
|
||||
/**
|
||||
* @brief Return if instantiated ActivityStream is valid.
|
||||
*
|
||||
* @return bool Return true if the JSON string could be decoded.
|
||||
*/
|
||||
|
||||
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||
public function is_valid()
|
||||
{
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
if ((! $this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['inReplyTo'];
|
||||
}
|
||||
if ((! $this->parent_id) && is_array($this->obj)) {
|
||||
$this->parent_id = $this->obj['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
public function set_recips($arr)
|
||||
{
|
||||
$this->saved_recips = $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return if instantiated ActivityStream is valid.
|
||||
*
|
||||
* @return boolean Return true if the JSON string could be decoded.
|
||||
*/
|
||||
/**
|
||||
* @brief Collects all recipients.
|
||||
*
|
||||
* @param string $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return array
|
||||
*/
|
||||
public function collect_recips($base = '', $namespace = '')
|
||||
{
|
||||
$x = [];
|
||||
|
||||
function is_valid() {
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
function set_recips($arr) {
|
||||
$this->saved_recips = $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Collects all recipients.
|
||||
*
|
||||
* @param string $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return array
|
||||
*/
|
||||
function collect_recips($base = '', $namespace = '') {
|
||||
$x = [];
|
||||
|
||||
$fields = [ 'to', 'cc', 'bto', 'bcc', 'audience'];
|
||||
foreach ($fields as $f) {
|
||||
// don't expand these yet
|
||||
$y = $this->get_property_obj($f, $base, $namespace);
|
||||
if ($y) {
|
||||
if (! is_array($this->raw_recips)) {
|
||||
$this->raw_recips = [];
|
||||
}
|
||||
if (! is_array($y)) {
|
||||
$y = [ $y ];
|
||||
}
|
||||
$this->raw_recips[$f] = $y;
|
||||
$x = array_merge($x, $y);
|
||||
}
|
||||
}
|
||||
$fields = ['to', 'cc', 'bto', 'bcc', 'audience'];
|
||||
foreach ($fields as $f) {
|
||||
// don't expand these yet
|
||||
$y = $this->get_property_obj($f, $base, $namespace);
|
||||
if ($y) {
|
||||
if (!is_array($this->raw_recips)) {
|
||||
$this->raw_recips = [];
|
||||
}
|
||||
if (!is_array($y)) {
|
||||
$y = [$y];
|
||||
}
|
||||
$this->raw_recips[$f] = $y;
|
||||
$x = array_merge($x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
// not yet ready for prime time
|
||||
// $x = $this->expand($x,$base,$namespace);
|
||||
return $x;
|
||||
}
|
||||
// $x = $this->expand($x,$base,$namespace);
|
||||
return $x;
|
||||
}
|
||||
|
||||
function expand($arr,$base = '',$namespace = '') {
|
||||
$ret = [];
|
||||
public function expand($arr, $base = '', $namespace = '')
|
||||
{
|
||||
$ret = [];
|
||||
|
||||
// right now use a hardwired recursion depth of 5
|
||||
// right now use a hardwired recursion depth of 5
|
||||
|
||||
for ($z = 0; $z < 5; $z ++) {
|
||||
if (is_array($arr) && $arr) {
|
||||
foreach ($arr as $a) {
|
||||
if (is_array($a)) {
|
||||
$ret[] = $a;
|
||||
}
|
||||
else {
|
||||
$x = $this->get_compound_property($a,$base,$namespace);
|
||||
if ($x) {
|
||||
$ret = array_merge($ret,$x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for ($z = 0; $z < 5; $z++) {
|
||||
if (is_array($arr) && $arr) {
|
||||
foreach ($arr as $a) {
|
||||
if (is_array($a)) {
|
||||
$ret[] = $a;
|
||||
} else {
|
||||
$x = $this->get_compound_property($a, $base, $namespace);
|
||||
if ($x) {
|
||||
$ret = array_merge($ret, $x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @fixme de-duplicate
|
||||
/// @fixme de-duplicate
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param array $base
|
||||
* @param string $namespace if not set return empty string
|
||||
* @return string|NULL
|
||||
*/
|
||||
|
||||
public function get_namespace($base, $namespace)
|
||||
{
|
||||
|
||||
if (!$namespace) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$key = null;
|
||||
|
||||
foreach ([$this->data, $base] as $b) {
|
||||
if (!$b) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (array_key_exists('@context', $b)) {
|
||||
if (is_array($b['@context'])) {
|
||||
foreach ($b['@context'] as $ns) {
|
||||
if (is_array($ns)) {
|
||||
foreach ($ns as $k => $v) {
|
||||
if ($namespace === $v) {
|
||||
$key = $k;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($namespace === $ns) {
|
||||
$key = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($namespace === $b['@context']) {
|
||||
$key = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base (optional)
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
public function get_property_obj($property, $base = '', $namespace = '')
|
||||
{
|
||||
$prefix = $this->get_namespace($base, $namespace);
|
||||
if ($prefix === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$base = (($base) ? $base : $this->data);
|
||||
$propname = (($prefix) ? $prefix . ':' : '') . $property;
|
||||
|
||||
if (!is_array($base)) {
|
||||
btlogger('not an array: ' . print_r($base, true));
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Fetches a property from an URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $channel (signing channel, default system channel)
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
public function fetch_property($url, $channel = null, $hub = null)
|
||||
{
|
||||
return Activity::fetch($url, $channel, $hub);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief given a type, determine if this object represents an actor
|
||||
*
|
||||
* @param array $base
|
||||
* @param string $namespace if not set return empty string
|
||||
* @return string|NULL
|
||||
*/
|
||||
|
||||
function get_namespace($base, $namespace) {
|
||||
|
||||
if (! $namespace) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
|
||||
$key = null;
|
||||
|
||||
foreach ( [ $this->data, $base ] as $b ) {
|
||||
if (! $b) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (array_key_exists('@context', $b)) {
|
||||
if (is_array($b['@context'])) {
|
||||
foreach ($b['@context'] as $ns) {
|
||||
if (is_array($ns)) {
|
||||
foreach ($ns as $k => $v) {
|
||||
if ($namespace === $v) {
|
||||
$key = $k;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($namespace === $ns) {
|
||||
$key = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($namespace === $b['@context']) {
|
||||
$key = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* If $type is an array, recurse through each element and return true if any
|
||||
* of the elements are a known actor type
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base (optional)
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function get_property_obj($property, $base = '', $namespace = '') {
|
||||
$prefix = $this->get_namespace($base, $namespace);
|
||||
if ($prefix === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$base = (($base) ? $base : $this->data);
|
||||
$propname = (($prefix) ? $prefix . ':' : '') . $property;
|
||||
|
||||
if (! is_array($base)) {
|
||||
btlogger('not an array: ' . print_r($base,true));
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Fetches a property from an URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $channel (signing channel, default system channel)
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function fetch_property($url,$channel = null,$hub = null) {
|
||||
return Activity::fetch($url,$channel,$hub);
|
||||
}
|
||||
|
||||
static function is_an_actor($s) {
|
||||
if (! $s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s,[ 'Application','Group','Organization','Person','Service' ]));
|
||||
}
|
||||
|
||||
static function is_response_activity($s) {
|
||||
if (! $s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact' ]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function get_actor($property,$base='',$namespace = '') {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if (self::is_url($x)) {
|
||||
$y = Activity::get_cached_actor($x);
|
||||
if ($y) {
|
||||
return $y;
|
||||
}
|
||||
}
|
||||
|
||||
$actor = $this->get_compound_property($property,$base,$namespace,true);
|
||||
if (is_array($actor) && self::is_an_actor($actor['type'])) {
|
||||
if (array_key_exists('id',$actor) && (! array_key_exists('inbox',$actor))) {
|
||||
$actor = $this->fetch_property($actor['id']);
|
||||
}
|
||||
return $actor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @param boolean $first (optional) default false, if true and result is a sequential array return only the first element
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if (self::is_url($x)) {
|
||||
$y = $this->fetch_property($x);
|
||||
if (is_array($y)) {
|
||||
$x = $y;
|
||||
}
|
||||
}
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
// This may be present in Zot6 packets
|
||||
|
||||
if (is_array($x) && array_key_exists('signed',$x)) {
|
||||
$ret = JSalmon::verify($x);
|
||||
$tmp = JSalmon::unpack($x['data']);
|
||||
if ($ret && $ret['success']) {
|
||||
if ($ret['signer']) {
|
||||
logger('Unpacked: ' . json_encode($tmp,JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT),LOGGER_DATA,LOG_DEBUG);
|
||||
$saved = json_encode($x,JSON_UNESCAPED_SLASHES);
|
||||
$x = $tmp;
|
||||
$x['signer'] = $ret['signer'];
|
||||
$x['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$x['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($first && is_array($x) && array_key_exists(0,$x)) {
|
||||
return $x[0];
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if string starts with http.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string|array $type
|
||||
* @return boolean
|
||||
*/
|
||||
|
||||
static public function is_url($url) {
|
||||
if (($url) && (! is_array($url)) && ((strpos($url, 'http') === 0) || (strpos($url,'x-zot') === 0) || (strpos($url,'bear') === 0))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the type property.
|
||||
*
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
function get_primary_type($base = '', $namespace = '') {
|
||||
if (! $base) {
|
||||
$base = $this->data;
|
||||
}
|
||||
$x = $this->get_property_obj('type', $base, $namespace);
|
||||
if (is_array($x)) {
|
||||
foreach ($x as $y) {
|
||||
if (strpos($y, ':') === false) {
|
||||
return $y;
|
||||
public static function is_an_actor($type)
|
||||
{
|
||||
if (!$type) {
|
||||
return false;
|
||||
}
|
||||
if (is_array($type)) {
|
||||
foreach ($type as $x) {
|
||||
if (self::is_an_actor($x)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return (in_array($type, ['Application', 'Group', 'Organization', 'Person', 'Service']));
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
function debug() {
|
||||
$x = var_export($this, true);
|
||||
return $x;
|
||||
}
|
||||
public static function is_response_activity($s)
|
||||
{
|
||||
if (!$s) {
|
||||
return false;
|
||||
}
|
||||
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
|
||||
}
|
||||
|
||||
|
||||
static function is_as_request() {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
$x = getBestSupportedMimeType([
|
||||
'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
|
||||
'application/activity+json',
|
||||
'application/ld+json;profile="http://www.w3.org/ns/activitystreams"',
|
||||
'application/ld+json', // required for Friendica ~2021-09, can possibly be removed after next release of that project
|
||||
'application/x-zot-activity+json'
|
||||
]);
|
||||
public function get_actor($property, $base = '', $namespace = '')
|
||||
{
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if (self::is_url($x)) {
|
||||
$y = Activity::get_cached_actor($x);
|
||||
if ($y) {
|
||||
return $y;
|
||||
}
|
||||
}
|
||||
|
||||
return(($x) ? true : false);
|
||||
}
|
||||
$actor = $this->get_compound_property($property, $base, $namespace, true);
|
||||
if (is_array($actor) && self::is_an_actor($actor['type'])) {
|
||||
if (array_key_exists('id', $actor) && (!array_key_exists('inbox', $actor))) {
|
||||
$actor = $this->fetch_property($actor['id']);
|
||||
}
|
||||
return $actor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @param bool $first (optional) default false, if true and result is a sequential array return only the first element
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
public function get_compound_property($property, $base = '', $namespace = '', $first = false)
|
||||
{
|
||||
$x = $this->get_property_obj($property, $base, $namespace);
|
||||
if (self::is_url($x)) {
|
||||
$y = $this->fetch_property($x);
|
||||
if (is_array($y)) {
|
||||
$x = $y;
|
||||
}
|
||||
}
|
||||
|
||||
// verify and unpack JSalmon signature if present
|
||||
// This may be present in Zot6 packets
|
||||
|
||||
if (is_array($x) && array_key_exists('signed', $x)) {
|
||||
$ret = JSalmon::verify($x);
|
||||
$tmp = JSalmon::unpack($x['data']);
|
||||
if ($ret && $ret['success']) {
|
||||
if ($ret['signer']) {
|
||||
logger('Unpacked: ' . json_encode($tmp, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOGGER_DATA, LOG_DEBUG);
|
||||
$saved = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$x = $tmp;
|
||||
$x['signer'] = $ret['signer'];
|
||||
$x['signed_data'] = $saved;
|
||||
if ($ret['hubloc']) {
|
||||
$x['hubloc'] = $ret['hubloc'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($first && is_array($x) && array_key_exists(0, $x)) {
|
||||
return $x[0];
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if string starts with http.
|
||||
*
|
||||
* @param string $url
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public static function is_url($url)
|
||||
{
|
||||
if (($url) && (!is_array($url)) && ((strpos($url, 'http') === 0) || (strpos($url, 'x-zot') === 0) || (strpos($url, 'bear') === 0))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the type property.
|
||||
*
|
||||
* @param array $base
|
||||
* @param string $namespace (optional) default empty
|
||||
* @return NULL|mixed
|
||||
*/
|
||||
|
||||
public function get_primary_type($base = '', $namespace = '')
|
||||
{
|
||||
if (!$base) {
|
||||
$base = $this->data;
|
||||
}
|
||||
$x = $this->get_property_obj('type', $base, $namespace);
|
||||
if (is_array($x)) {
|
||||
foreach ($x as $y) {
|
||||
if (strpos($y, ':') === false) {
|
||||
return $y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function debug()
|
||||
{
|
||||
$x = var_export($this, true);
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
||||
public static function is_as_request()
|
||||
{
|
||||
|
||||
$x = getBestSupportedMimeType([
|
||||
'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
|
||||
'application/activity+json',
|
||||
'application/ld+json;profile="http://www.w3.org/ns/activitystreams"',
|
||||
'application/ld+json', // required for Friendica ~2021-09, can possibly be removed after next release of that project
|
||||
'application/x-zot-activity+json'
|
||||
]);
|
||||
|
||||
return (($x) ? true : false);
|
||||
}
|
||||
}
|
|
@ -2,31 +2,33 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class Api_router
|
||||
{
|
||||
|
||||
class Api_router {
|
||||
private static $routes = [];
|
||||
|
||||
static private $routes = [];
|
||||
public static function register($path, $fn, $auth_required)
|
||||
{
|
||||
self::$routes[$path] = ['func' => $fn, 'auth' => $auth_required];
|
||||
}
|
||||
|
||||
static function register($path,$fn,$auth_required) {
|
||||
self::$routes[$path] = [ 'func' => $fn, 'auth' => $auth_required ];
|
||||
}
|
||||
public static function find($path)
|
||||
{
|
||||
if (array_key_exists($path, self::$routes)) {
|
||||
return self::$routes[$path];
|
||||
}
|
||||
|
||||
static function find($path) {
|
||||
if (array_key_exists($path,self::$routes)) {
|
||||
return self::$routes[$path];
|
||||
}
|
||||
$with_params = dirname($path) . '/[id]';
|
||||
|
||||
$with_params = dirname($path) . '/[id]';
|
||||
if (array_key_exists($with_params, self::$routes)) {
|
||||
return self::$routes[$with_params];
|
||||
}
|
||||
|
||||
if (array_key_exists($with_params,self::$routes)) {
|
||||
return self::$routes[$with_params];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static function dbg() {
|
||||
return self::$routes;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function dbg()
|
||||
{
|
||||
return self::$routes;
|
||||
}
|
||||
}
|
2634
Zotlabs/Lib/Apps.php
2634
Zotlabs/Lib/Apps.php
File diff suppressed because it is too large
Load diff
|
@ -1,51 +1,63 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
/**
|
||||
* cache api
|
||||
*/
|
||||
|
||||
class Cache {
|
||||
public static function get($key) {
|
||||
class Cache
|
||||
{
|
||||
public static function get($key)
|
||||
{
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
$hash = hash('whirlpool', $key);
|
||||
|
||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
$r = q(
|
||||
"SELECT v FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if ($r)
|
||||
return $r[0]['v'];
|
||||
return null;
|
||||
}
|
||||
if ($r) {
|
||||
return $r[0]['v'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function set($key,$value) {
|
||||
public static function set($key, $value)
|
||||
{
|
||||
|
||||
$hash = hash('whirlpool',$key);
|
||||
$hash = hash('whirlpool', $key);
|
||||
|
||||
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
if($r) {
|
||||
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($hash));
|
||||
}
|
||||
else {
|
||||
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
dbesc($hash),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()));
|
||||
}
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * FROM cache WHERE k = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
if ($r) {
|
||||
q(
|
||||
"UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($hash)
|
||||
);
|
||||
} else {
|
||||
q(
|
||||
"INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
|
||||
dbesc($hash),
|
||||
dbesc($value),
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function clear() {
|
||||
q("DELETE FROM cache WHERE updated < '%s'",
|
||||
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
|
||||
}
|
||||
|
||||
public static function clear()
|
||||
{
|
||||
q(
|
||||
"DELETE FROM cache WHERE updated < '%s'",
|
||||
dbesc(datetime_convert('UTC', 'UTC', "now - 30 days"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
@ -6,272 +7,307 @@ use Zotlabs\Lib\Libsync;
|
|||
/**
|
||||
* @brief A class with chatroom related static methods.
|
||||
*/
|
||||
class Chatroom {
|
||||
/**
|
||||
* @brief Creates a chatroom.
|
||||
*
|
||||
* @param array $channel
|
||||
* @param array $arr
|
||||
* @return array An associative array containing:
|
||||
* * \e boolean \b success - A boolean success status
|
||||
* * \e string \b message - (optional) A string
|
||||
*/
|
||||
static public function create($channel, $arr) {
|
||||
class Chatroom
|
||||
{
|
||||
/**
|
||||
* @brief Creates a chatroom.
|
||||
*
|
||||
* @param array $channel
|
||||
* @param array $arr
|
||||
* @return array An associative array containing:
|
||||
* * \e boolean \b success - A boolean success status
|
||||
* * \e string \b message - (optional) A string
|
||||
*/
|
||||
public static function create($channel, $arr)
|
||||
{
|
||||
|
||||
$ret = array('success' => false);
|
||||
$ret = array('success' => false);
|
||||
|
||||
$name = trim($arr['name']);
|
||||
if(! $name) {
|
||||
$ret['message'] = t('Missing room name');
|
||||
return $ret;
|
||||
}
|
||||
$name = trim($arr['name']);
|
||||
if (!$name) {
|
||||
$ret['message'] = t('Missing room name');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("select cr_id from chatroom where cr_uid = %d and cr_name = '%s' limit 1",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name)
|
||||
);
|
||||
if($r) {
|
||||
$ret['message'] = t('Duplicate room name');
|
||||
return $ret;
|
||||
}
|
||||
$r = q(
|
||||
"select cr_id from chatroom where cr_uid = %d and cr_name = '%s' limit 1",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name)
|
||||
);
|
||||
if ($r) {
|
||||
$ret['message'] = t('Duplicate room name');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("select count(cr_id) as total from chatroom where cr_aid = %d",
|
||||
intval($channel['channel_account_id'])
|
||||
);
|
||||
if($r)
|
||||
$limit = service_class_fetch($channel['channel_id'], 'chatrooms');
|
||||
$r = q(
|
||||
"select count(cr_id) as total from chatroom where cr_aid = %d",
|
||||
intval($channel['channel_account_id'])
|
||||
);
|
||||
if ($r) {
|
||||
$limit = service_class_fetch($channel['channel_id'], 'chatrooms');
|
||||
}
|
||||
|
||||
if(($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
|
||||
$ret['message'] = upgrade_message();
|
||||
return $ret;
|
||||
}
|
||||
if (($r) && ($limit !== false) && ($r[0]['total'] >= $limit)) {
|
||||
$ret['message'] = upgrade_message();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if(! array_key_exists('expire', $arr))
|
||||
$arr['expire'] = 120; // minutes, e.g. 2 hours
|
||||
if (!array_key_exists('expire', $arr)) {
|
||||
$arr['expire'] = 120; // minutes, e.g. 2 hours
|
||||
}
|
||||
|
||||
$created = datetime_convert();
|
||||
$created = datetime_convert();
|
||||
|
||||
$x = q("insert into chatroom ( cr_aid, cr_uid, cr_name, cr_created, cr_edited, cr_expire, allow_cid, allow_gid, deny_cid, deny_gid )
|
||||
$x = q(
|
||||
"insert into chatroom ( cr_aid, cr_uid, cr_name, cr_created, cr_edited, cr_expire, allow_cid, allow_gid, deny_cid, deny_gid )
|
||||
values ( %d, %d , '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($channel['channel_account_id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name),
|
||||
dbesc($created),
|
||||
dbesc($created),
|
||||
intval($arr['expire']),
|
||||
dbesc($arr['allow_cid']),
|
||||
dbesc($arr['allow_gid']),
|
||||
dbesc($arr['deny_cid']),
|
||||
dbesc($arr['deny_gid'])
|
||||
);
|
||||
intval($channel['channel_account_id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($name),
|
||||
dbesc($created),
|
||||
dbesc($created),
|
||||
intval($arr['expire']),
|
||||
dbesc($arr['allow_cid']),
|
||||
dbesc($arr['allow_gid']),
|
||||
dbesc($arr['deny_cid']),
|
||||
dbesc($arr['deny_gid'])
|
||||
);
|
||||
|
||||
if($x)
|
||||
$ret['success'] = true;
|
||||
if ($x) {
|
||||
$ret['success'] = true;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static public function destroy($channel,$arr) {
|
||||
public static function destroy($channel, $arr)
|
||||
{
|
||||
|
||||
$ret = array('success' => false);
|
||||
$ret = array('success' => false);
|
||||
|
||||
if(intval($arr['cr_id']))
|
||||
$sql_extra = " and cr_id = " . intval($arr['cr_id']) . " ";
|
||||
elseif(trim($arr['cr_name']))
|
||||
$sql_extra = " and cr_name = '" . protect_sprintf(dbesc(trim($arr['cr_name']))) . "' ";
|
||||
else {
|
||||
$ret['message'] = t('Invalid room specifier.');
|
||||
return $ret;
|
||||
}
|
||||
if (intval($arr['cr_id'])) {
|
||||
$sql_extra = " and cr_id = " . intval($arr['cr_id']) . " ";
|
||||
} elseif (trim($arr['cr_name'])) {
|
||||
$sql_extra = " and cr_name = '" . protect_sprintf(dbesc(trim($arr['cr_name']))) . "' ";
|
||||
} else {
|
||||
$ret['message'] = t('Invalid room specifier.');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$r = q("select * from chatroom where cr_uid = %d $sql_extra limit 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(! $r) {
|
||||
$ret['message'] = t('Invalid room specifier.');
|
||||
return $ret;
|
||||
}
|
||||
$r = q(
|
||||
"select * from chatroom where cr_uid = %d $sql_extra limit 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if (!$r) {
|
||||
$ret['message'] = t('Invalid room specifier.');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
Libsync::build_sync_packet($channel['channel_id'],array('chatroom' => $r));
|
||||
Libsync::build_sync_packet($channel['channel_id'], array('chatroom' => $r));
|
||||
|
||||
q("delete from chatroom where cr_id = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
if($r[0]['cr_id']) {
|
||||
q("delete from chatpresence where cp_room = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
q("delete from chat where chat_room = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
}
|
||||
q(
|
||||
"delete from chatroom where cr_id = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
if ($r[0]['cr_id']) {
|
||||
q(
|
||||
"delete from chatpresence where cp_room = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
q(
|
||||
"delete from chat where chat_room = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static public function enter($observer_xchan, $room_id, $status, $client) {
|
||||
public static function enter($observer_xchan, $room_id, $status, $client)
|
||||
{
|
||||
|
||||
if(! $room_id || ! $observer_xchan)
|
||||
return;
|
||||
if (!$room_id || !$observer_xchan) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from chatroom where cr_id = %d limit 1",
|
||||
intval($room_id)
|
||||
);
|
||||
if(! $r) {
|
||||
notice( t('Room not found.') . EOL);
|
||||
return false;
|
||||
}
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($r[0]['cr_uid']);
|
||||
$r = q(
|
||||
"select * from chatroom where cr_id = %d limit 1",
|
||||
intval($room_id)
|
||||
);
|
||||
if (!$r) {
|
||||
notice(t('Room not found.') . EOL);
|
||||
return false;
|
||||
}
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($r[0]['cr_uid']);
|
||||
|
||||
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
|
||||
intval($room_id),
|
||||
intval($r[0]['cr_uid'])
|
||||
);
|
||||
if(! $x) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return false;
|
||||
}
|
||||
$x = q(
|
||||
"select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
|
||||
intval($room_id),
|
||||
intval($r[0]['cr_uid'])
|
||||
);
|
||||
if (!$x) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return false;
|
||||
}
|
||||
|
||||
$limit = service_class_fetch($r[0]['cr_uid'], 'chatters_inroom');
|
||||
if($limit !== false) {
|
||||
$y = q("select count(*) as total from chatpresence where cp_room = %d",
|
||||
intval($room_id)
|
||||
);
|
||||
if($y && $y[0]['total'] > $limit) {
|
||||
notice( t('Room is full') . EOL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$limit = service_class_fetch($r[0]['cr_uid'], 'chatters_inroom');
|
||||
if ($limit !== false) {
|
||||
$y = q(
|
||||
"select count(*) as total from chatpresence where cp_room = %d",
|
||||
intval($room_id)
|
||||
);
|
||||
if ($y && $y[0]['total'] > $limit) {
|
||||
notice(t('Room is full') . EOL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(intval($x[0]['cr_expire'])) {
|
||||
$r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
|
||||
db_utcnow(),
|
||||
db_quoteinterval( intval($x[0]['cr_expire']) . ' MINUTE' ),
|
||||
intval($x[0]['cr_id'])
|
||||
);
|
||||
}
|
||||
if (intval($x[0]['cr_expire'])) {
|
||||
$r = q(
|
||||
"delete from chat where created < %s - INTERVAL %s and chat_room = %d",
|
||||
db_utcnow(),
|
||||
db_quoteinterval(intval($x[0]['cr_expire']) . ' MINUTE'),
|
||||
intval($x[0]['cr_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1",
|
||||
dbesc($observer_xchan),
|
||||
intval($room_id)
|
||||
);
|
||||
if($r) {
|
||||
q("update chatpresence set cp_last = '%s' where cp_id = %d and cp_client = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['cp_id']),
|
||||
dbesc($client)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
$r = q(
|
||||
"select * from chatpresence where cp_xchan = '%s' and cp_room = %d limit 1",
|
||||
dbesc($observer_xchan),
|
||||
intval($room_id)
|
||||
);
|
||||
if ($r) {
|
||||
q(
|
||||
"update chatpresence set cp_last = '%s' where cp_id = %d and cp_client = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['cp_id']),
|
||||
dbesc($client)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
$r = q("insert into chatpresence ( cp_room, cp_xchan, cp_last, cp_status, cp_client )
|
||||
$r = q(
|
||||
"insert into chatpresence ( cp_room, cp_xchan, cp_last, cp_status, cp_client )
|
||||
values ( %d, '%s', '%s', '%s', '%s' )",
|
||||
intval($room_id),
|
||||
dbesc($observer_xchan),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($status),
|
||||
dbesc($client)
|
||||
);
|
||||
intval($room_id),
|
||||
dbesc($observer_xchan),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($status),
|
||||
dbesc($client)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
function leave($observer_xchan, $room_id, $client) {
|
||||
if(! $room_id || ! $observer_xchan)
|
||||
return;
|
||||
public function leave($observer_xchan, $room_id, $client)
|
||||
{
|
||||
if (!$room_id || !$observer_xchan) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from chatpresence where cp_xchan = '%s' and cp_room = %d and cp_client = '%s' limit 1",
|
||||
dbesc($observer_xchan),
|
||||
intval($room_id),
|
||||
dbesc($client)
|
||||
);
|
||||
if($r) {
|
||||
q("delete from chatpresence where cp_id = %d",
|
||||
intval($r[0]['cp_id'])
|
||||
);
|
||||
}
|
||||
$r = q(
|
||||
"select * from chatpresence where cp_xchan = '%s' and cp_room = %d and cp_client = '%s' limit 1",
|
||||
dbesc($observer_xchan),
|
||||
intval($room_id),
|
||||
dbesc($client)
|
||||
);
|
||||
if ($r) {
|
||||
q(
|
||||
"delete from chatpresence where cp_id = %d",
|
||||
intval($r[0]['cp_id'])
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static public function roomlist($uid) {
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($uid);
|
||||
public static function roomlist($uid)
|
||||
{
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($uid);
|
||||
|
||||
$r = q("select allow_cid, allow_gid, deny_cid, deny_gid, cr_name, cr_expire, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d $sql_extra group by cr_name, cr_id order by cr_name",
|
||||
intval($uid)
|
||||
);
|
||||
$r = q(
|
||||
"select allow_cid, allow_gid, deny_cid, deny_gid, cr_name, cr_expire, cr_id, count(cp_id) as cr_inroom from chatroom left join chatpresence on cr_id = cp_room where cr_uid = %d $sql_extra group by cr_name, cr_id order by cr_name",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
static public function list_count($uid) {
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($uid);
|
||||
public static function list_count($uid)
|
||||
{
|
||||
require_once('include/security.php');
|
||||
$sql_extra = permissions_sql($uid);
|
||||
|
||||
$r = q("select count(*) as total from chatroom where cr_uid = %d $sql_extra",
|
||||
intval($uid)
|
||||
);
|
||||
$r = q(
|
||||
"select count(*) as total from chatroom where cr_uid = %d $sql_extra",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
return $r[0]['total'];
|
||||
}
|
||||
return $r[0]['total'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a chat message via API.
|
||||
*
|
||||
* It is the caller's responsibility to enter the room.
|
||||
*
|
||||
* @param int $uid
|
||||
* @param int $room_id
|
||||
* @param string $xchan
|
||||
* @param string $text
|
||||
* @return array
|
||||
*/
|
||||
static public function message($uid, $room_id, $xchan, $text) {
|
||||
/**
|
||||
* @brief Create a chat message via API.
|
||||
*
|
||||
* It is the caller's responsibility to enter the room.
|
||||
*
|
||||
* @param int $uid
|
||||
* @param int $room_id
|
||||
* @param string $xchan
|
||||
* @param string $text
|
||||
* @return array
|
||||
*/
|
||||
public static function message($uid, $room_id, $xchan, $text)
|
||||
{
|
||||
|
||||
$ret = array('success' => false);
|
||||
$ret = array('success' => false);
|
||||
|
||||
if(! $text)
|
||||
return;
|
||||
if (!$text) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql_extra = permissions_sql($uid);
|
||||
$sql_extra = permissions_sql($uid);
|
||||
|
||||
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
|
||||
intval($uid),
|
||||
intval($room_id)
|
||||
);
|
||||
if(! $r)
|
||||
return $ret;
|
||||
$r = q(
|
||||
"select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
|
||||
intval($uid),
|
||||
intval($room_id)
|
||||
);
|
||||
if (!$r) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$arr = [
|
||||
'chat_room' => $room_id,
|
||||
'chat_xchan' => $xchan,
|
||||
'chat_text' => $text
|
||||
];
|
||||
/**
|
||||
* @hooks chat_message
|
||||
* Called to create a chat message.
|
||||
* * \e int \b chat_room
|
||||
* * \e string \b chat_xchan
|
||||
* * \e string \b chat_text
|
||||
*/
|
||||
call_hooks('chat_message', $arr);
|
||||
$arr = [
|
||||
'chat_room' => $room_id,
|
||||
'chat_xchan' => $xchan,
|
||||
'chat_text' => $text
|
||||
];
|
||||
/**
|
||||
* @hooks chat_message
|
||||
* Called to create a chat message.
|
||||
* * \e int \b chat_room
|
||||
* * \e string \b chat_xchan
|
||||
* * \e string \b chat_text
|
||||
*/
|
||||
call_hooks('chat_message', $arr);
|
||||
|
||||
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
|
||||
$x = q(
|
||||
"insert into chat ( chat_room, chat_xchan, created, chat_text )
|
||||
values( %d, '%s', '%s', '%s' )",
|
||||
intval($room_id),
|
||||
dbesc($xchan),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(str_rot47(base64url_encode($arr['chat_text'])))
|
||||
);
|
||||
intval($room_id),
|
||||
dbesc($xchan),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(str_rot47(base64url_encode($arr['chat_text'])))
|
||||
);
|
||||
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,161 +2,174 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
class Config {
|
||||
class Config
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Loads the hub's configuration from database to a cached storage.
|
||||
*
|
||||
* Retrieve a category ($family) of config variables from database to a cached
|
||||
* storage in the global App::$config[$family].
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
*/
|
||||
static public function Load($family) {
|
||||
if(! array_key_exists($family, \App::$config))
|
||||
\App::$config[$family] = [];
|
||||
/**
|
||||
* @brief Loads the hub's configuration from database to a cached storage.
|
||||
*
|
||||
* Retrieve a category ($family) of config variables from database to a cached
|
||||
* storage in the global App::$config[$family].
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
*/
|
||||
public static function Load($family)
|
||||
{
|
||||
if (! array_key_exists($family, App::$config)) {
|
||||
App::$config[$family] = [];
|
||||
}
|
||||
|
||||
if(! array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
|
||||
if($r !== false) {
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
\App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
\App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! array_key_exists('config_loaded', App::$config[$family])) {
|
||||
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
|
||||
if ($r !== false) {
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
App::$config[$family][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
App::$config[$family]['config_loaded'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a configuration value for the hub.
|
||||
*
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key).
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to set
|
||||
* @param mixed $value
|
||||
* The value to store in the configuration
|
||||
* @return mixed
|
||||
* Return the set value, or false if the database update failed
|
||||
*/
|
||||
static public function Set($family, $key, $value) {
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
/**
|
||||
* @brief Sets a configuration value for the hub.
|
||||
*
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key).
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to set
|
||||
* @param mixed $value
|
||||
* The value to store in the configuration
|
||||
* @return mixed
|
||||
* Return the set value, or false if the database update failed
|
||||
*/
|
||||
public static function Set($family, $key, $value)
|
||||
{
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
if (self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
|
||||
$ret = q(
|
||||
"INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret = q("UPDATE config SET v = '%s' WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
$ret = q(
|
||||
"UPDATE config SET v = '%s' WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
if($ret) {
|
||||
\App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
if ($ret) {
|
||||
App::$config[$family][$key] = $value;
|
||||
$ret = $value;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a particular config variable given the category name ($family)
|
||||
* and a key.
|
||||
*
|
||||
* Get a particular config variable from the given category ($family) and the
|
||||
* $key from a cached storage in App::$config[$family]. If a key is found in the
|
||||
* DB but does not exist in local config cache, pull it into the cache so we
|
||||
* do not have to hit the DB again for this item.
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param string $default (optional) default false
|
||||
* @return mixed Return value or false on error or if not set
|
||||
*/
|
||||
static public function Get($family, $key, $default = false) {
|
||||
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
|
||||
self::Load($family);
|
||||
/**
|
||||
* @brief Get a particular config variable given the category name ($family)
|
||||
* and a key.
|
||||
*
|
||||
* Get a particular config variable from the given category ($family) and the
|
||||
* $key from a cached storage in App::$config[$family]. If a key is found in the
|
||||
* DB but does not exist in local config cache, pull it into the cache so we
|
||||
* do not have to hit the DB again for this item.
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param string $default (optional) default false
|
||||
* @return mixed Return value or false on error or if not set
|
||||
*/
|
||||
public static function Get($family, $key, $default = false)
|
||||
{
|
||||
if ((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family]))) {
|
||||
self::Load($family);
|
||||
}
|
||||
|
||||
if(array_key_exists('config_loaded', \App::$config[$family])) {
|
||||
if(! array_key_exists($key, \App::$config[$family])) {
|
||||
return $default;
|
||||
}
|
||||
return unserialise(\App::$config[$family][$key]);
|
||||
}
|
||||
if (array_key_exists('config_loaded', App::$config[$family])) {
|
||||
if (! array_key_exists($key, App::$config[$family])) {
|
||||
return $default;
|
||||
}
|
||||
return unserialise(App::$config[$family][$key]);
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deletes the given key from the hub's configuration database.
|
||||
*
|
||||
* Removes the configured value from the stored cache in App::$config[$family]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($family, $key) {
|
||||
/**
|
||||
* @brief Deletes the given key from the hub's configuration database.
|
||||
*
|
||||
* Removes the configured value from the stored cache in App::$config[$family]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
public static function Delete($family, $key)
|
||||
{
|
||||
|
||||
$ret = false;
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
|
||||
unset(\App::$config[$family][$key]);
|
||||
if (array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family])) {
|
||||
unset(App::$config[$family][$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
$ret = q(
|
||||
"DELETE FROM config WHERE cat = '%s' AND k = '%s'",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns a record directly from the database configuration storage.
|
||||
*
|
||||
* This function queries directly the database and bypasses the cached storage
|
||||
* from get_config($family, $key).
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @return mixed
|
||||
*/
|
||||
static private function get_from_storage($family,$key) {
|
||||
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
/**
|
||||
* @brief Returns a record directly from the database configuration storage.
|
||||
*
|
||||
* This function queries directly the database and bypasses the cached storage
|
||||
* from get_config($family, $key).
|
||||
*
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @return mixed
|
||||
*/
|
||||
private static function get_from_storage($family, $key)
|
||||
{
|
||||
$ret = q(
|
||||
"SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
@ -6,303 +8,304 @@ use App;
|
|||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Run;
|
||||
|
||||
class Connect
|
||||
{
|
||||
|
||||
/**
|
||||
* Takes a $channel and a $url/handle and adds a new connection
|
||||
*
|
||||
* Returns array
|
||||
* $return['success'] boolean true if successful
|
||||
* $return['abook'] Address book entry joined with xchan if successful
|
||||
* $return['message'] error text if success is false.
|
||||
*
|
||||
* This function does NOT send sync packets to clones. The caller is responsible for doing this
|
||||
*/
|
||||
|
||||
public static function connect($channel, $url, $sub_channel = false)
|
||||
{
|
||||
|
||||
$uid = $channel['channel_id'];
|
||||
|
||||
if (strpos($url, '@') === false && strpos($url, '/') === false) {
|
||||
$url = $url . '@' . App::get_hostname();
|
||||
}
|
||||
|
||||
$result = ['success' => false, 'message' => ''];
|
||||
|
||||
$my_perms = false;
|
||||
$protocol = '';
|
||||
|
||||
$ap_allowed = get_config('system', 'activitypub', ACTIVITYPUB_ENABLED) && get_pconfig($uid, 'system', 'activitypub', ACTIVITYPUB_ENABLED);
|
||||
|
||||
if (substr($url, 0, 1) === '[') {
|
||||
$x = strpos($url, ']');
|
||||
if ($x) {
|
||||
$protocol = substr($url, 1, $x - 1);
|
||||
$url = substr($url, $x + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_siteallowed($url)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (!$url) {
|
||||
$result['message'] = t('Channel location missing.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
// check service class limits
|
||||
|
||||
$r = q(
|
||||
"select count(*) as total from abook where abook_channel = %d and abook_self = 0 ",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$total_channels = $r[0]['total'];
|
||||
}
|
||||
|
||||
if (!service_class_allows($uid, 'total_channels', $total_channels)) {
|
||||
$result['message'] = upgrade_message();
|
||||
return $result;
|
||||
}
|
||||
|
||||
$xchan_hash = '';
|
||||
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
|
||||
|
||||
$r = q(
|
||||
"select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ",
|
||||
dbesc($url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
// reset results to the best record or the first if we don't have the best
|
||||
// note: this returns a single record and not an array of records
|
||||
|
||||
$r = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
|
||||
// ensure there's a valid hubloc for this xchan before proceeding - you cannot connect without it
|
||||
|
||||
if (in_array($r['xchan_network'], ['nomad', 'zot6', 'activitypub'])) {
|
||||
$h = q(
|
||||
"select * from hubloc where hubloc_hash = '%s'",
|
||||
dbesc($r['xchan_hash'])
|
||||
);
|
||||
if (!$h) {
|
||||
$r = null;
|
||||
}
|
||||
}
|
||||
|
||||
// we may have nulled out this record so check again
|
||||
|
||||
if ($r) {
|
||||
// Check the site table to see if we should have a zot6 hubloc,
|
||||
// If so, clear the xchan and start fresh
|
||||
|
||||
if ($r['xchan_network'] === 'activitypub') {
|
||||
$m = parse_url($r['xchan_hash']);
|
||||
unset($m['path']);
|
||||
$h = unparse_url($m);
|
||||
$s = q(
|
||||
"select * from site where site_url = '%s'",
|
||||
dbesc($h)
|
||||
);
|
||||
if (intval($s['site_type']) === SITE_TYPE_ZOT) {
|
||||
logger('got zot - ignore activitypub entry');
|
||||
$r = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Connect {
|
||||
$singleton = false;
|
||||
|
||||
/**
|
||||
* Takes a $channel and a $url/handle and adds a new connection
|
||||
*
|
||||
* Returns array
|
||||
* $return['success'] boolean true if successful
|
||||
* $return['abook'] Address book entry joined with xchan if successful
|
||||
* $return['message'] error text if success is false.
|
||||
*
|
||||
* This function does NOT send sync packets to clones. The caller is responsible for doing this
|
||||
*/
|
||||
if (!$r) {
|
||||
// not in cache - try discovery
|
||||
|
||||
static function connect($channel, $url, $sub_channel = false) {
|
||||
$wf = discover_by_webbie($url, $protocol, false);
|
||||
|
||||
$uid = $channel['channel_id'];
|
||||
if (!$wf) {
|
||||
$result['message'] = t('Remote channel or protocol unavailable.');
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos($url,'@') === false && strpos($url,'/') === false) {
|
||||
$url = $url . '@' . App::get_hostname();
|
||||
}
|
||||
if ($wf) {
|
||||
// something was discovered - find the record which was just created.
|
||||
|
||||
$result = [ 'success' => false, 'message' => '' ];
|
||||
$r = q(
|
||||
"select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' ) $sql_options",
|
||||
dbesc(($wf) ? $wf : $url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
$my_perms = false;
|
||||
$protocol = '';
|
||||
// convert to a single record (once again preferring a zot solution in the case of multiples)
|
||||
|
||||
$ap_allowed = get_config('system','activitypub', ACTIVITYPUB_ENABLED) && get_pconfig($uid,'system','activitypub', ACTIVITYPUB_ENABLED);
|
||||
if ($r) {
|
||||
$r = Libzot::zot_record_preferred($r, 'xchan_network');
|
||||
}
|
||||
}
|
||||
|
||||
if (substr($url,0,1) === '[') {
|
||||
$x = strpos($url,']');
|
||||
if ($x) {
|
||||
$protocol = substr($url,1,$x-1);
|
||||
$url = substr($url,$x+1);
|
||||
}
|
||||
}
|
||||
// if discovery was a success or the channel was already cached we should have an xchan record in $r
|
||||
|
||||
if (! check_siteallowed($url)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
return $result;
|
||||
}
|
||||
if ($r) {
|
||||
$xchan = $r;
|
||||
$xchan_hash = $r['xchan_hash'];
|
||||
$their_perms = EMPTY_STR;
|
||||
}
|
||||
|
||||
if (! $url) {
|
||||
$result['message'] = t('Channel location missing.');
|
||||
return $result;
|
||||
}
|
||||
// failure case
|
||||
|
||||
// check service class limits
|
||||
if (!$xchan_hash) {
|
||||
$result['message'] = t('Channel discovery failed.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
$r = q("select count(*) as total from abook where abook_channel = %d and abook_self = 0 ",
|
||||
intval($uid)
|
||||
);
|
||||
if ($r) {
|
||||
$total_channels = $r[0]['total'];
|
||||
}
|
||||
|
||||
if (! service_class_allows($uid,'total_channels',$total_channels)) {
|
||||
$result['message'] = upgrade_message();
|
||||
return $result;
|
||||
}
|
||||
|
||||
$xchan_hash = '';
|
||||
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
|
||||
|
||||
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ",
|
||||
dbesc($url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
|
||||
// reset results to the best record or the first if we don't have the best
|
||||
// note: this returns a single record and not an array of records
|
||||
|
||||
$r = Libzot::zot_record_preferred($r,'xchan_network');
|
||||
|
||||
// ensure there's a valid hubloc for this xchan before proceeding - you cannot connect without it
|
||||
|
||||
if (in_array($r['xchan_network'], [ 'nomad','zot6','activitypub' ])) {
|
||||
$h = q("select * from hubloc where hubloc_hash = '%s'",
|
||||
dbesc($r['xchan_hash'])
|
||||
);
|
||||
if (! $h) {
|
||||
$r = null;
|
||||
}
|
||||
}
|
||||
|
||||
// we may have nulled out this record so check again
|
||||
|
||||
if ($r) {
|
||||
|
||||
// Check the site table to see if we should have a zot6 hubloc,
|
||||
// If so, clear the xchan and start fresh
|
||||
|
||||
if ($r['xchan_network'] === 'activitypub') {
|
||||
$m = parse_url($r['xchan_hash']);
|
||||
unset($m['path']);
|
||||
$h = unparse_url($m);
|
||||
$s = q("select * from site where site_url = '%s'",
|
||||
dbesc($h)
|
||||
);
|
||||
if (intval($s['site_type']) === SITE_TYPE_ZOT) {
|
||||
logger('got zot - ignore activitypub entry');
|
||||
$r = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!check_channelallowed($xchan_hash)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
$singleton = false;
|
||||
if ($r['xchan_network'] === 'activitypub') {
|
||||
if (!$ap_allowed) {
|
||||
$result['message'] = t('Protocol not supported');
|
||||
return $result;
|
||||
}
|
||||
$singleton = true;
|
||||
}
|
||||
|
||||
if (! $r) {
|
||||
// Now start processing the new connection
|
||||
|
||||
// not in cache - try discovery
|
||||
$aid = $channel['channel_account_id'];
|
||||
$hash = $channel['channel_hash'];
|
||||
$default_group = $channel['channel_default_group'];
|
||||
|
||||
$wf = discover_by_webbie($url,$protocol,false);
|
||||
if ($hash === $xchan_hash) {
|
||||
$result['message'] = t('Cannot connect to yourself.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (! $wf) {
|
||||
$result['message'] = t('Remote channel or protocol unavailable.');
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
$p = Permissions::connect_perms($uid);
|
||||
|
||||
if ($wf) {
|
||||
// parent channels have unencumbered write permission
|
||||
|
||||
// something was discovered - find the record which was just created.
|
||||
if ($sub_channel) {
|
||||
$p['perms']['post_wall'] = 1;
|
||||
$p['perms']['post_comments'] = 1;
|
||||
$p['perms']['write_storage'] = 1;
|
||||
$p['perms']['post_like'] = 1;
|
||||
$p['perms']['delegate'] = 0;
|
||||
$p['perms']['moderated'] = 0;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' ) $sql_options",
|
||||
dbesc(($wf) ? $wf : $url),
|
||||
dbesc($url),
|
||||
dbesc($url)
|
||||
);
|
||||
$my_perms = Permissions::serialise($p['perms']);
|
||||
|
||||
// convert to a single record (once again preferring a zot solution in the case of multiples)
|
||||
$profile_assign = get_pconfig($uid, 'system', 'profile_assign', '');
|
||||
|
||||
if ($r) {
|
||||
$r = Libzot::zot_record_preferred($r,'xchan_network');
|
||||
}
|
||||
}
|
||||
// See if we are already connected by virtue of having an abook record
|
||||
|
||||
// if discovery was a success or the channel was already cached we should have an xchan record in $r
|
||||
|
||||
if ($r) {
|
||||
$xchan = $r;
|
||||
$xchan_hash = $r['xchan_hash'];
|
||||
$their_perms = EMPTY_STR;
|
||||
}
|
||||
|
||||
// failure case
|
||||
|
||||
if (! $xchan_hash) {
|
||||
$result['message'] = t('Channel discovery failed.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (! check_channelallowed($xchan_hash)) {
|
||||
$result['message'] = t('Channel is blocked on this site.');
|
||||
logger('follow: ' . $result['message']);
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($r['xchan_network'] === 'activitypub') {
|
||||
if (! $ap_allowed) {
|
||||
$result['message'] = t('Protocol not supported');
|
||||
return $result;
|
||||
}
|
||||
$singleton = true;
|
||||
}
|
||||
|
||||
// Now start processing the new connection
|
||||
|
||||
$aid = $channel['channel_account_id'];
|
||||
$hash = $channel['channel_hash'];
|
||||
$default_group = $channel['channel_default_group'];
|
||||
|
||||
if ($hash === $xchan_hash) {
|
||||
$result['message'] = t('Cannot connect to yourself.');
|
||||
return $result;
|
||||
}
|
||||
|
||||
$p = Permissions::connect_perms($uid);
|
||||
|
||||
// parent channels have unencumbered write permission
|
||||
|
||||
if ($sub_channel) {
|
||||
$p['perms']['post_wall'] = 1;
|
||||
$p['perms']['post_comments'] = 1;
|
||||
$p['perms']['write_storage'] = 1;
|
||||
$p['perms']['post_like'] = 1;
|
||||
$p['perms']['delegate'] = 0;
|
||||
$p['perms']['moderated'] = 0;
|
||||
}
|
||||
|
||||
$my_perms = Permissions::serialise($p['perms']);
|
||||
|
||||
$profile_assign = get_pconfig($uid,'system','profile_assign','');
|
||||
|
||||
// See if we are already connected by virtue of having an abook record
|
||||
|
||||
$r = q("select abook_id, abook_xchan, abook_pending, abook_instance from abook
|
||||
$r = q(
|
||||
"select abook_id, abook_xchan, abook_pending, abook_instance from abook
|
||||
where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
);
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
if ($r) {
|
||||
$abook_instance = $r[0]['abook_instance'];
|
||||
|
||||
$abook_instance = $r[0]['abook_instance'];
|
||||
// If they are on a non-nomadic network, add them to this location
|
||||
|
||||
// If they are on a non-nomadic network, add them to this location
|
||||
if (($singleton) && strpos($abook_instance, z_root()) === false) {
|
||||
if ($abook_instance) {
|
||||
$abook_instance .= ',';
|
||||
}
|
||||
$abook_instance .= z_root();
|
||||
|
||||
if (($singleton) && strpos($abook_instance,z_root()) === false) {
|
||||
if ($abook_instance) {
|
||||
$abook_instance .= ',';
|
||||
}
|
||||
$abook_instance .= z_root();
|
||||
$x = q(
|
||||
"update abook set abook_instance = '%s', abook_not_here = 0 where abook_id = %d",
|
||||
dbesc($abook_instance),
|
||||
intval($r[0]['abook_id'])
|
||||
);
|
||||
}
|
||||
|
||||
$x = q("update abook set abook_instance = '%s', abook_not_here = 0 where abook_id = %d",
|
||||
dbesc($abook_instance),
|
||||
intval($r[0]['abook_id'])
|
||||
);
|
||||
}
|
||||
// if they have a pending connection, we just followed them so approve the connection request
|
||||
|
||||
// if they have a pending connection, we just followed them so approve the connection request
|
||||
if (intval($r[0]['abook_pending'])) {
|
||||
$x = q(
|
||||
"update abook set abook_pending = 0 where abook_id = %d",
|
||||
intval($r[0]['abook_id'])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// create a new abook record
|
||||
|
||||
if (intval($r[0]['abook_pending'])) {
|
||||
$x = q("update abook set abook_pending = 0 where abook_id = %d",
|
||||
intval($r[0]['abook_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$closeness = get_pconfig($uid, 'system', 'new_abook_closeness', 80);
|
||||
|
||||
// create a new abook record
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
'abook_account' => intval($aid),
|
||||
'abook_channel' => intval($uid),
|
||||
'abook_closeness' => intval($closeness),
|
||||
'abook_xchan' => $xchan_hash,
|
||||
'abook_profile' => $profile_assign,
|
||||
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_instance' => (($singleton) ? z_root() : '')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$closeness = get_pconfig($uid,'system','new_abook_closeness',80);
|
||||
if (!$r) {
|
||||
logger('abook creation failed');
|
||||
$result['message'] = t('error saving data');
|
||||
return $result;
|
||||
}
|
||||
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
'abook_account' => intval($aid),
|
||||
'abook_channel' => intval($uid),
|
||||
'abook_closeness' => intval($closeness),
|
||||
'abook_xchan' => $xchan_hash,
|
||||
'abook_profile' => $profile_assign,
|
||||
'abook_feed' => intval(($xchan['xchan_network'] === 'rss') ? 1 : 0),
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_instance' => (($singleton) ? z_root() : '')
|
||||
]
|
||||
);
|
||||
}
|
||||
// Set suitable permissions to the connection
|
||||
|
||||
if (! $r) {
|
||||
logger('abook creation failed');
|
||||
$result['message'] = t('error saving data');
|
||||
return $result;
|
||||
}
|
||||
if ($my_perms) {
|
||||
set_abconfig($uid, $xchan_hash, 'system', 'my_perms', $my_perms);
|
||||
}
|
||||
|
||||
// Set suitable permissions to the connection
|
||||
// fetch the entire record
|
||||
|
||||
if ($my_perms) {
|
||||
set_abconfig($uid,$xchan_hash,'system','my_perms',$my_perms);
|
||||
}
|
||||
|
||||
// fetch the entire record
|
||||
|
||||
$r = q("select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
$r = q(
|
||||
"select abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash
|
||||
where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
);
|
||||
dbesc($xchan_hash),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$result['abook'] = array_shift($r);
|
||||
Run::Summon([ 'Notifier', 'permissions_create', $result['abook']['abook_id'] ]);
|
||||
}
|
||||
if ($r) {
|
||||
$result['abook'] = array_shift($r);
|
||||
Run::Summon(['Notifier', 'permissions_create', $result['abook']['abook_id']]);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'channel' => $channel, 'abook' => $result['abook'] ];
|
||||
$arr = ['channel_id' => $uid, 'channel' => $channel, 'abook' => $result['abook']];
|
||||
|
||||
call_hooks('follow', $arr);
|
||||
call_hooks('follow', $arr);
|
||||
|
||||
/** If there is a default group for this channel, add this connection to it */
|
||||
/** If there is a default group for this channel, add this connection to it */
|
||||
|
||||
if ($default_group) {
|
||||
$g = AccessList::rec_byhash($uid,$default_group);
|
||||
if ($g) {
|
||||
AccessList::member_add($uid,'',$xchan_hash,$g['id']);
|
||||
}
|
||||
}
|
||||
if ($default_group) {
|
||||
$g = AccessList::rec_byhash($uid, $default_group);
|
||||
if ($g) {
|
||||
AccessList::member_add($uid, '', $xchan_hash, $g['id']);
|
||||
}
|
||||
}
|
||||
|
||||
$result['success'] = true;
|
||||
return $result;
|
||||
}
|
||||
$result['success'] = true;
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -1,210 +1,213 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Exception;
|
||||
|
||||
class Crypto {
|
||||
class Crypto
|
||||
{
|
||||
|
||||
static public $openssl_algorithms = [
|
||||
public static $openssl_algorithms = [
|
||||
|
||||
// zot6 nickname, opensslname, keylength, ivlength
|
||||
// zot6 nickname, opensslname, keylength, ivlength
|
||||
|
||||
[ 'aes256ctr', 'aes-256-ctr', 32, 16 ],
|
||||
[ 'camellia256cfb', 'camellia-256-cfb', 32, 16 ],
|
||||
[ 'cast5cfb', 'cast5-cfb', 16, 8 ]
|
||||
[ 'aes256ctr', 'aes-256-ctr', 32, 16 ],
|
||||
[ 'camellia256cfb', 'camellia-256-cfb', 32, 16 ],
|
||||
[ 'cast5cfb', 'cast5-cfb', 16, 8 ]
|
||||
|
||||
];
|
||||
];
|
||||
|
||||
|
||||
static public function methods() {
|
||||
$ret = [];
|
||||
public static function methods()
|
||||
{
|
||||
$ret = [];
|
||||
|
||||
foreach(self::$openssl_algorithms as $ossl) {
|
||||
$ret[] = $ossl[0] . '.oaep';
|
||||
}
|
||||
foreach (self::$openssl_algorithms as $ossl) {
|
||||
$ret[] = $ossl[0] . '.oaep';
|
||||
}
|
||||
|
||||
call_hooks('crypto_methods',$ret);
|
||||
return $ret;
|
||||
}
|
||||
call_hooks('crypto_methods', $ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static public function signing_methods() {
|
||||
public static function signing_methods()
|
||||
{
|
||||
|
||||
$ret = [ 'sha256' ];
|
||||
call_hooks('signing_methods',$ret);
|
||||
return $ret;
|
||||
|
||||
}
|
||||
$ret = [ 'sha256' ];
|
||||
call_hooks('signing_methods', $ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
static public function new_keypair($bits) {
|
||||
public static function new_keypair($bits)
|
||||
{
|
||||
|
||||
$openssl_options = [
|
||||
'digest_alg' => 'sha1',
|
||||
'private_key_bits' => $bits,
|
||||
'encrypt_key' => false
|
||||
];
|
||||
$openssl_options = [
|
||||
'digest_alg' => 'sha1',
|
||||
'private_key_bits' => $bits,
|
||||
'encrypt_key' => false
|
||||
];
|
||||
|
||||
$conf = get_config('system','openssl_conf_file');
|
||||
$conf = get_config('system', 'openssl_conf_file');
|
||||
|
||||
if ($conf) {
|
||||
$openssl_options['config'] = $conf;
|
||||
}
|
||||
if ($conf) {
|
||||
$openssl_options['config'] = $conf;
|
||||
}
|
||||
|
||||
$result = openssl_pkey_new($openssl_options);
|
||||
$result = openssl_pkey_new($openssl_options);
|
||||
|
||||
if (empty($result)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get private key
|
||||
// Get private key
|
||||
|
||||
$response = [ 'prvkey' => '', 'pubkey' => '' ];
|
||||
$response = [ 'prvkey' => '', 'pubkey' => '' ];
|
||||
|
||||
openssl_pkey_export($result, $response['prvkey']);
|
||||
openssl_pkey_export($result, $response['prvkey']);
|
||||
|
||||
// Get public key
|
||||
$pkey = openssl_pkey_get_details($result);
|
||||
$response['pubkey'] = $pkey["key"];
|
||||
// Get public key
|
||||
$pkey = openssl_pkey_get_details($result);
|
||||
$response['pubkey'] = $pkey["key"];
|
||||
|
||||
return $response;
|
||||
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
static public function sign($data,$key,$alg = 'sha256') {
|
||||
public static function sign($data, $key, $alg = 'sha256')
|
||||
{
|
||||
|
||||
if (! $key) {
|
||||
return false;
|
||||
}
|
||||
if (! $key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sig = '';
|
||||
openssl_sign($data,$sig,$key,$alg);
|
||||
return $sig;
|
||||
}
|
||||
$sig = '';
|
||||
openssl_sign($data, $sig, $key, $alg);
|
||||
return $sig;
|
||||
}
|
||||
|
||||
|
||||
static public function verify($data,$sig,$key,$alg = 'sha256') {
|
||||
public static function verify($data, $sig, $key, $alg = 'sha256')
|
||||
{
|
||||
|
||||
if (! $key) {
|
||||
return false;
|
||||
}
|
||||
if (! $key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$verify = openssl_verify($data,$sig,$key,$alg);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$verify = (-1);
|
||||
}
|
||||
try {
|
||||
$verify = openssl_verify($data, $sig, $key, $alg);
|
||||
} catch (Exception $e) {
|
||||
$verify = (-1);
|
||||
}
|
||||
|
||||
if ($verify === (-1)) {
|
||||
while ($msg = openssl_error_string()) {
|
||||
logger('openssl_verify: ' . $msg,LOGGER_NORMAL,LOG_ERR);
|
||||
}
|
||||
btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
if ($verify === (-1)) {
|
||||
while ($msg = openssl_error_string()) {
|
||||
logger('openssl_verify: ' . $msg, LOGGER_NORMAL, LOG_ERR);
|
||||
}
|
||||
btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
|
||||
return (($verify > 0) ? true : false);
|
||||
}
|
||||
return (($verify > 0) ? true : false);
|
||||
}
|
||||
|
||||
static public function encapsulate($data,$pubkey,$alg) {
|
||||
public static function encapsulate($data, $pubkey, $alg)
|
||||
{
|
||||
|
||||
if (! ($alg && $pubkey)) {
|
||||
return $data;
|
||||
}
|
||||
if (! ($alg && $pubkey)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$alg_base = $alg;
|
||||
$padding = OPENSSL_PKCS1_PADDING;
|
||||
$alg_base = $alg;
|
||||
$padding = OPENSSL_PKCS1_PADDING;
|
||||
|
||||
$exts = explode('.',$alg);
|
||||
if (count($exts) > 1) {
|
||||
switch ($exts[1]) {
|
||||
case 'oaep':
|
||||
$padding = OPENSSL_PKCS1_OAEP_PADDING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$alg_base = $exts[0];
|
||||
}
|
||||
$exts = explode('.', $alg);
|
||||
if (count($exts) > 1) {
|
||||
switch ($exts[1]) {
|
||||
case 'oaep':
|
||||
$padding = OPENSSL_PKCS1_OAEP_PADDING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$alg_base = $exts[0];
|
||||
}
|
||||
|
||||
$method = null;
|
||||
$method = null;
|
||||
|
||||
foreach (self::$openssl_algorithms as $ossl) {
|
||||
if ($ossl[0] === $alg_base) {
|
||||
$method = $ossl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (self::$openssl_algorithms as $ossl) {
|
||||
if ($ossl[0] === $alg_base) {
|
||||
$method = $ossl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($method) {
|
||||
$result = [ 'encrypted' => true ];
|
||||
if ($method) {
|
||||
$result = [ 'encrypted' => true ];
|
||||
|
||||
$key = openssl_random_pseudo_bytes(256);
|
||||
$iv = openssl_random_pseudo_bytes(256);
|
||||
$key = openssl_random_pseudo_bytes(256);
|
||||
$iv = openssl_random_pseudo_bytes(256);
|
||||
|
||||
$key1 = substr($key, 0, $method[2]);
|
||||
$iv1 = substr($iv, 0, $method[3]);
|
||||
$key1 = substr($key, 0, $method[2]);
|
||||
$iv1 = substr($iv, 0, $method[3]);
|
||||
|
||||
$result['data'] = base64url_encode(openssl_encrypt($data,$method[1],$key1,OPENSSL_RAW_DATA,$iv1),true);
|
||||
$result['data'] = base64url_encode(openssl_encrypt($data, $method[1], $key1, OPENSSL_RAW_DATA, $iv1), true);
|
||||
|
||||
openssl_public_encrypt($key, $k, $pubkey, $padding);
|
||||
openssl_public_encrypt($iv, $i, $pubkey, $padding);
|
||||
openssl_public_encrypt($key, $k, $pubkey, $padding);
|
||||
openssl_public_encrypt($iv, $i, $pubkey, $padding);
|
||||
|
||||
$result['alg'] = $alg;
|
||||
$result['key'] = base64url_encode($k,true);
|
||||
$result['iv'] = base64url_encode($i,true);
|
||||
return $result;
|
||||
$result['alg'] = $alg;
|
||||
$result['key'] = base64url_encode($k, true);
|
||||
$result['iv'] = base64url_encode($i, true);
|
||||
return $result;
|
||||
} else {
|
||||
$x = [ 'data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data ];
|
||||
call_hooks('crypto_encapsulate', $x);
|
||||
return $x['result'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
$x = [ 'data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data ];
|
||||
call_hooks('crypto_encapsulate', $x);
|
||||
return $x['result'];
|
||||
}
|
||||
}
|
||||
public static function unencapsulate($data, $prvkey)
|
||||
{
|
||||
|
||||
static public function unencapsulate($data,$prvkey) {
|
||||
if (! (is_array($data) && array_key_exists('encrypted', $data) && array_key_exists('alg', $data) && $data['alg'])) {
|
||||
logger('not encrypted');
|
||||
|
||||
if (! (is_array($data) && array_key_exists('encrypted',$data) && array_key_exists('alg',$data) && $data['alg'])) {
|
||||
logger('not encrypted');
|
||||
return $data;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
$alg_base = $data['alg'];
|
||||
$padding = OPENSSL_PKCS1_PADDING;
|
||||
|
||||
$alg_base = $data['alg'];
|
||||
$padding = OPENSSL_PKCS1_PADDING;
|
||||
$exts = explode('.', $data['alg']);
|
||||
if (count($exts) > 1) {
|
||||
switch ($exts[1]) {
|
||||
case 'oaep':
|
||||
$padding = OPENSSL_PKCS1_OAEP_PADDING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$alg_base = $exts[0];
|
||||
}
|
||||
|
||||
$exts = explode('.',$data['alg']);
|
||||
if (count($exts) > 1) {
|
||||
switch ($exts[1]) {
|
||||
case 'oaep':
|
||||
$padding = OPENSSL_PKCS1_OAEP_PADDING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$alg_base = $exts[0];
|
||||
}
|
||||
$method = null;
|
||||
|
||||
$method = null;
|
||||
foreach (self::$openssl_algorithms as $ossl) {
|
||||
if ($ossl[0] === $alg_base) {
|
||||
$method = $ossl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::$openssl_algorithms as $ossl) {
|
||||
if ($ossl[0] === $alg_base) {
|
||||
$method = $ossl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($method) {
|
||||
openssl_private_decrypt(base64url_decode($data['key']),$k,$prvkey,$padding);
|
||||
openssl_private_decrypt(base64url_decode($data['iv']), $i,$prvkey,$padding);
|
||||
return openssl_decrypt(base64url_decode($data['data']),$method[1],substr($k,0,$method[2]),OPENSSL_RAW_DATA,substr($i,0,$method[3]));
|
||||
}
|
||||
else {
|
||||
$x = [ 'data' => $data, 'prvkey' => $prvkey, 'alg' => $data['alg'], 'result' => $data ];
|
||||
call_hooks('crypto_unencapsulate',$x);
|
||||
return $x['result'];
|
||||
}
|
||||
}
|
||||
if ($method) {
|
||||
openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey, $padding);
|
||||
openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey, $padding);
|
||||
return openssl_decrypt(base64url_decode($data['data']), $method[1], substr($k, 0, $method[2]), OPENSSL_RAW_DATA, substr($i, 0, $method[3]));
|
||||
} else {
|
||||
$x = [ 'data' => $data, 'prvkey' => $prvkey, 'alg' => $data['alg'], 'result' => $data ];
|
||||
call_hooks('crypto_unencapsulate', $x);
|
||||
return $x['result'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,113 +2,116 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
class DB_Upgrade {
|
||||
class DB_Upgrade
|
||||
{
|
||||
|
||||
public $config_name = '';
|
||||
public $func_prefix = '';
|
||||
public $config_name = '';
|
||||
public $func_prefix = '';
|
||||
|
||||
function __construct($db_revision) {
|
||||
public function __construct($db_revision)
|
||||
{
|
||||
|
||||
$this->config_name = 'db_version';
|
||||
$this->func_prefix = '_';
|
||||
$this->config_name = 'db_version';
|
||||
$this->func_prefix = '_';
|
||||
|
||||
$build = get_config('system', 'db_version', 0);
|
||||
if(! intval($build))
|
||||
$build = set_config('system', 'db_version', $db_revision);
|
||||
$build = get_config('system', 'db_version', 0);
|
||||
if (!intval($build)) {
|
||||
$build = set_config('system', 'db_version', $db_revision);
|
||||
}
|
||||
|
||||
if($build == $db_revision) {
|
||||
// Nothing to be done.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
$stored = intval($build);
|
||||
if(! $stored) {
|
||||
logger('Critical: check_config unable to determine database schema version');
|
||||
return;
|
||||
}
|
||||
if ($build == $db_revision) {
|
||||
// Nothing to be done.
|
||||
return;
|
||||
} else {
|
||||
$stored = intval($build);
|
||||
if (!$stored) {
|
||||
logger('Critical: check_config unable to determine database schema version');
|
||||
return;
|
||||
}
|
||||
|
||||
$current = intval($db_revision);
|
||||
$current = intval($db_revision);
|
||||
|
||||
if($stored < $current) {
|
||||
if ($stored < $current) {
|
||||
// The last update we performed was $stored.
|
||||
// Start at $stored + 1 and continue until we have completed $current
|
||||
|
||||
// The last update we performed was $stored.
|
||||
// Start at $stored + 1 and continue until we have completed $current
|
||||
for ($x = $stored + 1; $x <= $current; $x++) {
|
||||
$s = '_' . $x;
|
||||
$cls = '\\Zotlabs\Update\\' . $s;
|
||||
if (!class_exists($cls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for($x = $stored + 1; $x <= $current; $x ++) {
|
||||
$s = '_' . $x;
|
||||
$cls = '\\Zotlabs\Update\\' . $s ;
|
||||
if(! class_exists($cls)) {
|
||||
return;
|
||||
}
|
||||
// There could be a lot of processes running or about to run.
|
||||
// We want exactly one process to run the update command.
|
||||
// So store the fact that we're taking responsibility
|
||||
// after first checking to see if somebody else already has.
|
||||
|
||||
// There could be a lot of processes running or about to run.
|
||||
// We want exactly one process to run the update command.
|
||||
// So store the fact that we're taking responsibility
|
||||
// after first checking to see if somebody else already has.
|
||||
// If the update fails or times-out completely you may need to
|
||||
// delete the config entry to try again.
|
||||
|
||||
// If the update fails or times-out completely you may need to
|
||||
// delete the config entry to try again.
|
||||
Config::Load('database');
|
||||
|
||||
Config::Load('database');
|
||||
|
||||
if(get_config('database', $s))
|
||||
break;
|
||||
set_config('database',$s, '1');
|
||||
if (get_config('database', $s)) {
|
||||
break;
|
||||
}
|
||||
set_config('database', $s, '1');
|
||||
|
||||
|
||||
$c = new $cls();
|
||||
$c = new $cls();
|
||||
|
||||
$retval = $c->run();
|
||||
$retval = $c->run();
|
||||
|
||||
if($retval != UPDATE_SUCCESS) {
|
||||
if ($retval != UPDATE_SUCCESS) {
|
||||
$source = t('Source code of failed update: ') . "\n\n" . @file_get_contents('Zotlabs/Update/' . $s . '.php');
|
||||
|
||||
|
||||
$source = t('Source code of failed update: ') . "\n\n" . @file_get_contents('Zotlabs/Update/' . $s . '.php');
|
||||
// Prevent sending hundreds of thousands of emails by creating
|
||||
// a lockfile.
|
||||
|
||||
$lockfile = 'cache/mailsent';
|
||||
|
||||
// Prevent sending hundreds of thousands of emails by creating
|
||||
// a lockfile.
|
||||
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400))) {
|
||||
return;
|
||||
}
|
||||
@unlink($lockfile);
|
||||
//send the administrator an e-mail
|
||||
file_put_contents($lockfile, $x);
|
||||
|
||||
$lockfile = 'cache/mailsent';
|
||||
$r = q(
|
||||
"select account_language from account where account_email = '%s' limit 1",
|
||||
dbesc(App::$config['system']['admin_email'])
|
||||
);
|
||||
push_lang(($r) ? $r[0]['account_language'] : 'en');
|
||||
z_mail(
|
||||
[
|
||||
'toEmail' => App::$config['system']['admin_email'],
|
||||
'messageSubject' => sprintf(t('Update Error at %s'), z_root()),
|
||||
'textVersion' => replace_macros(
|
||||
get_intltext_template('update_fail_eml.tpl'),
|
||||
[
|
||||
'$sitename' => App::$config['system']['sitename'],
|
||||
'$siteurl' => z_root(),
|
||||
'$update' => $x,
|
||||
'$error' => sprintf(t('Update %s failed. See error logs.'), $x),
|
||||
'$baseurl' => z_root(),
|
||||
'$source' => $source
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400)))
|
||||
return;
|
||||
@unlink($lockfile);
|
||||
//send the administrator an e-mail
|
||||
file_put_contents($lockfile, $x);
|
||||
|
||||
$r = q("select account_language from account where account_email = '%s' limit 1",
|
||||
dbesc(\App::$config['system']['admin_email'])
|
||||
);
|
||||
push_lang(($r) ? $r[0]['account_language'] : 'en');
|
||||
z_mail(
|
||||
[
|
||||
'toEmail' => \App::$config['system']['admin_email'],
|
||||
'messageSubject' => sprintf( t('Update Error at %s'), z_root()),
|
||||
'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'),
|
||||
[
|
||||
'$sitename' => \App::$config['system']['sitename'],
|
||||
'$siteurl' => z_root(),
|
||||
'$update' => $x,
|
||||
'$error' => sprintf( t('Update %s failed. See error logs.'), $x),
|
||||
'$baseurl' => z_root(),
|
||||
'$source' => $source
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
//try the logger
|
||||
logger('CRITICAL: Update Failed: ' . $x);
|
||||
pop_lang();
|
||||
}
|
||||
else {
|
||||
set_config('database',$s, 'success');
|
||||
}
|
||||
}
|
||||
}
|
||||
set_config('system', 'db_version', $db_revision);
|
||||
}
|
||||
}
|
||||
//try the logger
|
||||
logger('CRITICAL: Update Failed: ' . $x);
|
||||
pop_lang();
|
||||
} else {
|
||||
set_config('database', $s, 'success');
|
||||
}
|
||||
}
|
||||
}
|
||||
set_config('system', 'db_version', $db_revision);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,135 +1,154 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class DReport {
|
||||
class DReport
|
||||
{
|
||||
|
||||
private $location;
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $message_id;
|
||||
private $status;
|
||||
private $date;
|
||||
private $location;
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $message_id;
|
||||
private $status;
|
||||
private $date;
|
||||
|
||||
function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
public function __construct($location, $sender, $recipient, $message_id, $status = 'deliver')
|
||||
{
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->name = EMPTY_STR;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function update($status) {
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
public function update($status)
|
||||
{
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function set_name($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
public function set_name($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
function addto_update($status) {
|
||||
$this->status = $this->status . ' ' . $status;
|
||||
}
|
||||
public function addto_update($status)
|
||||
{
|
||||
$this->status = $this->status . ' ' . $status;
|
||||
}
|
||||
|
||||
|
||||
function set($arr) {
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
}
|
||||
public function set($arr)
|
||||
{
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->name = $arr['name'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
}
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
public function get()
|
||||
{
|
||||
return array(
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'name' => $this->name,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief decide whether to store a returned delivery report
|
||||
*
|
||||
* @param array $dr
|
||||
* @return boolean
|
||||
*/
|
||||
/**
|
||||
* @brief decide whether to store a returned delivery report
|
||||
*
|
||||
* @param array $dr
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
static function is_storable($dr) {
|
||||
public static function is_storable($dr)
|
||||
{
|
||||
|
||||
if(get_config('system', 'disable_dreport'))
|
||||
return false;
|
||||
if (get_config('system', 'disable_dreport')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hooks dreport_is_storable
|
||||
* Called before storing a dreport record to determine whether to store it.
|
||||
* * \e array
|
||||
*/
|
||||
/**
|
||||
* @hooks dreport_is_storable
|
||||
* Called before storing a dreport record to determine whether to store it.
|
||||
* * \e array
|
||||
*/
|
||||
|
||||
call_hooks('dreport_is_storable', $dr);
|
||||
call_hooks('dreport_is_storable', $dr);
|
||||
|
||||
// let plugins accept or reject - if neither, continue on
|
||||
if(array_key_exists('accept',$dr) && intval($dr['accept']))
|
||||
return true;
|
||||
if(array_key_exists('reject',$dr) && intval($dr['reject']))
|
||||
return false;
|
||||
// let plugins accept or reject - if neither, continue on
|
||||
if (array_key_exists('accept', $dr) && intval($dr['accept'])) {
|
||||
return true;
|
||||
}
|
||||
if (array_key_exists('reject', $dr) && intval($dr['reject'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! ($dr['sender']))
|
||||
return false;
|
||||
if (!($dr['sender'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the sender one of our channels?
|
||||
// Is the sender one of our channels?
|
||||
|
||||
$c = q("select channel_id from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($dr['sender'])
|
||||
);
|
||||
if(! $c)
|
||||
return false;
|
||||
$c = q(
|
||||
"select channel_id from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($dr['sender'])
|
||||
);
|
||||
if (!$c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// is the recipient one of our connections, or do we want to store every report?
|
||||
// is the recipient one of our connections, or do we want to store every report?
|
||||
|
||||
|
||||
$rxchan = $dr['recipient'];
|
||||
$pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all');
|
||||
if($pcf)
|
||||
return true;
|
||||
$rxchan = $dr['recipient'];
|
||||
$pcf = get_pconfig($c[0]['channel_id'], 'system', 'dreport_store_all');
|
||||
if ($pcf) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We always add ourself as a recipient to private and relayed posts
|
||||
// So if a remote site says they can't find us, that's no big surprise
|
||||
// and just creates a lot of extra report noise
|
||||
// We always add ourself as a recipient to private and relayed posts
|
||||
// So if a remote site says they can't find us, that's no big surprise
|
||||
// and just creates a lot of extra report noise
|
||||
|
||||
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found'))
|
||||
return false;
|
||||
if (($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If you have a private post with a recipient list, every single site is going to report
|
||||
// back a failed delivery for anybody on that list that isn't local to them. We're only
|
||||
// concerned about this if we have a local hubloc record which says we expected them to
|
||||
// have a channel on that site.
|
||||
// If you have a private post with a recipient list, every single site is going to report
|
||||
// back a failed delivery for anybody on that list that isn't local to them. We're only
|
||||
// concerned about this if we have a local hubloc record which says we expected them to
|
||||
// have a channel on that site.
|
||||
|
||||
$r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
|
||||
dbesc($rxchan),
|
||||
dbesc($dr['location'])
|
||||
);
|
||||
if((! $r) && ($dr['status'] === 'recipient not found'))
|
||||
return false;
|
||||
|
||||
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($rxchan),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if($r)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
$r = q(
|
||||
"select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
|
||||
dbesc($rxchan),
|
||||
dbesc($dr['location'])
|
||||
);
|
||||
if ((!$r) && ($dr['status'] === 'recipient not found')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q(
|
||||
"select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||
dbesc($rxchan),
|
||||
intval($c[0]['channel_id'])
|
||||
);
|
||||
if ($r) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -8,50 +8,56 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use ZipArchive;
|
||||
|
||||
/**
|
||||
* Description of ExtendedZip
|
||||
*
|
||||
* @author andrew
|
||||
*/
|
||||
class ExtendedZip extends \ZipArchive {
|
||||
class ExtendedZip extends ZipArchive
|
||||
{
|
||||
|
||||
// Member function to add a whole file system subtree to the archive
|
||||
public function addTree($dirname, $localname = '') {
|
||||
if ($localname)
|
||||
$this->addEmptyDir($localname);
|
||||
$this->_addTree($dirname, $localname);
|
||||
}
|
||||
// Member function to add a whole file system subtree to the archive
|
||||
public function addTree($dirname, $localname = '')
|
||||
{
|
||||
if ($localname) {
|
||||
$this->addEmptyDir($localname);
|
||||
}
|
||||
$this->_addTree($dirname, $localname);
|
||||
}
|
||||
|
||||
// Internal function, to recurse
|
||||
protected function _addTree($dirname, $localname) {
|
||||
$dir = opendir($dirname);
|
||||
while ($filename = readdir($dir)) {
|
||||
// Discard . and ..
|
||||
if ($filename == '.' || $filename == '..')
|
||||
continue;
|
||||
// Internal function, to recurse
|
||||
protected function _addTree($dirname, $localname)
|
||||
{
|
||||
$dir = opendir($dirname);
|
||||
while ($filename = readdir($dir)) {
|
||||
// Discard . and ..
|
||||
if ($filename == '.' || $filename == '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Proceed according to type
|
||||
$path = $dirname . '/' . $filename;
|
||||
$localpath = $localname ? ($localname . '/' . $filename) : $filename;
|
||||
if (is_dir($path)) {
|
||||
// Directory: add & recurse
|
||||
$this->addEmptyDir($localpath);
|
||||
$this->_addTree($path, $localpath);
|
||||
}
|
||||
else if (is_file($path)) {
|
||||
// File: just add
|
||||
$this->addFile($path, $localpath);
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
// Helper function
|
||||
public static function zipTree($dirname, $zipFilename, $flags = 0, $localname = '') {
|
||||
$zip = new self();
|
||||
$zip->open($zipFilename, $flags);
|
||||
$zip->addTree($dirname, $localname);
|
||||
$zip->close();
|
||||
}
|
||||
// Proceed according to type
|
||||
$path = $dirname . '/' . $filename;
|
||||
$localpath = $localname ? ($localname . '/' . $filename) : $filename;
|
||||
if (is_dir($path)) {
|
||||
// Directory: add & recurse
|
||||
$this->addEmptyDir($localpath);
|
||||
$this->_addTree($path, $localpath);
|
||||
} elseif (is_file($path)) {
|
||||
// File: just add
|
||||
$this->addFile($path, $localpath);
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
// Helper function
|
||||
public static function zipTree($dirname, $zipFilename, $flags = 0, $localname = '')
|
||||
{
|
||||
$zip = new self();
|
||||
$zip->open($zipFilename, $flags);
|
||||
$zip->addTree($dirname, $localname);
|
||||
$zip->close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/*
|
||||
* Zotlabs\Lib\Hashpath
|
||||
|
@ -28,29 +28,30 @@ namespace Zotlabs\Lib;
|
|||
*
|
||||
*/
|
||||
|
||||
class Hashpath {
|
||||
class Hashpath
|
||||
{
|
||||
|
||||
static function path($url, $prefix = '.', $depth = 1, $mkdir = true) {
|
||||
$hash = hash('sha256', $url);
|
||||
$start = 0;
|
||||
$slice = 2;
|
||||
if ($depth < 1) {
|
||||
$depth = 1;
|
||||
}
|
||||
$sluglen = $depth * $slice;
|
||||
public static function path($url, $prefix = '.', $depth = 1, $mkdir = true)
|
||||
{
|
||||
$hash = hash('sha256', $url);
|
||||
$start = 0;
|
||||
$slice = 2;
|
||||
if ($depth < 1) {
|
||||
$depth = 1;
|
||||
}
|
||||
$sluglen = $depth * $slice;
|
||||
|
||||
do {
|
||||
$slug = substr($hash,$start,$slice);
|
||||
$prefix .= '/' . $slug;
|
||||
$start += $slice;
|
||||
$sluglen -= $slice;
|
||||
}
|
||||
while ($sluglen);
|
||||
do {
|
||||
$slug = substr($hash, $start, $slice);
|
||||
$prefix .= '/' . $slug;
|
||||
$start += $slice;
|
||||
$sluglen -= $slice;
|
||||
} while ($sluglen);
|
||||
|
||||
if ($mkdir) {
|
||||
os_mkdir($prefix, STORAGE_DEFAULT_PERMISSIONS, true);
|
||||
}
|
||||
if ($mkdir) {
|
||||
os_mkdir($prefix, STORAGE_DEFAULT_PERMISSIONS, true);
|
||||
}
|
||||
|
||||
return $prefix . '/' . $hash;
|
||||
}
|
||||
return $prefix . '/' . $hash;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,173 +2,181 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class IConfig
|
||||
{
|
||||
|
||||
public static function Load(&$item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public static function Get(&$item, $family, $key, $default = false)
|
||||
{
|
||||
|
||||
$is_item = false;
|
||||
|
||||
if (is_array($item)) {
|
||||
$is_item = true;
|
||||
|
||||
if ((! array_key_exists('iconfig', $item)) || (! is_array($item['iconfig']))) {
|
||||
$item['iconfig'] = [];
|
||||
}
|
||||
|
||||
if (array_key_exists('item_id', $item)) {
|
||||
$iid = $item['item_id'];
|
||||
} else {
|
||||
$iid = ((isset($item['id'])) ? $item['id'] : 0);
|
||||
}
|
||||
|
||||
if (array_key_exists('iconfig', $item) && is_array($item['iconfig'])) {
|
||||
foreach ($item['iconfig'] as $c) {
|
||||
if ($c['cat'] == $family && $c['k'] == $key) {
|
||||
return $c['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (intval($item)) {
|
||||
$iid = $item;
|
||||
}
|
||||
|
||||
if (! $iid) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$r = q(
|
||||
"select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
if ($r) {
|
||||
$r[0]['v'] = unserialise($r[0]['v']);
|
||||
if ($is_item) {
|
||||
$item['iconfig'][] = $r[0];
|
||||
}
|
||||
return $r[0]['v'];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* IConfig::Set(&$item, $family, $key, $value, $sharing = false);
|
||||
*
|
||||
* $item - item array or item id. If passed an array the iconfig meta information is
|
||||
* added to the item structure (which will need to be saved with item_store eventually).
|
||||
* If passed an id, the DB is updated, but may not be federated and/or cloned.
|
||||
* $family - namespace of meta variable
|
||||
* $key - key of meta variable
|
||||
* $value - value of meta variable
|
||||
* $sharing - boolean (default false); if true the meta information is propagated with the item
|
||||
* to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
|
||||
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
|
||||
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
|
||||
* timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
|
||||
*/
|
||||
|
||||
|
||||
class IConfig {
|
||||
public static function Set(&$item, $family, $key, $value, $sharing = false)
|
||||
{
|
||||
|
||||
static public function Load(&$item) {
|
||||
return;
|
||||
}
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
static public function Get(&$item, $family, $key, $default = false) {
|
||||
$is_item = false;
|
||||
$idx = null;
|
||||
|
||||
$is_item = false;
|
||||
if (is_array($item)) {
|
||||
$is_item = true;
|
||||
if ((! array_key_exists('iconfig', $item)) || (! is_array($item['iconfig']))) {
|
||||
$item['iconfig'] = [];
|
||||
} elseif ($item['iconfig']) {
|
||||
for ($x = 0; $x < count($item['iconfig']); $x++) {
|
||||
if ($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
|
||||
$idx = $x;
|
||||
}
|
||||
}
|
||||
}
|
||||
$entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
|
||||
|
||||
if (is_array($item)) {
|
||||
$is_item = true;
|
||||
if (is_null($idx)) {
|
||||
$item['iconfig'][] = $entry;
|
||||
} else {
|
||||
$item['iconfig'][$idx] = $entry;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig']))) {
|
||||
$item['iconfig'] = [];
|
||||
}
|
||||
if (intval($item)) {
|
||||
$iid = intval($item);
|
||||
}
|
||||
|
||||
if (array_key_exists('item_id',$item)) {
|
||||
$iid = $item['item_id'];
|
||||
}
|
||||
else {
|
||||
$iid = ((isset($item['id'])) ? $item['id'] : 0);
|
||||
}
|
||||
if (! $iid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (array_key_exists('iconfig',$item) && is_array($item['iconfig'])) {
|
||||
foreach ($item['iconfig'] as $c) {
|
||||
if ($c['cat'] == $family && $c['k'] == $key) {
|
||||
return $c['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (intval($item)) {
|
||||
$iid = $item;
|
||||
}
|
||||
if (self::Get($item, $family, $key) === false) {
|
||||
$r = q(
|
||||
"insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue),
|
||||
intval($sharing)
|
||||
);
|
||||
} else {
|
||||
$r = q(
|
||||
"update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
intval($sharing),
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
|
||||
if (! $iid) {
|
||||
return $default;
|
||||
}
|
||||
if (! $r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
if ($r) {
|
||||
$r[0]['v'] = unserialise($r[0]['v']);
|
||||
if ($is_item) {
|
||||
$item['iconfig'][] = $r[0];
|
||||
}
|
||||
return $r[0]['v'];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* IConfig::Set(&$item, $family, $key, $value, $sharing = false);
|
||||
*
|
||||
* $item - item array or item id. If passed an array the iconfig meta information is
|
||||
* added to the item structure (which will need to be saved with item_store eventually).
|
||||
* If passed an id, the DB is updated, but may not be federated and/or cloned.
|
||||
* $family - namespace of meta variable
|
||||
* $key - key of meta variable
|
||||
* $value - value of meta variable
|
||||
* $sharing - boolean (default false); if true the meta information is propagated with the item
|
||||
* to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
|
||||
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
|
||||
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
|
||||
* timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
|
||||
*/
|
||||
|
||||
|
||||
static public function Set(&$item, $family, $key, $value, $sharing = false) {
|
||||
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
$is_item = false;
|
||||
$idx = null;
|
||||
|
||||
if(is_array($item)) {
|
||||
$is_item = true;
|
||||
if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
|
||||
$item['iconfig'] = [];
|
||||
elseif($item['iconfig']) {
|
||||
for($x = 0; $x < count($item['iconfig']); $x ++) {
|
||||
if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
|
||||
$idx = $x;
|
||||
}
|
||||
}
|
||||
}
|
||||
$entry = array('cat' => $family, 'k' => $key, 'v' => $value, 'sharing' => $sharing);
|
||||
|
||||
if(is_null($idx))
|
||||
$item['iconfig'][] = $entry;
|
||||
else
|
||||
$item['iconfig'][$idx] = $entry;
|
||||
return $value;
|
||||
}
|
||||
|
||||
if(intval($item))
|
||||
$iid = intval($item);
|
||||
|
||||
if(! $iid)
|
||||
return false;
|
||||
|
||||
if(self::Get($item, $family, $key) === false) {
|
||||
$r = q("insert into iconfig( iid, cat, k, v, sharing ) values ( %d, '%s', '%s', '%s', %d ) ",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue),
|
||||
intval($sharing)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("update iconfig set v = '%s', sharing = %d where iid = %d and cat = '%s' and k = '%s' ",
|
||||
dbesc($dbvalue),
|
||||
intval($sharing),
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
|
||||
if(! $r)
|
||||
return false;
|
||||
|
||||
return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static public function Delete(&$item, $family, $key) {
|
||||
public static function Delete(&$item, $family, $key)
|
||||
{
|
||||
|
||||
|
||||
$is_item = false;
|
||||
$idx = null;
|
||||
$is_item = false;
|
||||
$idx = null;
|
||||
|
||||
if(is_array($item)) {
|
||||
$is_item = true;
|
||||
if(is_array($item['iconfig'])) {
|
||||
for($x = 0; $x < count($item['iconfig']); $x ++) {
|
||||
if($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
|
||||
unset($item['iconfig'][$x]);
|
||||
}
|
||||
}
|
||||
// re-order the array index
|
||||
$item['iconfig'] = array_values($item['iconfig']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (is_array($item)) {
|
||||
$is_item = true;
|
||||
if (is_array($item['iconfig'])) {
|
||||
for ($x = 0; $x < count($item['iconfig']); $x++) {
|
||||
if ($item['iconfig'][$x]['cat'] == $family && $item['iconfig'][$x]['k'] == $key) {
|
||||
unset($item['iconfig'][$x]);
|
||||
}
|
||||
}
|
||||
// re-order the array index
|
||||
$item['iconfig'] = array_values($item['iconfig']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(intval($item))
|
||||
$iid = intval($item);
|
||||
if (intval($item)) {
|
||||
$iid = intval($item);
|
||||
}
|
||||
|
||||
if(! $iid)
|
||||
return false;
|
||||
|
||||
return q("delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
}
|
||||
if (! $iid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return q(
|
||||
"delete from iconfig where iid = %d and cat = '%s' and k = '%s' ",
|
||||
intval($iid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,87 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Zotlabs\Lib\Hashpath;
|
||||
use Zotlabs\Daemon\Run;
|
||||
|
||||
class Img_cache {
|
||||
class Img_cache
|
||||
{
|
||||
|
||||
static $cache_life = 18600 * 7;
|
||||
public static $cache_life = 18600 * 7;
|
||||
|
||||
static function get_filename($url, $prefix = '.') {
|
||||
return Hashpath::path($url,$prefix);
|
||||
}
|
||||
public static function get_filename($url, $prefix = '.')
|
||||
{
|
||||
return Hashpath::path($url, $prefix);
|
||||
}
|
||||
|
||||
// Check to see if we have this url in our cache
|
||||
// If we have it return true.
|
||||
// If we do not, or the cache file is empty or expired, return false
|
||||
// but attempt to fetch the entry in the background
|
||||
// Check to see if we have this url in our cache
|
||||
// If we have it return true.
|
||||
// If we do not, or the cache file is empty or expired, return false
|
||||
// but attempt to fetch the entry in the background
|
||||
|
||||
static function check($url, $prefix = '.') {
|
||||
public static function check($url, $prefix = '.')
|
||||
{
|
||||
|
||||
if (strpos($url,z_root()) !== false) {
|
||||
return false;
|
||||
}
|
||||
if (strpos($url, z_root()) !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = self::get_filename($url,$prefix);
|
||||
if (file_exists($path)) {
|
||||
$t = filemtime($path);
|
||||
if ($t && time() - $t >= self::$cache_life) {
|
||||
Run::Summon( [ 'Cache_image', $url, $path ] );
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return ((filesize($path)) ? true : false);
|
||||
}
|
||||
}
|
||||
$path = self::get_filename($url, $prefix);
|
||||
if (file_exists($path)) {
|
||||
$t = filemtime($path);
|
||||
if ($t && time() - $t >= self::$cache_life) {
|
||||
Run::Summon(['Cache_image', $url, $path]);
|
||||
return false;
|
||||
} else {
|
||||
return ((filesize($path)) ? true : false);
|
||||
}
|
||||
}
|
||||
|
||||
// Cache_image invokes url_to_cache() as a background task
|
||||
// Cache_image invokes url_to_cache() as a background task
|
||||
|
||||
Run::Summon( [ 'Cache_image', $url, $path ] );
|
||||
return false;
|
||||
}
|
||||
Run::Summon(['Cache_image', $url, $path]);
|
||||
return false;
|
||||
}
|
||||
|
||||
static function url_to_cache($url,$file) {
|
||||
public static function url_to_cache($url, $file)
|
||||
{
|
||||
|
||||
$fp = fopen($file,'wb');
|
||||
$fp = fopen($file, 'wb');
|
||||
|
||||
if (! $fp) {
|
||||
logger('failed to open storage file: ' . $file,LOGGER_NORMAL,LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
if (!$fp) {
|
||||
logger('failed to open storage file: ' . $file, LOGGER_NORMAL, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// don't check certs, and since we're running in the background,
|
||||
// allow a two-minute timeout rather than the default one minute.
|
||||
// This is a compromise. We want to cache all the slow sites we can,
|
||||
// but don't want to rack up too many processes doing so.
|
||||
// don't check certs, and since we're running in the background,
|
||||
// allow a two-minute timeout rather than the default one minute.
|
||||
// This is a compromise. We want to cache all the slow sites we can,
|
||||
// but don't want to rack up too many processes doing so.
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_fetch_url($url,true,$redirects,[ 'filep' => $fp, 'novalidate' => true, 'timeout' => 120 ]);
|
||||
$redirects = 0;
|
||||
$x = z_fetch_url($url, true, $redirects, ['filep' => $fp, 'novalidate' => true, 'timeout' => 120]);
|
||||
|
||||
fclose($fp);
|
||||
fclose($fp);
|
||||
|
||||
if ($x['success'] && file_exists($file)) {
|
||||
$i = @getimagesize($file);
|
||||
if ($i && $i[2]) { // looking for non-zero imagetype
|
||||
Run::Summon( [ 'CacheThumb' , basename($file) ] );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($x['success'] && file_exists($file)) {
|
||||
$i = @getimagesize($file);
|
||||
if ($i && $i[2]) { // looking for non-zero imagetype
|
||||
Run::Summon(['CacheThumb', basename($file)]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We could not cache the image for some reason. Leave an empty file here
|
||||
// to provide a record of the attempt. We'll use this as a flag to avoid
|
||||
// doing it again repeatedly.
|
||||
|
||||
file_put_contents($file, EMPTY_STR);
|
||||
logger('cache failed from ' . $url);
|
||||
return false;
|
||||
}
|
||||
// We could not cache the image for some reason. Leave an empty file here
|
||||
// to provide a record of the attempt. We'll use this as a flag to avoid
|
||||
// doing it again repeatedly.
|
||||
|
||||
file_put_contents($file, EMPTY_STR);
|
||||
logger('cache failed from ' . $url);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,51 +2,56 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class Img_filesize {
|
||||
class Img_filesize
|
||||
{
|
||||
|
||||
private $url;
|
||||
private $url;
|
||||
|
||||
function __construct($url) {
|
||||
$this->url = $url;
|
||||
}
|
||||
public function __construct($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
function getSize() {
|
||||
$size = null;
|
||||
public function getSize()
|
||||
{
|
||||
$size = null;
|
||||
|
||||
if(stripos($this->url,z_root() . '/photo') !== false) {
|
||||
$size = self::getLocalFileSize($this->url);
|
||||
}
|
||||
if(! $size) {
|
||||
$size = getRemoteFileSize($this->url);
|
||||
}
|
||||
if (stripos($this->url, z_root() . '/photo') !== false) {
|
||||
$size = self::getLocalFileSize($this->url);
|
||||
}
|
||||
if (!$size) {
|
||||
$size = getRemoteFileSize($this->url);
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
|
||||
static function getLocalFileSize($url) {
|
||||
public static function getLocalFileSize($url)
|
||||
{
|
||||
|
||||
$fname = basename($url);
|
||||
$resolution = 0;
|
||||
$fname = basename($url);
|
||||
$resolution = 0;
|
||||
|
||||
if(strpos($fname,'.') !== false)
|
||||
$fname = substr($fname,0,strpos($fname,'.'));
|
||||
if (strpos($fname, '.') !== false) {
|
||||
$fname = substr($fname, 0, strpos($fname, '.'));
|
||||
}
|
||||
|
||||
if(substr($fname,-2,1) == '-') {
|
||||
$resolution = intval(substr($fname,-1,1));
|
||||
$fname = substr($fname,0,-2);
|
||||
}
|
||||
|
||||
$r = q("SELECT filesize FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
dbesc($fname),
|
||||
intval($resolution)
|
||||
);
|
||||
if($r) {
|
||||
return $r[0]['filesize'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (substr($fname, -2, 1) == '-') {
|
||||
$resolution = intval(substr($fname, -1, 1));
|
||||
$fname = substr($fname, 0, -2);
|
||||
}
|
||||
|
||||
$r = q(
|
||||
"SELECT filesize FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
|
||||
dbesc($fname),
|
||||
intval($resolution)
|
||||
);
|
||||
if ($r) {
|
||||
return $r[0]['filesize'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +83,7 @@ function getRemoteFileSize($url)
|
|||
curl_setopt($ch, CURLOPT_VERBOSE, 0); // set to 1 to debug
|
||||
curl_setopt($ch, CURLOPT_STDERR, fopen('php://output', 'r'));
|
||||
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $line) use (&$in_headers, &$size) {
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $line) use (&$in_headers, &$size) {
|
||||
$length = strlen($line);
|
||||
|
||||
if (trim($line) == '') {
|
||||
|
@ -93,7 +98,7 @@ function getRemoteFileSize($url)
|
|||
list($rng, $s) = explode('/', $content, 2);
|
||||
$size = (int)$s;
|
||||
return 0; // aborts transfer
|
||||
} else if ($header == 'content-length' && 206 != curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
|
||||
} elseif ($header == 'content-length' && 206 != curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
|
||||
// found content-length header and this is not a 206 Partial Content response (range response)
|
||||
$size = (int)$content;
|
||||
return 0;
|
||||
|
@ -103,7 +108,7 @@ function getRemoteFileSize($url)
|
|||
}
|
||||
});
|
||||
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use ($in_headers) {
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($curl, $data) use ($in_headers) {
|
||||
if (!$in_headers) {
|
||||
// shouldn't be here unless we couldn't determine file size
|
||||
// abort transfer
|
||||
|
@ -116,7 +121,7 @@ function getRemoteFileSize($url)
|
|||
|
||||
curl_exec($ch);
|
||||
curl_getinfo($ch);
|
||||
curl_close($ch);
|
||||
curl_close($ch);
|
||||
|
||||
return $size;
|
||||
}
|
|
@ -4,69 +4,70 @@ namespace Zotlabs\Lib;
|
|||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class JSalmon {
|
||||
class JSalmon
|
||||
{
|
||||
|
||||
static function sign($data,$key_id,$key,$data_type = 'application/x-nomad+json') {
|
||||
public static function sign($data, $key_id, $key, $data_type = 'application/x-nomad+json')
|
||||
{
|
||||
|
||||
$data = base64url_encode(json_encode($data,true),true); // strip padding
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
$data = base64url_encode(json_encode($data, true), true); // strip padding
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
|
||||
$data = preg_replace('/\s+/','',$data);
|
||||
$data = preg_replace('/\s+/', '', $data);
|
||||
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
|
||||
$precomputed = '.' . base64url_encode($data_type,true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
|
||||
$precomputed = '.' . base64url_encode($data_type, true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
|
||||
|
||||
$signature = base64url_encode(Crypto::sign($data . $precomputed, $key), true);
|
||||
$signature = base64url_encode(Crypto::sign($data . $precomputed, $key), true);
|
||||
|
||||
return ([
|
||||
'signed' => true,
|
||||
'data' => $data,
|
||||
'data_type' => $data_type,
|
||||
'encoding' => $encoding,
|
||||
'alg' => $algorithm,
|
||||
'sigs' => [
|
||||
'value' => $signature,
|
||||
'key_id' => base64url_encode($key_id, true)
|
||||
]
|
||||
]);
|
||||
return ([
|
||||
'signed' => true,
|
||||
'data' => $data,
|
||||
'data_type' => $data_type,
|
||||
'encoding' => $encoding,
|
||||
'alg' => $algorithm,
|
||||
'sigs' => [
|
||||
'value' => $signature,
|
||||
'key_id' => base64url_encode($key_id, true)
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
public static function verify($x)
|
||||
{
|
||||
|
||||
static function verify($x) {
|
||||
logger('verify');
|
||||
$ret = ['results' => []];
|
||||
|
||||
logger('verify');
|
||||
$ret = [ 'results' => [] ];
|
||||
if (!is_array($x)) {
|
||||
return false;
|
||||
}
|
||||
if (!(array_key_exists('signed', $x) && $x['signed'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! is_array($x)) {
|
||||
return false;
|
||||
}
|
||||
if(! ( array_key_exists('signed',$x) && $x['signed'])) {
|
||||
return false;
|
||||
}
|
||||
$signed_data = preg_replace('/\s+/', '', $x['data']) . '.'
|
||||
. base64url_encode($x['data_type'], true) . '.'
|
||||
. base64url_encode($x['encoding'], true) . '.'
|
||||
. base64url_encode($x['alg'], true);
|
||||
|
||||
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
|
||||
. base64url_encode($x['data_type'],true) . '.'
|
||||
. base64url_encode($x['encoding'],true) . '.'
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
|
||||
logger('key: ' . print_r($key,true));
|
||||
if($key['portable_id'] && $key['public_key']) {
|
||||
if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
|
||||
logger('verified');
|
||||
$ret = [ 'success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc'] ];
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
static function unpack($data) {
|
||||
return json_decode(base64url_decode($data),true);
|
||||
}
|
||||
$key = HTTPSig::get_key(EMPTY_STR, 'zot6', base64url_decode($x['sigs']['key_id']));
|
||||
logger('key: ' . print_r($key, true));
|
||||
if ($key['portable_id'] && $key['public_key']) {
|
||||
if (Crypto::verify($signed_data, base64url_decode($x['sigs']['value']), $key['public_key'])) {
|
||||
logger('verified');
|
||||
$ret = ['success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc']];
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function unpack($data)
|
||||
{
|
||||
return json_decode(base64url_decode($data), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,91 +9,94 @@ use phpseclib\Math\BigInteger;
|
|||
* Keyutils
|
||||
* Convert RSA keys between various formats
|
||||
*/
|
||||
class Keyutils {
|
||||
class Keyutils
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $m modulo
|
||||
* @param string $e exponent
|
||||
* @return string
|
||||
*/
|
||||
public static function meToPem($m, $e) {
|
||||
/**
|
||||
* @param string $m modulo
|
||||
* @param string $e exponent
|
||||
* @return string
|
||||
*/
|
||||
public static function meToPem($m, $e)
|
||||
{
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey([
|
||||
'e' => new BigInteger($e, 256),
|
||||
'n' => new BigInteger($m, 256)
|
||||
]);
|
||||
return $rsa->getPublicKey();
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey([
|
||||
'e' => new BigInteger($e, 256),
|
||||
'n' => new BigInteger($m, 256)
|
||||
]);
|
||||
return $rsa->getPublicKey();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @param string key
|
||||
* @return string
|
||||
*/
|
||||
public static function rsaToPem($key)
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string key
|
||||
* @return string
|
||||
*/
|
||||
public static function rsaToPem($key) {
|
||||
$rsa = new RSA();
|
||||
$rsa->setPublicKey($key);
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->setPublicKey($key);
|
||||
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS8);
|
||||
}
|
||||
|
||||
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS8);
|
||||
/**
|
||||
* @param string key
|
||||
* @return string
|
||||
*/
|
||||
public static function pemToRsa($key)
|
||||
{
|
||||
|
||||
}
|
||||
$rsa = new RSA();
|
||||
$rsa->setPublicKey($key);
|
||||
|
||||
/**
|
||||
* @param string key
|
||||
* @return string
|
||||
*/
|
||||
public static function pemToRsa($key) {
|
||||
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
|
||||
}
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->setPublicKey($key);
|
||||
/**
|
||||
* @param string $key key
|
||||
* @param string $m reference modulo
|
||||
* @param string $e reference exponent
|
||||
*/
|
||||
public static function pemToMe($key, &$m, &$e)
|
||||
{
|
||||
|
||||
return $rsa->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($key);
|
||||
$rsa->setPublicKey();
|
||||
|
||||
}
|
||||
$m = $rsa->modulus->toBytes();
|
||||
$e = $rsa->exponent->toBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key key
|
||||
* @param string $m reference modulo
|
||||
* @param string $e reference exponent
|
||||
*/
|
||||
public static function pemToMe($key, &$m, &$e) {
|
||||
/**
|
||||
* @param string $pubkey
|
||||
* @return string
|
||||
*/
|
||||
public static function salmonKey($pubkey)
|
||||
{
|
||||
self::pemToMe($pubkey, $m, $e);
|
||||
return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true);
|
||||
}
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($key);
|
||||
$rsa->setPublicKey();
|
||||
/**
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public static function convertSalmonKey($key)
|
||||
{
|
||||
if (strstr($key, ',')) {
|
||||
$rawkey = substr($key, strpos($key, ',') + 1);
|
||||
} else {
|
||||
$rawkey = substr($key, 5);
|
||||
}
|
||||
|
||||
$m = $rsa->modulus->toBytes();
|
||||
$e = $rsa->exponent->toBytes();
|
||||
$key_info = explode('.', $rawkey);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $pubkey
|
||||
* @return string
|
||||
*/
|
||||
public static function salmonKey($pubkey) {
|
||||
self::pemToMe($pubkey, $m, $e);
|
||||
return 'RSA' . '.' . base64url_encode($m, true) . '.' . base64url_encode($e, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public static function convertSalmonKey($key) {
|
||||
if (strstr($key, ','))
|
||||
$rawkey = substr($key, strpos($key, ',') + 1);
|
||||
else
|
||||
$rawkey = substr($key, 5);
|
||||
|
||||
$key_info = explode('.', $rawkey);
|
||||
|
||||
$m = base64url_decode($key_info[1]);
|
||||
$e = base64url_decode($key_info[2]);
|
||||
|
||||
return self::meToPem($m, $e);
|
||||
}
|
||||
$m = base64url_decode($key_info[1]);
|
||||
$e = base64url_decode($key_info[2]);
|
||||
|
||||
return self::meToPem($m, $e);
|
||||
}
|
||||
}
|
|
@ -2,131 +2,137 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use Exception;
|
||||
use Zotlabs\Lib\Activity;
|
||||
|
||||
require_once('library/jsonld/jsonld.php');
|
||||
|
||||
class LDSignatures {
|
||||
class LDSignatures
|
||||
{
|
||||
|
||||
|
||||
static function verify($data,$pubkey) {
|
||||
public static function verify($data, $pubkey)
|
||||
{
|
||||
|
||||
$ohash = self::hash(self::signable_options($data['signature']));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
$ohash = self::hash(self::signable_options($data['signature']));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
|
||||
$x = Crypto::verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
|
||||
logger('LD-verify: ' . intval($x));
|
||||
$x = Crypto::verify($ohash . $dhash, base64_decode($data['signature']['signatureValue']), $pubkey);
|
||||
logger('LD-verify: ' . intval($x));
|
||||
|
||||
return $x;
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
static function dopplesign(&$data,$channel) {
|
||||
// remove for the time being - performance issues
|
||||
// $data['magicEnv'] = self::salmon_sign($data,$channel);
|
||||
return self::sign($data,$channel);
|
||||
}
|
||||
public static function dopplesign(&$data, $channel)
|
||||
{
|
||||
// remove for the time being - performance issues
|
||||
// $data['magicEnv'] = self::salmon_sign($data,$channel);
|
||||
return self::sign($data, $channel);
|
||||
}
|
||||
|
||||
static function sign($data,$channel) {
|
||||
public static function sign($data, $channel)
|
||||
{
|
||||
|
||||
$options = [
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => random_string(64),
|
||||
'creator' => channel_url($channel),
|
||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\TH:i:s\Z')
|
||||
];
|
||||
$options = [
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => random_string(64),
|
||||
'creator' => channel_url($channel),
|
||||
'created' => datetime_convert('UTC', 'UTC', 'now', 'Y-m-d\TH:i:s\Z')
|
||||
];
|
||||
|
||||
$ohash = self::hash(self::signable_options($options));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
$options['signatureValue'] = base64_encode(Crypto::sign($ohash . $dhash,$channel['channel_prvkey']));
|
||||
$ohash = self::hash(self::signable_options($options));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
$options['signatureValue'] = base64_encode(Crypto::sign($ohash . $dhash, $channel['channel_prvkey']));
|
||||
|
||||
return $options;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
||||
static function signable_data($data) {
|
||||
public static function signable_data($data)
|
||||
{
|
||||
|
||||
$newdata = [];
|
||||
if($data) {
|
||||
foreach($data as $k => $v) {
|
||||
if(! in_array($k,[ 'signature' ])) {
|
||||
$newdata[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return json_encode($newdata,JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
$newdata = [];
|
||||
if ($data) {
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, ['signature'])) {
|
||||
$newdata[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return json_encode($newdata, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
|
||||
static function signable_options($options) {
|
||||
public static function signable_options($options)
|
||||
{
|
||||
|
||||
$newopts = [ '@context' => 'https://w3id.org/identity/v1' ];
|
||||
if($options) {
|
||||
foreach($options as $k => $v) {
|
||||
if(! in_array($k,[ 'type','id','signatureValue' ])) {
|
||||
$newopts[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return json_encode($newopts,JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
$newopts = ['@context' => 'https://w3id.org/identity/v1'];
|
||||
if ($options) {
|
||||
foreach ($options as $k => $v) {
|
||||
if (!in_array($k, ['type', 'id', 'signatureValue'])) {
|
||||
$newopts[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return json_encode($newopts, JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
static function hash($obj) {
|
||||
public static function hash($obj)
|
||||
{
|
||||
|
||||
return hash('sha256',self::normalise($obj));
|
||||
}
|
||||
return hash('sha256', self::normalise($obj));
|
||||
}
|
||||
|
||||
static function normalise($data) {
|
||||
if(is_string($data)) {
|
||||
$data = json_decode($data);
|
||||
}
|
||||
public static function normalise($data)
|
||||
{
|
||||
if (is_string($data)) {
|
||||
$data = json_decode($data);
|
||||
}
|
||||
|
||||
if(! is_object($data))
|
||||
return '';
|
||||
if (!is_object($data)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
jsonld_set_document_loader('jsonld_document_loader');
|
||||
jsonld_set_document_loader('jsonld_document_loader');
|
||||
|
||||
try {
|
||||
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Don't log the exception - this can exhaust memory
|
||||
// logger('normalise error:' . print_r($e,true));
|
||||
logger('normalise error: ' . print_r($data,true));
|
||||
}
|
||||
try {
|
||||
$d = jsonld_normalize($data, ['algorithm' => 'URDNA2015', 'format' => 'application/nquads']);
|
||||
} catch (Exception $e) {
|
||||
// Don't log the exception - this can exhaust memory
|
||||
// logger('normalise error:' . print_r($e,true));
|
||||
logger('normalise error: ' . print_r($data, true));
|
||||
}
|
||||
|
||||
return $d;
|
||||
}
|
||||
return $d;
|
||||
}
|
||||
|
||||
static function salmon_sign($data,$channel) {
|
||||
public static function salmon_sign($data, $channel)
|
||||
{
|
||||
|
||||
$arr = $data;
|
||||
$data = json_encode($data,JSON_UNESCAPED_SLASHES);
|
||||
$data = base64url_encode($data, false); // do not strip padding
|
||||
$data_type = 'application/activity+json';
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
$keyhash = base64url_encode(channel_url($channel));
|
||||
$arr = $data;
|
||||
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
$data = base64url_encode($data, false); // do not strip padding
|
||||
$data_type = 'application/activity+json';
|
||||
$encoding = 'base64url';
|
||||
$algorithm = 'RSA-SHA256';
|
||||
$keyhash = base64url_encode(channel_url($channel));
|
||||
|
||||
$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$data);
|
||||
$data = str_replace(array(" ", "\t", "\r", "\n"), array("", "", "", ""), $data);
|
||||
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
|
||||
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
|
||||
|
||||
$signature = base64url_encode(Crypto::sign($data . $precomputed,$channel['channel_prvkey']));
|
||||
|
||||
return ([
|
||||
'id' => $arr['id'],
|
||||
'meData' => $data,
|
||||
'meDataType' => $data_type,
|
||||
'meEncoding' => $encoding,
|
||||
'meAlgorithm' => $algorithm,
|
||||
'meCreator' => channel_url($channel),
|
||||
'meSignatureValue' => $signature
|
||||
]);
|
||||
|
||||
}
|
||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||
|
||||
$precomputed = '.' . base64url_encode($data_type, false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
|
||||
|
||||
$signature = base64url_encode(Crypto::sign($data . $precomputed, $channel['channel_prvkey']));
|
||||
|
||||
return ([
|
||||
'id' => $arr['id'],
|
||||
'meData' => $data,
|
||||
'meDataType' => $data_type,
|
||||
'meEncoding' => $encoding,
|
||||
'meAlgorithm' => $algorithm,
|
||||
'meCreator' => channel_url($channel),
|
||||
'meSignatureValue' => $signature
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -2,109 +2,117 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class LibBlock
|
||||
{
|
||||
|
||||
class LibBlock {
|
||||
public static $cache = [];
|
||||
public static $empty = [];
|
||||
|
||||
static $cache = [];
|
||||
static $empty = [];
|
||||
// This limits the number of DB queries for fetch_by_entity to once per page load.
|
||||
|
||||
// This limits the number of DB queries for fetch_by_entity to once per page load.
|
||||
|
||||
static function fetch_from_cache($channel_id,$entity) {
|
||||
if (! isset(self::$cache[$channel_id])) {
|
||||
if (! isset(self::$empty[$channel_id])) {
|
||||
self::$cache[$channel_id] = self::fetch($channel_id);
|
||||
if (! self::$cache[$channel_id]) {
|
||||
self::$empty[$channel_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset(self::$cache[$channel_id]) && self::$cache[$channel_id] && is_array(self::$cache[$channel_id])) {
|
||||
foreach (self::$cache[$channel_id] as $entry) {
|
||||
if (is_array($entry) && strcasecmp($entry['block_entity'],$entity) === 0) {
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static function fetch_from_cache($channel_id, $entity)
|
||||
{
|
||||
if (!isset(self::$cache[$channel_id])) {
|
||||
if (!isset(self::$empty[$channel_id])) {
|
||||
self::$cache[$channel_id] = self::fetch($channel_id);
|
||||
if (!self::$cache[$channel_id]) {
|
||||
self::$empty[$channel_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset(self::$cache[$channel_id]) && self::$cache[$channel_id] && is_array(self::$cache[$channel_id])) {
|
||||
foreach (self::$cache[$channel_id] as $entry) {
|
||||
if (is_array($entry) && strcasecmp($entry['block_entity'], $entity) === 0) {
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static function store($arr) {
|
||||
public static function store($arr)
|
||||
{
|
||||
|
||||
$arr['block_entity'] = trim($arr['block_entity']);
|
||||
$arr['block_entity'] = trim($arr['block_entity']);
|
||||
|
||||
if (! $arr['block_entity']) {
|
||||
return false;
|
||||
}
|
||||
if (!$arr['block_entity']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$arr['block_channel_id'] = ((array_key_exists('block_channel_id',$arr)) ? intval($arr['block_channel_id']) : 0);
|
||||
$arr['block_type'] = ((array_key_exists('block_type',$arr)) ? intval($arr['block_type']) : BLOCKTYPE_CHANNEL );
|
||||
$arr['block_comment'] = ((array_key_exists('block_comment',$arr)) ? escape_tags(trim($arr['block_comment'])) : EMPTY_STR);
|
||||
$arr['block_channel_id'] = ((array_key_exists('block_channel_id', $arr)) ? intval($arr['block_channel_id']) : 0);
|
||||
$arr['block_type'] = ((array_key_exists('block_type', $arr)) ? intval($arr['block_type']) : BLOCKTYPE_CHANNEL);
|
||||
$arr['block_comment'] = ((array_key_exists('block_comment', $arr)) ? escape_tags(trim($arr['block_comment'])) : EMPTY_STR);
|
||||
|
||||
if (! intval($arr['block_id'])) {
|
||||
$r = q("select * from block where block_channel_id = %d and block_entity = '%s' and block_type = %d limit 1",
|
||||
intval($arr['block_channel_id']),
|
||||
dbesc($arr['block_entity']),
|
||||
intval($arr['block_type'])
|
||||
);
|
||||
if ($r) {
|
||||
$arr['block_id'] = $r[0]['block_id'];
|
||||
}
|
||||
}
|
||||
if (!intval($arr['block_id'])) {
|
||||
$r = q(
|
||||
"select * from block where block_channel_id = %d and block_entity = '%s' and block_type = %d limit 1",
|
||||
intval($arr['block_channel_id']),
|
||||
dbesc($arr['block_entity']),
|
||||
intval($arr['block_type'])
|
||||
);
|
||||
if ($r) {
|
||||
$arr['block_id'] = $r[0]['block_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (intval($arr['block_id'])) {
|
||||
return q("UPDATE block set block_channel_id = %d, block_entity = '%s', block_type = %d, block_comment = '%s' where block_id = %d",
|
||||
intval($arr['block_channel_id']),
|
||||
dbesc($arr['block_entity']),
|
||||
intval($arr['block_type']),
|
||||
dbesc($arr['block_comment']),
|
||||
intval($arr['block_id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
return create_table_from_array('block',$arr);
|
||||
}
|
||||
}
|
||||
if (intval($arr['block_id'])) {
|
||||
return q(
|
||||
"UPDATE block set block_channel_id = %d, block_entity = '%s', block_type = %d, block_comment = '%s' where block_id = %d",
|
||||
intval($arr['block_channel_id']),
|
||||
dbesc($arr['block_entity']),
|
||||
intval($arr['block_type']),
|
||||
dbesc($arr['block_comment']),
|
||||
intval($arr['block_id'])
|
||||
);
|
||||
} else {
|
||||
return create_table_from_array('block', $arr);
|
||||
}
|
||||
}
|
||||
|
||||
static function remove($channel_id,$entity) {
|
||||
return q("delete from block where block_channel_id = %d and block_entity = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($entity)
|
||||
);
|
||||
}
|
||||
public static function remove($channel_id, $entity)
|
||||
{
|
||||
return q(
|
||||
"delete from block where block_channel_id = %d and block_entity = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc($entity)
|
||||
);
|
||||
}
|
||||
|
||||
static function fetch_by_id($channel_id,$id) {
|
||||
if (! intval($channel_id)) {
|
||||
return false;
|
||||
}
|
||||
$r = q("select * from block where block_channel_id = %d and block_id = %d ",
|
||||
intval($channel_id)
|
||||
);
|
||||
return (($r) ? array_shift($r) : $r);
|
||||
}
|
||||
public static function fetch_by_id($channel_id, $id)
|
||||
{
|
||||
if (!intval($channel_id)) {
|
||||
return false;
|
||||
}
|
||||
$r = q(
|
||||
"select * from block where block_channel_id = %d and block_id = %d ",
|
||||
intval($channel_id)
|
||||
);
|
||||
return (($r) ? array_shift($r) : $r);
|
||||
}
|
||||
|
||||
|
||||
static function fetch_by_entity($channel_id,$entity) {
|
||||
if (! intval($channel_id)) {
|
||||
return false;
|
||||
}
|
||||
public static function fetch_by_entity($channel_id, $entity)
|
||||
{
|
||||
if (!intval($channel_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::fetch_from_cache($channel_id,$entity);
|
||||
return self::fetch_from_cache($channel_id, $entity);
|
||||
}
|
||||
|
||||
}
|
||||
public static function fetch($channel_id, $type = false)
|
||||
{
|
||||
if (!intval($channel_id)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
static function fetch($channel_id,$type = false) {
|
||||
if (! intval($channel_id)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sql_extra = (($type === false) ? EMPTY_STR : " and block_type = " . intval($type));
|
||||
|
||||
$r = q("select * from block where block_channel_id = %d $sql_extra",
|
||||
intval($channel_id)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
$sql_extra = (($type === false) ? EMPTY_STR : " and block_type = " . intval($type));
|
||||
|
||||
$r = q(
|
||||
"select * from block where block_channel_id = %d $sql_extra",
|
||||
intval($channel_id)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Webfinger;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
|
@ -9,332 +10,359 @@ use Zotlabs\Lib\Zotfinger;
|
|||
require_once('include/permissions.php');
|
||||
|
||||
|
||||
class Libzotdir {
|
||||
class Libzotdir
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Directories may come and go over time. We will need to check that our
|
||||
* directory server is still valid occasionally, and reset to something that
|
||||
* is if our directory has gone offline for any reason
|
||||
*/
|
||||
/**
|
||||
* Directories may come and go over time. We will need to check that our
|
||||
* directory server is still valid occasionally, and reset to something that
|
||||
* is if our directory has gone offline for any reason
|
||||
*/
|
||||
|
||||
static function check_upstream_directory() {
|
||||
public static function check_upstream_directory()
|
||||
{
|
||||
|
||||
$directory = get_config('system', 'directory_server');
|
||||
$directory = get_config('system', 'directory_server');
|
||||
|
||||
// it's possible there is no directory server configured and the local hub is being used.
|
||||
// If so, default to preserving the absence of a specific server setting.
|
||||
// it's possible there is no directory server configured and the local hub is being used.
|
||||
// If so, default to preserving the absence of a specific server setting.
|
||||
|
||||
$isadir = true;
|
||||
$isadir = true;
|
||||
|
||||
if ($directory) {
|
||||
$j = Zotfinger::exec($directory);
|
||||
if (array_path_exists('data/directory_mode',$j)) {
|
||||
if ($j['data']['directory_mode'] === 'normal') {
|
||||
$isadir = false;
|
||||
}
|
||||
}
|
||||
if ($directory) {
|
||||
$j = Zotfinger::exec($directory);
|
||||
if (array_path_exists('data/directory_mode', $j)) {
|
||||
if ($j['data']['directory_mode'] === 'normal') {
|
||||
$isadir = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isadir) {
|
||||
set_config('system', 'directory_server', '');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function get_directory_setting($observer, $setting)
|
||||
{
|
||||
|
||||
|
||||
if ($observer) {
|
||||
$ret = get_xconfig($observer, 'directory', $setting);
|
||||
} else {
|
||||
$ret = ((array_key_exists($setting, $_SESSION)) ? intval($_SESSION[$setting]) : false);
|
||||
}
|
||||
|
||||
if ($ret === false) {
|
||||
$ret = get_config('directory', $setting);
|
||||
if ($ret === false) {
|
||||
$ret = (in_array($setting, ['globaldir', 'safemode', 'activedir']) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($setting === 'globaldir' && intval(get_config('system', 'localdir_hide'))) {
|
||||
$ret = 1;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called by the directory_sort widget.
|
||||
*/
|
||||
public static function dir_sort_links()
|
||||
{
|
||||
|
||||
$safe_mode = 1;
|
||||
|
||||
$observer = get_observer_hash();
|
||||
|
||||
$safe_mode = self::get_directory_setting($observer, 'safemode');
|
||||
$globaldir = self::get_directory_setting($observer, 'globaldir');
|
||||
$pubforums = self::get_directory_setting($observer, 'chantype');
|
||||
$activedir = self::get_directory_setting($observer, 'activedir');
|
||||
|
||||
$hide_local = intval(get_config('system', 'localdir_hide'));
|
||||
if ($hide_local) {
|
||||
$globaldir = 1;
|
||||
}
|
||||
|
||||
// Build urls without order and pubforums so it's easy to tack on the changed value
|
||||
// Probably there's an easier way to do this
|
||||
|
||||
$directory_sort_order = get_config('system', 'directory_sort_order');
|
||||
if (!$directory_sort_order) {
|
||||
$directory_sort_order = 'date';
|
||||
}
|
||||
|
||||
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
|
||||
$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
|
||||
|
||||
$url = 'directory?f=';
|
||||
|
||||
$tmp = array_merge($_GET, $_POST);
|
||||
unset($tmp['suggest']);
|
||||
unset($tmp['pubforums']);
|
||||
unset($tmp['type']);
|
||||
unset($tmp['global']);
|
||||
unset($tmp['safe']);
|
||||
unset($tmp['active']);
|
||||
unset($tmp['req']);
|
||||
unset($tmp['f']);
|
||||
$q = http_build_query($tmp);
|
||||
$forumsurl = $url . (($q) ? '&' . $q : '') . $suggest;
|
||||
|
||||
$o = replace_macros(get_markup_template('dir_sort_links.tpl'), [
|
||||
'$header' => t('Directory Options'),
|
||||
'$forumsurl' => $forumsurl,
|
||||
'$safemode' => array('safemode', t('Safe Mode'), $safe_mode, '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''),
|
||||
'$pubforums' => array('pubforums', t('Groups Only'), (($pubforums == 1) ? true : false), '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 1 : 0)\''),
|
||||
// '$collections' => array('collections', t('Collections Only'),(($pubforums == 2) ? true : false),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 2 : 0)\''),
|
||||
'$hide_local' => $hide_local,
|
||||
'$globaldir' => array('globaldir', t('This Website Only'), 1 - intval($globaldir), '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''),
|
||||
'$activedir' => array('activedir', t('Recently Updated'), intval($activedir), '', array(t('No'), t('Yes')), ' onchange=\'window.location.href="' . $forumsurl . '&active="+(this.checked ? 1 : 0)\''),
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data.
|
||||
*
|
||||
* Ignore updating records marked as deleted.
|
||||
*
|
||||
* If successful, sets ud_last in the DB to the current datetime for this
|
||||
* reddress/webbie.
|
||||
*
|
||||
* @param array $ud Entry from update table
|
||||
*/
|
||||
|
||||
public static function update_directory_entry($ud)
|
||||
{
|
||||
|
||||
logger('update_directory_entry: ' . print_r($ud, true), LOGGER_DATA);
|
||||
|
||||
if ($ud['ud_addr'] && (!($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||
$success = false;
|
||||
|
||||
$href = Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
if ($href) {
|
||||
$zf = Zotfinger::exec($href);
|
||||
}
|
||||
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
|
||||
} else {
|
||||
q(
|
||||
"update updates set ud_last = '%s' where ud_addr = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($ud['ud_addr'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Push local channel updates to a local directory server.
|
||||
*
|
||||
* This is called from Zotlabs/Daemon/Directory.php if a profile is to be pushed to the
|
||||
* directory and the local hub in this case is any kind of directory server.
|
||||
*
|
||||
* @param int $uid
|
||||
* @param bool $force
|
||||
*/
|
||||
|
||||
public static function local_dir_update($uid, $force)
|
||||
{
|
||||
|
||||
|
||||
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$p = q(
|
||||
"select channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$profile = [];
|
||||
$profile['encoding'] = 'zot';
|
||||
|
||||
if ($p) {
|
||||
$hash = $p[0]['channel_hash'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'], $p[0]['channel_timezone'], '')) {
|
||||
$profile['age'] = $age;
|
||||
}
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
$profile['marital'] = $p[0]['marital'];
|
||||
$profile['sexual'] = $p[0]['sexual'];
|
||||
$profile['locale'] = $p[0]['locality'];
|
||||
$profile['region'] = $p[0]['region'];
|
||||
$profile['postcode'] = $p[0]['postal_code'];
|
||||
$profile['country'] = $p[0]['country_name'];
|
||||
$profile['about'] = $p[0]['about'];
|
||||
$profile['homepage'] = $p[0]['homepage'];
|
||||
$profile['hometown'] = $p[0]['hometown'];
|
||||
|
||||
if ($p[0]['keywords']) {
|
||||
$tags = [];
|
||||
$k = explode(' ', $p[0]['keywords']);
|
||||
if ($k) {
|
||||
foreach ($k as $kk) {
|
||||
if (trim($kk)) {
|
||||
$tags[] = trim($kk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($tags) {
|
||||
$profile['keywords'] = $tags;
|
||||
}
|
||||
}
|
||||
|
||||
$hidden = (1 - intval($p[0]['publish']));
|
||||
|
||||
// logger('hidden: ' . $hidden);
|
||||
|
||||
$r = q(
|
||||
"select xchan_hidden from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($p[0]['channel_hash'])
|
||||
);
|
||||
|
||||
if (intval($r[0]['xchan_hidden']) != $hidden) {
|
||||
$r = q(
|
||||
"update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||
intval($hidden),
|
||||
dbesc($p[0]['channel_hash'])
|
||||
);
|
||||
}
|
||||
|
||||
$arr = ['channel_id' => $uid, 'hash' => $hash, 'profile' => $profile];
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
$address = channel_reddress($p[0]);
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
self::import_directory_profile($hash, $arr['profile'], $address, 0);
|
||||
} else {
|
||||
// they may have made it private
|
||||
$r = q(
|
||||
"delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
$r = q(
|
||||
"delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$ud_hash = random_string() . '@' . App::get_hostname();
|
||||
self::update_modtime($hash, $ud_hash, channel_reddress($p[0]), (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Imports a directory profile.
|
||||
*
|
||||
* @param string $hash
|
||||
* @param array $profile
|
||||
* @param string $addr
|
||||
* @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
|
||||
* @param number $suppress_update (optional) default 0
|
||||
* @return bool $updated if something changed
|
||||
*/
|
||||
|
||||
public static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0)
|
||||
{
|
||||
|
||||
logger('import_directory_profile', LOGGER_DEBUG);
|
||||
if (!$hash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$maxlen = get_max_import_size();
|
||||
|
||||
if ($maxlen && mb_strlen($profile['about']) > $maxlen) {
|
||||
$profile['about'] = mb_substr($profile['about'], 0, $maxlen, 'UTF-8');
|
||||
}
|
||||
|
||||
$arr = [];
|
||||
|
||||
$arr['xprof_hash'] = $hash;
|
||||
if (isset($profile['birthday'])) {
|
||||
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00')
|
||||
? $profile['birthday']
|
||||
: datetime_convert('', '', $profile['birthday'], 'Y-m-d')); // !!!! check this for 0000 year
|
||||
}
|
||||
$arr['xprof_age'] = (isset($profile['age']) ? intval($profile['age']) : 0);
|
||||
$arr['xprof_desc'] = ((isset($profile['description']) && $profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_gender'] = ((isset($profile['gender']) && $profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_marital'] = ((isset($profile['marital']) && $profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_sexual'] = ((isset($profile['sexual']) && $profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_locale'] = ((isset($profile['locale']) && $profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_region'] = ((isset($profile['region']) && $profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_postcode'] = ((isset($profile['postcode']) && $profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_country'] = ((isset($profile['country']) && $profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_about'] = ((isset($profile['about']) && $profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_pronouns'] = ((isset($profile['pronouns']) && $profile['pronouns']) ? htmlspecialchars($profile['pronouns'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_homepage'] = ((isset($profile['homepage']) && $profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
$arr['xprof_hometown'] = ((isset($profile['hometown']) && $profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
|
||||
if (! $isadir)
|
||||
set_config('system', 'directory_server', '');
|
||||
}
|
||||
$clean = [];
|
||||
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
|
||||
self::import_directory_keywords($hash, $profile['keywords']);
|
||||
foreach ($profile['keywords'] as $kw) {
|
||||
$kw = trim(htmlspecialchars($kw, ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
}
|
||||
}
|
||||
|
||||
$arr['xprof_keywords'] = implode(' ', $clean);
|
||||
|
||||
// Self censored, make it so
|
||||
// These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult".
|
||||
|
||||
|
||||
static function get_directory_setting($observer, $setting) {
|
||||
if (in_arrayi('nsfw', $clean) || in_arrayi('adult', $clean)) {
|
||||
q(
|
||||
"update xchan set xchan_selfcensored = 1 where xchan_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
$r = q(
|
||||
"select * from xprof where xprof_hash = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if ($observer)
|
||||
$ret = get_xconfig($observer, 'directory', $setting);
|
||||
else
|
||||
$ret = ((array_key_exists($setting,$_SESSION)) ? intval($_SESSION[$setting]) : false);
|
||||
if ($arr['xprof_age'] > 150) {
|
||||
$arr['xprof_age'] = 150;
|
||||
}
|
||||
if ($arr['xprof_age'] < 0) {
|
||||
$arr['xprof_age'] = 0;
|
||||
}
|
||||
|
||||
if($ret === false) {
|
||||
$ret = get_config('directory', $setting);
|
||||
if($ret === false) {
|
||||
$ret = (in_array($setting,[ 'globaldir','safemode', 'activedir' ]) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if($setting === 'globaldir' && intval(get_config('system','localdir_hide')))
|
||||
$ret = 1;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called by the directory_sort widget.
|
||||
*/
|
||||
static function dir_sort_links() {
|
||||
|
||||
$safe_mode = 1;
|
||||
|
||||
$observer = get_observer_hash();
|
||||
|
||||
$safe_mode = self::get_directory_setting($observer, 'safemode');
|
||||
$globaldir = self::get_directory_setting($observer, 'globaldir');
|
||||
$pubforums = self::get_directory_setting($observer, 'chantype');
|
||||
$activedir = self::get_directory_setting($observer, 'activedir');
|
||||
|
||||
$hide_local = intval(get_config('system','localdir_hide'));
|
||||
if ($hide_local) {
|
||||
$globaldir = 1;
|
||||
}
|
||||
|
||||
// Build urls without order and pubforums so it's easy to tack on the changed value
|
||||
// Probably there's an easier way to do this
|
||||
|
||||
$directory_sort_order = get_config('system','directory_sort_order');
|
||||
if (! $directory_sort_order) {
|
||||
$directory_sort_order = 'date';
|
||||
}
|
||||
|
||||
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
|
||||
$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
|
||||
|
||||
$url = 'directory?f=';
|
||||
|
||||
$tmp = array_merge($_GET,$_POST);
|
||||
unset($tmp['suggest']);
|
||||
unset($tmp['pubforums']);
|
||||
unset($tmp['type']);
|
||||
unset($tmp['global']);
|
||||
unset($tmp['safe']);
|
||||
unset($tmp['active']);
|
||||
unset($tmp['req']);
|
||||
unset($tmp['f']);
|
||||
$q = http_build_query($tmp);
|
||||
$forumsurl = $url . (($q) ? '&' . $q : '') . $suggest;
|
||||
|
||||
$o = replace_macros(get_markup_template('dir_sort_links.tpl'), [
|
||||
'$header' => t('Directory Options'),
|
||||
'$forumsurl' => $forumsurl,
|
||||
'$safemode' => array('safemode', t('Safe Mode'),$safe_mode,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''),
|
||||
'$pubforums' => array('pubforums', t('Groups Only'),(($pubforums == 1) ? true : false),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 1 : 0)\''),
|
||||
// '$collections' => array('collections', t('Collections Only'),(($pubforums == 2) ? true : false),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&type="+(this.checked ? 2 : 0)\''),
|
||||
'$hide_local' => $hide_local,
|
||||
'$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''),
|
||||
'$activedir' => array('activedir', t('Recently Updated'), intval($activedir),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&active="+(this.checked ? 1 : 0)\''),
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data.
|
||||
*
|
||||
* Ignore updating records marked as deleted.
|
||||
*
|
||||
* If successful, sets ud_last in the DB to the current datetime for this
|
||||
* reddress/webbie.
|
||||
*
|
||||
* @param array $ud Entry from update table
|
||||
*/
|
||||
|
||||
static function update_directory_entry($ud) {
|
||||
|
||||
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
|
||||
|
||||
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||
$success = false;
|
||||
|
||||
$href = Webfinger::zot_url(punify($ud['ud_addr']));
|
||||
if($href) {
|
||||
$zf = Zotfinger::exec($href);
|
||||
}
|
||||
if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_last = '%s' where ud_addr = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($ud['ud_addr'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Push local channel updates to a local directory server.
|
||||
*
|
||||
* This is called from Zotlabs/Daemon/Directory.php if a profile is to be pushed to the
|
||||
* directory and the local hub in this case is any kind of directory server.
|
||||
*
|
||||
* @param int $uid
|
||||
* @param boolean $force
|
||||
*/
|
||||
|
||||
static function local_dir_update($uid, $force) {
|
||||
|
||||
|
||||
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$p = q("select channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$profile = [];
|
||||
$profile['encoding'] = 'zot';
|
||||
|
||||
if ($p) {
|
||||
$hash = $p[0]['channel_hash'];
|
||||
|
||||
$profile['description'] = $p[0]['pdesc'];
|
||||
$profile['birthday'] = $p[0]['dob'];
|
||||
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||
$profile['age'] = $age;
|
||||
|
||||
$profile['gender'] = $p[0]['gender'];
|
||||
$profile['marital'] = $p[0]['marital'];
|
||||
$profile['sexual'] = $p[0]['sexual'];
|
||||
$profile['locale'] = $p[0]['locality'];
|
||||
$profile['region'] = $p[0]['region'];
|
||||
$profile['postcode'] = $p[0]['postal_code'];
|
||||
$profile['country'] = $p[0]['country_name'];
|
||||
$profile['about'] = $p[0]['about'];
|
||||
$profile['homepage'] = $p[0]['homepage'];
|
||||
$profile['hometown'] = $p[0]['hometown'];
|
||||
|
||||
if ($p[0]['keywords']) {
|
||||
$tags = [];
|
||||
$k = explode(' ', $p[0]['keywords']);
|
||||
if ($k)
|
||||
foreach ($k as $kk)
|
||||
if (trim($kk))
|
||||
$tags[] = trim($kk);
|
||||
|
||||
if ($tags)
|
||||
$profile['keywords'] = $tags;
|
||||
}
|
||||
|
||||
$hidden = (1 - intval($p[0]['publish']));
|
||||
|
||||
// logger('hidden: ' . $hidden);
|
||||
|
||||
$r = q("select xchan_hidden from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($p[0]['channel_hash'])
|
||||
);
|
||||
|
||||
if(intval($r[0]['xchan_hidden']) != $hidden) {
|
||||
$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||
intval($hidden),
|
||||
dbesc($p[0]['channel_hash'])
|
||||
);
|
||||
}
|
||||
|
||||
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
|
||||
call_hooks('local_dir_update', $arr);
|
||||
|
||||
$address = channel_reddress($p[0]);
|
||||
|
||||
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||
self::import_directory_profile($hash, $arr['profile'], $address, 0);
|
||||
}
|
||||
else {
|
||||
// they may have made it private
|
||||
$r = q("delete from xprof where xprof_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
$r = q("delete from xtag where xtag_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$ud_hash = random_string() . '@' . \App::get_hostname();
|
||||
self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Imports a directory profile.
|
||||
*
|
||||
* @param string $hash
|
||||
* @param array $profile
|
||||
* @param string $addr
|
||||
* @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
|
||||
* @param number $suppress_update (optional) default 0
|
||||
* @return boolean $updated if something changed
|
||||
*/
|
||||
|
||||
static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
|
||||
|
||||
logger('import_directory_profile', LOGGER_DEBUG);
|
||||
if (! $hash)
|
||||
return false;
|
||||
|
||||
|
||||
$maxlen = get_max_import_size();
|
||||
|
||||
if($maxlen && mb_strlen($profile['about']) > $maxlen) {
|
||||
$profile['about'] = mb_substr($profile['about'],0,$maxlen,'UTF-8');
|
||||
}
|
||||
|
||||
$arr = [];
|
||||
|
||||
$arr['xprof_hash'] = $hash;
|
||||
$arr['xprof_dob'] = ((isset($profile['birthday']) && $profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
|
||||
$arr['xprof_age'] = (isset($profile['age']) ? intval($profile['age']) : 0);
|
||||
$arr['xprof_desc'] = ((isset($profile['description']) && $profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_gender'] = ((isset($profile['gender']) && $profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_marital'] = ((isset($profile['marital']) && $profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_sexual'] = ((isset($profile['sexual']) && $profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_locale'] = ((isset($profile['locale']) && $profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_region'] = ((isset($profile['region']) && $profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_postcode'] = ((isset($profile['postcode']) && $profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_country'] = ((isset($profile['country']) && $profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_about'] = ((isset($profile['about']) && $profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_pronouns'] = ((isset($profile['pronouns']) && $profile['pronouns']) ? htmlspecialchars($profile['pronouns'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_homepage'] = ((isset($profile['homepage']) && $profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['xprof_hometown'] = ((isset($profile['hometown']) && $profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
|
||||
$clean = [];
|
||||
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
|
||||
self::import_directory_keywords($hash,$profile['keywords']);
|
||||
foreach ($profile['keywords'] as $kw) {
|
||||
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
}
|
||||
}
|
||||
|
||||
$arr['xprof_keywords'] = implode(' ',$clean);
|
||||
|
||||
// Self censored, make it so
|
||||
// These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult".
|
||||
|
||||
|
||||
if(in_arrayi('nsfw',$clean) || in_arrayi('adult',$clean)) {
|
||||
q("update xchan set xchan_selfcensored = 1 where xchan_hash = '%s'",
|
||||
dbesc($hash)
|
||||
);
|
||||
}
|
||||
|
||||
$r = q("select * from xprof where xprof_hash = '%s' limit 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if ($arr['xprof_age'] > 150)
|
||||
$arr['xprof_age'] = 150;
|
||||
if ($arr['xprof_age'] < 0)
|
||||
$arr['xprof_age'] = 0;
|
||||
|
||||
if ($r) {
|
||||
$update = false;
|
||||
foreach ($r[0] as $k => $v) {
|
||||
if ((array_key_exists($k,$arr)) && ($arr[$k] != $v)) {
|
||||
logger('import_directory_profile: update ' . $k . ' => ' . $arr[$k]);
|
||||
$update = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($update) {
|
||||
q("update xprof set
|
||||
if ($r) {
|
||||
$update = false;
|
||||
foreach ($r[0] as $k => $v) {
|
||||
if ((array_key_exists($k, $arr)) && ($arr[$k] != $v)) {
|
||||
logger('import_directory_profile: update ' . $k . ' => ' . $arr[$k]);
|
||||
$update = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($update) {
|
||||
q(
|
||||
"update xprof set
|
||||
xprof_desc = '%s',
|
||||
xprof_dob = '%s',
|
||||
xprof_age = %d,
|
||||
|
@ -351,156 +379,161 @@ class Libzotdir {
|
|||
xprof_keywords = '%s',
|
||||
xprof_pronouns = '%s'
|
||||
where xprof_hash = '%s'",
|
||||
dbesc($arr['xprof_desc']),
|
||||
dbesc($arr['xprof_dob']),
|
||||
intval($arr['xprof_age']),
|
||||
dbesc($arr['xprof_gender']),
|
||||
dbesc($arr['xprof_marital']),
|
||||
dbesc($arr['xprof_sexual']),
|
||||
dbesc($arr['xprof_locale']),
|
||||
dbesc($arr['xprof_region']),
|
||||
dbesc($arr['xprof_postcode']),
|
||||
dbesc($arr['xprof_country']),
|
||||
dbesc($arr['xprof_about']),
|
||||
dbesc($arr['xprof_homepage']),
|
||||
dbesc($arr['xprof_hometown']),
|
||||
dbesc($arr['xprof_keywords']),
|
||||
dbesc($arr['xprof_pronouns']),
|
||||
dbesc($arr['xprof_hash'])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$update = true;
|
||||
logger('New profile');
|
||||
q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords, xprof_pronouns) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
|
||||
dbesc($arr['xprof_hash']),
|
||||
dbesc($arr['xprof_desc']),
|
||||
dbesc($arr['xprof_dob']),
|
||||
intval($arr['xprof_age']),
|
||||
dbesc($arr['xprof_gender']),
|
||||
dbesc($arr['xprof_marital']),
|
||||
dbesc($arr['xprof_sexual']),
|
||||
dbesc($arr['xprof_locale']),
|
||||
dbesc($arr['xprof_region']),
|
||||
dbesc($arr['xprof_postcode']),
|
||||
dbesc($arr['xprof_country']),
|
||||
dbesc($arr['xprof_about']),
|
||||
dbesc($arr['xprof_homepage']),
|
||||
dbesc($arr['xprof_hometown']),
|
||||
dbesc($arr['xprof_keywords']),
|
||||
dbesc($arr['xprof_pronouns'])
|
||||
);
|
||||
}
|
||||
dbesc($arr['xprof_desc']),
|
||||
dbesc($arr['xprof_dob']),
|
||||
intval($arr['xprof_age']),
|
||||
dbesc($arr['xprof_gender']),
|
||||
dbesc($arr['xprof_marital']),
|
||||
dbesc($arr['xprof_sexual']),
|
||||
dbesc($arr['xprof_locale']),
|
||||
dbesc($arr['xprof_region']),
|
||||
dbesc($arr['xprof_postcode']),
|
||||
dbesc($arr['xprof_country']),
|
||||
dbesc($arr['xprof_about']),
|
||||
dbesc($arr['xprof_homepage']),
|
||||
dbesc($arr['xprof_hometown']),
|
||||
dbesc($arr['xprof_keywords']),
|
||||
dbesc($arr['xprof_pronouns']),
|
||||
dbesc($arr['xprof_hash'])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$update = true;
|
||||
logger('New profile');
|
||||
q(
|
||||
"insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords, xprof_pronouns) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
|
||||
dbesc($arr['xprof_hash']),
|
||||
dbesc($arr['xprof_desc']),
|
||||
dbesc($arr['xprof_dob']),
|
||||
intval($arr['xprof_age']),
|
||||
dbesc($arr['xprof_gender']),
|
||||
dbesc($arr['xprof_marital']),
|
||||
dbesc($arr['xprof_sexual']),
|
||||
dbesc($arr['xprof_locale']),
|
||||
dbesc($arr['xprof_region']),
|
||||
dbesc($arr['xprof_postcode']),
|
||||
dbesc($arr['xprof_country']),
|
||||
dbesc($arr['xprof_about']),
|
||||
dbesc($arr['xprof_homepage']),
|
||||
dbesc($arr['xprof_hometown']),
|
||||
dbesc($arr['xprof_keywords']),
|
||||
dbesc($arr['xprof_pronouns'])
|
||||
);
|
||||
}
|
||||
|
||||
$d = [
|
||||
'xprof' => $arr,
|
||||
'profile' => $profile,
|
||||
'update' => $update
|
||||
];
|
||||
$d = [
|
||||
'xprof' => $arr,
|
||||
'profile' => $profile,
|
||||
'update' => $update
|
||||
];
|
||||
|
||||
/**
|
||||
* @hooks import_directory_profile
|
||||
* Called when processing delivery of a profile structure from an external source (usually for directory storage).
|
||||
* * \e array \b xprof
|
||||
* * \e array \b profile
|
||||
* * \e boolean \b update
|
||||
*/
|
||||
/**
|
||||
* @hooks import_directory_profile
|
||||
* Called when processing delivery of a profile structure from an external source (usually for directory storage).
|
||||
* * \e array \b xprof
|
||||
* * \e array \b profile
|
||||
* * \e boolean \b update
|
||||
*/
|
||||
|
||||
call_hooks('import_directory_profile', $d);
|
||||
call_hooks('import_directory_profile', $d);
|
||||
|
||||
if (($d['update']) && (! $suppress_update)) {
|
||||
self::update_modtime($arr['xprof_hash'], new_uuid(), $addr, $ud_flags);
|
||||
}
|
||||
if (($d['update']) && (!$suppress_update)) {
|
||||
self::update_modtime($arr['xprof_hash'], new_uuid(), $addr, $ud_flags);
|
||||
}
|
||||
|
||||
q("update xchan set xchan_updated = '%s' where xchan_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($arr['xprof_hash'])
|
||||
);
|
||||
q(
|
||||
"update xchan set xchan_updated = '%s' where xchan_hash = '%s'",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($arr['xprof_hash'])
|
||||
);
|
||||
|
||||
return $d['update'];
|
||||
}
|
||||
return $d['update'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $hash An xtag_hash
|
||||
* @param array $keywords
|
||||
*/
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $hash An xtag_hash
|
||||
* @param array $keywords
|
||||
*/
|
||||
|
||||
static function import_directory_keywords($hash, $keywords) {
|
||||
public static function import_directory_keywords($hash, $keywords)
|
||||
{
|
||||
|
||||
$existing = [];
|
||||
$r = q("select * from xtag where xtag_hash = '%s' and xtag_flags = 0",
|
||||
dbesc($hash)
|
||||
);
|
||||
$existing = [];
|
||||
$r = q(
|
||||
"select * from xtag where xtag_hash = '%s' and xtag_flags = 0",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
$existing[] = $rr['xtag_term'];
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$existing[] = $rr['xtag_term'];
|
||||
}
|
||||
}
|
||||
|
||||
$clean = [];
|
||||
foreach($keywords as $kw) {
|
||||
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
}
|
||||
$clean = [];
|
||||
foreach ($keywords as $kw) {
|
||||
$kw = trim(htmlspecialchars($kw, ENT_COMPAT, 'UTF-8', false));
|
||||
$kw = trim($kw, ',');
|
||||
$clean[] = $kw;
|
||||
}
|
||||
|
||||
foreach($existing as $x) {
|
||||
if(! in_array($x, $clean))
|
||||
$r = q("delete from xtag where xtag_hash = '%s' and xtag_term = '%s' and xtag_flags = 0",
|
||||
dbesc($hash),
|
||||
dbesc($x)
|
||||
);
|
||||
}
|
||||
foreach($clean as $x) {
|
||||
if(! in_array($x, $existing)) {
|
||||
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
|
||||
dbesc($hash),
|
||||
dbesc($x)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $hash
|
||||
* @param string $guid
|
||||
* @param string $addr
|
||||
* @param int $flags (optional) default 0
|
||||
*/
|
||||
|
||||
static function update_modtime($hash, $guid, $addr, $flags = 0) {
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
|
||||
if($dirmode == DIRECTORY_MODE_NORMAL)
|
||||
return;
|
||||
|
||||
if($flags) {
|
||||
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
|
||||
dbesc($hash),
|
||||
dbesc($guid),
|
||||
dbesc(datetime_convert()),
|
||||
intval($flags),
|
||||
dbesc($addr)
|
||||
);
|
||||
}
|
||||
else {
|
||||
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and (ud_flags & %d) = 0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($addr),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
}
|
||||
}
|
||||
foreach ($existing as $x) {
|
||||
if (!in_array($x, $clean)) {
|
||||
$r = q(
|
||||
"delete from xtag where xtag_hash = '%s' and xtag_term = '%s' and xtag_flags = 0",
|
||||
dbesc($hash),
|
||||
dbesc($x)
|
||||
);
|
||||
}
|
||||
}
|
||||
foreach ($clean as $x) {
|
||||
if (!in_array($x, $existing)) {
|
||||
$r = q(
|
||||
"insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
|
||||
dbesc($hash),
|
||||
dbesc($x)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $hash
|
||||
* @param string $guid
|
||||
* @param string $addr
|
||||
* @param int $flags (optional) default 0
|
||||
*/
|
||||
|
||||
public static function update_modtime($hash, $guid, $addr, $flags = 0)
|
||||
{
|
||||
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($flags) {
|
||||
q(
|
||||
"insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
|
||||
dbesc($hash),
|
||||
dbesc($guid),
|
||||
dbesc(datetime_convert()),
|
||||
intval($flags),
|
||||
dbesc($addr)
|
||||
);
|
||||
} else {
|
||||
q(
|
||||
"update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and (ud_flags & %d) = 0 ",
|
||||
intval(UPDATE_FLAGS_UPDATED),
|
||||
dbesc($addr),
|
||||
intval(UPDATE_FLAGS_UPDATED)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
/**
|
||||
|
@ -6,7 +7,6 @@ namespace Zotlabs\Lib;
|
|||
*/
|
||||
|
||||
use Michelf\MarkdownExtra;
|
||||
|
||||
use League\HTMLToMarkdown\HtmlConverter;
|
||||
use League\HTMLToMarkdown\Environment;
|
||||
use League\HTMLToMarkdown\Converter\ConverterInterface;
|
||||
|
@ -18,308 +18,329 @@ require_once("include/html2bbcode.php");
|
|||
require_once("include/bbcode.php");
|
||||
|
||||
|
||||
class Markdown {
|
||||
|
||||
/**
|
||||
* @brief Convert Markdown to bbcode.
|
||||
*
|
||||
* We don't want to support a bbcode specific markdown interpreter
|
||||
* and the markdown library we have is pretty good, but provides HTML output.
|
||||
* So we'll use that to convert to HTML, then convert the HTML back to bbcode,
|
||||
* and then clean up a few Diaspora specific constructs.
|
||||
*
|
||||
* @param string $s The message as Markdown
|
||||
* @param boolean $use_zrl default false
|
||||
* @param array $options default empty
|
||||
* @return string The message converted to bbcode
|
||||
*/
|
||||
|
||||
static public function to_bbcode($s, $use_zrl = false, $options = []) {
|
||||
|
||||
if(is_array($s)) {
|
||||
btlogger('markdown_to_bb called with array. ' . print_r($s, true), LOGGER_NORMAL, LOG_WARNING);
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = str_replace("
","\r",$s);
|
||||
$s = str_replace("
\n>","",$s);
|
||||
|
||||
$s = html_entity_decode($s,ENT_COMPAT,'UTF-8');
|
||||
|
||||
// if empty link text replace with the url
|
||||
$s = preg_replace("/\[\]\((.*?)\)/ism",'[$1]($1)',$s);
|
||||
|
||||
$x = [
|
||||
'text' => $s,
|
||||
'zrl' => $use_zrl,
|
||||
'options' => $options
|
||||
];
|
||||
|
||||
/**
|
||||
* @hooks markdown_to_bb_init
|
||||
* * \e string \b text - The message as Markdown and what will get returned
|
||||
* * \e boolean \b zrl
|
||||
* * \e array \b options
|
||||
*/
|
||||
call_hooks('markdown_to_bb_init', $x);
|
||||
|
||||
$s = $x['text'];
|
||||
|
||||
// Escaping the hash tags
|
||||
$s = preg_replace('/\#([^\s\#])/','#$1',$s);
|
||||
|
||||
$s = MarkdownExtra::defaultTransform($s);
|
||||
|
||||
if($options && $options['preserve_lf']) {
|
||||
$s = str_replace(["\r","\n"],["",'<br>'],$s);
|
||||
}
|
||||
else {
|
||||
$s = str_replace("\r","",$s);
|
||||
}
|
||||
|
||||
$s = str_replace('#','#',$s);
|
||||
|
||||
$s = html2bbcode($s);
|
||||
|
||||
// Convert everything that looks like a link to a link
|
||||
if($use_zrl) {
|
||||
if (strpos($s,'[/img]') !== false) {
|
||||
$s = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", [ '\\Zotlabs\\Lib\\Markdown', 'use_zrl_cb_img'], $s);
|
||||
$s = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", [ '\\Zotlabs\\Lib\\Markdown', 'use_zrl_cb_img_x' ], $s);
|
||||
}
|
||||
$s = preg_replace_callback("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", [ '\\Zotlabs\\Lib\\Markdown', 'use_zrl_cb_link'] ,$s);
|
||||
}
|
||||
else {
|
||||
$s = preg_replace("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[url=$2$3]$2$3[/url]',$s);
|
||||
}
|
||||
|
||||
// remove duplicate adjacent code tags
|
||||
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s);
|
||||
|
||||
/**
|
||||
* @hooks markdown_to_bb
|
||||
* * \e string - The already converted message as bbcode
|
||||
*/
|
||||
call_hooks('markdown_to_bb', $s);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
static function use_zrl_cb_link($match) {
|
||||
$res = '';
|
||||
$is_zid = is_matrix_url(trim($match[0]));
|
||||
|
||||
if($is_zid)
|
||||
$res = $match[1] . '[zrl=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/zrl]';
|
||||
else
|
||||
$res = $match[1] . '[url=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/url]';
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
static function use_zrl_cb_img($match) {
|
||||
$res = '';
|
||||
$is_zid = is_matrix_url(trim($match[1]));
|
||||
|
||||
if($is_zid)
|
||||
$res = '[zmg]' . $match[1] . '[/zmg]';
|
||||
else
|
||||
$res = $match[0];
|
||||
|
||||
return $res;
|
||||
}
|
||||
class Markdown
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Convert Markdown to bbcode.
|
||||
*
|
||||
* We don't want to support a bbcode specific markdown interpreter
|
||||
* and the markdown library we have is pretty good, but provides HTML output.
|
||||
* So we'll use that to convert to HTML, then convert the HTML back to bbcode,
|
||||
* and then clean up a few Diaspora specific constructs.
|
||||
*
|
||||
* @param string $s The message as Markdown
|
||||
* @param bool $use_zrl default false
|
||||
* @param array $options default empty
|
||||
* @return string The message converted to bbcode
|
||||
*/
|
||||
|
||||
public static function to_bbcode($s, $use_zrl = false, $options = [])
|
||||
{
|
||||
|
||||
if (is_array($s)) {
|
||||
btlogger('markdown_to_bb called with array. ' . print_r($s, true), LOGGER_NORMAL, LOG_WARNING);
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = str_replace("
", "\r", $s);
|
||||
$s = str_replace("
\n>", "", $s);
|
||||
|
||||
$s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
|
||||
|
||||
// if empty link text replace with the url
|
||||
$s = preg_replace("/\[\]\((.*?)\)/ism", '[$1]($1)', $s);
|
||||
|
||||
$x = [
|
||||
'text' => $s,
|
||||
'zrl' => $use_zrl,
|
||||
'options' => $options
|
||||
];
|
||||
|
||||
/**
|
||||
* @hooks markdown_to_bb_init
|
||||
* * \e string \b text - The message as Markdown and what will get returned
|
||||
* * \e boolean \b zrl
|
||||
* * \e array \b options
|
||||
*/
|
||||
call_hooks('markdown_to_bb_init', $x);
|
||||
|
||||
$s = $x['text'];
|
||||
|
||||
// Escaping the hash tags
|
||||
$s = preg_replace('/\#([^\s\#])/', '#$1', $s);
|
||||
|
||||
$s = MarkdownExtra::defaultTransform($s);
|
||||
|
||||
if ($options && $options['preserve_lf']) {
|
||||
$s = str_replace(["\r", "\n"], ["", '<br>'], $s);
|
||||
} else {
|
||||
$s = str_replace("\r", "", $s);
|
||||
}
|
||||
|
||||
$s = str_replace('#', '#', $s);
|
||||
|
||||
$s = html2bbcode($s);
|
||||
|
||||
// Convert everything that looks like a link to a link
|
||||
if ($use_zrl) {
|
||||
if (strpos($s, '[/img]') !== false) {
|
||||
$s = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", ['\\Zotlabs\\Lib\\Markdown', 'use_zrl_cb_img'], $s);
|
||||
$s = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", ['\\Zotlabs\\Lib\\Markdown', 'use_zrl_cb_img_x'], $s);
|
||||
}
|
||||
$s = preg_replace_callback("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", ['\\Zotlabs\\Lib\\Markdown', 'use_zrl_cb_link'], $s);
|
||||
} else {
|
||||
$s = preg_replace("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[url=$2$3]$2$3[/url]', $s);
|
||||
}
|
||||
|
||||
// remove duplicate adjacent code tags
|
||||
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism", "[code]$2[/code]", $s);
|
||||
|
||||
/**
|
||||
* @hooks markdown_to_bb
|
||||
* * \e string - The already converted message as bbcode
|
||||
*/
|
||||
call_hooks('markdown_to_bb', $s);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
public static function use_zrl_cb_link($match)
|
||||
{
|
||||
$res = '';
|
||||
$is_zid = is_matrix_url(trim($match[0]));
|
||||
|
||||
if ($is_zid) {
|
||||
$res = $match[1] . '[zrl=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/zrl]';
|
||||
} else {
|
||||
$res = $match[1] . '[url=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/url]';
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public static function use_zrl_cb_img($match)
|
||||
{
|
||||
$res = '';
|
||||
$is_zid = is_matrix_url(trim($match[1]));
|
||||
|
||||
if ($is_zid) {
|
||||
$res = '[zmg]' . $match[1] . '[/zmg]';
|
||||
} else {
|
||||
$res = $match[0];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public static function use_zrl_cb_img_x($match)
|
||||
{
|
||||
$res = '';
|
||||
$is_zid = is_matrix_url(trim($match[3]));
|
||||
|
||||
if ($is_zid) {
|
||||
$res = '[zmg=' . $match[1] . 'x' . $match[2] . ']' . $match[3] . '[/zmg]';
|
||||
} else {
|
||||
$res = $match[0];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param array $match
|
||||
* @return string
|
||||
*/
|
||||
|
||||
public static function from_bbcode_share($match)
|
||||
{
|
||||
|
||||
$matches = [];
|
||||
$attributes = $match[1];
|
||||
|
||||
$author = "";
|
||||
preg_match("/author='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$author = urldecode($matches[1]);
|
||||
}
|
||||
|
||||
$link = "";
|
||||
preg_match("/link='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$link = $matches[1];
|
||||
}
|
||||
|
||||
$avatar = "";
|
||||
preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$avatar = $matches[1];
|
||||
}
|
||||
|
||||
$profile = "";
|
||||
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$profile = $matches[1];
|
||||
}
|
||||
|
||||
$posted = "";
|
||||
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$posted = $matches[1];
|
||||
}
|
||||
|
||||
static function use_zrl_cb_img_x($match) {
|
||||
$res = '';
|
||||
$is_zid = is_matrix_url(trim($match[3]));
|
||||
// message_id is never used, do we still need it?
|
||||
$message_id = "";
|
||||
preg_match("/message_id='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$message_id = $matches[1];
|
||||
}
|
||||
|
||||
if($is_zid)
|
||||
$res = '[zmg=' . $match[1] . 'x' . $match[2] . ']' . $match[3] . '[/zmg]';
|
||||
else
|
||||
$res = $match[0];
|
||||
if (!$message_id) {
|
||||
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "") {
|
||||
$message_id = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param array $match
|
||||
* @return string
|
||||
*/
|
||||
$reldate = datetime_convert('UTC', date_default_timezone_get(), $posted, 'r');
|
||||
|
||||
static public function from_bbcode_share($match) {
|
||||
$headline = '';
|
||||
|
||||
$matches = [];
|
||||
$attributes = $match[1];
|
||||
if ($avatar != "") {
|
||||
$headline .= '[url=' . zid($profile) . '][img]' . $avatar . '[/img][/url]';
|
||||
}
|
||||
|
||||
$author = "";
|
||||
preg_match("/author='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$author = urldecode($matches[1]);
|
||||
// Bob Smith wrote the following post 2 hours ago
|
||||
|
||||
$link = "";
|
||||
preg_match("/link='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$link = $matches[1];
|
||||
$fmt = sprintf(
|
||||
t('%1$s wrote the following %2$s %3$s'),
|
||||
'[url=' . zid($profile) . ']' . $author . '[/url]',
|
||||
'[url=' . zid($link) . ']' . t('post') . '[/url]',
|
||||
$reldate
|
||||
);
|
||||
|
||||
$headline .= $fmt . "\n\n";
|
||||
|
||||
$text = $headline . trim($match[2]);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert bbcode to Markdown.
|
||||
*
|
||||
* @param string $Text The message as bbcode
|
||||
* @param array $options default empty
|
||||
* @return string The message converted to Markdown
|
||||
*/
|
||||
|
||||
public static function from_bbcode($Text, $options = [])
|
||||
{
|
||||
|
||||
/*
|
||||
* Transform #tags, strip off the [url] and replace spaces with underscore
|
||||
*/
|
||||
|
||||
$Text = preg_replace_callback(
|
||||
'/#\[([zu])rl\=(.*?)\](.*?)\[\/[(zu)]rl\]/i',
|
||||
create_function('$match', 'return \'#\'. str_replace(\' \', \'_\', $match[3]);'),
|
||||
$Text
|
||||
);
|
||||
|
||||
$Text = preg_replace('/#\^\[([zu])rl\=(.*?)\](.*?)\[\/([zu])rl\]/i', '[$1rl=$2]$3[/$4rl]', $Text);
|
||||
|
||||
// Converting images with size parameters to simple images. Markdown doesn't know it.
|
||||
$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $Text);
|
||||
|
||||
$Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism", ['\\Zotlabs\\Lib\\Markdown', 'from_bbcode_share'], $Text);
|
||||
|
||||
$x = ['bbcode' => $Text, 'options' => $options];
|
||||
|
||||
/**
|
||||
* @hooks bb_to_markdown_bb
|
||||
* * \e string \b bbcode - The message as bbcode and what will get returned
|
||||
* * \e array \b options
|
||||
*/
|
||||
call_hooks('bb_to_markdown_bb', $x);
|
||||
|
||||
$Text = $x['bbcode'];
|
||||
|
||||
// Convert it to HTML - don't try oembed
|
||||
$Text = bbcode($Text, ['tryoembed' => false]);
|
||||
|
||||
$avatar = "";
|
||||
preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$avatar = $matches[1];
|
||||
// Now convert HTML to Markdown
|
||||
|
||||
$Text = self::from_html($Text);
|
||||
|
||||
$profile = "";
|
||||
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$profile = $matches[1];
|
||||
//html2markdown adds backslashes infront of hashes after a new line. remove them
|
||||
$Text = str_replace("\n\#", "\n#", $Text);
|
||||
|
||||
$posted = "";
|
||||
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$posted = $matches[1];
|
||||
|
||||
// message_id is never used, do we still need it?
|
||||
$message_id = "";
|
||||
preg_match("/message_id='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$message_id = $matches[1];
|
||||
// If the text going into bbcode() has a plain URL in it, i.e.
|
||||
// with no [url] tags around it, it will come out of parseString()
|
||||
// looking like: <http://url.com>, which gets removed by strip_tags().
|
||||
// So take off the angle brackets of any such URL
|
||||
$Text = preg_replace("/<http(.*?)>/is", "http$1", $Text);
|
||||
|
||||
if(! $message_id) {
|
||||
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$message_id = $matches[1];
|
||||
}
|
||||
// Remove empty zrl links
|
||||
$Text = preg_replace("/\[zrl\=\].*?\[\/zrl\]/is", "", $Text);
|
||||
|
||||
$Text = trim($Text);
|
||||
|
||||
$reldate = datetime_convert('UTC', date_default_timezone_get(), $posted, 'r');
|
||||
/**
|
||||
* @hooks bb_to_markdown
|
||||
* * \e string - The already converted message as bbcode and what will get returned
|
||||
*/
|
||||
call_hooks('bb_to_markdown', $Text);
|
||||
|
||||
$headline = '';
|
||||
return $Text;
|
||||
}
|
||||
|
||||
if ($avatar != "")
|
||||
$headline .= '[url=' . zid($profile) . '][img]' . $avatar . '[/img][/url]';
|
||||
|
||||
// Bob Smith wrote the following post 2 hours ago
|
||||
/**
|
||||
* @brief Convert a HTML text into Markdown.
|
||||
*
|
||||
* This function uses the library league/html-to-markdown for this task.
|
||||
*
|
||||
* If the HTML text can not get parsed it will return an empty string.
|
||||
*
|
||||
* @param string $html The HTML code to convert
|
||||
* @return string Markdown representation of the given HTML text, empty on error
|
||||
*/
|
||||
|
||||
$fmt = sprintf( t('%1$s wrote the following %2$s %3$s'),
|
||||
'[url=' . zid($profile) . ']' . $author . '[/url]',
|
||||
'[url=' . zid($link) . ']' . t('post') . '[/url]',
|
||||
$reldate
|
||||
);
|
||||
public static function from_html($html, $options = [])
|
||||
{
|
||||
$markdown = '';
|
||||
|
||||
$headline .= $fmt . "\n\n";
|
||||
if (!$options) {
|
||||
$options = [
|
||||
'header_style' => 'setext', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
|
||||
'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
|
||||
'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
|
||||
'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style
|
||||
'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style
|
||||
'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
|
||||
'hard_break' => false, // Set to true to turn <br> into `\n` instead of ` \n`
|
||||
'list_item_style' => '-', // Set the default character for each <li> in a <ul>. Can be '-', '*', or '+'
|
||||
];
|
||||
}
|
||||
|
||||
$text = $headline . trim($match[2]);
|
||||
$environment = Environment::createDefaultEnvironment($options);
|
||||
$environment->addConverter(new TableConverter());
|
||||
$converter = new HtmlConverter($environment);
|
||||
|
||||
try {
|
||||
$markdown = $converter->convert($html);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
logger("Invalid HTML. HTMLToMarkdown library threw an exception.");
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert bbcode to Markdown.
|
||||
*
|
||||
* @param string $Text The message as bbcode
|
||||
* @param array $options default empty
|
||||
* @return string The message converted to Markdown
|
||||
*/
|
||||
|
||||
static public function from_bbcode($Text, $options = []) {
|
||||
|
||||
/*
|
||||
* Transform #tags, strip off the [url] and replace spaces with underscore
|
||||
*/
|
||||
|
||||
$Text = preg_replace_callback('/#\[([zu])rl\=(.*?)\](.*?)\[\/[(zu)]rl\]/i',
|
||||
create_function('$match', 'return \'#\'. str_replace(\' \', \'_\', $match[3]);'), $Text);
|
||||
|
||||
$Text = preg_replace('/#\^\[([zu])rl\=(.*?)\](.*?)\[\/([zu])rl\]/i', '[$1rl=$2]$3[/$4rl]', $Text);
|
||||
|
||||
// Converting images with size parameters to simple images. Markdown doesn't know it.
|
||||
$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $Text);
|
||||
|
||||
$Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism", [ '\\Zotlabs\\Lib\\Markdown', 'from_bbcode_share'], $Text);
|
||||
|
||||
$x = [ 'bbcode' => $Text, 'options' => $options ];
|
||||
|
||||
/**
|
||||
* @hooks bb_to_markdown_bb
|
||||
* * \e string \b bbcode - The message as bbcode and what will get returned
|
||||
* * \e array \b options
|
||||
*/
|
||||
call_hooks('bb_to_markdown_bb', $x);
|
||||
|
||||
$Text = $x['bbcode'];
|
||||
|
||||
// Convert it to HTML - don't try oembed
|
||||
$Text = bbcode($Text, [ 'tryoembed' => false ]);
|
||||
|
||||
// Now convert HTML to Markdown
|
||||
|
||||
$Text = self::from_html($Text);
|
||||
|
||||
//html2markdown adds backslashes infront of hashes after a new line. remove them
|
||||
$Text = str_replace("\n\#", "\n#", $Text);
|
||||
|
||||
|
||||
// If the text going into bbcode() has a plain URL in it, i.e.
|
||||
// with no [url] tags around it, it will come out of parseString()
|
||||
// looking like: <http://url.com>, which gets removed by strip_tags().
|
||||
// So take off the angle brackets of any such URL
|
||||
$Text = preg_replace("/<http(.*?)>/is", "http$1", $Text);
|
||||
|
||||
// Remove empty zrl links
|
||||
$Text = preg_replace("/\[zrl\=\].*?\[\/zrl\]/is", "", $Text);
|
||||
|
||||
$Text = trim($Text);
|
||||
|
||||
/**
|
||||
* @hooks bb_to_markdown
|
||||
* * \e string - The already converted message as bbcode and what will get returned
|
||||
*/
|
||||
call_hooks('bb_to_markdown', $Text);
|
||||
|
||||
return $Text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert a HTML text into Markdown.
|
||||
*
|
||||
* This function uses the library league/html-to-markdown for this task.
|
||||
*
|
||||
* If the HTML text can not get parsed it will return an empty string.
|
||||
*
|
||||
* @param string $html The HTML code to convert
|
||||
* @return string Markdown representation of the given HTML text, empty on error
|
||||
*/
|
||||
|
||||
static public function from_html($html,$options = []) {
|
||||
$markdown = '';
|
||||
|
||||
if(! $options) {
|
||||
$options = [
|
||||
'header_style' => 'setext', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
|
||||
'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
|
||||
'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
|
||||
'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style
|
||||
'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style
|
||||
'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
|
||||
'hard_break' => false, // Set to true to turn <br> into `\n` instead of ` \n`
|
||||
'list_item_style' => '-', // Set the default character for each <li> in a <ul>. Can be '-', '*', or '+'
|
||||
];
|
||||
}
|
||||
|
||||
$environment = Environment::createDefaultEnvironment($options);
|
||||
$environment->addConverter(new TableConverter());
|
||||
$converter = new HtmlConverter($environment);
|
||||
|
||||
try {
|
||||
$markdown = $converter->convert($html);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
logger("Invalid HTML. HTMLToMarkdown library threw an exception.");
|
||||
}
|
||||
|
||||
return $markdown;
|
||||
}
|
||||
return $markdown;
|
||||
}
|
||||
}
|
||||
|
||||
// Tables are not an official part of the markdown specification.
|
||||
|
@ -330,64 +351,64 @@ class Markdown {
|
|||
|
||||
class TableConverter implements ConverterInterface
|
||||
{
|
||||
/**
|
||||
* @param ElementInterface $element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert(ElementInterface $element)
|
||||
{
|
||||
switch ($element->getTagName()) {
|
||||
case 'tr':
|
||||
$line = [];
|
||||
$i = 1;
|
||||
foreach ($element->getChildren() as $td) {
|
||||
$i++;
|
||||
$v = $td->getValue();
|
||||
$v = trim($v);
|
||||
if ($i % 2 === 0 || $v !== '') {
|
||||
$line[] = $v;
|
||||
}
|
||||
}
|
||||
return '| ' . implode(' | ', $line) . " |\n";
|
||||
case 'td':
|
||||
case 'th':
|
||||
return trim($element->getValue());
|
||||
case 'tbody':
|
||||
return trim($element->getValue());
|
||||
case 'thead':
|
||||
$headerLine = reset($element->getChildren())->getValue();
|
||||
$headers = explode(' | ', trim(trim($headerLine, "\n"), '|'));
|
||||
$hr = [];
|
||||
foreach ($headers as $td) {
|
||||
$length = strlen(trim($td)) + 2;
|
||||
$hr[] = str_repeat('-', $length > 3 ? $length : 3);
|
||||
}
|
||||
$hr = '|' . implode('|', $hr) . '|';
|
||||
return $headerLine . $hr . "\n";
|
||||
case 'table':
|
||||
$inner = $element->getValue();
|
||||
if (strpos($inner, '-----') === false) {
|
||||
$inner = explode("\n", $inner);
|
||||
$single = explode(' | ', trim($inner[0], '|'));
|
||||
$hr = [];
|
||||
foreach ($single as $td) {
|
||||
$length = strlen(trim($td)) + 2;
|
||||
$hr[] = str_repeat('-', $length > 3 ? $length : 3);
|
||||
}
|
||||
$hr = '|' . implode('|', $hr) . '|';
|
||||
array_splice($inner, 1, 0, $hr);
|
||||
$inner = implode("\n", $inner);
|
||||
}
|
||||
return trim($inner) . "\n\n";
|
||||
}
|
||||
return $element->getValue();
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSupportedTags()
|
||||
{
|
||||
return array('table', 'tr', 'thead', 'td', 'tbody');
|
||||
}
|
||||
/**
|
||||
* @param ElementInterface $element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert(ElementInterface $element)
|
||||
{
|
||||
switch ($element->getTagName()) {
|
||||
case 'tr':
|
||||
$line = [];
|
||||
$i = 1;
|
||||
foreach ($element->getChildren() as $td) {
|
||||
$i++;
|
||||
$v = $td->getValue();
|
||||
$v = trim($v);
|
||||
if ($i % 2 === 0 || $v !== '') {
|
||||
$line[] = $v;
|
||||
}
|
||||
}
|
||||
return '| ' . implode(' | ', $line) . " |\n";
|
||||
case 'td':
|
||||
case 'th':
|
||||
return trim($element->getValue());
|
||||
case 'tbody':
|
||||
return trim($element->getValue());
|
||||
case 'thead':
|
||||
$headerLine = reset($element->getChildren())->getValue();
|
||||
$headers = explode(' | ', trim(trim($headerLine, "\n"), '|'));
|
||||
$hr = [];
|
||||
foreach ($headers as $td) {
|
||||
$length = strlen(trim($td)) + 2;
|
||||
$hr[] = str_repeat('-', $length > 3 ? $length : 3);
|
||||
}
|
||||
$hr = '|' . implode('|', $hr) . '|';
|
||||
return $headerLine . $hr . "\n";
|
||||
case 'table':
|
||||
$inner = $element->getValue();
|
||||
if (strpos($inner, '-----') === false) {
|
||||
$inner = explode("\n", $inner);
|
||||
$single = explode(' | ', trim($inner[0], '|'));
|
||||
$hr = [];
|
||||
foreach ($single as $td) {
|
||||
$length = strlen(trim($td)) + 2;
|
||||
$hr[] = str_repeat('-', $length > 3 ? $length : 3);
|
||||
}
|
||||
$hr = '|' . implode('|', $hr) . '|';
|
||||
array_splice($inner, 1, 0, $hr);
|
||||
$inner = implode("\n", $inner);
|
||||
}
|
||||
return trim($inner) . "\n\n";
|
||||
}
|
||||
return $element->getValue();
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSupportedTags()
|
||||
{
|
||||
return array('table', 'tr', 'thead', 'td', 'tbody');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,111 +22,126 @@ namespace Zotlabs\Lib;
|
|||
* $html = \Michelf\MarkdownExtra::DefaultTransform($markdown);
|
||||
* @endcode
|
||||
*/
|
||||
class MarkdownSoap {
|
||||
class MarkdownSoap
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $str;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $token;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $str;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $token;
|
||||
|
||||
|
||||
function __construct($s) {
|
||||
$this->str = $s;
|
||||
$this->token = random_string(20);
|
||||
}
|
||||
public function __construct($s)
|
||||
{
|
||||
$this->str = $s;
|
||||
$this->token = random_string(20);
|
||||
}
|
||||
|
||||
function clean() {
|
||||
public function clean()
|
||||
{
|
||||
|
||||
$x = $this->extract_code($this->str);
|
||||
$x = $this->extract_code($this->str);
|
||||
|
||||
$x = $this->purify($x);
|
||||
$x = $this->purify($x);
|
||||
|
||||
$x = $this->putback_code($x);
|
||||
$x = $this->putback_code($x);
|
||||
|
||||
$x = $this->escape($x);
|
||||
$x = $this->escape($x);
|
||||
|
||||
return $x;
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extracts code blocks and privately escapes them from processing.
|
||||
*
|
||||
* @see encode_code()
|
||||
* @see putback_code()
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
function extract_code($s) {
|
||||
/**
|
||||
* @brief Extracts code blocks and privately escapes them from processing.
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @see encode_code()
|
||||
* @see putback_code()
|
||||
*
|
||||
*/
|
||||
public function extract_code($s)
|
||||
{
|
||||
|
||||
$text = preg_replace_callback('{
|
||||
$text = preg_replace_callback(
|
||||
'{
|
||||
(?:\n\n|\A\n?)
|
||||
( # $1 = the code block -- one or more lines, starting with a space/tab
|
||||
(?>
|
||||
[ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces
|
||||
[ ]{' . '4' . '} # Lines must start with a tab or a tab-width of spaces
|
||||
.*\n+
|
||||
)+
|
||||
)
|
||||
((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
|
||||
((?=^[ ]{0,' . '4' . '}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
|
||||
}xm',
|
||||
[ $this , 'encode_code' ], $s);
|
||||
[$this, 'encode_code'],
|
||||
$s
|
||||
);
|
||||
|
||||
return $text;
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
function encode_code($matches) {
|
||||
return $this->token . ';' . base64_encode($matches[0]) . ';' ;
|
||||
}
|
||||
public function encode_code($matches)
|
||||
{
|
||||
return $this->token . ';' . base64_encode($matches[0]) . ';';
|
||||
}
|
||||
|
||||
function decode_code($matches) {
|
||||
return base64_decode($matches[1]);
|
||||
}
|
||||
public function decode_code($matches)
|
||||
{
|
||||
return base64_decode($matches[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put back the code blocks.
|
||||
*
|
||||
* @see extract_code()
|
||||
* @see decode_code()
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
function putback_code($s) {
|
||||
$text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm', [ $this, 'decode_code' ], $s);
|
||||
return $text;
|
||||
}
|
||||
/**
|
||||
* @brief Put back the code blocks.
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @see extract_code()
|
||||
* @see decode_code()
|
||||
*
|
||||
*/
|
||||
public function putback_code($s)
|
||||
{
|
||||
$text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm', [$this, 'decode_code'], $s);
|
||||
return $text;
|
||||
}
|
||||
|
||||
function purify($s) {
|
||||
$s = $this->protect_autolinks($s);
|
||||
$s = purify_html($s);
|
||||
$s = $this->unprotect_autolinks($s);
|
||||
return $s;
|
||||
}
|
||||
public function purify($s)
|
||||
{
|
||||
$s = $this->protect_autolinks($s);
|
||||
$s = purify_html($s);
|
||||
$s = $this->unprotect_autolinks($s);
|
||||
return $s;
|
||||
}
|
||||
|
||||
function protect_autolinks($s) {
|
||||
$s = preg_replace('/\<(https?\:\/\/)(.*?)\>/', '[$1$2]($1$2)', $s);
|
||||
return $s;
|
||||
}
|
||||
public function protect_autolinks($s)
|
||||
{
|
||||
$s = preg_replace('/\<(https?\:\/\/)(.*?)\>/', '[$1$2]($1$2)', $s);
|
||||
return $s;
|
||||
}
|
||||
|
||||
function unprotect_autolinks($s) {
|
||||
return $s;
|
||||
}
|
||||
public function unprotect_autolinks($s)
|
||||
{
|
||||
return $s;
|
||||
}
|
||||
|
||||
function escape($s) {
|
||||
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
public function escape($s)
|
||||
{
|
||||
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts special HTML entities back to characters.
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
static public function unescape($s) {
|
||||
return htmlspecialchars_decode($s, ENT_QUOTES);
|
||||
}
|
||||
/**
|
||||
* @brief Converts special HTML entities back to characters.
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
public static function unescape($s)
|
||||
{
|
||||
return htmlspecialchars_decode($s, ENT_QUOTES);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,99 +5,104 @@ namespace Zotlabs\Lib;
|
|||
use App;
|
||||
use Zotlabs\Lib\PConfig;
|
||||
|
||||
class MastAPI
|
||||
{
|
||||
|
||||
class MastAPI {
|
||||
public static function format_channel($channel)
|
||||
{
|
||||
$p = q(
|
||||
"select * from profile where uid = %d and is_default = 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
static function format_channel($channel) {
|
||||
$p = q("select * from profile where uid = %d and is_default = 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
$a = q(
|
||||
"select * from account where account_id = %d",
|
||||
intval($channel['channel_account_id'])
|
||||
);
|
||||
|
||||
$a = q("select * from account where account_id = %d",
|
||||
intval($channel['channel_account_id'])
|
||||
);
|
||||
|
||||
$followers = q("select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 ",
|
||||
$followers = q(
|
||||
"select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'their_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0 ",
|
||||
intval($channel['channel_id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
$following = q("select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
|
||||
intval($channel['channel_id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
$following = q(
|
||||
"select count(xchan_hash) as total from xchan left join abconfig on abconfig.xchan = xchan_hash left join abook on abook_xchan = xchan_hash where abook_channel = %d and abconfig.chan = %d and abconfig.cat = 'system' and abconfig.k = 'my_perms' and abconfig.v like '%%send_stream%%' and xchan_hash != '%s' and xchan_orphan = 0 and xchan_deleted = 0 and abook_hidden = 0 and abook_pending = 0 and abook_self = 0",
|
||||
intval($channel['channel_id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
$cover_photo = get_cover_photo($channel['channel_id'],'array');
|
||||
$cover_photo = get_cover_photo($channel['channel_id'], 'array');
|
||||
|
||||
$item_normal = item_normal();
|
||||
|
||||
// count posts/comments
|
||||
$statuses = q("SELECT COUNT(id) as total FROM item
|
||||
$statuses = q(
|
||||
"SELECT COUNT(id) as total FROM item
|
||||
WHERE uid = %d
|
||||
AND author_xchan = '%s' $item_normal ",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($channel['channel_hash'])
|
||||
dbesc($channel['channel_hash'])
|
||||
);
|
||||
|
||||
$ret = [];
|
||||
$ret['id'] = (string) $channel['channel_id'];
|
||||
$ret['username'] = $channel['channel_address'];
|
||||
$ret['acct'] = $channel['channel_address'];
|
||||
$ret['display_name'] = $channel['channel_name'];
|
||||
$ret['locked'] = ((intval(PConfig::Get($channel['channel_id'],'system','autoperms'))) ? false : true );
|
||||
$ret['discoverable'] = ((1 - intval($channel['xchan_hidden'])) ? true : false);
|
||||
$ret['created_at'] = datetime_convert('UTC','UTC', $a[0]['account_created'], ATOM_TIME);
|
||||
$ret['note'] = bbcode($p[0]['about'], [ 'export' => true ]);
|
||||
$ret['url'] = channel_url($channel);
|
||||
$ret['avatar'] = $channel['xchan_photo_l'];
|
||||
$ret['avatar_static'] = $channel['xchan_photo_l'];
|
||||
if ($cover_photo) {
|
||||
$ret['header'] = $cover_photo['url'];
|
||||
$ret['header_static'] = $cover_photo['url'];
|
||||
}
|
||||
$ret['followers_count'] = intval($followers[0]['total']);
|
||||
$ret['following_count'] = intval($following[0]['total']);
|
||||
$ret['statuses_count'] = intval($statuses[0]['total']);
|
||||
$ret['last_status_at'] = datetime_convert('UTC','UTC', $channel['lastpost'], ATOM_TIME);
|
||||
$ret = [];
|
||||
$ret['id'] = (string)$channel['channel_id'];
|
||||
$ret['username'] = $channel['channel_address'];
|
||||
$ret['acct'] = $channel['channel_address'];
|
||||
$ret['display_name'] = $channel['channel_name'];
|
||||
$ret['locked'] = ((intval(PConfig::Get($channel['channel_id'], 'system', 'autoperms'))) ? false : true);
|
||||
$ret['discoverable'] = ((1 - intval($channel['xchan_hidden'])) ? true : false);
|
||||
$ret['created_at'] = datetime_convert('UTC', 'UTC', $a[0]['account_created'], ATOM_TIME);
|
||||
$ret['note'] = bbcode($p[0]['about'], ['export' => true]);
|
||||
$ret['url'] = channel_url($channel);
|
||||
$ret['avatar'] = $channel['xchan_photo_l'];
|
||||
$ret['avatar_static'] = $channel['xchan_photo_l'];
|
||||
if ($cover_photo) {
|
||||
$ret['header'] = $cover_photo['url'];
|
||||
$ret['header_static'] = $cover_photo['url'];
|
||||
}
|
||||
$ret['followers_count'] = intval($followers[0]['total']);
|
||||
$ret['following_count'] = intval($following[0]['total']);
|
||||
$ret['statuses_count'] = intval($statuses[0]['total']);
|
||||
$ret['last_status_at'] = datetime_convert('UTC', 'UTC', $channel['lastpost'], ATOM_TIME);
|
||||
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
static function format_site() {
|
||||
public static function format_site()
|
||||
{
|
||||
|
||||
$register = intval(get_config('system','register_policy'));
|
||||
$register = intval(get_config('system', 'register_policy'));
|
||||
|
||||
$u = q("select count(channel_id) as total from channel where channel_removed = 0");
|
||||
$i = q("select count(id) as total from item where item_origin = 1");
|
||||
$s = q("select count(site_url) as total from site");
|
||||
$u = q("select count(channel_id) as total from channel where channel_removed = 0");
|
||||
$i = q("select count(id) as total from item where item_origin = 1");
|
||||
$s = q("select count(site_url) as total from site");
|
||||
|
||||
$admins = q("select * from channel left join account on account_id = channel_account_id where ( account_roles & 4096 ) > 0 and account_default_channel = channel_id");
|
||||
$adminsx = channelx_by_n($admins[0]['channel_id']);
|
||||
$admins = q("select * from channel left join account on account_id = channel_account_id where ( account_roles & 4096 ) > 0 and account_default_channel = channel_id");
|
||||
$adminsx = channelx_by_n($admins[0]['channel_id']);
|
||||
|
||||
|
||||
$ret = [];
|
||||
$ret['uri'] = z_root();
|
||||
$ret['title'] = System::get_site_name();
|
||||
$ret['description'] = bbcode(get_config('system','siteinfo',''), [ 'export' => true ] );
|
||||
$ret['email'] = get_config('system','admin_email');
|
||||
$ret['version'] = System::get_project_version();
|
||||
$ret['registrations'] = (($register) ? true : false);
|
||||
$ret['approval_required'] = (($register === REGISTER_APPROVE) ? true : false);
|
||||
$ret['invites_enabled'] = false;
|
||||
$ret['urls'] = [];
|
||||
$ret['stats'] = [
|
||||
'user_count' => intval($u[0]['total']),
|
||||
'status_count' => intval($i[0]['total']),
|
||||
'domain_count' => intval($s[0]['total']),
|
||||
];
|
||||
$ret = [];
|
||||
$ret['uri'] = z_root();
|
||||
$ret['title'] = System::get_site_name();
|
||||
$ret['description'] = bbcode(get_config('system', 'siteinfo', ''), ['export' => true]);
|
||||
$ret['email'] = get_config('system', 'admin_email');
|
||||
$ret['version'] = System::get_project_version();
|
||||
$ret['registrations'] = (($register) ? true : false);
|
||||
$ret['approval_required'] = (($register === REGISTER_APPROVE) ? true : false);
|
||||
$ret['invites_enabled'] = false;
|
||||
$ret['urls'] = [];
|
||||
$ret['stats'] = [
|
||||
'user_count' => intval($u[0]['total']),
|
||||
'status_count' => intval($i[0]['total']),
|
||||
'domain_count' => intval($s[0]['total']),
|
||||
];
|
||||
|
||||
$ret['contact_account'] = self::format_channel($adminsx);
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
$ret['contact_account'] = self::format_channel($adminsx);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
|
@ -3,88 +3,94 @@
|
|||
namespace Zotlabs\Lib;
|
||||
|
||||
|
||||
|
||||
class MessageFilter {
|
||||
class MessageFilter
|
||||
{
|
||||
|
||||
|
||||
static public function evaluate($item,$incl,$excl) {
|
||||
public static function evaluate($item, $incl, $excl)
|
||||
{
|
||||
|
||||
require_once('include/html2plain.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/x-multicode'));
|
||||
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
|
||||
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
|
||||
|
||||
$lang = null;
|
||||
$lang = null;
|
||||
|
||||
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
|
||||
$lang = detect_language($text);
|
||||
}
|
||||
if ((strpos($incl, 'lang=') !== false) || (strpos($excl, 'lang=') !== false) || (strpos($incl, 'lang!=') !== false) || (strpos($excl, 'lang!=') !== false)) {
|
||||
$lang = detect_language($text);
|
||||
}
|
||||
|
||||
$tags = ((isset($item['term']) && is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
|
||||
$tags = ((isset($item['term']) && is_array($item['term']) && count($item['term'])) ? $item['term'] : false);
|
||||
|
||||
// exclude always has priority
|
||||
// exclude always has priority
|
||||
|
||||
$exclude = (($excl) ? explode("\n",$excl) : null);
|
||||
$exclude = (($excl) ? explode("\n", $excl) : null);
|
||||
|
||||
if($exclude) {
|
||||
foreach($exclude as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return false;
|
||||
}
|
||||
elseif(substr($word,0,1) === '$' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return false;
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
return false;
|
||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||
return false;
|
||||
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||
return false;
|
||||
elseif(stristr($text,$word) !== false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($exclude) {
|
||||
foreach ($exclude as $word) {
|
||||
$word = trim($word);
|
||||
if (! $word) {
|
||||
continue;
|
||||
}
|
||||
if (substr($word, 0, 1) === '#' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '$' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if (($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
|
||||
return false;
|
||||
} elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
|
||||
return false;
|
||||
} elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
|
||||
return false;
|
||||
} elseif (stristr($text, $word) !== false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$include = (($incl) ? explode("\n",$incl) : null);
|
||||
|
||||
if($include) {
|
||||
foreach($include as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return true;
|
||||
}
|
||||
elseif(substr($word,0,1) === '$' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
return true;
|
||||
}
|
||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||
return true;
|
||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||
return true;
|
||||
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||
return true;
|
||||
elseif(stristr($text,$word) !== false)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
$include = (($incl) ? explode("\n", $incl) : null);
|
||||
|
||||
if ($include) {
|
||||
foreach ($include as $word) {
|
||||
$word = trim($word);
|
||||
if (! $word) {
|
||||
continue;
|
||||
}
|
||||
if (substr($word, 0, 1) === '#' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif (substr($word, 0, 1) === '$' && $tags) {
|
||||
foreach ($tags as $t) {
|
||||
if (($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
|
||||
return true;
|
||||
} elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
|
||||
return true;
|
||||
} elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
|
||||
return true;
|
||||
} elseif (stristr($text, $word) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,43 +2,40 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class Nodeinfo
|
||||
{
|
||||
|
||||
|
||||
class Nodeinfo {
|
||||
|
||||
static public function fetch($url) {
|
||||
$href = EMPTY_STR;
|
||||
$m = parse_url($url);
|
||||
if ($m['scheme'] && $m['host']) {
|
||||
$s = $m['scheme'] . '://' . $m['host'] . '/.well-known/nodeinfo';
|
||||
$n = z_fetch_url($s);
|
||||
if ($n['success']) {
|
||||
$j = json_decode($n['body'], true);
|
||||
if ($j && $j['links']) {
|
||||
// lemmy just sends one result
|
||||
if (isset($j['links']['rel'])) {
|
||||
if ($j['links']['rel'] === 'http://nodeinfo.diaspora.software/ns/schema/2.0' && isset($j['links']['href'])) {
|
||||
$href = $j['links']['href'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach ($j['links'] as $l) {
|
||||
if (isset($l['rel']) && $l['rel'] === 'http://nodeinfo.diaspora.software/ns/schema/2.0' && isset($l['href'])) {
|
||||
$href = $l['href'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($href) {
|
||||
$n = z_fetch_url($href);
|
||||
if ($n['success']) {
|
||||
return json_decode($n['body'],true);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
|
||||
}
|
||||
|
||||
public static function fetch($url)
|
||||
{
|
||||
$href = EMPTY_STR;
|
||||
$m = parse_url($url);
|
||||
if ($m['scheme'] && $m['host']) {
|
||||
$s = $m['scheme'] . '://' . $m['host'] . '/.well-known/nodeinfo';
|
||||
$n = z_fetch_url($s);
|
||||
if ($n['success']) {
|
||||
$j = json_decode($n['body'], true);
|
||||
if ($j && $j['links']) {
|
||||
// lemmy just sends one result
|
||||
if (isset($j['links']['rel'])) {
|
||||
if ($j['links']['rel'] === 'http://nodeinfo.diaspora.software/ns/schema/2.0' && isset($j['links']['href'])) {
|
||||
$href = $j['links']['href'];
|
||||
}
|
||||
} else {
|
||||
foreach ($j['links'] as $l) {
|
||||
if (isset($l['rel']) && $l['rel'] === 'http://nodeinfo.diaspora.software/ns/schema/2.0' && isset($l['href'])) {
|
||||
$href = $l['href'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($href) {
|
||||
$n = z_fetch_url($href);
|
||||
if ($n['success']) {
|
||||
return json_decode($n['body'], true);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
/**
|
||||
* @brief Class for handling channel specific configurations.
|
||||
*
|
||||
|
@ -16,193 +18,212 @@ namespace Zotlabs\Lib;
|
|||
* The old (deprecated?) way to access a PConfig value is:
|
||||
* @code{.php}$var = get_pconfig(local_channel(), 'category', 'key');@endcode
|
||||
*/
|
||||
class PConfig {
|
||||
class PConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Loads all configuration values of a channel into a cached storage.
|
||||
*
|
||||
* All configuration values of the given channel are stored in global cache
|
||||
* which is available under the global variable App::$config[$uid].
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @return void|false Nothing or false if $uid is null or false
|
||||
*/
|
||||
static public function Load($uid) {
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
/**
|
||||
* @brief Loads all configuration values of a channel into a cached storage.
|
||||
*
|
||||
* All configuration values of the given channel are stored in global cache
|
||||
* which is available under the global variable App::$config[$uid].
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @return void|false Nothing or false if $uid is null or false
|
||||
*/
|
||||
public static function Load($uid)
|
||||
{
|
||||
if (is_null($uid) || $uid === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! is_array(\App::$config)) {
|
||||
btlogger('App::$config not an array');
|
||||
}
|
||||
if (! is_array(App::$config)) {
|
||||
btlogger('App::$config not an array');
|
||||
}
|
||||
|
||||
if(! array_key_exists($uid, \App::$config)) {
|
||||
\App::$config[$uid] = [];
|
||||
}
|
||||
if (! array_key_exists($uid, App::$config)) {
|
||||
App::$config[$uid] = [];
|
||||
}
|
||||
|
||||
if(! is_array(\App::$config[$uid])) {
|
||||
btlogger('App::$config[$uid] not an array: ' . $uid);
|
||||
}
|
||||
if (! is_array(App::$config[$uid])) {
|
||||
btlogger('App::$config[$uid] not an array: ' . $uid);
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM pconfig WHERE uid = %d",
|
||||
intval($uid)
|
||||
);
|
||||
$r = q(
|
||||
"SELECT * FROM pconfig WHERE uid = %d",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if(! array_key_exists($c, \App::$config[$uid])) {
|
||||
\App::$config[$uid][$c] = [];
|
||||
\App::$config[$uid][$c]['config_loaded'] = true;
|
||||
}
|
||||
\App::$config[$uid][$c][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if (! array_key_exists($c, App::$config[$uid])) {
|
||||
App::$config[$uid][$c] = [];
|
||||
App::$config[$uid][$c]['config_loaded'] = true;
|
||||
}
|
||||
App::$config[$uid][$c][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a particular channel's config variable given the category name
|
||||
* ($family) and a key.
|
||||
*
|
||||
* Get a particular channel's config value from the given category ($family)
|
||||
* and the $key from a cached storage in App::$config[$uid].
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param mixed $default (optional, default false)
|
||||
* Default value to return if key does not exist
|
||||
* @return mixed Stored value or false if it does not exist
|
||||
*/
|
||||
static public function Get($uid, $family, $key, $default = false) {
|
||||
/**
|
||||
* @brief Get a particular channel's config variable given the category name
|
||||
* ($family) and a key.
|
||||
*
|
||||
* Get a particular channel's config value from the given category ($family)
|
||||
* and the $key from a cached storage in App::$config[$uid].
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param mixed $default (optional, default false)
|
||||
* Default value to return if key does not exist
|
||||
* @return mixed Stored value or false if it does not exist
|
||||
*/
|
||||
public static function Get($uid, $family, $key, $default = false)
|
||||
{
|
||||
|
||||
if(is_null($uid) || $uid === false)
|
||||
return $default;
|
||||
if (is_null($uid) || $uid === false) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
self::Load($uid);
|
||||
if (! array_key_exists($uid, App::$config)) {
|
||||
self::Load($uid);
|
||||
}
|
||||
|
||||
if((! array_key_exists($family, \App::$config[$uid])) || (! array_key_exists($key, \App::$config[$uid][$family])))
|
||||
return $default;
|
||||
if ((! array_key_exists($family, App::$config[$uid])) || (! array_key_exists($key, App::$config[$uid][$family]))) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return unserialise(\App::$config[$uid][$family][$key]);
|
||||
}
|
||||
return unserialise(App::$config[$uid][$family][$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a configuration value for a channel.
|
||||
*
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key)
|
||||
* for the channel_id $uid.
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to set
|
||||
* @param string $value
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
static public function Set($uid, $family, $key, $value) {
|
||||
/**
|
||||
* @brief Sets a configuration value for a channel.
|
||||
*
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key)
|
||||
* for the channel_id $uid.
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to set
|
||||
* @param string $value
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
public static function Set($uid, $family, $key, $value)
|
||||
{
|
||||
|
||||
// this catches subtle errors where this function has been called
|
||||
// with local_channel() when not logged in (which returns false)
|
||||
// and throws an error in array_key_exists below.
|
||||
// we provide a function backtrace in the logs so that we can find
|
||||
// and fix the calling function.
|
||||
// this catches subtle errors where this function has been called
|
||||
// with local_channel() when not logged in (which returns false)
|
||||
// and throws an error in array_key_exists below.
|
||||
// we provide a function backtrace in the logs so that we can find
|
||||
// and fix the calling function.
|
||||
|
||||
if(is_null($uid) || $uid === false) {
|
||||
btlogger('UID is FALSE!', LOGGER_NORMAL, LOG_ERR);
|
||||
return;
|
||||
}
|
||||
if (is_null($uid) || $uid === false) {
|
||||
btlogger('UID is FALSE!', LOGGER_NORMAL, LOG_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($uid, $family, $key) === false) {
|
||||
if(! array_key_exists($uid, \App::$config))
|
||||
\App::$config[$uid] = [];
|
||||
if(! array_key_exists($family, \App::$config[$uid]))
|
||||
\App::$config[$uid][$family] = [];
|
||||
if (self::Get($uid, $family, $key) === false) {
|
||||
if (! array_key_exists($uid, App::$config)) {
|
||||
App::$config[$uid] = [];
|
||||
}
|
||||
if (! array_key_exists($family, App::$config[$uid])) {
|
||||
App::$config[$uid][$family] = [];
|
||||
}
|
||||
|
||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$ret = q(
|
||||
"INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
} else {
|
||||
$ret = q(
|
||||
"UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
|
||||
$ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
// keep a separate copy for all variables which were
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel clones.
|
||||
|
||||
// keep a separate copy for all variables which were
|
||||
// set in the life of this page. We need this to
|
||||
// synchronise channel clones.
|
||||
if (! array_key_exists('transient', App::$config[$uid])) {
|
||||
App::$config[$uid]['transient'] = [];
|
||||
}
|
||||
if (! array_key_exists($family, App::$config[$uid]['transient'])) {
|
||||
App::$config[$uid]['transient'][$family] = [];
|
||||
}
|
||||
|
||||
if(! array_key_exists('transient', \App::$config[$uid]))
|
||||
\App::$config[$uid]['transient'] = [];
|
||||
if(! array_key_exists($family, \App::$config[$uid]['transient']))
|
||||
\App::$config[$uid]['transient'][$family] = [];
|
||||
App::$config[$uid][$family][$key] = $value;
|
||||
App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
|
||||
\App::$config[$uid][$family][$key] = $value;
|
||||
\App::$config[$uid]['transient'][$family][$key] = $value;
|
||||
if ($ret) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes the given key from the channel's configuration.
|
||||
*
|
||||
* Removes the configured value from the stored cache in App::$config[$uid]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($uid, $family, $key) {
|
||||
/**
|
||||
* @brief Deletes the given key from the channel's configuration.
|
||||
*
|
||||
* Removes the configured value from the stored cache in App::$config[$uid]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $uid
|
||||
* The channel_id
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
public static function Delete($uid, $family, $key)
|
||||
{
|
||||
|
||||
if(is_null($uid) || $uid === false)
|
||||
return false;
|
||||
if (is_null($uid) || $uid === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = false;
|
||||
$ret = false;
|
||||
|
||||
if(array_key_exists($uid,\App::$config)
|
||||
&& is_array(\App::$config['uid'])
|
||||
&& array_key_exists($family,\App::$config['uid'])
|
||||
&& array_key_exists($key, \App::$config[$uid][$family]))
|
||||
unset(\App::$config[$uid][$family][$key]);
|
||||
if (
|
||||
array_key_exists($uid, App::$config)
|
||||
&& is_array(App::$config['uid'])
|
||||
&& array_key_exists($family, App::$config['uid'])
|
||||
&& array_key_exists($key, App::$config[$uid][$family])
|
||||
) {
|
||||
unset(App::$config[$uid][$family][$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
$ret = q(
|
||||
"DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||
intval($uid),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,157 +21,168 @@ use Zotlabs\Access\Permissions;
|
|||
* These answer the question "Can Joe view *this* album/photo?".
|
||||
*/
|
||||
|
||||
class Permcat {
|
||||
class Permcat
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $permcats = [];
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $permcats = [];
|
||||
|
||||
/**
|
||||
* @brief Permcat constructor.
|
||||
*
|
||||
* @param int $channel_id
|
||||
*/
|
||||
public function __construct($channel_id) {
|
||||
/**
|
||||
* @brief Permcat constructor.
|
||||
*
|
||||
* @param int $channel_id
|
||||
*/
|
||||
public function __construct($channel_id)
|
||||
{
|
||||
|
||||
$perms = [];
|
||||
$perms = [];
|
||||
|
||||
// first check role perms for a perms_connect setting
|
||||
// first check role perms for a perms_connect setting
|
||||
|
||||
$role = get_pconfig($channel_id,'system','permissions_role');
|
||||
if($role) {
|
||||
$x = PermissionRoles::role_perms($role);
|
||||
if($x['perms_connect']) {
|
||||
$perms = Permissions::FilledPerms($x['perms_connect']);
|
||||
}
|
||||
}
|
||||
$role = get_pconfig($channel_id, 'system', 'permissions_role');
|
||||
if ($role) {
|
||||
$x = PermissionRoles::role_perms($role);
|
||||
if ($x['perms_connect']) {
|
||||
$perms = Permissions::FilledPerms($x['perms_connect']);
|
||||
}
|
||||
}
|
||||
|
||||
// if no role perms it may be a custom role, see if there any autoperms
|
||||
// if no role perms it may be a custom role, see if there any autoperms
|
||||
|
||||
if(! $perms) {
|
||||
$perms = Permissions::FilledAutoPerms($channel_id);
|
||||
}
|
||||
if (! $perms) {
|
||||
$perms = Permissions::FilledAutoPerms($channel_id);
|
||||
}
|
||||
|
||||
// if no autoperms it may be a custom role with manual perms
|
||||
// if no autoperms it may be a custom role with manual perms
|
||||
|
||||
if(! $perms) {
|
||||
$c = channelx_by_n($channel_id);
|
||||
if($c) {
|
||||
$perms = Permissions::FilledPerms(get_abconfig($channel_id,$c['channel_hash'],'system','my_perms',EMPTY_STR));
|
||||
}
|
||||
}
|
||||
if (! $perms) {
|
||||
$c = channelx_by_n($channel_id);
|
||||
if ($c) {
|
||||
$perms = Permissions::FilledPerms(get_abconfig($channel_id, $c['channel_hash'], 'system', 'my_perms', EMPTY_STR));
|
||||
}
|
||||
}
|
||||
|
||||
// nothing was found - create a filled permission array where all permissions are 0
|
||||
// nothing was found - create a filled permission array where all permissions are 0
|
||||
|
||||
if(! $perms) {
|
||||
$perms = Permissions::FilledPerms([]);
|
||||
}
|
||||
if (! $perms) {
|
||||
$perms = Permissions::FilledPerms([]);
|
||||
}
|
||||
|
||||
$this->permcats[] = [
|
||||
'name' => 'default',
|
||||
'localname' => t('default','permcat'),
|
||||
'perms' => Permissions::Operms($perms),
|
||||
'system' => 1
|
||||
];
|
||||
$this->permcats[] = [
|
||||
'name' => 'default',
|
||||
'localname' => t('default', 'permcat'),
|
||||
'perms' => Permissions::Operms($perms),
|
||||
'system' => 1
|
||||
];
|
||||
|
||||
|
||||
$p = $this->load_permcats($channel_id);
|
||||
if($p) {
|
||||
for($x = 0; $x < count($p); $x++) {
|
||||
$this->permcats[] = [
|
||||
'name' => $p[$x][0],
|
||||
'localname' => $p[$x][1],
|
||||
'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
|
||||
'system' => intval($p[$x][3])
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
$p = $this->load_permcats($channel_id);
|
||||
if ($p) {
|
||||
for ($x = 0; $x < count($p); $x++) {
|
||||
$this->permcats[] = [
|
||||
'name' => $p[$x][0],
|
||||
'localname' => $p[$x][1],
|
||||
'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
|
||||
'system' => intval($p[$x][3])
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return array with permcats.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listing() {
|
||||
return $this->permcats;
|
||||
}
|
||||
/**
|
||||
* @brief Return array with permcats.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listing()
|
||||
{
|
||||
return $this->permcats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
* * \e array with permcats
|
||||
* * \e bool \b error if $name not found in permcats true
|
||||
*/
|
||||
public function fetch($name) {
|
||||
if($name && $this->permcats) {
|
||||
foreach($this->permcats as $permcat) {
|
||||
if(strcasecmp($permcat['name'], $name) === 0) {
|
||||
return $permcat;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
* * \e array with permcats
|
||||
* * \e bool \b error if $name not found in permcats true
|
||||
*/
|
||||
public function fetch($name)
|
||||
{
|
||||
if ($name && $this->permcats) {
|
||||
foreach ($this->permcats as $permcat) {
|
||||
if (strcasecmp($permcat['name'], $name) === 0) {
|
||||
return $permcat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ['error' => true];
|
||||
}
|
||||
return ['error' => true];
|
||||
}
|
||||
|
||||
public function load_permcats($uid) {
|
||||
public function load_permcats($uid)
|
||||
{
|
||||
|
||||
$permcats = [
|
||||
[ 'follower', t('follower','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_like' ], 1
|
||||
],
|
||||
[ 'contributor', t('contributor','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_wall','post_comments','write_wiki','post_like','tag_deliver','chat' ], 1
|
||||
],
|
||||
[ 'publisher', t('publisher','permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
|
||||
'write_storage','post_wall','write_pages','write_wiki','post_comments','post_like','tag_deliver',
|
||||
'chat', 'republish' ], 1
|
||||
]
|
||||
];
|
||||
$permcats = [
|
||||
[ 'follower', t('follower', 'permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_like' ], 1
|
||||
],
|
||||
[ 'contributor', t('contributor', 'permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages','view_wiki',
|
||||
'post_wall','post_comments','write_wiki','post_like','tag_deliver','chat' ], 1
|
||||
],
|
||||
[ 'publisher', t('publisher', 'permcat'),
|
||||
[ 'view_stream','view_profile','view_contacts','view_storage','view_pages',
|
||||
'write_storage','post_wall','write_pages','write_wiki','post_comments','post_like','tag_deliver',
|
||||
'chat', 'republish' ], 1
|
||||
]
|
||||
];
|
||||
|
||||
if($uid) {
|
||||
$x = q("select * from pconfig where uid = %d and cat = 'permcat'",
|
||||
intval($uid)
|
||||
);
|
||||
if($x) {
|
||||
foreach($x as $xv) {
|
||||
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
|
||||
$permcats[] = [ $xv['k'], $xv['k'], $value, 0 ];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($uid) {
|
||||
$x = q(
|
||||
"select * from pconfig where uid = %d and cat = 'permcat'",
|
||||
intval($uid)
|
||||
);
|
||||
if ($x) {
|
||||
foreach ($x as $xv) {
|
||||
$value = ((preg_match('|^a:[0-9]+:{.*}$|s', $xv['v'])) ? unserialize($xv['v']) : $xv['v']);
|
||||
$permcats[] = [ $xv['k'], $xv['k'], $value, 0 ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hooks permcats
|
||||
* * \e array
|
||||
*/
|
||||
call_hooks('permcats', $permcats);
|
||||
/**
|
||||
* @hooks permcats
|
||||
* * \e array
|
||||
*/
|
||||
call_hooks('permcats', $permcats);
|
||||
|
||||
return $permcats;
|
||||
}
|
||||
return $permcats;
|
||||
}
|
||||
|
||||
static public function find_permcat($arr, $name) {
|
||||
if((! $arr) || (! $name))
|
||||
return false;
|
||||
public static function find_permcat($arr, $name)
|
||||
{
|
||||
if ((! $arr) || (! $name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($arr as $p)
|
||||
if($p['name'] == $name)
|
||||
return $p['value'];
|
||||
}
|
||||
foreach ($arr as $p) {
|
||||
if ($p['name'] == $name) {
|
||||
return $p['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public function update($channel_id, $name, $permarr) {
|
||||
PConfig::Set($channel_id, 'permcat', $name, $permarr);
|
||||
}
|
||||
|
||||
static public function delete($channel_id, $name) {
|
||||
PConfig::Delete($channel_id, 'permcat', $name);
|
||||
}
|
||||
public static function update($channel_id, $name, $permarr)
|
||||
{
|
||||
PConfig::Set($channel_id, 'permcat', $name, $permarr);
|
||||
}
|
||||
|
||||
public static function delete($channel_id, $name)
|
||||
{
|
||||
PConfig::Delete($channel_id, 'permcat', $name);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\Permissions;
|
||||
|
||||
require_once("include/permissions.php");
|
||||
require_once("include/language.php");
|
||||
require_once("include/text.php");
|
||||
|
@ -12,148 +16,178 @@ require_once("include/text.php");
|
|||
* permission settings for an item with an empty ACL.
|
||||
* i.e the caption, icon, and tooltip for the no-ACL option in the ACL dialog.
|
||||
*/
|
||||
class PermissionDescription {
|
||||
class PermissionDescription
|
||||
{
|
||||
|
||||
private $global_perm;
|
||||
private $channel_perm;
|
||||
private $fallback_description;
|
||||
private $global_perm;
|
||||
private $channel_perm;
|
||||
private $fallback_description;
|
||||
|
||||
/**
|
||||
* Constructor is private.
|
||||
* Use static methods fromGlobalPermission(), fromStandalonePermission(),
|
||||
* or fromDescription() to create instances.
|
||||
*
|
||||
* @internal
|
||||
* @param int $global_perm
|
||||
* @param int $channel_perm
|
||||
* @param string $description (optional) default empty
|
||||
*/
|
||||
private function __construct($global_perm, $channel_perm, $description = '') {
|
||||
$this->global_perm = $global_perm;
|
||||
$this->channel_perm = $channel_perm;
|
||||
$this->fallback_description = ($description == '') ? t('Visible to your default audience') : $description;
|
||||
}
|
||||
/**
|
||||
* Constructor is private.
|
||||
* Use static methods fromGlobalPermission(), fromStandalonePermission(),
|
||||
* or fromDescription() to create instances.
|
||||
*
|
||||
* @internal
|
||||
* @param int $global_perm
|
||||
* @param int $channel_perm
|
||||
* @param string $description (optional) default empty
|
||||
*/
|
||||
private function __construct($global_perm, $channel_perm, $description = '')
|
||||
{
|
||||
$this->global_perm = $global_perm;
|
||||
$this->channel_perm = $channel_perm;
|
||||
$this->fallback_description = ($description == '') ? t('Visible to your default audience') : $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the interpretation of an empty ACL can't be summarised with a global default permission
|
||||
* or a specific permission setting then use this method and describe what it means instead.
|
||||
* Remember to localize the description first.
|
||||
*
|
||||
* @param string $description - the localized caption for the no-ACL option in the ACL dialog.
|
||||
* @return a new instance of PermissionDescription
|
||||
*/
|
||||
public static function fromDescription($description) {
|
||||
return new PermissionDescription('', 0x80000, $description);
|
||||
}
|
||||
/**
|
||||
* If the interpretation of an empty ACL can't be summarised with a global default permission
|
||||
* or a specific permission setting then use this method and describe what it means instead.
|
||||
* Remember to localize the description first.
|
||||
*
|
||||
* @param string $description - the localized caption for the no-ACL option in the ACL dialog.
|
||||
* @return a new instance of PermissionDescription
|
||||
*/
|
||||
public static function fromDescription($description)
|
||||
{
|
||||
return new PermissionDescription('', 0x80000, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method only if the interpretation of an empty ACL doesn't fall back to a global
|
||||
* default permission. You should pass one of the constants from boot.php - PERMS_PUBLIC,
|
||||
* PERMS_NETWORK etc.
|
||||
*
|
||||
* @param integer $perm - a single enumerated constant permission - PERMS_PUBLIC, PERMS_NETWORK etc.
|
||||
* @return a new instance of PermissionDescription
|
||||
*/
|
||||
public static function fromStandalonePermission($perm) {
|
||||
/**
|
||||
* Use this method only if the interpretation of an empty ACL doesn't fall back to a global
|
||||
* default permission. You should pass one of the constants from boot.php - PERMS_PUBLIC,
|
||||
* PERMS_NETWORK etc.
|
||||
*
|
||||
* @param int $perm - a single enumerated constant permission - PERMS_PUBLIC, PERMS_NETWORK etc.
|
||||
* @return a new instance of PermissionDescription
|
||||
*/
|
||||
public static function fromStandalonePermission($perm)
|
||||
{
|
||||
|
||||
$result = new PermissionDescription('', $perm);
|
||||
$result = new PermissionDescription('', $perm);
|
||||
|
||||
$checkPerm = $result->get_permission_description();
|
||||
if($checkPerm == $result->fallback_description) {
|
||||
$result = null;
|
||||
logger('null PermissionDescription from unknown standalone permission: ' . $perm, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
$checkPerm = $result->get_permission_description();
|
||||
if ($checkPerm == $result->fallback_description) {
|
||||
$result = null;
|
||||
logger('null PermissionDescription from unknown standalone permission: ' . $perm, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the preferred way to create a PermissionDescription, as it provides the most details.
|
||||
* Use this method if you know an empty ACL will result in one of the global default permissions
|
||||
* being used, such as channel_r_stream (for which you would pass 'view_stream').
|
||||
*
|
||||
* @param string $permname - a key for the global perms array from get_perms() in permissions.php,
|
||||
* e.g. 'view_stream', 'view_profile', etc.
|
||||
* @return a new instance of PermissionDescription
|
||||
*/
|
||||
public static function fromGlobalPermission($permname) {
|
||||
/**
|
||||
* This is the preferred way to create a PermissionDescription, as it provides the most details.
|
||||
* Use this method if you know an empty ACL will result in one of the global default permissions
|
||||
* being used, such as channel_r_stream (for which you would pass 'view_stream').
|
||||
*
|
||||
* @param string $permname - a key for the global perms array from get_perms() in permissions.php,
|
||||
* e.g. 'view_stream', 'view_profile', etc.
|
||||
* @return a new instance of PermissionDescription
|
||||
*/
|
||||
public static function fromGlobalPermission($permname)
|
||||
{
|
||||
|
||||
$result = null;
|
||||
$result = null;
|
||||
|
||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||
$global_perms = Permissions::Perms();
|
||||
|
||||
if(array_key_exists($permname, $global_perms)) {
|
||||
if (array_key_exists($permname, $global_perms)) {
|
||||
$channelPerm = PermissionLimits::Get(App::$channel['channel_id'], $permname);
|
||||
|
||||
$channelPerm = \Zotlabs\Access\PermissionLimits::Get(\App::$channel['channel_id'], $permname);
|
||||
$result = new PermissionDescription('', $channelPerm);
|
||||
} else {
|
||||
// The acl dialog can handle null arguments, but it shouldn't happen
|
||||
logger('null PermissionDescription from unknown global permission: ' . $permname, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
|
||||
$result = new PermissionDescription('', $channelPerm);
|
||||
} else {
|
||||
// The acl dialog can handle null arguments, but it shouldn't happen
|
||||
logger('null PermissionDescription from unknown global permission: ' . $permname, LOGGER_DEBUG, LOG_ERR);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Gets a localized description of the permission, or a generic message if the permission
|
||||
* is unknown.
|
||||
*
|
||||
* @return string description
|
||||
*/
|
||||
public function get_permission_description()
|
||||
{
|
||||
|
||||
/**
|
||||
* Gets a localized description of the permission, or a generic message if the permission
|
||||
* is unknown.
|
||||
*
|
||||
* @return string description
|
||||
*/
|
||||
public function get_permission_description() {
|
||||
switch ($this->channel_perm) {
|
||||
case 0:
|
||||
return t('Only me');
|
||||
case PERMS_PUBLIC:
|
||||
return t('Public');
|
||||
case PERMS_NETWORK:
|
||||
return t('Anybody in the $Projectname network');
|
||||
case PERMS_SITE:
|
||||
return sprintf(t('Any account on %s'), App::get_hostname());
|
||||
case PERMS_CONTACTS:
|
||||
return t('Any of my connections');
|
||||
case PERMS_SPECIFIC:
|
||||
return t('Only connections I specifically allow');
|
||||
case PERMS_AUTHED:
|
||||
return t('Anybody authenticated (could include visitors from other networks)');
|
||||
case PERMS_PENDING:
|
||||
return t('Any connections including those who haven\'t yet been approved');
|
||||
default:
|
||||
return $this->fallback_description;
|
||||
}
|
||||
}
|
||||
|
||||
switch($this->channel_perm) {
|
||||
case 0: return t('Only me');
|
||||
case PERMS_PUBLIC: return t('Public');
|
||||
case PERMS_NETWORK: return t('Anybody in the $Projectname network');
|
||||
case PERMS_SITE: return sprintf(t('Any account on %s'), \App::get_hostname());
|
||||
case PERMS_CONTACTS: return t('Any of my connections');
|
||||
case PERMS_SPECIFIC: return t('Only connections I specifically allow');
|
||||
case PERMS_AUTHED: return t('Anybody authenticated (could include visitors from other networks)');
|
||||
case PERMS_PENDING: return t('Any connections including those who haven\'t yet been approved');
|
||||
default: return $this->fallback_description;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns an icon css class name if an appropriate one is available, e.g. "fa-globe" for Public,
|
||||
* otherwise returns empty string.
|
||||
*
|
||||
* @return string icon css class name (often FontAwesome)
|
||||
*/
|
||||
public function get_permission_icon()
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an icon css class name if an appropriate one is available, e.g. "fa-globe" for Public,
|
||||
* otherwise returns empty string.
|
||||
*
|
||||
* @return string icon css class name (often FontAwesome)
|
||||
*/
|
||||
public function get_permission_icon() {
|
||||
switch ($this->channel_perm) {
|
||||
case 0:
|
||||
return 'fa-eye-slash';
|
||||
case PERMS_PUBLIC:
|
||||
return 'fa-globe';
|
||||
case PERMS_NETWORK:
|
||||
return 'fa-share-alt-square'; // fa-share-alt-square is very similiar to the hubzilla logo, but we should create our own logo class to use
|
||||
case PERMS_SITE:
|
||||
return 'fa-sitemap';
|
||||
case PERMS_CONTACTS:
|
||||
return 'fa-group';
|
||||
case PERMS_SPECIFIC:
|
||||
return 'fa-list';
|
||||
case PERMS_AUTHED:
|
||||
return '';
|
||||
case PERMS_PENDING:
|
||||
return '';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
switch($this->channel_perm) {
|
||||
case 0:/* only me */ return 'fa-eye-slash';
|
||||
case PERMS_PUBLIC: return 'fa-globe';
|
||||
case PERMS_NETWORK: return 'fa-share-alt-square'; // fa-share-alt-square is very similiar to the hubzilla logo, but we should create our own logo class to use
|
||||
case PERMS_SITE: return 'fa-sitemap';
|
||||
case PERMS_CONTACTS: return 'fa-group';
|
||||
case PERMS_SPECIFIC: return 'fa-list';
|
||||
case PERMS_AUTHED: return '';
|
||||
case PERMS_PENDING: return '';
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized description of where the permission came from, if this is known.
|
||||
* If it's not know, or if the permission is standalone and didn't come from a default
|
||||
* permission setting, then empty string is returned.
|
||||
*
|
||||
* @return string description or empty string
|
||||
*/
|
||||
public function get_permission_origin_description() {
|
||||
|
||||
switch($this->global_perm) {
|
||||
case PERMS_R_STREAM: return t('This is your default setting for the audience of your normal stream, and posts.');
|
||||
case PERMS_R_PROFILE: return t('This is your default setting for who can view your default channel profile');
|
||||
case PERMS_R_ABOOK: return t('This is your default setting for who can view your connections');
|
||||
case PERMS_R_STORAGE: return t('This is your default setting for who can view your file storage and photos');
|
||||
case PERMS_R_PAGES: return t('This is your default setting for the audience of your webpages');
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a localized description of where the permission came from, if this is known.
|
||||
* If it's not know, or if the permission is standalone and didn't come from a default
|
||||
* permission setting, then empty string is returned.
|
||||
*
|
||||
* @return string description or empty string
|
||||
*/
|
||||
public function get_permission_origin_description()
|
||||
{
|
||||
|
||||
switch ($this->global_perm) {
|
||||
case PERMS_R_STREAM:
|
||||
return t('This is your default setting for the audience of your normal stream, and posts.');
|
||||
case PERMS_R_PROFILE:
|
||||
return t('This is your default setting for who can view your default channel profile');
|
||||
case PERMS_R_ABOOK:
|
||||
return t('This is your default setting for who can view your connections');
|
||||
case PERMS_R_STORAGE:
|
||||
return t('This is your default setting for who can view your file storage and photos');
|
||||
case PERMS_R_PAGES:
|
||||
return t('This is your default setting for the audience of your webpages');
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
|
@ -6,463 +8,481 @@ use Zotlabs\Lib\Libzot;
|
|||
use Zotlabs\Web\HTTPSig;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Zot6\Receiver;
|
||||
use Zotlabs\Zot6\Zot6Handler;
|
||||
|
||||
class Queue {
|
||||
class Queue
|
||||
{
|
||||
|
||||
static function update($id, $add_priority = 0) {
|
||||
public static function update($id, $add_priority = 0)
|
||||
{
|
||||
|
||||
logger('queue: requeue item ' . $id,LOGGER_DEBUG);
|
||||
logger('queue: requeue item ' . $id, LOGGER_DEBUG);
|
||||
|
||||
// This queue item failed. Perhaps it was rejected. Perhaps the site is dead.
|
||||
// Since we don't really know, check and see if we've got something else destined
|
||||
// for that server and give it priority. At a minimum it will keep the queue from
|
||||
// getting stuck on a particular message when another one with different content
|
||||
// might actually succeed.
|
||||
// This queue item failed. Perhaps it was rejected. Perhaps the site is dead.
|
||||
// Since we don't really know, check and see if we've got something else destined
|
||||
// for that server and give it priority. At a minimum it will keep the queue from
|
||||
// getting stuck on a particular message when another one with different content
|
||||
// might actually succeed.
|
||||
|
||||
$x = q("select outq_created, outq_hash, outq_posturl from outq where outq_hash = '%s' limit 1",
|
||||
dbesc($id)
|
||||
);
|
||||
if (! $x) {
|
||||
return;
|
||||
}
|
||||
$x = q(
|
||||
"select outq_created, outq_hash, outq_posturl from outq where outq_hash = '%s' limit 1",
|
||||
dbesc($id)
|
||||
);
|
||||
if (!$x) {
|
||||
return;
|
||||
}
|
||||
|
||||
$g = q("select outq_created, outq_hash, outq_posturl from outq where outq_posturl = '%s' and outq_hash != '%s' limit 1",
|
||||
dbesc($x[0]['outq_posturl']),
|
||||
dbesc($id)
|
||||
);
|
||||
$g = q(
|
||||
"select outq_created, outq_hash, outq_posturl from outq where outq_posturl = '%s' and outq_hash != '%s' limit 1",
|
||||
dbesc($x[0]['outq_posturl']),
|
||||
dbesc($id)
|
||||
);
|
||||
|
||||
// swap them
|
||||
// swap them
|
||||
|
||||
if ($g) {
|
||||
$x = $g;
|
||||
}
|
||||
if ($g) {
|
||||
$x = $g;
|
||||
}
|
||||
|
||||
|
||||
$y = q(
|
||||
"select min(outq_created) as earliest from outq where outq_posturl = '%s'",
|
||||
dbesc($x[0]['outq_posturl'])
|
||||
);
|
||||
|
||||
$y = q("select min(outq_created) as earliest from outq where outq_posturl = '%s'",
|
||||
dbesc($x[0]['outq_posturl'])
|
||||
);
|
||||
// look for the oldest queue entry with this destination URL. If it's older than a couple of days,
|
||||
// the destination is considered to be down and only scheduled once an hour, regardless of the
|
||||
// age of the current queue item.
|
||||
|
||||
// look for the oldest queue entry with this destination URL. If it's older than a couple of days,
|
||||
// the destination is considered to be down and only scheduled once an hour, regardless of the
|
||||
// age of the current queue item.
|
||||
$might_be_down = false;
|
||||
|
||||
$might_be_down = false;
|
||||
|
||||
if($y)
|
||||
$might_be_down = ((datetime_convert('UTC','UTC',$y[0]['earliest']) < datetime_convert('UTC','UTC','now - 2 days')) ? true : false);
|
||||
if ($y) {
|
||||
$might_be_down = ((datetime_convert('UTC', 'UTC', $y[0]['earliest']) < datetime_convert('UTC', 'UTC', 'now - 2 days')) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
// Set all other records for this destination way into the future.
|
||||
// The queue delivers by destination. We'll keep one queue item for
|
||||
// this destination (this one) with a shorter delivery. If we succeed
|
||||
// once, we'll try to deliver everything for that destination.
|
||||
// The delivery will be set to at most once per hour, and if the
|
||||
// queue item is less than 12 hours old, we'll schedule for fifteen
|
||||
// minutes.
|
||||
// Set all other records for this destination way into the future.
|
||||
// The queue delivers by destination. We'll keep one queue item for
|
||||
// this destination (this one) with a shorter delivery. If we succeed
|
||||
// once, we'll try to deliver everything for that destination.
|
||||
// The delivery will be set to at most once per hour, and if the
|
||||
// queue item is less than 12 hours old, we'll schedule for fifteen
|
||||
// minutes.
|
||||
|
||||
$r = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
|
||||
dbesc(datetime_convert('UTC','UTC','now + 5 days')),
|
||||
dbesc($x[0]['outq_posturl'])
|
||||
);
|
||||
$r = q(
|
||||
"UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
|
||||
dbesc(datetime_convert('UTC', 'UTC', 'now + 5 days')),
|
||||
dbesc($x[0]['outq_posturl'])
|
||||
);
|
||||
|
||||
$since = datetime_convert('UTC','UTC',$y[0]['earliest']);
|
||||
$since = datetime_convert('UTC', 'UTC', $y[0]['earliest']);
|
||||
|
||||
if(($might_be_down) || ($since < datetime_convert('UTC','UTC','now - 12 hour'))) {
|
||||
$next = datetime_convert('UTC','UTC','now + 1 hour');
|
||||
}
|
||||
else {
|
||||
$next = datetime_convert('UTC','UTC','now + ' . intval($add_priority) . ' minutes');
|
||||
}
|
||||
if (($might_be_down) || ($since < datetime_convert('UTC', 'UTC', 'now - 12 hour'))) {
|
||||
$next = datetime_convert('UTC', 'UTC', 'now + 1 hour');
|
||||
} else {
|
||||
$next = datetime_convert('UTC', 'UTC', 'now + ' . intval($add_priority) . ' minutes');
|
||||
}
|
||||
|
||||
q("UPDATE outq SET outq_updated = '%s',
|
||||
q(
|
||||
"UPDATE outq SET outq_updated = '%s',
|
||||
outq_priority = outq_priority + %d,
|
||||
outq_scheduled = '%s'
|
||||
WHERE outq_hash = '%s'",
|
||||
|
||||
dbesc(datetime_convert()),
|
||||
intval($add_priority),
|
||||
dbesc($next),
|
||||
dbesc($x[0]['outq_hash'])
|
||||
);
|
||||
}
|
||||
dbesc(datetime_convert()),
|
||||
intval($add_priority),
|
||||
dbesc($next),
|
||||
dbesc($x[0]['outq_hash'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static function remove($id,$channel_id = 0) {
|
||||
logger('queue: remove queue item ' . $id,LOGGER_DEBUG);
|
||||
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
|
||||
public static function remove($id, $channel_id = 0)
|
||||
{
|
||||
logger('queue: remove queue item ' . $id, LOGGER_DEBUG);
|
||||
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
|
||||
|
||||
q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
|
||||
dbesc($id)
|
||||
);
|
||||
}
|
||||
q(
|
||||
"DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
|
||||
dbesc($id)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static function remove_by_posturl($posturl) {
|
||||
logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG);
|
||||
public static function remove_by_posturl($posturl)
|
||||
{
|
||||
logger('queue: remove queue posturl ' . $posturl, LOGGER_DEBUG);
|
||||
|
||||
q("DELETE FROM outq WHERE outq_posturl = '%s' ",
|
||||
dbesc($posturl)
|
||||
);
|
||||
}
|
||||
q(
|
||||
"DELETE FROM outq WHERE outq_posturl = '%s' ",
|
||||
dbesc($posturl)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function set_delivered($id, $channel = 0)
|
||||
{
|
||||
logger('queue: set delivered ' . $id, LOGGER_DEBUG);
|
||||
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
|
||||
|
||||
static function set_delivered($id,$channel = 0) {
|
||||
logger('queue: set delivered ' . $id,LOGGER_DEBUG);
|
||||
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
|
||||
// Set the next scheduled run date so far in the future that it will be expired
|
||||
// long before it ever makes it back into the delivery chain.
|
||||
|
||||
// Set the next scheduled run date so far in the future that it will be expired
|
||||
// long before it ever makes it back into the delivery chain.
|
||||
|
||||
q("update outq set outq_delivered = 1, outq_updated = '%s', outq_scheduled = '%s' where outq_hash = '%s' $sql_extra ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert('UTC','UTC','now + 5 days')),
|
||||
dbesc($id)
|
||||
);
|
||||
}
|
||||
q(
|
||||
"update outq set outq_delivered = 1, outq_updated = '%s', outq_scheduled = '%s' where outq_hash = '%s' $sql_extra ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert('UTC', 'UTC', 'now + 5 days')),
|
||||
dbesc($id)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function insert($arr)
|
||||
{
|
||||
|
||||
static function insert($arr) {
|
||||
logger('insert: ' . print_r($arr, true), LOGGER_DATA);
|
||||
|
||||
logger('insert: ' . print_r($arr,true), LOGGER_DATA);
|
||||
// do not queue anything with no destination
|
||||
|
||||
// do not queue anything with no destination
|
||||
|
||||
if (! (array_key_exists('posturl',$arr) && trim($arr['posturl']))) {
|
||||
logger('no destination');
|
||||
return false;
|
||||
}
|
||||
if (!(array_key_exists('posturl', $arr) && trim($arr['posturl']))) {
|
||||
logger('no destination');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
|
||||
$x = q(
|
||||
"insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
|
||||
outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
|
||||
values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' )",
|
||||
dbesc($arr['hash']),
|
||||
intval($arr['account_id']),
|
||||
intval($arr['channel_id']),
|
||||
dbesc($arr['hash']),
|
||||
intval($arr['account_id']),
|
||||
intval($arr['channel_id']),
|
||||
dbesc((isset($arr['driver']) && $arr['driver']) ? $arr['driver'] : 'nomad'),
|
||||
dbesc($arr['posturl']),
|
||||
intval(1),
|
||||
intval((isset($arr['priority'])) ? $arr['priority'] : 0),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc((isset($arr['scheduled'])) ? $arr['scheduled'] : datetime_convert()),
|
||||
dbesc($arr['notify']),
|
||||
dbesc(($arr['msg']) ? $arr['msg'] : '')
|
||||
);
|
||||
return $x;
|
||||
|
||||
}
|
||||
dbesc($arr['posturl']),
|
||||
intval(1),
|
||||
intval((isset($arr['priority'])) ? $arr['priority'] : 0),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc((isset($arr['scheduled'])) ? $arr['scheduled'] : datetime_convert()),
|
||||
dbesc($arr['notify']),
|
||||
dbesc(($arr['msg']) ? $arr['msg'] : '')
|
||||
);
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
||||
public static function deliver($outq, $immediate = false)
|
||||
{
|
||||
|
||||
static function deliver($outq, $immediate = false) {
|
||||
$base = null;
|
||||
$h = parse_url($outq['outq_posturl']);
|
||||
if ($h !== false) {
|
||||
$base = $h['scheme'] . '://' . $h['host'] . ((isset($h['port']) && intval($h['port'])) ? ':' . $h['port'] : '');
|
||||
}
|
||||
|
||||
$base = null;
|
||||
$h = parse_url($outq['outq_posturl']);
|
||||
if ($h !== false) {
|
||||
$base = $h['scheme'] . '://' . $h['host'] . ((isset($h['port']) && intval($h['port'])) ? ':' . $h['port'] : '');
|
||||
}
|
||||
if (($base) && ($base !== z_root()) && ($immediate)) {
|
||||
$y = q(
|
||||
"select site_update, site_dead from site where site_url = '%s' ",
|
||||
dbesc($base)
|
||||
);
|
||||
if ($y) {
|
||||
if (intval($y[0]['site_dead'])) {
|
||||
q(
|
||||
"update dreport set dreport_result = '%s' where dreport_queue = '%s'",
|
||||
dbesc('site dead'),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
|
||||
if (($base) && ($base !== z_root()) && ($immediate)) {
|
||||
$y = q("select site_update, site_dead from site where site_url = '%s' ",
|
||||
dbesc($base)
|
||||
);
|
||||
if ($y) {
|
||||
if (intval($y[0]['site_dead'])) {
|
||||
q("update dreport set dreport_result = '%s' where dreport_queue = '%s'",
|
||||
dbesc('site dead'),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::remove_by_posturl($outq['outq_posturl']);
|
||||
logger('dead site ignored ' . $base);
|
||||
return;
|
||||
}
|
||||
if ($y[0]['site_update'] < datetime_convert('UTC', 'UTC', 'now - 1 month')) {
|
||||
q(
|
||||
"update dreport set dreport_log = '%s' where dreport_queue = '%s'",
|
||||
dbesc('site deferred'),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::update($outq['outq_hash'], 10);
|
||||
logger('immediate delivery deferred for site ' . $base);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// zot sites should all have a site record, unless they've been dead for as long as
|
||||
// your site has existed. Since we don't know for sure what these sites are,
|
||||
// call them unknown
|
||||
|
||||
self::remove_by_posturl($outq['outq_posturl']);
|
||||
logger('dead site ignored ' . $base);
|
||||
return;
|
||||
}
|
||||
if ($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) {
|
||||
q("update dreport set dreport_log = '%s' where dreport_queue = '%s'",
|
||||
dbesc('site deferred'),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::update($outq['outq_hash'],10);
|
||||
logger('immediate delivery deferred for site ' . $base);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
site_store_lowlevel(
|
||||
[
|
||||
'site_url' => $base,
|
||||
'site_update' => datetime_convert(),
|
||||
'site_dead' => 0,
|
||||
'site_type' => ((in_array($outq['outq_driver'], ['post', 'activitypub'])) ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN),
|
||||
'site_crypto' => ''
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// zot sites should all have a site record, unless they've been dead for as long as
|
||||
// your site has existed. Since we don't know for sure what these sites are,
|
||||
// call them unknown
|
||||
$arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate);
|
||||
call_hooks('queue_deliver', $arr);
|
||||
if ($arr['handled']) {
|
||||
return;
|
||||
}
|
||||
|
||||
site_store_lowlevel(
|
||||
[
|
||||
'site_url' => $base,
|
||||
'site_update' => datetime_convert(),
|
||||
'site_dead' => 0,
|
||||
'site_type' => ((in_array($outq['outq_driver'], [ 'post', 'activitypub' ])) ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN),
|
||||
'site_crypto' => ''
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
|
||||
|
||||
$arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate);
|
||||
call_hooks('queue_deliver',$arr);
|
||||
if($arr['handled'])
|
||||
return;
|
||||
if ($outq['outq_driver'] === 'post') {
|
||||
$result = z_post_url($outq['outq_posturl'], $outq['outq_msg']);
|
||||
if ($result['success'] && $result['return_code'] < 300) {
|
||||
logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
if ($base) {
|
||||
q(
|
||||
"update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($base)
|
||||
);
|
||||
}
|
||||
q(
|
||||
"update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc('accepted for delivery'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::remove($outq['outq_hash']);
|
||||
|
||||
// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
|
||||
// server is responding - see if anything else is going to this destination and is piled up
|
||||
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||
// immediate delivery otherwise we could get into a queue loop.
|
||||
|
||||
if($outq['outq_driver'] === 'post') {
|
||||
$result = z_post_url($outq['outq_posturl'],$outq['outq_msg']);
|
||||
if($result['success'] && $result['return_code'] < 300) {
|
||||
logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
if($base) {
|
||||
q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($base)
|
||||
);
|
||||
}
|
||||
q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc('accepted for delivery'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::remove($outq['outq_hash']);
|
||||
if (!$immediate) {
|
||||
$x = q(
|
||||
"select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||
dbesc($outq['outq_posturl'])
|
||||
);
|
||||
|
||||
// server is responding - see if anything else is going to this destination and is piled up
|
||||
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||
// immediate delivery otherwise we could get into a queue loop.
|
||||
$piled_up = [];
|
||||
if ($x) {
|
||||
foreach ($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if ($piled_up) {
|
||||
// call do_delivery() with the force flag
|
||||
do_delivery($piled_up, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger('deliver: queue post returned ' . $result['return_code']
|
||||
. ' from ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
self::update($outq['outq_hash'], 10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(! $immediate) {
|
||||
$x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||
dbesc($outq['outq_posturl'])
|
||||
);
|
||||
if ($outq['outq_driver'] === 'asfetch') {
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
if (!$channel) {
|
||||
logger('missing channel: ' . $outq['outq_channel']);
|
||||
return;
|
||||
}
|
||||
|
||||
$piled_up = [];
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if($piled_up) {
|
||||
// call do_delivery() with the force flag
|
||||
do_delivery($piled_up, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger('deliver: queue post returned ' . $result['return_code']
|
||||
. ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
|
||||
self::update($outq['outq_hash'],10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!ActivityStreams::is_url($outq['outq_posturl'])) {
|
||||
logger('fetch item is not url: ' . $outq['outq_posturl']);
|
||||
self::remove($outq['outq_hash']);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($outq['outq_driver'] === 'asfetch') {
|
||||
$j = Activity::fetch($outq['outq_posturl'], $channel);
|
||||
if ($j) {
|
||||
$AS = new ActivityStreams($j, null, true);
|
||||
if ($AS->is_valid() && isset($AS->data['type'])) {
|
||||
if (ActivityStreams::is_an_actor($AS->data['type'])) {
|
||||
Activity::actor_store($AS->data['id'], $AS->data);
|
||||
}
|
||||
if (strpos($AS->data['type'], 'Collection') !== false) {
|
||||
// we are probably fetching a collection already - and do not support collection recursion at this time
|
||||
self::remove($outq['outq_hash']);
|
||||
return;
|
||||
}
|
||||
$item = Activity::decode_note($AS, true);
|
||||
if ($item) {
|
||||
Activity::store($channel, $channel['channnel_hash'], $AS, $item, true, true);
|
||||
}
|
||||
}
|
||||
logger('deliver: queue fetch success from ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
self::remove($outq['outq_hash']);
|
||||
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
if (! $channel) {
|
||||
logger('missing channel: ' . $outq['outq_channel']);
|
||||
return;
|
||||
}
|
||||
// server is responding - see if anything else is going to this destination and is piled up
|
||||
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||
// immediate delivery otherwise we could get into a queue loop.
|
||||
|
||||
if (! ActivityStreams::is_url($outq['outq_posturl'])) {
|
||||
logger('fetch item is not url: ' . $outq['outq_posturl']);
|
||||
self::remove($outq['outq_hash']);
|
||||
return;
|
||||
}
|
||||
if (!$immediate) {
|
||||
$x = q(
|
||||
"select outq_hash from outq where outq_driver = 'asfetch' and outq_channel = %d and outq_delivered = 0",
|
||||
dbesc($outq['outq_channel'])
|
||||
);
|
||||
|
||||
$j = Activity::fetch($outq['outq_posturl'],$channel);
|
||||
if ($j) {
|
||||
$AS = new ActivityStreams($j, null, true);
|
||||
if ($AS->is_valid() && isset($AS->data['type'])) {
|
||||
if (ActivityStreams::is_an_actor($AS->data['type'])) {
|
||||
Activity::actor_store($AS->data['id'],$AS->data);
|
||||
}
|
||||
if (strpos($AS->data['type'],'Collection') !== false) {
|
||||
// we are probably fetching a collection already - and do not support collection recursion at this time
|
||||
self::remove($outq['outq_hash']);
|
||||
return;
|
||||
}
|
||||
$item = Activity::decode_note($AS,true);
|
||||
if ($item) {
|
||||
Activity::store($channel,$channel['channnel_hash'],$AS,$item,true,true);
|
||||
}
|
||||
}
|
||||
logger('deliver: queue fetch success from ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
self::remove($outq['outq_hash']);
|
||||
$piled_up = [];
|
||||
if ($x) {
|
||||
foreach ($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if ($piled_up) {
|
||||
do_delivery($piled_up, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger('deliver: queue fetch failed' . ' from ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
self::update($outq['outq_hash'], 10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// server is responding - see if anything else is going to this destination and is piled up
|
||||
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||
// immediate delivery otherwise we could get into a queue loop.
|
||||
|
||||
if (! $immediate) {
|
||||
$x = q("select outq_hash from outq where outq_driver = 'asfetch' and outq_channel = %d and outq_delivered = 0",
|
||||
dbesc($outq['outq_channel'])
|
||||
);
|
||||
|
||||
$piled_up = [];
|
||||
if ($x) {
|
||||
foreach ($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if ($piled_up) {
|
||||
do_delivery($piled_up,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger('deliver: queue fetch failed' . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
|
||||
self::update($outq['outq_hash'],10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if($outq['outq_driver'] === 'activitypub') {
|
||||
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
if (! $channel) {
|
||||
logger('missing channel: ' . $outq['outq_channel']);
|
||||
return;
|
||||
}
|
||||
if ($outq['outq_driver'] === 'activitypub') {
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
if (!$channel) {
|
||||
logger('missing channel: ' . $outq['outq_channel']);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$retries = 0;
|
||||
$m = parse_url($outq['outq_posturl']);
|
||||
$retries = 0;
|
||||
$m = parse_url($outq['outq_posturl']);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
|
||||
$ret = $outq['outq_msg'];
|
||||
logger('ActivityPub send: ' . jindent($ret), LOGGER_DATA);
|
||||
$headers['Date'] = datetime_convert('UTC','UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['Host'] = $m['host'];
|
||||
$headers['(request-target)'] = 'post ' . get_request_string($outq['outq_posturl']);
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
$ret = $outq['outq_msg'];
|
||||
logger('ActivityPub send: ' . jindent($ret), LOGGER_DATA);
|
||||
$headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['Host'] = $m['host'];
|
||||
$headers['(request-target)'] = 'post ' . get_request_string($outq['outq_posturl']);
|
||||
|
||||
$xhead = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||
if(strpos($outq['outq_posturl'],'http') !== 0) {
|
||||
logger('bad url: ' . $outq['outq_posturl']);
|
||||
self::remove($outq['outq_hash']);
|
||||
}
|
||||
$xhead = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel));
|
||||
if (strpos($outq['outq_posturl'], 'http') !== 0) {
|
||||
logger('bad url: ' . $outq['outq_posturl']);
|
||||
self::remove($outq['outq_hash']);
|
||||
}
|
||||
|
||||
$result = z_post_url($outq['outq_posturl'],$outq['outq_msg'],$retries,[ 'headers' => $xhead ]);
|
||||
$result = z_post_url($outq['outq_posturl'], $outq['outq_msg'], $retries, ['headers' => $xhead]);
|
||||
|
||||
if($result['success'] && $result['return_code'] < 300) {
|
||||
logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
if($base) {
|
||||
q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($base)
|
||||
);
|
||||
}
|
||||
q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc('accepted for delivery'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::remove($outq['outq_hash']);
|
||||
if ($result['success'] && $result['return_code'] < 300) {
|
||||
logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
if ($base) {
|
||||
q(
|
||||
"update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($base)
|
||||
);
|
||||
}
|
||||
q(
|
||||
"update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc('accepted for delivery'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
self::remove($outq['outq_hash']);
|
||||
|
||||
// server is responding - see if anything else is going to this destination and is piled up
|
||||
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||
// immediate delivery otherwise we could get into a queue loop.
|
||||
// server is responding - see if anything else is going to this destination and is piled up
|
||||
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||
// immediate delivery otherwise we could get into a queue loop.
|
||||
|
||||
if(! $immediate) {
|
||||
$x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||
dbesc($outq['outq_posturl'])
|
||||
);
|
||||
if (!$immediate) {
|
||||
$x = q(
|
||||
"select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||
dbesc($outq['outq_posturl'])
|
||||
);
|
||||
|
||||
$piled_up = [];
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if($piled_up) {
|
||||
do_delivery($piled_up,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($result['return_code'] >= 300) {
|
||||
q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc('delivery rejected' . ' ' . $result['return_code']),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
$dr = q("select * from dreport where dreport_queue = '%s'",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
if ($dr) {
|
||||
// update every queue entry going to this site with the most recent communication error
|
||||
q("update dreport set dreport_log = '%s' where dreport_site = '%s'",
|
||||
dbesc(z_curl_error($result)),
|
||||
dbesc($dr[0]['dreport_site'])
|
||||
);
|
||||
}
|
||||
}
|
||||
logger('deliver: queue post returned ' . $result['return_code'] . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
|
||||
self::update($outq['outq_hash'],10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
$piled_up = [];
|
||||
if ($x) {
|
||||
foreach ($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if ($piled_up) {
|
||||
do_delivery($piled_up, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($result['return_code'] >= 300) {
|
||||
q(
|
||||
"update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
|
||||
dbesc('delivery rejected' . ' ' . $result['return_code']),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
} else {
|
||||
$dr = q(
|
||||
"select * from dreport where dreport_queue = '%s'",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
if ($dr) {
|
||||
// update every queue entry going to this site with the most recent communication error
|
||||
q(
|
||||
"update dreport set dreport_log = '%s' where dreport_site = '%s'",
|
||||
dbesc(z_curl_error($result)),
|
||||
dbesc($dr[0]['dreport_site'])
|
||||
);
|
||||
}
|
||||
}
|
||||
logger('deliver: queue post returned ' . $result['return_code'] . ' from ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
self::update($outq['outq_hash'], 10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// normal zot delivery
|
||||
// normal zot delivery
|
||||
|
||||
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
|
||||
|
||||
if($outq['outq_posturl'] === z_root() . '/zot') {
|
||||
// local delivery
|
||||
$zot = new \Zotlabs\Zot6\Receiver(new \Zotlabs\Zot6\Zot6Handler(),$outq['outq_notify']);
|
||||
$result = $zot->run();
|
||||
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
|
||||
logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'],[ 'success' => true, 'body' => json_encode($result) ], $outq);
|
||||
if ($outq['outq_posturl'] === z_root() . '/zot') {
|
||||
// local delivery
|
||||
$zot = new Receiver(new Zot6Handler(), $outq['outq_notify']);
|
||||
$result = $zot->run();
|
||||
logger('returned_json: ' . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOGGER_DATA);
|
||||
logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'], ['success' => true, 'body' => json_encode($result)], $outq);
|
||||
|
||||
if(! $immediate) {
|
||||
$x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||
dbesc($outq['outq_posturl'])
|
||||
);
|
||||
if (!$immediate) {
|
||||
$x = q(
|
||||
"select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||
dbesc($outq['outq_posturl'])
|
||||
);
|
||||
|
||||
$piled_up = [];
|
||||
if($x) {
|
||||
foreach($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if($piled_up) {
|
||||
do_delivery($piled_up,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger('remote');
|
||||
$channel = null;
|
||||
$piled_up = [];
|
||||
if ($x) {
|
||||
foreach ($x as $xx) {
|
||||
$piled_up[] = $xx['outq_hash'];
|
||||
}
|
||||
}
|
||||
if ($piled_up) {
|
||||
do_delivery($piled_up, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger('remote');
|
||||
$channel = null;
|
||||
|
||||
if($outq['outq_channel']) {
|
||||
$channel = channelx_by_n($outq['outq_channel'],true);
|
||||
}
|
||||
if ($outq['outq_channel']) {
|
||||
$channel = channelx_by_n($outq['outq_channel'], true);
|
||||
}
|
||||
|
||||
$host_crypto = null;
|
||||
$host_crypto = null;
|
||||
|
||||
if($channel && $base) {
|
||||
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_network in ('nomad','zot6') order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if($h) {
|
||||
$host_crypto = $h[0];
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $outq['outq_notify'];
|
||||
if ($channel && $base) {
|
||||
$h = q(
|
||||
"select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_network in ('zot6','nomad') order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if ($h) {
|
||||
$host_crypto = $h[0];
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $outq['outq_notify'];
|
||||
|
||||
if ($outq['outq_driver'] === 'nomad') {
|
||||
$result = Libzot::nomad($outq['outq_posturl'],$msg,$channel,$host_crypto);
|
||||
|
@ -471,27 +491,27 @@ class Queue {
|
|||
$result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
|
||||
}
|
||||
|
||||
if($result['success']) {
|
||||
logger('deliver: remote nomad/zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'],$result, $outq);
|
||||
}
|
||||
else {
|
||||
$dr = q("select * from dreport where dreport_queue = '%s'",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
if ($result['success']) {
|
||||
logger('deliver: remote nomad/zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'], $result, $outq);
|
||||
} else {
|
||||
$dr = q(
|
||||
"select * from dreport where dreport_queue = '%s'",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
|
||||
// update every queue entry going to this site with the most recent communication error
|
||||
q("update dreport set dreport_log = '%s' where dreport_site = '%s'",
|
||||
dbesc(z_curl_error($result)),
|
||||
dbesc($dr[0]['dreport_site'])
|
||||
);
|
||||
// update every queue entry going to this site with the most recent communication error
|
||||
q(
|
||||
"update dreport set dreport_log = '%s' where dreport_site = '%s'",
|
||||
dbesc(z_curl_error($result)),
|
||||
dbesc($dr[0]['dreport_site'])
|
||||
);
|
||||
|
||||
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
|
||||
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
|
||||
self::update($outq['outq_hash'],10);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
logger('deliver: remote nomad/zot delivery failed to ' . $outq['outq_posturl']);
|
||||
logger('deliver: remote nomad/zot delivery fail data: ' . print_r($result, true), LOGGER_DATA);
|
||||
self::update($outq['outq_hash'], 10);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,22 +8,26 @@ namespace Zotlabs\Lib;
|
|||
* @see XConfig
|
||||
*/
|
||||
|
||||
class SConfig {
|
||||
class SConfig
|
||||
{
|
||||
|
||||
static public function Load($server_id) {
|
||||
return XConfig::Load('s_' . $server_id);
|
||||
}
|
||||
public static function Load($server_id)
|
||||
{
|
||||
return XConfig::Load('s_' . $server_id);
|
||||
}
|
||||
|
||||
static public function Get($server_id,$family,$key,$default = false) {
|
||||
return XConfig::Get('s_' . $server_id,$family,$key, $default);
|
||||
}
|
||||
public static function Get($server_id, $family, $key, $default = false)
|
||||
{
|
||||
return XConfig::Get('s_' . $server_id, $family, $key, $default);
|
||||
}
|
||||
|
||||
static public function Set($server_id,$family,$key,$value) {
|
||||
return XConfig::Set('s_' . $server_id,$family,$key,$value);
|
||||
}
|
||||
|
||||
static public function Delete($server_id,$family,$key) {
|
||||
return XConfig::Delete('s_' . $server_id,$family,$key);
|
||||
}
|
||||
public static function Set($server_id, $family, $key, $value)
|
||||
{
|
||||
return XConfig::Set('s_' . $server_id, $family, $key, $value);
|
||||
}
|
||||
|
||||
public static function Delete($server_id, $family, $key)
|
||||
{
|
||||
return XConfig::Delete('s_' . $server_id, $family, $key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,222 +6,227 @@ use App;
|
|||
use Zotlabs\Daemon\Run;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
class Share {
|
||||
class Share
|
||||
{
|
||||
|
||||
private $item = null;
|
||||
private $item = null;
|
||||
|
||||
|
||||
public function __construct($post_id) {
|
||||
public function __construct($post_id)
|
||||
{
|
||||
|
||||
if (! $post_id) {
|
||||
return;
|
||||
}
|
||||
if (! $post_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($post_id)) {
|
||||
$this->item = $post_id;
|
||||
return;
|
||||
}
|
||||
if (is_array($post_id)) {
|
||||
$this->item = $post_id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (! (local_channel() || remote_channel())) {
|
||||
return;
|
||||
}
|
||||
if (! (local_channel() || remote_channel())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
|
||||
intval($post_id)
|
||||
);
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
$r = q(
|
||||
"SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
|
||||
intval($post_id)
|
||||
);
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss')) {
|
||||
return;
|
||||
}
|
||||
if (($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql_extra = item_permissions_sql($r[0]['uid']);
|
||||
$sql_extra = item_permissions_sql($r[0]['uid']);
|
||||
|
||||
$r = q("select * from item where id = %d $sql_extra",
|
||||
intval($post_id)
|
||||
);
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
$r = q(
|
||||
"select * from item where id = %d $sql_extra",
|
||||
intval($post_id)
|
||||
);
|
||||
if (! $r) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! in_array($r[0]['mimetype'], [ 'text/bbcode', 'text/x-multicode' ])) {
|
||||
return;
|
||||
}
|
||||
if (! in_array($r[0]['mimetype'], [ 'text/bbcode', 'text/x-multicode' ])) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @FIXME eventually we want to post remotely via rpost on your home site */
|
||||
// When that works remove this next bit:
|
||||
/** @FIXME eventually we want to post remotely via rpost on your home site */
|
||||
// When that works remove this next bit:
|
||||
|
||||
if (! local_channel()) {
|
||||
return;
|
||||
}
|
||||
if (! local_channel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
xchan_query($r);
|
||||
xchan_query($r);
|
||||
|
||||
$this->item = array_shift($r);
|
||||
$this->item = array_shift($r);
|
||||
|
||||
$arr = [];
|
||||
$arr = [];
|
||||
|
||||
$owner_uid = $this->item['uid'];
|
||||
$owner_aid = $this->item['aid'];
|
||||
$owner_uid = $this->item['uid'];
|
||||
$owner_aid = $this->item['aid'];
|
||||
|
||||
$channel = channelx_by_n($this->item['uid']);
|
||||
$observer = App::get_observer();
|
||||
$channel = channelx_by_n($this->item['uid']);
|
||||
$observer = App::get_observer();
|
||||
|
||||
$can_comment = false;
|
||||
if ((array_key_exists('owner',$this->item)) && intval($this->item['owner']['abook_self'])) {
|
||||
$can_comment = perm_is_allowed($this->item['uid'],$observer['xchan_hash'],'post_comments');
|
||||
}
|
||||
else {
|
||||
$can_comment = can_comment_on_post($observer['xchan_hash'],$this->item);
|
||||
}
|
||||
$can_comment = false;
|
||||
if ((array_key_exists('owner', $this->item)) && intval($this->item['owner']['abook_self'])) {
|
||||
$can_comment = perm_is_allowed($this->item['uid'], $observer['xchan_hash'], 'post_comments');
|
||||
} else {
|
||||
$can_comment = can_comment_on_post($observer['xchan_hash'], $this->item);
|
||||
}
|
||||
|
||||
if (! $can_comment) {
|
||||
return;
|
||||
}
|
||||
if (! $can_comment) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($this->item['owner_xchan'])
|
||||
);
|
||||
$r = q(
|
||||
"select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($this->item['owner_xchan'])
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$thread_owner = array_shift($r);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
if ($r) {
|
||||
$thread_owner = array_shift($r);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($this->item['author_xchan'])
|
||||
);
|
||||
if ($r) {
|
||||
$item_author = array_shift($r);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
$r = q(
|
||||
"select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($this->item['author_xchan'])
|
||||
);
|
||||
if ($r) {
|
||||
$item_author = array_shift($r);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($item_author['network'] === 'activitypub') {
|
||||
if ($item_author['network'] === 'activitypub') {
|
||||
// for Mastodon compatibility, send back an ActivityPub Announce activity.
|
||||
// We don't need or want these on our own network as there is no mechanism for providing
|
||||
// a fair-use defense to copyright claims and frivolous lawsuits.
|
||||
|
||||
// for Mastodon compatibility, send back an ActivityPub Announce activity.
|
||||
// We don't need or want these on our own network as there is no mechanism for providing
|
||||
// a fair-use defense to copyright claims and frivolous lawsuits.
|
||||
$arr['aid'] = $owner_aid;
|
||||
$arr['uid'] = $owner_uid;
|
||||
|
||||
$arr['aid'] = $owner_aid;
|
||||
$arr['uid'] = $owner_uid;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = $this->item['item_wall'];
|
||||
$arr['uuid'] = new_uuid();
|
||||
$arr['mid'] = z_root() . '/item/' . $arr['uuid'];
|
||||
$arr['mid'] = str_replace('/item/', '/activity/', $arr['mid']);
|
||||
$arr['parent_mid'] = $this->item['mid'];
|
||||
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_wall'] = $this->item['item_wall'];
|
||||
$arr['uuid'] = new_uuid();
|
||||
$arr['mid'] = z_root() . '/item/' . $arr['uuid'];
|
||||
$arr['mid'] = str_replace('/item/','/activity/',$arr['mid']);
|
||||
$arr['parent_mid'] = $this->item['mid'];
|
||||
$mention = '@[zrl=' . $this->item['author']['xchan_url'] . ']' . $this->item['author']['xchan_name'] . '[/zrl]';
|
||||
$arr['body'] = sprintf(t('🔁 Repeated %1$s\'s %2$s'), $mention, $this->item['obj_type']);
|
||||
|
||||
$mention = '@[zrl=' . $this->item['author']['xchan_url'] . ']' . $this->item['author']['xchan_name'] . '[/zrl]';
|
||||
$arr['body'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, $this->item['obj_type']);
|
||||
$arr['author_xchan'] = $observer['xchan_hash'];
|
||||
$arr['owner_xchan'] = $this->item['author_xchan'];
|
||||
$arr['obj'] = $this->item['obj'];
|
||||
$arr['obj_type'] = $this->item['obj_type'];
|
||||
$arr['verb'] = 'Announce';
|
||||
|
||||
$arr['author_xchan'] = $observer['xchan_hash'];
|
||||
$arr['owner_xchan'] = $this->item['author_xchan'];
|
||||
$arr['obj'] = $this->item['obj'];
|
||||
$arr['obj_type'] = $this->item['obj_type'];
|
||||
$arr['verb'] = 'Announce';
|
||||
$post = item_store($arr);
|
||||
|
||||
$post = item_store($arr);
|
||||
$post_id = $post['item_id'];
|
||||
|
||||
$post_id = $post['item_id'];
|
||||
$arr['id'] = $post_id;
|
||||
|
||||
$arr['id'] = $post_id;
|
||||
call_hooks('post_local_end', $arr);
|
||||
|
||||
call_hooks('post_local_end', $arr);
|
||||
$r = q(
|
||||
"select * from item where id = %d",
|
||||
intval($post_id)
|
||||
);
|
||||
if ($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0], true) ] ]);
|
||||
}
|
||||
|
||||
$r = q("select * from item where id = %d",
|
||||
intval($post_id)
|
||||
);
|
||||
if ($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
|
||||
}
|
||||
Run::Summon([ 'Notifier','like',$post_id ]);
|
||||
}
|
||||
|
||||
Run::Summon([ 'Notifier','like',$post_id ]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
public function obj()
|
||||
{
|
||||
$obj = [];
|
||||
|
||||
}
|
||||
if (! $this->item) {
|
||||
return $obj;
|
||||
}
|
||||
|
||||
public function obj() {
|
||||
$obj = [];
|
||||
$obj['type'] = $this->item['obj_type'];
|
||||
$obj['id'] = $this->item['mid'];
|
||||
$obj['content'] = bbcode($this->item['body']);
|
||||
$obj['source'] = [
|
||||
'mediaType' => $this->item['mimetype'],
|
||||
'content' => $this->item['body']
|
||||
];
|
||||
|
||||
if(! $this->item)
|
||||
return $obj;
|
||||
$obj['name'] = $this->item['title'];
|
||||
$obj['published'] = $this->item['created'];
|
||||
$obj['updated'] = $this->item['edited'];
|
||||
$obj['attributedTo'] = ((strpos($this->item['author']['xchan_hash'], 'http') === 0)
|
||||
? $this->item['author']['xchan_hash']
|
||||
: $this->item['author']['xchan_url']);
|
||||
|
||||
$obj['type'] = $this->item['obj_type'];
|
||||
$obj['id'] = $this->item['mid'];
|
||||
$obj['content'] = bbcode($this->item['body']);
|
||||
$obj['source'] = [
|
||||
'mediaType' => $this->item['mimetype'],
|
||||
'content' => $this->item['body']
|
||||
];
|
||||
return $obj;
|
||||
}
|
||||
|
||||
$obj['name'] = $this->item['title'];
|
||||
$obj['published'] = $this->item['created'];
|
||||
$obj['updated'] = $this->item['edited'];
|
||||
$obj['attributedTo'] = ((strpos($this->item['author']['xchan_hash'],'http') === 0)
|
||||
? $this->item['author']['xchan_hash']
|
||||
: $this->item['author']['xchan_url']);
|
||||
public function bbcode()
|
||||
{
|
||||
$bb = EMPTY_STR;
|
||||
|
||||
return $obj;
|
||||
}
|
||||
if (! $this->item) {
|
||||
return $bb;
|
||||
}
|
||||
|
||||
public function bbcode() {
|
||||
$bb = EMPTY_STR;
|
||||
if (! $this->item['author']) {
|
||||
$author = q(
|
||||
"select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($this->item['author_xchan'])
|
||||
);
|
||||
if ($author) {
|
||||
$this->item['author'] = array_shift($author);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $this->item)
|
||||
return $bb;
|
||||
$special_object = (in_array($this->item['obj_type'], [ ACTIVITY_OBJ_PHOTO, 'Event', 'Question' ]) ? true : false);
|
||||
if ($special_object) {
|
||||
$object = json_decode($this->item['obj'], true);
|
||||
$special = (($object['source']) ? $object['source']['content'] : $object['body']);
|
||||
}
|
||||
|
||||
if (! $this->item['author']) {
|
||||
$author = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($this->item['author_xchan'])
|
||||
);
|
||||
if ($author) {
|
||||
$this->item['author'] = array_shift($author);
|
||||
}
|
||||
}
|
||||
|
||||
$special_object = (in_array($this->item['obj_type'], [ ACTIVITY_OBJ_PHOTO, 'Event', 'Question' ]) ? true : false);
|
||||
if($special_object) {
|
||||
$object = json_decode($this->item['obj'],true);
|
||||
$special = (($object['source']) ? $object['source']['content'] : $object['body']);
|
||||
}
|
||||
|
||||
if (strpos($this->item['body'], "[/share]") !== false) {
|
||||
$pos = strpos($this->item['body'], "[share");
|
||||
$bb = substr($this->item['body'], $pos);
|
||||
} else {
|
||||
$bb = "[share author='" . urlencode($this->item['author']['xchan_name']).
|
||||
"' profile='" . $this->item['author']['xchan_url'] .
|
||||
"' portable_id='" . $this->item['author']['xchan_hash'] .
|
||||
"' avatar='" . $this->item['author']['xchan_photo_s'] .
|
||||
"' link='" . $this->item['plink'] .
|
||||
if (strpos($this->item['body'], "[/share]") !== false) {
|
||||
$pos = strpos($this->item['body'], "[share");
|
||||
$bb = substr($this->item['body'], $pos);
|
||||
} else {
|
||||
$bb = "[share author='" . urlencode($this->item['author']['xchan_name']) .
|
||||
"' profile='" . $this->item['author']['xchan_url'] .
|
||||
"' portable_id='" . $this->item['author']['xchan_hash'] .
|
||||
"' avatar='" . $this->item['author']['xchan_photo_s'] .
|
||||
"' link='" . $this->item['plink'] .
|
||||
"' auth='" . (in_array($this->item['author']['network'],['nomad','zot6']) ? 'true' : 'false') .
|
||||
"' posted='" . $this->item['created'] .
|
||||
"' message_id='" . $this->item['mid'] .
|
||||
"']";
|
||||
if ($this->item['title']) {
|
||||
$bb .= '[b]'.$this->item['title'].'[/b]'."\r\n";
|
||||
}
|
||||
if ($this->item['summary']) {
|
||||
$bb .= $this->item['summary'] . "\r\n";
|
||||
}
|
||||
"' posted='" . $this->item['created'] .
|
||||
"' message_id='" . $this->item['mid'] .
|
||||
"']";
|
||||
if ($this->item['title']) {
|
||||
$bb .= '[b]' . $this->item['title'] . '[/b]' . "\r\n";
|
||||
}
|
||||
if ($this->item['summary']) {
|
||||
$bb .= $this->item['summary'] . "\r\n";
|
||||
}
|
||||
|
||||
$bb .= (($special_object) ? $special . "\r\n" . $this->item['body'] : $this->item['body']);
|
||||
$bb .= "[/share]";
|
||||
}
|
||||
|
||||
return $bb;
|
||||
|
||||
}
|
||||
$bb .= (($special_object) ? $special . "\r\n" . $this->item['body'] : $this->item['body']);
|
||||
$bb .= "[/share]";
|
||||
}
|
||||
|
||||
return $bb;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,141 +16,145 @@ use Zotlabs\Lib\Config;
|
|||
* @license http://opensource.org/licenses/mit-license.php The MIT License
|
||||
* @package svgsanitizer
|
||||
*/
|
||||
class SvgSanitizer
|
||||
{
|
||||
|
||||
class SvgSanitizer {
|
||||
private $xmlDoc; // PHP XML DOMDocument
|
||||
|
||||
private $xmlDoc; // PHP XML DOMDocument
|
||||
private $removedattrs = [];
|
||||
|
||||
private $removedattrs = [];
|
||||
private static $allowed_functions = ['matrix', 'url', 'translate', 'rgb'];
|
||||
|
||||
private static $allowed_functions = [ 'matrix', 'url', 'translate', 'rgb' ];
|
||||
// defines the allowlist of elements and attributes allowed.
|
||||
private static $allowlist = [
|
||||
'a' => ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'href', 'xlink:href', 'xlink:title'],
|
||||
'circle' => ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||
'clipPath' => ['class', 'clipPathUnits', 'id'],
|
||||
'defs' => [],
|
||||
'style' => ['type'],
|
||||
'desc' => [],
|
||||
'ellipse' => ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||
'feGaussianBlur' => ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],
|
||||
'filter' => ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],
|
||||
'foreignObject' => ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],
|
||||
'g' => ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],
|
||||
'image' => ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],
|
||||
'line' => ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],
|
||||
'linearGradient' => ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],
|
||||
'marker' => ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],
|
||||
'mask' => ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],
|
||||
'metadata' => ['class', 'id'],
|
||||
'path' => ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||
'pattern' => ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],
|
||||
'polygon' => ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||
'polyline' => ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||
'radialGradient' => ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],
|
||||
'rect' => ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],
|
||||
'stop' => ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],
|
||||
'svg' => ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],
|
||||
'switch' => ['class', 'id', 'requiredFeatures', 'systemLanguage'],
|
||||
'symbol' => ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],
|
||||
'text' => ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],
|
||||
'textPath' => ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],
|
||||
'title' => [],
|
||||
'tspan' => ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],
|
||||
'use' => ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],
|
||||
];
|
||||
|
||||
// defines the allowlist of elements and attributes allowed.
|
||||
private static $allowlist = [
|
||||
'a' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'href', 'xlink:href', 'xlink:title' ],
|
||||
'circle' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'clipPath' => [ 'class', 'clipPathUnits', 'id' ],
|
||||
'defs' => [ ],
|
||||
'style' => [ 'type' ],
|
||||
'desc' => [ ],
|
||||
'ellipse' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'feGaussianBlur' => [ 'class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation' ],
|
||||
'filter' => [ 'class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y' ],
|
||||
'foreignObject' => [ 'class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y' ],
|
||||
'g' => [ 'class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor' ],
|
||||
'image' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y' ],
|
||||
'line' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2' ],
|
||||
'linearGradient' => [ 'class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2' ],
|
||||
'marker' => [ 'id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox' ],
|
||||
'mask' => [ 'class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y' ],
|
||||
'metadata' => [ 'class', 'id' ],
|
||||
'path' => [ 'class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'pattern' => [ 'class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y' ],
|
||||
'polygon' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'polyline' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||
'radialGradient' => [ 'class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href' ],
|
||||
'rect' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y' ],
|
||||
'stop' => [ 'class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage' ],
|
||||
'svg' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y' ],
|
||||
'switch' => [ 'class', 'id', 'requiredFeatures', 'systemLanguage' ],
|
||||
'symbol' => [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox' ],
|
||||
'text' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y' ],
|
||||
'textPath' => [ 'class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href' ],
|
||||
'title' => [ ],
|
||||
'tspan' => [ 'class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y' ],
|
||||
'use' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y' ],
|
||||
];
|
||||
public function __construct()
|
||||
{
|
||||
$this->xmlDoc = new DOMDocument('1.0', 'UTF-8');
|
||||
$this->xmlDoc->preserveWhiteSpace = false;
|
||||
libxml_use_internal_errors(true);
|
||||
}
|
||||
|
||||
function __construct() {
|
||||
$this->xmlDoc = new DOMDocument('1.0','UTF-8');
|
||||
$this->xmlDoc->preserveWhiteSpace = false;
|
||||
libxml_use_internal_errors(true);
|
||||
}
|
||||
// load XML SVG
|
||||
public function load($file)
|
||||
{
|
||||
$this->xmlDoc->load($file);
|
||||
}
|
||||
|
||||
// load XML SVG
|
||||
function load($file) {
|
||||
$this->xmlDoc->load($file);
|
||||
}
|
||||
public function loadXML($str)
|
||||
{
|
||||
if (!$str) {
|
||||
logger('loadxml: empty input', LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
if (!$this->xmlDoc->loadXML($str)) {
|
||||
logger('loadxml: ' . print_r(array_slice(libxml_get_errors(), 0, Config::Get('system', 'svg_backtrace_limit', 3)), true), LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function loadXML($str) {
|
||||
if (! $str) {
|
||||
logger('loadxml: empty input', LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
if (! $this->xmlDoc->loadXML($str)) {
|
||||
logger('loadxml: ' . print_r(array_slice(libxml_get_errors(),0,Config::Get('system','svg_backtrace_limit',3)),true), LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function sanitize()
|
||||
{
|
||||
// all elements in xml doc
|
||||
$allElements = $this->xmlDoc->getElementsByTagName('*');
|
||||
|
||||
function sanitize()
|
||||
{
|
||||
// all elements in xml doc
|
||||
$allElements = $this->xmlDoc->getElementsByTagName('*');
|
||||
// loop through all elements
|
||||
for ($i = 0; $i < $allElements->length; $i++) {
|
||||
$this->removedattrs = [];
|
||||
|
||||
// loop through all elements
|
||||
for($i = 0; $i < $allElements->length; $i++)
|
||||
{
|
||||
$this->removedattrs = [];
|
||||
$currentNode = $allElements->item($i);
|
||||
|
||||
$currentNode = $allElements->item($i);
|
||||
// logger('current_node: ' . print_r($currentNode,true));
|
||||
|
||||
// logger('current_node: ' . print_r($currentNode,true));
|
||||
// array of allowed attributes in specific element
|
||||
$allowlist_attr_arr = self::$allowlist[$currentNode->tagName];
|
||||
|
||||
// array of allowed attributes in specific element
|
||||
$allowlist_attr_arr = self::$allowlist[$currentNode->tagName];
|
||||
// does element exist in allowlist?
|
||||
if (isset($allowlist_attr_arr)) {
|
||||
$total = $currentNode->attributes->length;
|
||||
|
||||
// does element exist in allowlist?
|
||||
if(isset($allowlist_attr_arr)) {
|
||||
$total = $currentNode->attributes->length;
|
||||
for ($x = 0; $x < $total; $x++) {
|
||||
// get attributes name
|
||||
$attrName = $currentNode->attributes->item($x)->nodeName;
|
||||
|
||||
for($x = 0; $x < $total; $x++) {
|
||||
// logger('checking: ' . print_r($currentNode->attributes->item($x),true));
|
||||
$matches = false;
|
||||
|
||||
// get attributes name
|
||||
$attrName = $currentNode->attributes->item($x)->nodeName;
|
||||
// check if attribute isn't in allowlist
|
||||
if (!in_array($attrName, $allowlist_attr_arr)) {
|
||||
$this->removedattrs[] = $attrName;
|
||||
} // check for disallowed functions
|
||||
elseif (
|
||||
preg_match_all(
|
||||
'/([a-zA-Z0-9]+)[\s]*\(/',
|
||||
$currentNode->attributes->item($x)->textContent,
|
||||
$matches,
|
||||
PREG_SET_ORDER
|
||||
)
|
||||
) {
|
||||
if ($attrName === 'text') {
|
||||
continue;
|
||||
}
|
||||
foreach ($matches as $match) {
|
||||
if (!in_array($match[1], self::$allowed_functions)) {
|
||||
logger('queue_remove_function: ' . $match[1], LOGGER_DEBUG);
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->removedattrs) {
|
||||
foreach ($this->removedattrs as $attr) {
|
||||
$currentNode->removeAttribute($attr);
|
||||
logger('removed: ' . $attr, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
} // else remove element
|
||||
else {
|
||||
logger('remove_node: ' . print_r($currentNode, true));
|
||||
$currentNode->parentNode->removeChild($currentNode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// logger('checking: ' . print_r($currentNode->attributes->item($x),true));
|
||||
$matches = false;
|
||||
|
||||
// check if attribute isn't in allowlist
|
||||
if(! in_array($attrName, $allowlist_attr_arr)) {
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
// check for disallowed functions
|
||||
elseif (preg_match_all('/([a-zA-Z0-9]+)[\s]*\(/',
|
||||
$currentNode->attributes->item($x)->textContent,$matches,PREG_SET_ORDER)) {
|
||||
if ($attrName === 'text') {
|
||||
continue;
|
||||
}
|
||||
foreach ($matches as $match) {
|
||||
if(! in_array($match[1],self::$allowed_functions)) {
|
||||
logger('queue_remove_function: ' . $match[1],LOGGER_DEBUG);
|
||||
$this->removedattrs[] = $attrName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->removedattrs) {
|
||||
foreach ($this->removedattrs as $attr) {
|
||||
$currentNode->removeAttribute($attr);
|
||||
logger('removed: ' . $attr, LOGGER_DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// else remove element
|
||||
else {
|
||||
logger('remove_node: ' . print_r($currentNode,true));
|
||||
$currentNode->parentNode->removeChild($currentNode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveSVG() {
|
||||
$this->xmlDoc->formatOutput = true;
|
||||
return($this->xmlDoc->saveXML());
|
||||
}
|
||||
public function saveSVG()
|
||||
{
|
||||
$this->xmlDoc->formatOutput = true;
|
||||
return ($this->xmlDoc->saveXML());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,116 +4,145 @@ namespace Zotlabs\Lib;
|
|||
|
||||
use App;
|
||||
|
||||
class System {
|
||||
class System
|
||||
{
|
||||
|
||||
static public function get_platform_name() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('platform_name',App::$config['system']))
|
||||
return App::$config['system']['platform_name'];
|
||||
return PLATFORM_NAME;
|
||||
}
|
||||
public static function get_platform_name()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('platform_name', App::$config['system'])) {
|
||||
return App::$config['system']['platform_name'];
|
||||
}
|
||||
return PLATFORM_NAME;
|
||||
}
|
||||
|
||||
static public function get_site_name() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['sitename'])
|
||||
return App::$config['system']['sitename'];
|
||||
return '';
|
||||
}
|
||||
public static function get_site_name()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['sitename']) {
|
||||
return App::$config['system']['sitename'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
static public function get_banner() {
|
||||
public static function get_banner()
|
||||
{
|
||||
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('banner',App::$config['system']) && App::$config['system']['banner']) {
|
||||
return App::$config['system']['banner'];
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('banner', App::$config['system']) && App::$config['system']['banner']) {
|
||||
return App::$config['system']['banner'];
|
||||
}
|
||||
return self::get_site_name();
|
||||
}
|
||||
|
||||
public static function get_project_icon()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('icon', App::$config['system'])) {
|
||||
return App::$config['system']['icon'];
|
||||
}
|
||||
return z_root() . '/images/' . PLATFORM_NAME . '-64.png';
|
||||
}
|
||||
|
||||
public static function get_project_favicon()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('favicon', App::$config['system'])) {
|
||||
return App::$config['system']['favicon'];
|
||||
}
|
||||
return z_root() . '/images/' . PLATFORM_NAME . '.ico';
|
||||
}
|
||||
|
||||
|
||||
public static function get_project_version()
|
||||
{
|
||||
if (array_path_exists('system/hide_version', App::$config) && intval(App::$config['system']['hide_version'])) {
|
||||
return '';
|
||||
}
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('std_version', App::$config['system'])) {
|
||||
return App::$config['system']['std_version'];
|
||||
}
|
||||
|
||||
return self::get_std_version();
|
||||
}
|
||||
|
||||
public static function get_update_version()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['hide_version']) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
return DB_UPDATE_VERSION;
|
||||
}
|
||||
|
||||
|
||||
public static function get_notify_icon()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['email_notify_icon_url']) {
|
||||
return App::$config['system']['email_notify_icon_url'];
|
||||
}
|
||||
return self::get_project_icon();
|
||||
}
|
||||
|
||||
public static function get_site_icon()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && isset(App::$config['system']['site_icon_url']) && App::$config['system']['site_icon_url']) {
|
||||
return App::$config['system']['site_icon_url'];
|
||||
}
|
||||
return self::get_project_icon();
|
||||
}
|
||||
|
||||
public static function get_site_favicon()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['site_favicon_url']) {
|
||||
return App::$config['system']['site_favicon_url'];
|
||||
}
|
||||
return self::get_project_favicon();
|
||||
}
|
||||
|
||||
public static function get_project_link()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['project_link']) {
|
||||
return App::$config['system']['project_link'];
|
||||
}
|
||||
return 'https://zotlabs.com/' . PLATFORM_NAME;
|
||||
}
|
||||
|
||||
public static function get_project_srclink()
|
||||
{
|
||||
if (is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['project_srclink']) {
|
||||
return App::$config['system']['project_srclink'];
|
||||
}
|
||||
if (PLATFORM_NAME === 'streams') {
|
||||
return 'https://codeberg.org/streams/' . PLATFORM_NAME;
|
||||
}
|
||||
return self::get_site_name();
|
||||
}
|
||||
|
||||
static public function get_project_icon() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('icon',App::$config['system'])) {
|
||||
return App::$config['system']['icon'];
|
||||
}
|
||||
return z_root() . '/images/' . PLATFORM_NAME . '-64.png';
|
||||
}
|
||||
return 'https://codeberg.org/zot/' . PLATFORM_NAME;
|
||||
}
|
||||
|
||||
static public function get_project_favicon() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('favicon',App::$config['system'])) {
|
||||
return App::$config['system']['favicon'];
|
||||
}
|
||||
return z_root() . '/images/' . PLATFORM_NAME . '.ico';
|
||||
}
|
||||
public static function ebs()
|
||||
{
|
||||
if (defined('EBSSTATE')) {
|
||||
return EBSSTATE;
|
||||
}
|
||||
return 'armed';
|
||||
}
|
||||
|
||||
public static function get_zot_revision()
|
||||
{
|
||||
$x = [ 'revision' => ZOT_REVISION ];
|
||||
call_hooks('zot_revision', $x);
|
||||
return $x['revision'];
|
||||
}
|
||||
|
||||
static public function get_project_version() {
|
||||
if(array_path_exists('system/hide_version', App::$config) && intval(App::$config['system']['hide_version']))
|
||||
return '';
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && array_key_exists('std_version',App::$config['system']))
|
||||
return App::$config['system']['std_version'];
|
||||
public static function get_std_version()
|
||||
{
|
||||
if (defined('STD_VERSION')) {
|
||||
return STD_VERSION;
|
||||
}
|
||||
return '0.0.0';
|
||||
}
|
||||
|
||||
return self::get_std_version();
|
||||
}
|
||||
public static function compatible_project($p)
|
||||
{
|
||||
|
||||
static public function get_update_version() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['hide_version'])
|
||||
return EMPTY_STR;
|
||||
return DB_UPDATE_VERSION;
|
||||
}
|
||||
|
||||
|
||||
static public function get_notify_icon() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['email_notify_icon_url'])
|
||||
return App::$config['system']['email_notify_icon_url'];
|
||||
return self::get_project_icon();
|
||||
}
|
||||
|
||||
static public function get_site_icon() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && isset(App::$config['system']['site_icon_url']) && App::$config['system']['site_icon_url'])
|
||||
return App::$config['system']['site_icon_url'];
|
||||
return self::get_project_icon();
|
||||
}
|
||||
|
||||
static public function get_site_favicon() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['site_favicon_url'])
|
||||
return App::$config['system']['site_favicon_url'];
|
||||
return self::get_project_favicon();
|
||||
}
|
||||
|
||||
static public function get_project_link() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['project_link'])
|
||||
return App::$config['system']['project_link'];
|
||||
return 'https://zotlabs.com/' . PLATFORM_NAME;
|
||||
}
|
||||
|
||||
static public function get_project_srclink() {
|
||||
if(is_array(App::$config) && is_array(App::$config['system']) && App::$config['system']['project_srclink'])
|
||||
return App::$config['system']['project_srclink'];
|
||||
if (PLATFORM_NAME === 'streams') {
|
||||
return 'https://codeberg.org/streams/' . PLATFORM_NAME;
|
||||
}
|
||||
return 'https://codeberg.org/zot/' . PLATFORM_NAME;
|
||||
}
|
||||
|
||||
static public function ebs() {
|
||||
if(defined('EBSSTATE')) {
|
||||
return EBSSTATE;
|
||||
}
|
||||
return 'armed';
|
||||
}
|
||||
|
||||
static public function get_zot_revision() {
|
||||
$x = [ 'revision' => ZOT_REVISION ];
|
||||
call_hooks('zot_revision',$x);
|
||||
return $x['revision'];
|
||||
}
|
||||
|
||||
static public function get_std_version() {
|
||||
if(defined('STD_VERSION'))
|
||||
return STD_VERSION;
|
||||
return '0.0.0';
|
||||
}
|
||||
|
||||
static public function compatible_project($p) {
|
||||
|
||||
if (in_array(strtolower($p),['hubzilla', 'zap', 'red', 'misty', 'mistpark', 'redmatrix', 'osada', 'roadhouse', 'streams'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (in_array(strtolower($p), ['hubzilla', 'zap', 'red', 'misty', 'mistpark', 'redmatrix', 'osada', 'roadhouse','streams'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,52 +2,62 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class ThreadListener {
|
||||
class ThreadListener
|
||||
{
|
||||
|
||||
static public function store($target_id,$portable_id,$ltype = 0) {
|
||||
$x = self::fetch($target_id,$portable_id,$ltype = 0);
|
||||
if(! $x) {
|
||||
$r = q("insert into listeners ( target_id, portable_id, ltype ) values ( '%s', '%s' , %d ) ",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
}
|
||||
public static function store($target_id, $portable_id, $ltype = 0)
|
||||
{
|
||||
$x = self::fetch($target_id, $portable_id, $ltype = 0);
|
||||
if (! $x) {
|
||||
$r = q(
|
||||
"insert into listeners ( target_id, portable_id, ltype ) values ( '%s', '%s' , %d ) ",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static public function fetch($target_id,$portable_id,$ltype = 0) {
|
||||
$x = q("select * from listeners where target_id = '%s' and portable_id = '%s' and ltype = %d limit 1",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
if($x) {
|
||||
return $x[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static function fetch($target_id, $portable_id, $ltype = 0)
|
||||
{
|
||||
$x = q(
|
||||
"select * from listeners where target_id = '%s' and portable_id = '%s' and ltype = %d limit 1",
|
||||
dbesc($target_id),
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
if ($x) {
|
||||
return $x[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function fetch_by_target($target_id,$ltype = 0) {
|
||||
$x = q("select * from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
);
|
||||
public static function fetch_by_target($target_id, $ltype = 0)
|
||||
{
|
||||
$x = q(
|
||||
"select * from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
);
|
||||
|
||||
return $x;
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
static public function delete_by_target($target_id, $ltype = 0) {
|
||||
return q("delete from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
|
||||
static public function delete_by_pid($portable_id, $ltype = 0) {
|
||||
return q("delete from listeners where portable_id = '%s' and ltype = %d",
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
public static function delete_by_target($target_id, $ltype = 0)
|
||||
{
|
||||
return q(
|
||||
"delete from listeners where target_id = '%s' and ltype = %d",
|
||||
dbesc($target_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
|
||||
public static function delete_by_pid($portable_id, $ltype = 0)
|
||||
{
|
||||
return q(
|
||||
"delete from listeners where portable_id = '%s' and ltype = %d",
|
||||
dbesc($portable_id),
|
||||
intval($ltype)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
/** @file */
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
|
||||
require_once('boot.php');
|
||||
require_once('include/text.php');
|
||||
|
||||
|
@ -10,240 +14,257 @@ require_once('include/text.php');
|
|||
*
|
||||
*/
|
||||
|
||||
class ThreadStream {
|
||||
class ThreadStream
|
||||
{
|
||||
|
||||
private $threads = [];
|
||||
private $mode = null;
|
||||
private $observer = null;
|
||||
private $writable = false;
|
||||
private $commentable = false;
|
||||
private $uploadable = false;
|
||||
private $profile_owner = 0;
|
||||
private $preview = false;
|
||||
private $prepared_item = '';
|
||||
public $reload = '';
|
||||
private $cipher = 'AES-128-CCM';
|
||||
private $threads = [];
|
||||
private $mode = null;
|
||||
private $observer = null;
|
||||
private $writable = false;
|
||||
private $commentable = false;
|
||||
private $uploadable = false;
|
||||
private $profile_owner = 0;
|
||||
private $preview = false;
|
||||
private $prepared_item = '';
|
||||
public $reload = '';
|
||||
private $cipher = 'AES-128-CCM';
|
||||
|
||||
// $prepared_item is for use by alternate conversation structures such as photos
|
||||
// wherein we've already prepared a top level item which doesn't look anything like
|
||||
// a normal "post" item
|
||||
// $prepared_item is for use by alternate conversation structures such as photos
|
||||
// wherein we've already prepared a top level item which doesn't look anything like
|
||||
// a normal "post" item
|
||||
|
||||
public function __construct($mode, $preview, $uploadable, $prepared_item = '') {
|
||||
$this->set_mode($mode);
|
||||
$this->preview = $preview;
|
||||
$this->uploadable = $uploadable;
|
||||
$this->prepared_item = $prepared_item;
|
||||
$c = ((local_channel()) ? get_pconfig(local_channel(),'system','default_cipher') : '');
|
||||
if($c)
|
||||
$this->cipher = $c;
|
||||
}
|
||||
public function __construct($mode, $preview, $uploadable, $prepared_item = '')
|
||||
{
|
||||
$this->set_mode($mode);
|
||||
$this->preview = $preview;
|
||||
$this->uploadable = $uploadable;
|
||||
$this->prepared_item = $prepared_item;
|
||||
$c = ((local_channel()) ? get_pconfig(local_channel(), 'system', 'default_cipher') : '');
|
||||
if ($c) {
|
||||
$this->cipher = $c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode we'll be displayed on
|
||||
*/
|
||||
private function set_mode($mode) {
|
||||
if($this->get_mode() == $mode)
|
||||
return;
|
||||
/**
|
||||
* Set the mode we'll be displayed on
|
||||
*/
|
||||
private function set_mode($mode)
|
||||
{
|
||||
if ($this->get_mode() == $mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->observer = \App::get_observer();
|
||||
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
|
||||
$this->observer = App::get_observer();
|
||||
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
|
||||
|
||||
switch($mode) {
|
||||
case 'stream':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'pubstream':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = ((local_channel()) ? true : false);
|
||||
break;
|
||||
case 'hq':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'channel':
|
||||
$this->profile_owner = \App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
break;
|
||||
case 'cards':
|
||||
$this->profile_owner = \App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
$this->reload = $_SESSION['return_url'];
|
||||
break;
|
||||
case 'articles':
|
||||
$this->profile_owner = \App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
$this->reload = $_SESSION['return_url'];
|
||||
break;
|
||||
case 'display':
|
||||
// in this mode we set profile_owner after initialisation (from conversation()) and then
|
||||
// pull some trickery which allows us to re-invoke this function afterward
|
||||
// it's an ugly hack so @FIXME
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
$this->uploadable = perm_is_allowed($this->profile_owner,$ob_hash,'write_storage');
|
||||
break;
|
||||
case 'page':
|
||||
$this->profile_owner = \App::$profile['uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
|
||||
break;
|
||||
default:
|
||||
logger('[ERROR] Conversation::set_mode : Unhandled mode ('. $mode .').', LOGGER_DEBUG);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
$this->mode = $mode;
|
||||
}
|
||||
switch ($mode) {
|
||||
case 'stream':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'pubstream':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = ((local_channel()) ? true : false);
|
||||
break;
|
||||
case 'hq':
|
||||
$this->profile_owner = local_channel();
|
||||
$this->writable = true;
|
||||
break;
|
||||
case 'channel':
|
||||
$this->profile_owner = App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments');
|
||||
break;
|
||||
case 'cards':
|
||||
$this->profile_owner = App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments');
|
||||
$this->reload = $_SESSION['return_url'];
|
||||
break;
|
||||
case 'articles':
|
||||
$this->profile_owner = App::$profile['profile_uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments');
|
||||
$this->reload = $_SESSION['return_url'];
|
||||
break;
|
||||
case 'display':
|
||||
// in this mode we set profile_owner after initialisation (from conversation()) and then
|
||||
// pull some trickery which allows us to re-invoke this function afterward
|
||||
// it's an ugly hack so @FIXME
|
||||
$this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments');
|
||||
$this->uploadable = perm_is_allowed($this->profile_owner, $ob_hash, 'write_storage');
|
||||
break;
|
||||
case 'page':
|
||||
$this->profile_owner = App::$profile['uid'];
|
||||
$this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments');
|
||||
break;
|
||||
default:
|
||||
logger('[ERROR] Conversation::set_mode : Unhandled mode (' . $mode . ').', LOGGER_DEBUG);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mode
|
||||
*/
|
||||
public function get_mode() {
|
||||
return $this->mode;
|
||||
}
|
||||
/**
|
||||
* Get mode
|
||||
*/
|
||||
public function get_mode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if page is writable
|
||||
*/
|
||||
public function is_writable() {
|
||||
return $this->writable;
|
||||
}
|
||||
/**
|
||||
* Check if page is writable
|
||||
*/
|
||||
public function is_writable()
|
||||
{
|
||||
return $this->writable;
|
||||
}
|
||||
|
||||
public function is_commentable() {
|
||||
return $this->commentable;
|
||||
}
|
||||
public function is_commentable()
|
||||
{
|
||||
return $this->commentable;
|
||||
}
|
||||
|
||||
public function is_uploadable() {
|
||||
return $this->uploadable;
|
||||
}
|
||||
public function is_uploadable()
|
||||
{
|
||||
return $this->uploadable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if page is a preview
|
||||
*/
|
||||
public function is_preview() {
|
||||
return $this->preview;
|
||||
}
|
||||
/**
|
||||
* Check if page is a preview
|
||||
*/
|
||||
public function is_preview()
|
||||
{
|
||||
return $this->preview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get profile owner
|
||||
*/
|
||||
public function get_profile_owner() {
|
||||
return $this->profile_owner;
|
||||
}
|
||||
/**
|
||||
* Get profile owner
|
||||
*/
|
||||
public function get_profile_owner()
|
||||
{
|
||||
return $this->profile_owner;
|
||||
}
|
||||
|
||||
public function set_profile_owner($uid) {
|
||||
$this->profile_owner = $uid;
|
||||
$mode = $this->get_mode();
|
||||
$this->mode = null;
|
||||
$this->set_mode($mode);
|
||||
}
|
||||
public function set_profile_owner($uid)
|
||||
{
|
||||
$this->profile_owner = $uid;
|
||||
$mode = $this->get_mode();
|
||||
$this->mode = null;
|
||||
$this->set_mode($mode);
|
||||
}
|
||||
|
||||
public function get_observer() {
|
||||
return $this->observer;
|
||||
}
|
||||
public function get_observer()
|
||||
{
|
||||
return $this->observer;
|
||||
}
|
||||
|
||||
public function get_cipher() {
|
||||
return $this->cipher;
|
||||
}
|
||||
public function get_cipher()
|
||||
{
|
||||
return $this->cipher;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a thread to the conversation
|
||||
*
|
||||
* Returns:
|
||||
* _ The inserted item on success
|
||||
* _ false on failure
|
||||
*/
|
||||
public function add_thread($item) {
|
||||
$item_id = $item->get_id();
|
||||
if(!$item_id) {
|
||||
logger('Item has no ID!!', LOGGER_DEBUG, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
if($this->get_thread($item->get_id())) {
|
||||
logger('Thread already exists ('. $item->get_id() .').', LOGGER_DEBUG, LOG_WARNING);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Add a thread to the conversation
|
||||
*
|
||||
* Returns:
|
||||
* _ The inserted item on success
|
||||
* _ false on failure
|
||||
*/
|
||||
public function add_thread($item)
|
||||
{
|
||||
$item_id = $item->get_id();
|
||||
if (!$item_id) {
|
||||
logger('Item has no ID!!', LOGGER_DEBUG, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
if ($this->get_thread($item->get_id())) {
|
||||
logger('Thread already exists (' . $item->get_id() . ').', LOGGER_DEBUG, LOG_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only add things that will be displayed
|
||||
*/
|
||||
/*
|
||||
* Only add things that will be displayed
|
||||
*/
|
||||
|
||||
|
||||
if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
|
||||
return false;
|
||||
}
|
||||
if (($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'), ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'), ACTIVITY_DISLIKE))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$item->set_commentable(false);
|
||||
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
|
||||
$item->set_commentable(false);
|
||||
$ob_hash = (($this->observer) ? $this->observer['xchan_hash'] : '');
|
||||
|
||||
if(! comments_are_now_closed($item->get_data())) {
|
||||
if(($item->get_data_value('author_xchan') === $ob_hash) || ($item->get_data_value('owner_xchan') === $ob_hash))
|
||||
$item->set_commentable(true);
|
||||
if (! comments_are_now_closed($item->get_data())) {
|
||||
if (($item->get_data_value('author_xchan') === $ob_hash) || ($item->get_data_value('owner_xchan') === $ob_hash)) {
|
||||
$item->set_commentable(true);
|
||||
}
|
||||
|
||||
if(intval($item->get_data_value('item_nocomment'))) {
|
||||
$item->set_commentable(false);
|
||||
}
|
||||
elseif(! $item->is_commentable()) {
|
||||
if((array_key_exists('owner',$item->data)) && intval($item->data['owner']['abook_self']))
|
||||
$item->set_commentable(perm_is_allowed($this->profile_owner,$ob_hash,'post_comments'));
|
||||
else
|
||||
$item->set_commentable(can_comment_on_post($ob_hash,$item->data));
|
||||
}
|
||||
}
|
||||
if($this->mode === 'pubstream' && (! local_channel())) {
|
||||
$item->set_commentable(false);
|
||||
}
|
||||
if (intval($item->get_data_value('item_nocomment'))) {
|
||||
$item->set_commentable(false);
|
||||
} elseif (! $item->is_commentable()) {
|
||||
if ((array_key_exists('owner', $item->data)) && intval($item->data['owner']['abook_self'])) {
|
||||
$item->set_commentable(perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments'));
|
||||
} else {
|
||||
$item->set_commentable(can_comment_on_post($ob_hash, $item->data));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->mode === 'pubstream' && (! local_channel())) {
|
||||
$item->set_commentable(false);
|
||||
}
|
||||
|
||||
|
||||
$item->set_conversation($this);
|
||||
$this->threads[] = $item;
|
||||
return end($this->threads);
|
||||
}
|
||||
$item->set_conversation($this);
|
||||
$this->threads[] = $item;
|
||||
return end($this->threads);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data in a form usable by a conversation template
|
||||
*
|
||||
* We should find a way to avoid using those arguments (at least most of them)
|
||||
*
|
||||
* Returns:
|
||||
* _ The data requested on success
|
||||
* _ false on failure
|
||||
*/
|
||||
public function get_template_data($conv_responses) {
|
||||
$result = [];
|
||||
/**
|
||||
* Get data in a form usable by a conversation template
|
||||
*
|
||||
* We should find a way to avoid using those arguments (at least most of them)
|
||||
*
|
||||
* Returns:
|
||||
* _ The data requested on success
|
||||
* _ false on failure
|
||||
*/
|
||||
public function get_template_data($conv_responses)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach($this->threads as $item) {
|
||||
foreach ($this->threads as $item) {
|
||||
if (($item->get_data_value('id') == $item->get_data_value('parent')) && $this->prepared_item) {
|
||||
$item_data = $this->prepared_item;
|
||||
} else {
|
||||
$item_data = $item->get_template_data($conv_responses);
|
||||
}
|
||||
if (!$item_data) {
|
||||
logger('Failed to get item template data (' . $item->get_id() . ').', LOGGER_DEBUG, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
$result[] = $item_data;
|
||||
}
|
||||
|
||||
if(($item->get_data_value('id') == $item->get_data_value('parent')) && $this->prepared_item) {
|
||||
$item_data = $this->prepared_item;
|
||||
}
|
||||
else {
|
||||
$item_data = $item->get_template_data($conv_responses);
|
||||
}
|
||||
if(!$item_data) {
|
||||
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);
|
||||
return false;
|
||||
}
|
||||
$result[] = $item_data;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Get a thread based on its item id
|
||||
*
|
||||
* Returns:
|
||||
* _ The found item on success
|
||||
* _ false on failure
|
||||
*/
|
||||
private function get_thread($id)
|
||||
{
|
||||
foreach ($this->threads as $item) {
|
||||
if ($item->get_id() == $id) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a thread based on its item id
|
||||
*
|
||||
* Returns:
|
||||
* _ The found item on success
|
||||
* _ false on failure
|
||||
*/
|
||||
private function get_thread($id) {
|
||||
foreach($this->threads as $item) {
|
||||
if($item->get_id() == $id)
|
||||
return $item;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,62 +2,71 @@
|
|||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class Verify
|
||||
{
|
||||
|
||||
class Verify {
|
||||
public static function create($type, $channel_id, $token, $meta)
|
||||
{
|
||||
return q(
|
||||
"insert into verify ( vtype, channel, token, meta, created ) values ( '%s', %d, '%s', '%s', '%s' )",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token),
|
||||
dbesc($meta),
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
|
||||
static function create($type,$channel_id,$token,$meta) {
|
||||
return q("insert into verify ( vtype, channel, token, meta, created ) values ( '%s', %d, '%s', '%s', '%s' )",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token),
|
||||
dbesc($meta),
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
}
|
||||
public static function match($type, $channel_id, $token, $meta)
|
||||
{
|
||||
$r = q(
|
||||
"select id from verify where vtype = '%s' and channel = %d and token = '%s' and meta = '%s' limit 1",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token),
|
||||
dbesc($meta)
|
||||
);
|
||||
if ($r) {
|
||||
q(
|
||||
"delete from verify where id = %d",
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function match($type,$channel_id,$token,$meta) {
|
||||
$r = q("select id from verify where vtype = '%s' and channel = %d and token = '%s' and meta = '%s' limit 1",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token),
|
||||
dbesc($meta)
|
||||
);
|
||||
if($r) {
|
||||
q("delete from verify where id = %d",
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function get_meta($type,$channel_id,$token) {
|
||||
$r = q("select id, meta from verify where vtype = '%s' and channel = %d and token = '%s' limit 1",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token)
|
||||
);
|
||||
if($r) {
|
||||
q("delete from verify where id = %d",
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
return $r[0]['meta'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Purge entries of a verify-type older than interval.
|
||||
*
|
||||
* @param string $type Verify type
|
||||
* @param string $interval SQL compatible time interval
|
||||
*/
|
||||
static function purge($type, $interval) {
|
||||
q("delete from verify where vtype = '%s' and created < ( %s - INTERVAL %s )",
|
||||
dbesc($type),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($interval)
|
||||
);
|
||||
}
|
||||
public static function get_meta($type, $channel_id, $token)
|
||||
{
|
||||
$r = q(
|
||||
"select id, meta from verify where vtype = '%s' and channel = %d and token = '%s' limit 1",
|
||||
dbesc($type),
|
||||
intval($channel_id),
|
||||
dbesc($token)
|
||||
);
|
||||
if ($r) {
|
||||
q(
|
||||
"delete from verify where id = %d",
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
return $r[0]['meta'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Purge entries of a verify-type older than interval.
|
||||
*
|
||||
* @param string $type Verify type
|
||||
* @param string $interval SQL compatible time interval
|
||||
*/
|
||||
public static function purge($type, $interval)
|
||||
{
|
||||
q(
|
||||
"delete from verify where vtype = '%s' and created < ( %s - INTERVAL %s )",
|
||||
dbesc($type),
|
||||
db_utcnow(),
|
||||
db_quoteinterval($interval)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -6,104 +6,104 @@ namespace Zotlabs\Lib;
|
|||
* @brief Fetch and return a webfinger for a resource
|
||||
*
|
||||
* @param string $resource - The resource
|
||||
* @return boolean|string false or associative array from result JSON
|
||||
* @return bool|string false or associative array from result JSON
|
||||
*/
|
||||
class Webfinger
|
||||
{
|
||||
|
||||
class Webfinger {
|
||||
private static $server = EMPTY_STR;
|
||||
private static $resource = EMPTY_STR;
|
||||
|
||||
static private $server = EMPTY_STR;
|
||||
static private $resource = EMPTY_STR;
|
||||
public static function exec($resource)
|
||||
{
|
||||
|
||||
static function exec($resource) {
|
||||
if (!$resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $resource) {
|
||||
return false;
|
||||
}
|
||||
self::parse_resource($resource);
|
||||
|
||||
self::parse_resource($resource);
|
||||
if (!(self::$server && self::$resource)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! ( self::$server && self::$resource)) {
|
||||
return false;
|
||||
}
|
||||
if (!check_siteallowed(self::$server)) {
|
||||
logger('denied: ' . self::$server);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! check_siteallowed(self::$server)) {
|
||||
logger('denied: ' . self::$server);
|
||||
return false;
|
||||
}
|
||||
logger('fetching resource: ' . self::$resource . ' from ' . self::$server, LOGGER_DEBUG, LOG_INFO);
|
||||
|
||||
logger('fetching resource: ' . self::$resource . ' from ' . self::$server, LOGGER_DEBUG, LOG_INFO);
|
||||
$url = 'https://' . self::$server . '/.well-known/webfinger?f=&resource=' . self::$resource;
|
||||
|
||||
$url = 'https://' . self::$server . '/.well-known/webfinger?f=&resource=' . self::$resource ;
|
||||
$counter = 0;
|
||||
$s = z_fetch_url($url, false, $counter, ['headers' => ['Accept: application/jrd+json, */*']]);
|
||||
|
||||
$counter = 0;
|
||||
$s = z_fetch_url($url, false, $counter, [ 'headers' => [ 'Accept: application/jrd+json, */*' ] ]);
|
||||
if ($s['success']) {
|
||||
$j = json_decode($s['body'], true);
|
||||
return ($j);
|
||||
}
|
||||
|
||||
if ($s['success']) {
|
||||
$j = json_decode($s['body'], true);
|
||||
return($j);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public static function parse_resource($resource)
|
||||
{
|
||||
|
||||
static function parse_resource($resource) {
|
||||
self::$resource = urlencode($resource);
|
||||
|
||||
self::$resource = urlencode($resource);
|
||||
if (strpos($resource, 'http') === 0) {
|
||||
$m = parse_url($resource);
|
||||
if ($m) {
|
||||
if ($m['scheme'] !== 'https') {
|
||||
return false;
|
||||
}
|
||||
self::$server = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} elseif (strpos($resource, 'tag:') === 0) {
|
||||
$arr = explode(':', $resource); // split the tag
|
||||
$h = explode(',', $arr[1]); // split the host,date
|
||||
self::$server = $h[0];
|
||||
} else {
|
||||
$x = explode('@', $resource);
|
||||
if (!strlen($x[0])) {
|
||||
// e.g. @dan@pixelfed.org
|
||||
array_shift($x);
|
||||
}
|
||||
$username = $x[0];
|
||||
if (count($x) > 1) {
|
||||
self::$server = $x[1];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (strpos($resource, 'acct:') !== 0) {
|
||||
self::$resource = urlencode('acct:' . $resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos($resource,'http') === 0) {
|
||||
$m = parse_url($resource);
|
||||
if ($m) {
|
||||
if ($m['scheme'] !== 'https') {
|
||||
return false;
|
||||
}
|
||||
self::$server = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif (strpos($resource,'tag:') === 0) {
|
||||
$arr = explode(':',$resource); // split the tag
|
||||
$h = explode(',',$arr[1]); // split the host,date
|
||||
self::$server = $h[0];
|
||||
}
|
||||
else {
|
||||
$x = explode('@',$resource);
|
||||
if (! strlen($x[0])) {
|
||||
// e.g. @dan@pixelfed.org
|
||||
array_shift($x);
|
||||
}
|
||||
$username = $x[0];
|
||||
if (count($x) > 1) {
|
||||
self::$server = $x[1];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if (strpos($resource,'acct:') !== 0) {
|
||||
self::$resource = urlencode('acct:' . $resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief fetch a webfinger resource and return a zot6 discovery url if present
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief fetch a webfinger resource and return a zot6 discovery url if present
|
||||
*
|
||||
*/
|
||||
public static function zot_url($resource)
|
||||
{
|
||||
|
||||
static function zot_url($resource) {
|
||||
$arr = self::exec($resource);
|
||||
|
||||
$arr = self::exec($resource);
|
||||
|
||||
if (is_array($arr) && array_key_exists('links',$arr)) {
|
||||
foreach ($arr['links'] as $link) {
|
||||
if (is_array($arr) && array_key_exists('links', $arr)) {
|
||||
foreach ($arr['links'] as $link) {
|
||||
if (array_key_exists('rel',$link) && in_array($link['rel'], [ PROTOCOL_NOMAD, PROTOCOL_ZOT6 ])) {
|
||||
if (array_key_exists('href',$link) && $link['href'] !== EMPTY_STR) {
|
||||
return $link['href'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (array_key_exists('href', $link) && $link['href'] !== EMPTY_STR) {
|
||||
return $link['href'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,153 +24,169 @@ use App;
|
|||
* $var = get_xconfig($observer, 'category', 'key');
|
||||
* }@endcode
|
||||
*/
|
||||
class XConfig {
|
||||
class XConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Loads a full xchan's configuration into a cached storage.
|
||||
*
|
||||
* All configuration values of the given observer hash are stored in global
|
||||
* cache which is available under the global variable App::$config[$xchan].
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @return void|false Returns false if xchan is not set
|
||||
*/
|
||||
static public function Load($xchan) {
|
||||
/**
|
||||
* @brief Loads a full xchan's configuration into a cached storage.
|
||||
*
|
||||
* All configuration values of the given observer hash are stored in global
|
||||
* cache which is available under the global variable App::$config[$xchan].
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @return void|false Returns false if xchan is not set
|
||||
*/
|
||||
public static function Load($xchan)
|
||||
{
|
||||
|
||||
if(! $xchan)
|
||||
return false;
|
||||
if (! $xchan) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! array_key_exists($xchan, App::$config))
|
||||
App::$config[$xchan] = [];
|
||||
if (! array_key_exists($xchan, App::$config)) {
|
||||
App::$config[$xchan] = [];
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM xconfig WHERE xchan = '%s'",
|
||||
dbesc($xchan)
|
||||
);
|
||||
$r = q(
|
||||
"SELECT * FROM xconfig WHERE xchan = '%s'",
|
||||
dbesc($xchan)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if(! array_key_exists($c, App::$config[$xchan])) {
|
||||
App::$config[$xchan][$c] = [];
|
||||
App::$config[$xchan][$c]['config_loaded'] = true;
|
||||
}
|
||||
App::$config[$xchan][$c][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $rr) {
|
||||
$k = $rr['k'];
|
||||
$c = $rr['cat'];
|
||||
if (! array_key_exists($c, App::$config[$xchan])) {
|
||||
App::$config[$xchan][$c] = [];
|
||||
App::$config[$xchan][$c]['config_loaded'] = true;
|
||||
}
|
||||
App::$config[$xchan][$c][$k] = $rr['v'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a particular observer's config variable given the category
|
||||
* name ($family) and a key.
|
||||
*
|
||||
* Get a particular observer's config value from the given category ($family)
|
||||
* and the $key from a cached storage in App::$config[$xchan].
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param boolean $default (optional) default false
|
||||
* @return mixed Stored $value or false if it does not exist
|
||||
*/
|
||||
static public function Get($xchan, $family, $key, $default = false) {
|
||||
/**
|
||||
* @brief Get a particular observer's config variable given the category
|
||||
* name ($family) and a key.
|
||||
*
|
||||
* Get a particular observer's config value from the given category ($family)
|
||||
* and the $key from a cached storage in App::$config[$xchan].
|
||||
*
|
||||
* Returns false if not set.
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to query
|
||||
* @param bool $default (optional) default false
|
||||
* @return mixed Stored $value or false if it does not exist
|
||||
*/
|
||||
public static function Get($xchan, $family, $key, $default = false)
|
||||
{
|
||||
|
||||
if(! $xchan)
|
||||
return $default;
|
||||
if (! $xchan) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if(! array_key_exists($xchan, App::$config))
|
||||
load_xconfig($xchan);
|
||||
if (! array_key_exists($xchan, App::$config)) {
|
||||
load_xconfig($xchan);
|
||||
}
|
||||
|
||||
if((! array_key_exists($family, App::$config[$xchan])) || (! array_key_exists($key, App::$config[$xchan][$family])))
|
||||
return $default;
|
||||
if ((! array_key_exists($family, App::$config[$xchan])) || (! array_key_exists($key, App::$config[$xchan][$family]))) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return unserialise(App::$config[$xchan][$family][$key]);
|
||||
}
|
||||
return unserialise(App::$config[$xchan][$family][$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a configuration value for an observer.
|
||||
*
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key)
|
||||
* for the observer's $xchan hash.
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to set
|
||||
* @param string $value
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
static public function Set($xchan, $family, $key, $value) {
|
||||
/**
|
||||
* @brief Sets a configuration value for an observer.
|
||||
*
|
||||
* Stores a config value ($value) in the category ($family) under the key ($key)
|
||||
* for the observer's $xchan hash.
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to set
|
||||
* @param string $value
|
||||
* The value to store
|
||||
* @return mixed Stored $value or false
|
||||
*/
|
||||
public static function Set($xchan, $family, $key, $value)
|
||||
{
|
||||
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
// manage array value
|
||||
$dbvalue = ((is_array($value)) ? serialise($value) : $value);
|
||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||
|
||||
if(self::Get($xchan, $family, $key) === false) {
|
||||
if(! array_key_exists($xchan, App::$config))
|
||||
App::$config[$xchan] = [];
|
||||
if(! array_key_exists($family, App::$config[$xchan]))
|
||||
App::$config[$xchan][$family] = [];
|
||||
if (self::Get($xchan, $family, $key) === false) {
|
||||
if (! array_key_exists($xchan, App::$config)) {
|
||||
App::$config[$xchan] = [];
|
||||
}
|
||||
if (! array_key_exists($family, App::$config[$xchan])) {
|
||||
App::$config[$xchan][$family] = [];
|
||||
}
|
||||
|
||||
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' )",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$ret = q("UPDATE xconfig SET v = '%s' WHERE xchan = '%s' and cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
$ret = q(
|
||||
"INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' )",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key),
|
||||
dbesc($dbvalue)
|
||||
);
|
||||
} else {
|
||||
$ret = q(
|
||||
"UPDATE xconfig SET v = '%s' WHERE xchan = '%s' and cat = '%s' AND k = '%s'",
|
||||
dbesc($dbvalue),
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
}
|
||||
|
||||
App::$config[$xchan][$family][$key] = $value;
|
||||
App::$config[$xchan][$family][$key] = $value;
|
||||
|
||||
if($ret)
|
||||
return $value;
|
||||
if ($ret) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deletes the given key from the observer's config.
|
||||
*
|
||||
* Removes the configured value from the stored cache in App::$config[$xchan]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
static public function Delete($xchan, $family, $key) {
|
||||
/**
|
||||
* @brief Deletes the given key from the observer's config.
|
||||
*
|
||||
* Removes the configured value from the stored cache in App::$config[$xchan]
|
||||
* and removes it from the database.
|
||||
*
|
||||
* @param string $xchan
|
||||
* The observer's hash
|
||||
* @param string $family
|
||||
* The category of the configuration value
|
||||
* @param string $key
|
||||
* The configuration key to delete
|
||||
* @return mixed
|
||||
*/
|
||||
public static function Delete($xchan, $family, $key)
|
||||
{
|
||||
|
||||
if(isset(App::$config[$xchan]) && isset(App::$config[$xchan][$family]) && isset(App::$config[$xchan][$family][$key]))
|
||||
unset(App::$config[$xchan][$family][$key]);
|
||||
if (isset(App::$config[$xchan]) && isset(App::$config[$xchan][$family]) && isset(App::$config[$xchan][$family][$key])) {
|
||||
unset(App::$config[$xchan][$family][$key]);
|
||||
}
|
||||
|
||||
$ret = q("DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
$ret = q(
|
||||
"DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",
|
||||
dbesc($xchan),
|
||||
dbesc($family),
|
||||
dbesc($key)
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,123 +4,124 @@ namespace Zotlabs\Lib;
|
|||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class ZotURL
|
||||
{
|
||||
|
||||
class ZotURL {
|
||||
public static function fetch($url, $channel, $hub = null)
|
||||
{
|
||||
|
||||
static public function fetch($url,$channel,$hub = null) {
|
||||
$ret = [ 'success' => false ];
|
||||
|
||||
$ret = [ 'success' => false ];
|
||||
|
||||
if(strpos($url,'x-zot:') !== 0) {
|
||||
return $ret;
|
||||
}
|
||||
if (strpos($url, 'x-zot:') !== 0) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
if(! $url) {
|
||||
return $ret;
|
||||
}
|
||||
if (! $url) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$portable_url = substr($url,6);
|
||||
$u = explode('/',$portable_url);
|
||||
$portable_id = $u[0];
|
||||
$portable_url = substr($url, 6);
|
||||
$u = explode('/', $portable_url);
|
||||
$portable_id = $u[0];
|
||||
|
||||
$hosts = self::lookup($portable_id,$hub);
|
||||
$hosts = self::lookup($portable_id, $hub);
|
||||
|
||||
if(! $hosts) {
|
||||
return $ret;
|
||||
}
|
||||
if (! $hosts) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
foreach($hosts as $h) {
|
||||
$newurl = $h . '/id/' . $portable_url;
|
||||
foreach ($hosts as $h) {
|
||||
$newurl = $h . '/id/' . $portable_url;
|
||||
|
||||
$m = parse_url($newurl);
|
||||
$m = parse_url($newurl);
|
||||
|
||||
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||
|
||||
if($channel && $m) {
|
||||
|
||||
$headers = [
|
||||
if ($channel && $m) {
|
||||
$headers = [
|
||||
'Accept' => 'application/x-nomad+json, application/x-zot+json',
|
||||
'Content-Type' => 'application/x-nomad+json',
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($newurl)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||
}
|
||||
else {
|
||||
$h = [ 'Accept: application/x-nomad+json' ];
|
||||
}
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($newurl)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), false);
|
||||
} else {
|
||||
$h = [ 'Accept: application/x-nomad+json, application/x-zot+json' ];
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$result = [];
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_post_url($newurl,$data,$redirects, [ 'headers' => $h ] );
|
||||
if($x['success']) {
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
$redirects = 0;
|
||||
$x = z_post_url($newurl, $data, $redirects, [ 'headers' => $h ]);
|
||||
if ($x['success']) {
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
public static function is_zoturl($s)
|
||||
{
|
||||
|
||||
static public function is_zoturl($s) {
|
||||
|
||||
if(strpos($url,'x-zot:') === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (strpos($url, 'x-zot:') === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static public function lookup($portable_id,$hub) {
|
||||
public static function lookup($portable_id, $hub)
|
||||
{
|
||||
|
||||
$r = q("select * from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0 order by hubloc_primary desc",
|
||||
dbesc($portable_id)
|
||||
);
|
||||
$r = q(
|
||||
"select * from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0 order by hubloc_primary desc",
|
||||
dbesc($portable_id)
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
if (! $r) {
|
||||
// extend to network lookup
|
||||
|
||||
// extend to network lookup
|
||||
$path = '/q/' . $portable_id;
|
||||
|
||||
$path = '/q/' . $portable_id;
|
||||
// first check sending hub since they have recently communicated with this object
|
||||
|
||||
// first check sending hub since they have recently communicated with this object
|
||||
$redirects = 0;
|
||||
|
||||
$redirects = 0;
|
||||
if ($hub) {
|
||||
$x = z_fetch_url($hub['hubloc_url'] . $path, false, $redirects);
|
||||
$u = self::parse_response($x);
|
||||
if ($u) {
|
||||
return $u;
|
||||
}
|
||||
}
|
||||
|
||||
if($hub) {
|
||||
$x = z_fetch_url($hub['hubloc_url'] . $path, false, $redirects);
|
||||
$u = self::parse_response($x);
|
||||
if($u) {
|
||||
return $u;
|
||||
}
|
||||
}
|
||||
// If this fails, fallback on directory servers
|
||||
|
||||
// If this fails, fallback on directory servers
|
||||
|
||||
return false;
|
||||
}
|
||||
return ids_to_array($r,'hubloc_url');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return ids_to_array($r, 'hubloc_url');
|
||||
}
|
||||
|
||||
|
||||
static public function parse_response($arr) {
|
||||
if(! $arr['success']) {
|
||||
return false;
|
||||
}
|
||||
$a = json_decode($arr['body'],true);
|
||||
if($a['success'] && array_key_exists('results', $a) && is_array($a['results']) && count($a['results'])) {
|
||||
foreach($a['results'] as $b) {
|
||||
$m = discover_by_webbie($b);
|
||||
if($m) {
|
||||
return([ $b ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function parse_response($arr)
|
||||
{
|
||||
if (! $arr['success']) {
|
||||
return false;
|
||||
}
|
||||
$a = json_decode($arr['body'], true);
|
||||
if ($a['success'] && array_key_exists('results', $a) && is_array($a['results']) && count($a['results'])) {
|
||||
foreach ($a['results'] as $b) {
|
||||
$m = discover_by_webbie($b);
|
||||
if ($m) {
|
||||
return([ $b ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,60 +4,59 @@ namespace Zotlabs\Lib;
|
|||
|
||||
use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Zotfinger {
|
||||
class Zotfinger
|
||||
{
|
||||
|
||||
static function exec($resource,$channel = null,$verify = true) {
|
||||
public static function exec($resource, $channel = null, $verify = true)
|
||||
{
|
||||
|
||||
if (! $resource) {
|
||||
return false;
|
||||
}
|
||||
if (!$resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$m = parse_url($resource);
|
||||
$m = parse_url($resource);
|
||||
|
||||
if ($m['host'] !== punify($m['host'])) {
|
||||
$url = str_replace($m['host'],punify($m['host']),$url);
|
||||
$m['host'] = punify($m['host']);
|
||||
}
|
||||
if ($m['host'] !== punify($m['host'])) {
|
||||
$url = str_replace($m['host'], punify($m['host']), $url);
|
||||
$m['host'] = punify($m['host']);
|
||||
}
|
||||
|
||||
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||
$data = json_encode(['zot_token' => random_string()]);
|
||||
|
||||
if ($channel && $m) {
|
||||
if ($channel && $m) {
|
||||
$headers = [
|
||||
'Accept' => 'application/x-nomad+json, application/x-zot+json',
|
||||
'Content-Type' => 'application/x-nomad+json',
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($resource)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), false);
|
||||
} else {
|
||||
$h = ['Accept: application/x-nomad+json, application/x-zot+json'];
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Accept' => 'application/x-nomad+json, application/x-zot+json',
|
||||
'Content-Type' => 'application/x-nomad+json',
|
||||
'X-Zot-Token' => random_string(),
|
||||
'Digest' => HTTPSig::generate_digest_header($data),
|
||||
'Host' => $m['host'],
|
||||
'(request-target)' => 'post ' . get_request_string($resource)
|
||||
];
|
||||
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||
}
|
||||
else {
|
||||
$h = [ 'Accept: application/x-nomad+json, application/x-zot+json' ];
|
||||
}
|
||||
$result = [];
|
||||
|
||||
$result = [];
|
||||
$redirects = 0;
|
||||
$x = z_post_url($resource, $data, $redirects, ['headers' => $h]);
|
||||
|
||||
$redirects = 0;
|
||||
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
|
||||
if ($x['success']) {
|
||||
if ($verify) {
|
||||
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
|
||||
}
|
||||
|
||||
if ($x['success']) {
|
||||
$result['data'] = json_decode($x['body'], true);
|
||||
|
||||
if ($verify) {
|
||||
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
|
||||
}
|
||||
if ($result['data'] && is_array($result['data']) && array_key_exists('encrypted', $result['data']) && $result['data']['encrypted']) {
|
||||
$result['data'] = json_decode(Crypto::unencapsulate($result['data'], get_config('system', 'prvkey')), true);
|
||||
}
|
||||
|
||||
$result['data'] = json_decode($x['body'],true);
|
||||
|
||||
if ($result['data'] && is_array($result['data']) && array_key_exists('encrypted',$result['data']) && $result['data']['encrypted']) {
|
||||
$result['data'] = json_decode(Crypto::unencapsulate($result['data'],get_config('system','prvkey')),true);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,101 +23,98 @@ require_once('include/acl_selectors.php');
|
|||
* keys however this functionality has grown in an ad-hoc manner and has gotten
|
||||
* quite messy over time.
|
||||
*/
|
||||
class Acl extends Controller
|
||||
{
|
||||
|
||||
class Acl extends Controller {
|
||||
public function init()
|
||||
{
|
||||
|
||||
function init() {
|
||||
// logger('mod_acl: ' . print_r($_REQUEST,true),LOGGER_DATA);
|
||||
|
||||
// logger('mod_acl: ' . print_r($_REQUEST,true),LOGGER_DATA);
|
||||
|
||||
$start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
|
||||
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 500);
|
||||
$search = (x($_REQUEST,'search') ? $_REQUEST['search'] : '');
|
||||
$type = (x($_REQUEST,'type') ? $_REQUEST['type'] : '');
|
||||
$noforums = (x($_REQUEST,'n') ? $_REQUEST['n'] : false);
|
||||
$start = (x($_REQUEST, 'start') ? $_REQUEST['start'] : 0);
|
||||
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 500);
|
||||
$search = (x($_REQUEST, 'search') ? $_REQUEST['search'] : '');
|
||||
$type = (x($_REQUEST, 'type') ? $_REQUEST['type'] : '');
|
||||
$noforums = (x($_REQUEST, 'n') ? $_REQUEST['n'] : false);
|
||||
|
||||
|
||||
// $type =
|
||||
// '' => standard ACL request
|
||||
// 'g' => Groups only ACL request
|
||||
// 'f' => forums only ACL request
|
||||
// 'c' => Connections only ACL request or editor (textarea) mention request
|
||||
// $_REQUEST['search'] contains ACL search text.
|
||||
// $type =
|
||||
// '' => standard ACL request
|
||||
// 'g' => Groups only ACL request
|
||||
// 'f' => forums only ACL request
|
||||
// 'c' => Connections only ACL request or editor (textarea) mention request
|
||||
// $_REQUEST['search'] contains ACL search text.
|
||||
|
||||
|
||||
// $type =
|
||||
// 'm' => autocomplete private mail recipient (checks post_mail permission)
|
||||
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
|
||||
// 'x' => nav search bar autocomplete (match any xchan)
|
||||
// 'z' => autocomplete any xchan, but also include abook_alias, requires non-zero local_channel()
|
||||
// and also contains xid without urlencode, used specifically by activity_filter widget
|
||||
// $_REQUEST['query'] contains autocomplete search text.
|
||||
// $type =
|
||||
// 'm' => autocomplete private mail recipient (checks post_mail permission)
|
||||
// 'a' => autocomplete connections (mod_connections, mod_poke, mod_sources, mod_photos)
|
||||
// 'x' => nav search bar autocomplete (match any xchan)
|
||||
// 'z' => autocomplete any xchan, but also include abook_alias, requires non-zero local_channel()
|
||||
// and also contains xid without urlencode, used specifically by activity_filter widget
|
||||
// $_REQUEST['query'] contains autocomplete search text.
|
||||
|
||||
|
||||
// The different autocomplete libraries use different names for the search text
|
||||
// parameter. Internally we'll use $search to represent the search text no matter
|
||||
// what request variable it was attached to.
|
||||
// The different autocomplete libraries use different names for the search text
|
||||
// parameter. Internally we'll use $search to represent the search text no matter
|
||||
// what request variable it was attached to.
|
||||
|
||||
if (array_key_exists('query',$_REQUEST)) {
|
||||
$search = $_REQUEST['query'];
|
||||
}
|
||||
if (array_key_exists('query', $_REQUEST)) {
|
||||
$search = $_REQUEST['query'];
|
||||
}
|
||||
|
||||
if ( (! local_channel()) && (! in_array($type, [ 'x', 'c', 'f' ]))) {
|
||||
killme();
|
||||
}
|
||||
if ((!local_channel()) && (!in_array($type, ['x', 'c', 'f']))) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$permitted = [];
|
||||
$permitted = [];
|
||||
|
||||
if (in_array($type, [ 'm', 'a', 'f' ])) {
|
||||
if (in_array($type, ['m', 'a', 'f'])) {
|
||||
// These queries require permission checking. We'll create a simple array of xchan_hash for those with
|
||||
// the requisite permissions which we can check against.
|
||||
|
||||
// These queries require permission checking. We'll create a simple array of xchan_hash for those with
|
||||
// the requisite permissions which we can check against.
|
||||
$x = q(
|
||||
"select xchan from abconfig where chan = %d and cat = 'system' and k = 'their_perms' and v like '%s'",
|
||||
intval(local_channel()),
|
||||
dbesc(($type === 'm') ? '%post_mail%' : '%tag_deliver%')
|
||||
);
|
||||
|
||||
$x = q("select xchan from abconfig where chan = %d and cat = 'system' and k = 'their_perms' and v like '%s'",
|
||||
intval(local_channel()),
|
||||
dbesc(($type === 'm') ? '%post_mail%' : '%tag_deliver%')
|
||||
);
|
||||
|
||||
$permitted = ids_to_array($x,'xchan');
|
||||
}
|
||||
$permitted = ids_to_array($x, 'xchan');
|
||||
}
|
||||
|
||||
|
||||
if ($search) {
|
||||
$sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
|
||||
// sql_extra2 is typically used when we don't have a local_channel - so we are not search abook_alias
|
||||
$sql_extra2 = " AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
|
||||
if ($search) {
|
||||
$sql_extra = " AND pgrp.gname LIKE " . protect_sprintf("'%" . dbesc($search) . "%'") . " ";
|
||||
// sql_extra2 is typically used when we don't have a local_channel - so we are not search abook_alias
|
||||
$sql_extra2 = " AND ( xchan_name LIKE " . protect_sprintf("'%" . dbesc($search) . "%'") . " OR xchan_addr LIKE " . protect_sprintf("'%" . dbesc(punify($search)) . ((strpos($search, '@') === false) ? "%@%'" : "%'")) . ") ";
|
||||
|
||||
|
||||
// This horrible mess is needed because position also returns 0 if nothing is found.
|
||||
// Would be MUCH easier if it instead returned a very large value
|
||||
// Otherwise we could just
|
||||
// order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
|
||||
|
||||
// This horrible mess is needed because position also returns 0 if nothing is found.
|
||||
// Would be MUCH easier if it instead returned a very large value
|
||||
// Otherwise we could just
|
||||
// order by LEAST(POSITION($search IN xchan_name),POSITION($search IN xchan_addr)).
|
||||
$order_extra2 = "CASE WHEN xchan_name LIKE "
|
||||
. protect_sprintf("'%" . dbesc($search) . "%'")
|
||||
. " then POSITION('" . protect_sprintf(dbesc($search))
|
||||
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
|
||||
|
||||
$order_extra2 = "CASE WHEN xchan_name LIKE "
|
||||
. protect_sprintf( "'%" . dbesc($search) . "%'" )
|
||||
. " then POSITION('" . protect_sprintf(dbesc($search))
|
||||
. "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, ";
|
||||
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf("'%" . dbesc(punify($search)) . "%'") . " OR xchan_name like " . protect_sprintf("'%" . dbesc($search) . "%'") . " OR abook_alias like " . protect_sprintf("'%" . dbesc($search) . "%'") . " ) ";
|
||||
|
||||
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR abook_alias like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) ";
|
||||
|
||||
$sql_extra4 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . " OR abook_alias LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'") . ") ";
|
||||
$sql_extra4 = "AND ( xchan_name LIKE " . protect_sprintf("'%" . dbesc($search) . "%'") . " OR xchan_addr LIKE " . protect_sprintf("'%" . dbesc(punify($search)) . ((strpos($search, '@') === false) ? "%@%'" : "%'")) . " OR abook_alias LIKE " . protect_sprintf("'%" . dbesc($search) . "%'") . ") ";
|
||||
} else {
|
||||
$sql_extra = $sql_extra2 = $sql_extra3 = $sql_extra4 = "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
$sql_extra = $sql_extra2 = $sql_extra3 = $sql_extra4 = "";
|
||||
}
|
||||
$groups = [];
|
||||
$contacts = [];
|
||||
|
||||
if ($type == '' || $type == 'g') {
|
||||
// Normal privacy groups
|
||||
|
||||
$groups = [];
|
||||
$contacts = [];
|
||||
|
||||
if ($type == '' || $type == 'g') {
|
||||
|
||||
// Normal privacy groups
|
||||
|
||||
$r = q("SELECT pgrp.id, pgrp.hash, pgrp.gname
|
||||
$r = q(
|
||||
"SELECT pgrp.id, pgrp.hash, pgrp.gname
|
||||
FROM pgrp, pgrp_member
|
||||
WHERE pgrp.deleted = 0 AND pgrp.uid = %d
|
||||
AND pgrp_member.gid = pgrp.id
|
||||
|
@ -125,238 +122,226 @@ class Acl extends Controller {
|
|||
GROUP BY pgrp.id
|
||||
ORDER BY pgrp.gname
|
||||
LIMIT %d OFFSET %d",
|
||||
intval(local_channel()),
|
||||
intval($count),
|
||||
intval($start)
|
||||
);
|
||||
intval(local_channel()),
|
||||
intval($count),
|
||||
intval($start)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
// logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(),$g['id']));
|
||||
$groups[] = [
|
||||
"type" => "g",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['gname'],
|
||||
"id" => $g['id'],
|
||||
"xid" => $g['hash'],
|
||||
"uids" => AccessList::members_xchan(local_channel(),$g['id']),
|
||||
"link" => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
// logger('acl: group: ' . $g['gname'] . ' members: ' . AccessList::members_xchan(local_channel(),$g['id']));
|
||||
$groups[] = [
|
||||
"type" => "g",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['gname'],
|
||||
"id" => $g['id'],
|
||||
"xid" => $g['hash'],
|
||||
"uids" => AccessList::members_xchan(local_channel(), $g['id']),
|
||||
"link" => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($type == '' || $type == 'c' || $type === 'f') {
|
||||
if ($type == '' || $type == 'c' || $type === 'f') {
|
||||
// Getting info from the abook is better for local users because it contains info about permissions
|
||||
if (local_channel()) {
|
||||
// add connections
|
||||
|
||||
// Getting info from the abook is better for local users because it contains info about permissions
|
||||
if (local_channel()) {
|
||||
|
||||
// add connections
|
||||
|
||||
$r = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, xchan_type, abook_flags, abook_self
|
||||
$r = q(
|
||||
"SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, xchan_type, abook_flags, abook_self
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra4 order by xchan_name asc limit $count" ,
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
}
|
||||
else { // Visitors
|
||||
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_flags, 0 as abook_self
|
||||
WHERE abook_channel = %d AND abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 $sql_extra4 order by xchan_name asc limit $count",
|
||||
intval(local_channel())
|
||||
);
|
||||
} else { // Visitors
|
||||
$r = q(
|
||||
"SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_flags, 0 as abook_self
|
||||
FROM xchan left join xlink on xlink_link = xchan_hash
|
||||
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc limit $count" ,
|
||||
dbesc(get_observer_hash())
|
||||
);
|
||||
|
||||
}
|
||||
if ((count($r) < 100) && $type == 'c') {
|
||||
$r2 = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_flags, 0 as abook_self
|
||||
FROM xchan WHERE xchan_deleted = 0 and xchan_network != 'unknown' $sql_extra2 order by $order_extra2 xchan_name asc limit $count"
|
||||
);
|
||||
if ($r2) {
|
||||
$r = array_merge($r,$r2);
|
||||
$r = unique_multidim_array($r,'hash');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elseif ($type == 'm') {
|
||||
|
||||
$r = [];
|
||||
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
|
||||
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc limit $count",
|
||||
dbesc(get_observer_hash())
|
||||
);
|
||||
}
|
||||
if ((count($r) < 100) && $type == 'c') {
|
||||
$r2 = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_flags, 0 as abook_self
|
||||
FROM xchan WHERE xchan_deleted = 0 and xchan_network != 'unknown' $sql_extra2 order by $order_extra2 xchan_name asc limit $count");
|
||||
if ($r2) {
|
||||
$r = array_merge($r, $r2);
|
||||
$r = unique_multidim_array($r, 'hash');
|
||||
}
|
||||
}
|
||||
} elseif ($type == 'm') {
|
||||
$r = [];
|
||||
$z = q(
|
||||
"SELECT xchan_hash as hash, xchan_name as name, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
|
||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d
|
||||
and xchan_deleted = 0
|
||||
$sql_extra3
|
||||
ORDER BY xchan_name ASC ",
|
||||
intval(local_channel())
|
||||
);
|
||||
if ($z) {
|
||||
foreach ($z as $zz) {
|
||||
if (in_array($zz['hash'],$permitted)) {
|
||||
$r[] = $zz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elseif ($type == 'a') {
|
||||
|
||||
$r = q("SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
intval(local_channel())
|
||||
);
|
||||
if ($z) {
|
||||
foreach ($z as $zz) {
|
||||
if (in_array($zz['hash'], $permitted)) {
|
||||
$r[] = $zz;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($type == 'a') {
|
||||
$r = q(
|
||||
"SELECT abook_id as id, xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE abook_channel = %d
|
||||
and xchan_deleted = 0
|
||||
$sql_extra3
|
||||
ORDER BY xchan_name ASC ",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
}
|
||||
elseif ($type == 'z') {
|
||||
$r = q("SELECT xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag FROM xchan left join abook on xchan_hash = abook_xchan
|
||||
intval(local_channel())
|
||||
);
|
||||
} elseif ($type == 'z') {
|
||||
$r = q(
|
||||
"SELECT xchan_name as name, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_network as network, xchan_url as url, xchan_addr as attag FROM xchan left join abook on xchan_hash = abook_xchan
|
||||
WHERE ( abook_channel = %d OR abook_channel IS NULL )
|
||||
and xchan_deleted = 0
|
||||
$sql_extra3
|
||||
ORDER BY xchan_name ASC ",
|
||||
intval(local_channel())
|
||||
);
|
||||
}
|
||||
intval(local_channel())
|
||||
);
|
||||
} elseif ($type == 'x') {
|
||||
$contacts = [];
|
||||
$r = $this->navbar_complete();
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
$contacts[] = [
|
||||
"photo" => $g['photo'],
|
||||
"name" => $g['name'],
|
||||
"nick" => $g['address'],
|
||||
'link' => (($g['address']) ? $g['address'] : $g['url']),
|
||||
'xchan' => $g['hash']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
elseif ($type == 'x') {
|
||||
$contacts = [];
|
||||
$r = $this->navbar_complete();
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
$contacts[] = [
|
||||
"photo" => $g['photo'],
|
||||
"name" => $g['name'],
|
||||
"nick" => $g['address'],
|
||||
'link' => (($g['address']) ? $g['address'] : $g['url']),
|
||||
'xchan' => $g['hash']
|
||||
];
|
||||
}
|
||||
}
|
||||
$o = [
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'items' => $contacts,
|
||||
];
|
||||
json_return_and_die($o);
|
||||
} else {
|
||||
$r = [];
|
||||
}
|
||||
|
||||
$o = [
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'items' => $contacts,
|
||||
];
|
||||
json_return_and_die($o);
|
||||
}
|
||||
else {
|
||||
$r = [];
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
if (isset($g['network']) && in_array($g['network'], ['rss', 'anon', 'unknown']) && ($type != 'a')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
// 'z' (activity_filter autocomplete) requires an un-encoded hash to prevent double encoding
|
||||
|
||||
if (isset($g['network']) && in_array($g['network'],['rss','anon','unknown']) && ($type != 'a')) {
|
||||
continue;
|
||||
}
|
||||
if ($type !== 'z') {
|
||||
$g['hash'] = urlencode($g['hash']);
|
||||
}
|
||||
|
||||
// 'z' (activity_filter autocomplete) requires an un-encoded hash to prevent double encoding
|
||||
if (!$g['nick']) {
|
||||
$g['nick'] = $g['url'];
|
||||
}
|
||||
|
||||
if ($type !== 'z') {
|
||||
$g['hash'] = urlencode($g['hash']);
|
||||
}
|
||||
if (in_array($g['hash'], $permitted) && $type === 'f' && (!$noforums)) {
|
||||
$contacts[] = [
|
||||
"type" => "c",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
|
||||
"nick" => substr($g['nick'], 0, strpos($g['nick'], '@')),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => 'taggable',
|
||||
"label" => t('network')
|
||||
];
|
||||
}
|
||||
if ($type !== 'f') {
|
||||
$contacts[] = [
|
||||
"type" => "c",
|
||||
"photo" => $g['micro'],
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
|
||||
"nick" => ((strpos($g['nick'], '@')) ? substr($g['nick'], 0, strpos($g['nick'], '@')) : $g['nick']),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => '',
|
||||
"label" => '',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! $g['nick']) {
|
||||
$g['nick'] = $g['url'];
|
||||
}
|
||||
$items = array_merge($groups, $contacts);
|
||||
|
||||
if (in_array($g['hash'],$permitted) && $type === 'f' && (! $noforums)) {
|
||||
$contacts[] = [
|
||||
"type" => "c",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
|
||||
"nick" => substr($g['nick'],0,strpos($g['nick'],'@')),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => 'taggable',
|
||||
"label" => t('network')
|
||||
];
|
||||
}
|
||||
if ($type !== 'f') {
|
||||
$contacts[] = [
|
||||
"type" => "c",
|
||||
"photo" => $g['micro'],
|
||||
"name" => $g['name'],
|
||||
"id" => urlencode($g['id']),
|
||||
"xid" => $g['hash'],
|
||||
"link" => (($g['nick']) ? $g['nick'] : $g['url']),
|
||||
"nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
|
||||
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
|
||||
"taggable" => '',
|
||||
"label" => '',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
$o = [
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'items' => $items,
|
||||
];
|
||||
|
||||
$items = array_merge($groups, $contacts);
|
||||
|
||||
$o = [
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'items' => $items,
|
||||
];
|
||||
|
||||
json_return_and_die($o);
|
||||
}
|
||||
json_return_and_die($o);
|
||||
}
|
||||
|
||||
|
||||
function navbar_complete() {
|
||||
public function navbar_complete()
|
||||
{
|
||||
|
||||
// logger('navbar_complete');
|
||||
// logger('navbar_complete');
|
||||
|
||||
if (observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
if (observer_prohibited()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dirmode = intval(get_config('system','directory_mode'));
|
||||
$search = ((x($_REQUEST,'search')) ? htmlentities($_REQUEST['search'],ENT_COMPAT,'UTF-8',false) : '');
|
||||
if (! $search || mb_strlen($search) < 2) {
|
||||
return [];
|
||||
}
|
||||
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||
$search = ((x($_REQUEST, 'search')) ? htmlentities($_REQUEST['search'], ENT_COMPAT, 'UTF-8', false) : '');
|
||||
if (!$search || mb_strlen($search) < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$star = false;
|
||||
$address = false;
|
||||
$star = false;
|
||||
$address = false;
|
||||
|
||||
if (substr($search,0,1) === '@') {
|
||||
$search = substr($search,1);
|
||||
}
|
||||
if (substr($search, 0, 1) === '@') {
|
||||
$search = substr($search, 1);
|
||||
}
|
||||
|
||||
if (substr($search,0,1) === '*') {
|
||||
$star = true;
|
||||
$search = substr($search,1);
|
||||
}
|
||||
if (substr($search, 0, 1) === '*') {
|
||||
$star = true;
|
||||
$search = substr($search, 1);
|
||||
}
|
||||
|
||||
if (strpos($search,'@') !== false) {
|
||||
$address = true;
|
||||
}
|
||||
if (strpos($search, '@') !== false) {
|
||||
$address = true;
|
||||
}
|
||||
|
||||
|
||||
$url = z_root() . '/dirsearch';
|
||||
$url = z_root() . '/dirsearch';
|
||||
|
||||
|
||||
$results = [];
|
||||
$results = [];
|
||||
|
||||
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
|
||||
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 100);
|
||||
|
||||
if ($url) {
|
||||
$query = $url . '?f=';
|
||||
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');
|
||||
if ($url) {
|
||||
$query = $url . '?f=';
|
||||
$query .= '&name=' . urlencode($search) . "&limit=$count" . (($address) ? '&address=' . urlencode(punify($search)) : '');
|
||||
|
||||
$x = z_fetch_url($query);
|
||||
if ($x['success']) {
|
||||
$t = 0;
|
||||
$j = json_decode($x['body'],true);
|
||||
if ($j && $j['results']) {
|
||||
$results = $j['results'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
$x = z_fetch_url($query);
|
||||
if ($x['success']) {
|
||||
$t = 0;
|
||||
$j = json_decode($x['body'], true);
|
||||
if ($j && $j['results']) {
|
||||
$results = $j['results'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use Zotlabs\Web\Controller;
|
||||
|
@ -10,280 +11,292 @@ use Zotlabs\Lib\LDSignatures;
|
|||
use Zotlabs\Lib\ThreadListener;
|
||||
use App;
|
||||
|
||||
class Activity extends Controller {
|
||||
class Activity extends Controller
|
||||
{
|
||||
|
||||
function init() {
|
||||
public function init()
|
||||
{
|
||||
|
||||
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
$item_id = argv(1);
|
||||
if (ActivityStreams::is_as_request()) {
|
||||
$item_id = argv(1);
|
||||
|
||||
if (! $item_id) {
|
||||
return;
|
||||
}
|
||||
if (!$item_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ob_authorise = false;
|
||||
$item_uid = 0;
|
||||
$ob_authorise = false;
|
||||
$item_uid = 0;
|
||||
|
||||
$bear = ZlibActivity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
$t = q("select item.uid, iconfig.v from iconfig left join item on iid = item.id where cat = 'ocap' and item.uuid = '%s'",
|
||||
dbesc($item_id)
|
||||
);
|
||||
if ($t) {
|
||||
foreach ($t as $token) {
|
||||
if ($token['v'] === $bear) {
|
||||
$ob_authorize = true;
|
||||
$item_uid = $token['uid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$bear = ZlibActivity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
$t = q(
|
||||
"select item.uid, iconfig.v from iconfig left join item on iid = item.id where cat = 'ocap' and item.uuid = '%s'",
|
||||
dbesc($item_id)
|
||||
);
|
||||
if ($t) {
|
||||
foreach ($t as $token) {
|
||||
if ($token['v'] === $bear) {
|
||||
$ob_authorize = true;
|
||||
$item_uid = $token['uid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0
|
||||
and item.item_delayed = 0 and item.item_blocked = 0 ";
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
if (! check_channelallowed($portable_id)) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
if (! check_siteallowed($sigdata['signer'])) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
observer_auth($portable_id);
|
||||
}
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
if (!check_channelallowed($portable_id)) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
if (!check_siteallowed($sigdata['signer'])) {
|
||||
http_status_exit(403, 'Permission denied');
|
||||
}
|
||||
observer_auth($portable_id);
|
||||
}
|
||||
|
||||
// if passed an owner_id of 0 to item_permissions_sql(), we force "guest access" or observer checking
|
||||
// Give ocap tokens priority
|
||||
// if passed an owner_id of 0 to item_permissions_sql(), we force "guest access" or observer checking
|
||||
// Give ocap tokens priority
|
||||
|
||||
if ($ob_authorize) {
|
||||
$sql_extra = " and item.uid = " . intval($token['uid']) . " ";
|
||||
}
|
||||
else {
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
}
|
||||
if ($ob_authorize) {
|
||||
$sql_extra = " and item.uid = " . intval($token['uid']) . " ";
|
||||
} else {
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
}
|
||||
|
||||
$r = q("select * from item where ( uuid = '%s' or mid = '%s' or mid = '%s' ) $item_normal $sql_extra limit 1",
|
||||
dbesc($item_id),
|
||||
dbesc(z_root() . '/activity/' . $item_id),
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
);
|
||||
$r = q(
|
||||
"select * from item where ( uuid = '%s' or mid = '%s' or mid = '%s' ) $item_normal $sql_extra limit 1",
|
||||
dbesc($item_id),
|
||||
dbesc(z_root() . '/activity/' . $item_id),
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
);
|
||||
|
||||
if (! $r) {
|
||||
$r = q("select * from item where ( uuid = '%s' or mid = '%s' or mid = '%s' ) $item_normal limit 1",
|
||||
dbesc($item_id),
|
||||
dbesc(z_root() . '/activity/' . $item_id),
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
);
|
||||
if (!$r) {
|
||||
$r = q(
|
||||
"select * from item where ( uuid = '%s' or mid = '%s' or mid = '%s' ) $item_normal limit 1",
|
||||
dbesc($item_id),
|
||||
dbesc(z_root() . '/activity/' . $item_id),
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
if ($r) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($r,true);
|
||||
$items = fetch_post_tags($r,false);
|
||||
xchan_query($r, true);
|
||||
$items = fetch_post_tags($r, false);
|
||||
|
||||
if ($portable_id && (! intval($items[0]['item_private']))) {
|
||||
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
intval($items[0]['uid']),
|
||||
dbesc($portable_id)
|
||||
);
|
||||
if (! $c) {
|
||||
ThreadListener::store(z_root() . '/activity/' . $item_id,$portable_id);
|
||||
}
|
||||
}
|
||||
if ($portable_id && (!intval($items[0]['item_private']))) {
|
||||
$c = q(
|
||||
"select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
|
||||
intval($items[0]['uid']),
|
||||
dbesc($portable_id)
|
||||
);
|
||||
if (!$c) {
|
||||
ThreadListener::store(z_root() . '/activity/' . $item_id, $portable_id);
|
||||
}
|
||||
}
|
||||
|
||||
$channel = channelx_by_n($items[0]['uid']);
|
||||
$channel = channelx_by_n($items[0]['uid']);
|
||||
|
||||
as_return_and_die(ZlibActivity::encode_activity($items[0],true),$channel);
|
||||
as_return_and_die(ZlibActivity::encode_activity($items[0], true), $channel);
|
||||
}
|
||||
|
||||
}
|
||||
if (Libzot::is_zot_request()) {
|
||||
$item_id = argv(1);
|
||||
|
||||
if (Libzot::is_zot_request()) {
|
||||
if (!$item_id) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$item_id = argv(1);
|
||||
$portable_id = EMPTY_STR;
|
||||
|
||||
if (! $item_id) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and not verb in ( 'Follow', 'Ignore' ) ";
|
||||
|
||||
$portable_id = EMPTY_STR;
|
||||
$i = null;
|
||||
|
||||
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and not verb in ( 'Follow', 'Ignore' ) ";
|
||||
// do we have the item (at all)?
|
||||
|
||||
$i = null;
|
||||
$r = q(
|
||||
"select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id)
|
||||
);
|
||||
|
||||
// do we have the item (at all)?
|
||||
if (!$r) {
|
||||
$r = q(
|
||||
"select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
);
|
||||
if ($r) {
|
||||
goaway(z_root() . '/item/' . $item_id);
|
||||
}
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$r = q("select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/activity/' . $item_id)
|
||||
);
|
||||
// process an authenticated fetch
|
||||
|
||||
if (! $r) {
|
||||
$r = q("select * from item where mid = '%s' $item_normal limit 1",
|
||||
dbesc(z_root() . '/item/' . $item_id)
|
||||
);
|
||||
if ($r) {
|
||||
goaway(z_root() . '/item/' . $item_id);
|
||||
}
|
||||
http_status_exit(404,'Not found');
|
||||
}
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
observer_auth($portable_id);
|
||||
|
||||
// process an authenticated fetch
|
||||
// first see if we have a copy of this item's parent owned by the current signer
|
||||
// include xchans for all zot-like networks - these will have the same guid and public key
|
||||
|
||||
$sigdata = HTTPSig::verify(EMPTY_STR);
|
||||
if($sigdata['portable_id'] && $sigdata['header_valid']) {
|
||||
$portable_id = $sigdata['portable_id'];
|
||||
observer_auth($portable_id);
|
||||
$x = q(
|
||||
"select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($sigdata['portable_id'])
|
||||
);
|
||||
|
||||
// first see if we have a copy of this item's parent owned by the current signer
|
||||
// include xchans for all zot-like networks - these will have the same guid and public key
|
||||
if ($x) {
|
||||
$xchans = q(
|
||||
"select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
|
||||
dbesc($sigdata['portable_id']),
|
||||
dbesc($x[0]['xchan_guid']),
|
||||
dbesc($x[0]['xchan_pubkey'])
|
||||
);
|
||||
|
||||
$x = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($sigdata['portable_id'])
|
||||
);
|
||||
if ($xchans) {
|
||||
$hashes = ids_to_querystr($xchans, 'xchan_hash', true);
|
||||
$i = q(
|
||||
"select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($x) {
|
||||
$xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
|
||||
dbesc($sigdata['portable_id']),
|
||||
dbesc($x[0]['xchan_guid']),
|
||||
dbesc($x[0]['xchan_pubkey'])
|
||||
);
|
||||
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
|
||||
// with a bias towards those items owned by channels on this site (item_wall = 1)
|
||||
|
||||
if ($xchans) {
|
||||
$hashes = ids_to_querystr($xchans,'xchan_hash',true);
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
|
||||
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
|
||||
// with a bias towards those items owned by channels on this site (item_wall = 1)
|
||||
if (!$i) {
|
||||
$i = q(
|
||||
"select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
$sql_extra = item_permissions_sql(0);
|
||||
|
||||
if (! $i) {
|
||||
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
|
||||
dbesc($r[0]['parent_mid'])
|
||||
);
|
||||
}
|
||||
|
||||
$bear = ZlibActivity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
if (! $i) {
|
||||
$t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
|
||||
dbesc($bear)
|
||||
);
|
||||
if ($t) {
|
||||
$i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
|
||||
dbesc($item_id),
|
||||
intval($t[0]['iid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$bear = ZlibActivity::token_from_request();
|
||||
if ($bear) {
|
||||
logger('bear: ' . $bear, LOGGER_DEBUG);
|
||||
if (!$i) {
|
||||
$t = q(
|
||||
"select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
|
||||
dbesc($bear)
|
||||
);
|
||||
if ($t) {
|
||||
$i = q(
|
||||
"select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
|
||||
dbesc($item_id),
|
||||
intval($t[0]['iid'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (! $i) {
|
||||
http_status_exit(403,'Forbidden');
|
||||
}
|
||||
if (!$i) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
|
||||
$parents_str = ids_to_querystr($i,'item_id');
|
||||
$parents_str = ids_to_querystr($i, 'item_id');
|
||||
|
||||
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
$items = q(
|
||||
"SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal ",
|
||||
dbesc($parents_str)
|
||||
);
|
||||
|
||||
if(! $items) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
if (!$items) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
xchan_query($items,true);
|
||||
$items = fetch_post_tags($items,true);
|
||||
xchan_query($items, true);
|
||||
$items = fetch_post_tags($items, true);
|
||||
|
||||
$observer = App::get_observer();
|
||||
$parent = $items[0];
|
||||
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'],'activitypub','recips', []) : []);
|
||||
$to = (($recips && array_key_exists('to',$recips) && is_array($recips['to'])) ? $recips['to'] : null);
|
||||
$nitems = [];
|
||||
foreach($items as $i) {
|
||||
$observer = App::get_observer();
|
||||
$parent = $items[0];
|
||||
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
|
||||
$to = (($recips && array_key_exists('to', $recips) && is_array($recips['to'])) ? $recips['to'] : null);
|
||||
$nitems = [];
|
||||
foreach ($items as $i) {
|
||||
$mids = [];
|
||||
|
||||
$mids = [];
|
||||
if (intval($i['item_private'])) {
|
||||
if (!$observer) {
|
||||
continue;
|
||||
}
|
||||
// ignore private reshare, possibly from hubzilla
|
||||
if ($i['verb'] === 'Announce') {
|
||||
if (!in_array($i['thr_parent'], $mids)) {
|
||||
$mids[] = $i['thr_parent'];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// also ignore any children of the private reshares
|
||||
if (in_array($i['thr_parent'], $mids)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(intval($i['item_private'])) {
|
||||
if(! $observer) {
|
||||
continue;
|
||||
}
|
||||
// ignore private reshare, possibly from hubzilla
|
||||
if($i['verb'] === 'Announce') {
|
||||
if(! in_array($i['thr_parent'],$mids)) {
|
||||
$mids[] = $i['thr_parent'];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// also ignore any children of the private reshares
|
||||
if(in_array($i['thr_parent'],$mids)) {
|
||||
continue;
|
||||
}
|
||||
if ((!$to) || (!in_array($observer['xchan_url'], $to))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$nitems[] = $i;
|
||||
}
|
||||
|
||||
if((! $to) || (! in_array($observer['xchan_url'],$to))) {
|
||||
continue;
|
||||
}
|
||||
if (!$nitems) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
}
|
||||
$nitems[] = $i;
|
||||
}
|
||||
$chan = channelx_by_n($nitems[0]['uid']);
|
||||
|
||||
if(! $nitems)
|
||||
http_status_exit(404, 'Not found');
|
||||
if (!$chan) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$chan = channelx_by_n($nitems[0]['uid']);
|
||||
if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||
http_status_exit(403, 'Forbidden');
|
||||
}
|
||||
|
||||
if(! $chan)
|
||||
http_status_exit(404, 'Not found');
|
||||
$i = ZlibActivity::encode_item_collection($nitems, 'conversation/' . $item_id, 'OrderedCollection', true, count($nitems));
|
||||
if ($portable_id && (!intval($items[0]['item_private']))) {
|
||||
ThreadListener::store(z_root() . '/activity/' . $item_id, $portable_id);
|
||||
}
|
||||
|
||||
if(! perm_is_allowed($chan['channel_id'],get_observer_hash(),'view_stream'))
|
||||
http_status_exit(403, 'Forbidden');
|
||||
if (!$i) {
|
||||
http_status_exit(404, 'Not found');
|
||||
}
|
||||
|
||||
$i = ZlibActivity::encode_item_collection($nitems,'conversation/' . $item_id,'OrderedCollection',true, count($nitems));
|
||||
if ($portable_id && (! intval($items[0]['item_private']))) {
|
||||
ThreadListener::store(z_root() . '/activity/' . $item_id,$portable_id);
|
||||
}
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
ZlibActivity::ap_schema()
|
||||
]], $i);
|
||||
|
||||
if(! $i)
|
||||
http_status_exit(404, 'Not found');
|
||||
|
||||
$x = array_merge(['@context' => [
|
||||
ACTIVITYSTREAMS_JSONLD_REV,
|
||||
'https://w3id.org/security/v1',
|
||||
ZlibActivity::ap_schema()
|
||||
]], $i);
|
||||
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/x-nomad+json' ;
|
||||
$x['signature'] = LDSignatures::sign($x,$chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
|
||||
}
|
||||
$headers = [];
|
||||
$headers['Content-Type'] = 'application/x-nomad+json';
|
||||
$x['signature'] = LDSignatures::sign($x, $chan);
|
||||
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
|
||||
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
|
||||
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
|
||||
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
|
||||
HTTPSig::set_headers($h);
|
||||
echo $ret;
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
}
|
||||
|
||||
goaway(z_root() . '/item/' . argv(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file Zotlabs/Module/Admin.php
|
||||
* @brief Hubzilla's admin controller.
|
||||
|
@ -13,179 +14,181 @@ use Zotlabs\Web\Controller;
|
|||
use Zotlabs\Web\SubModule;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Admin area.
|
||||
*
|
||||
*/
|
||||
class Admin extends Controller
|
||||
{
|
||||
|
||||
class Admin extends Controller {
|
||||
private $sm = null;
|
||||
|
||||
private $sm = null;
|
||||
public function __construct()
|
||||
{
|
||||
$this->sm = new SubModule();
|
||||
}
|
||||
|
||||
function __construct() {
|
||||
$this->sm = new SubModule();
|
||||
}
|
||||
public function init()
|
||||
{
|
||||
|
||||
function init() {
|
||||
logger('admin_init', LOGGER_DEBUG);
|
||||
|
||||
logger('admin_init', LOGGER_DEBUG);
|
||||
if (!is_site_admin()) {
|
||||
logger('admin denied.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (! is_site_admin()) {
|
||||
logger('admin denied.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc() > 1) {
|
||||
$this->sm->call('init');
|
||||
}
|
||||
}
|
||||
if (argc() > 1) {
|
||||
$this->sm->call('init');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function post() {
|
||||
public function post()
|
||||
{
|
||||
|
||||
logger('admin_post', LOGGER_DEBUG);
|
||||
logger('admin_post', LOGGER_DEBUG);
|
||||
|
||||
if (! is_site_admin()) {
|
||||
logger('admin denied.');
|
||||
return;
|
||||
}
|
||||
if (!is_site_admin()) {
|
||||
logger('admin denied.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc() > 1) {
|
||||
$this->sm->call('post');
|
||||
}
|
||||
if (argc() > 1) {
|
||||
$this->sm->call('post');
|
||||
}
|
||||
|
||||
// goaway(z_root() . '/admin' );
|
||||
}
|
||||
// goaway(z_root() . '/admin' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
||||
function get() {
|
||||
public function get()
|
||||
{
|
||||
|
||||
logger('admin_content', LOGGER_DEBUG);
|
||||
logger('admin_content', LOGGER_DEBUG);
|
||||
|
||||
if (! is_site_admin()) {
|
||||
logger('admin denied.');
|
||||
return login(false);
|
||||
}
|
||||
if (!is_site_admin()) {
|
||||
logger('admin denied.');
|
||||
return login(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Page content
|
||||
*/
|
||||
/*
|
||||
* Page content
|
||||
*/
|
||||
|
||||
nav_set_selected('Admin');
|
||||
nav_set_selected('Admin');
|
||||
|
||||
$o = '';
|
||||
$o = '';
|
||||
|
||||
if (argc() > 1) {
|
||||
$o = $this->sm->call('get');
|
||||
if ($o === false) {
|
||||
notice( t('Item not found.') );
|
||||
}
|
||||
}
|
||||
else {
|
||||
$o = $this->admin_page_summary();
|
||||
}
|
||||
if (argc() > 1) {
|
||||
$o = $this->sm->call('get');
|
||||
if ($o === false) {
|
||||
notice(t('Item not found.'));
|
||||
}
|
||||
} else {
|
||||
$o = $this->admin_page_summary();
|
||||
}
|
||||
|
||||
if (is_ajax()) {
|
||||
echo $o;
|
||||
killme();
|
||||
}
|
||||
else {
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
if (is_ajax()) {
|
||||
echo $o;
|
||||
killme();
|
||||
} else {
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns content for Admin Summary Page.
|
||||
*
|
||||
* @return string HTML from parsed admin_summary.tpl
|
||||
*/
|
||||
/**
|
||||
* @brief Returns content for Admin Summary Page.
|
||||
*
|
||||
* @return string HTML from parsed admin_summary.tpl
|
||||
*/
|
||||
|
||||
function admin_page_summary() {
|
||||
public function admin_page_summary()
|
||||
{
|
||||
|
||||
// list total user accounts, expirations etc.
|
||||
$accounts = [];
|
||||
$r = q("SELECT COUNT(CASE WHEN account_id > 0 THEN 1 ELSE NULL END) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
||||
db_utcnow(),
|
||||
db_utcnow(),
|
||||
dbesc(NULL_DATE),
|
||||
intval(ACCOUNT_BLOCKED)
|
||||
);
|
||||
if ($r) {
|
||||
$accounts['total'] = [ 'label' => t('Accounts'), 'val' => $r[0]['total'] ];
|
||||
$accounts['blocked'] = [ 'label' => t('Blocked accounts'), 'val' => $r[0]['blocked'] ];
|
||||
$accounts['expired'] = [ 'label' => t('Expired accounts'), 'val' => $r[0]['expired'] ];
|
||||
$accounts['expiring'] = [ 'label' => t('Expiring accounts'), 'val' => $r[0]['expiring'] ];
|
||||
}
|
||||
// list total user accounts, expirations etc.
|
||||
$accounts = [];
|
||||
$r = q(
|
||||
"SELECT COUNT(CASE WHEN account_id > 0 THEN 1 ELSE NULL END) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
||||
db_utcnow(),
|
||||
db_utcnow(),
|
||||
dbesc(NULL_DATE),
|
||||
intval(ACCOUNT_BLOCKED)
|
||||
);
|
||||
if ($r) {
|
||||
$accounts['total'] = ['label' => t('Accounts'), 'val' => $r[0]['total']];
|
||||
$accounts['blocked'] = ['label' => t('Blocked accounts'), 'val' => $r[0]['blocked']];
|
||||
$accounts['expired'] = ['label' => t('Expired accounts'), 'val' => $r[0]['expired']];
|
||||
$accounts['expiring'] = ['label' => t('Expiring accounts'), 'val' => $r[0]['expiring']];
|
||||
}
|
||||
|
||||
// pending registrations
|
||||
// pending registrations
|
||||
|
||||
$pdg = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) > 0 ",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
$pdg = q(
|
||||
"SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) > 0 ",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
|
||||
$pending = (($pdg) ? count($pdg) : 0);
|
||||
$pending = (($pdg) ? count($pdg) : 0);
|
||||
|
||||
// available channels, primary and clones
|
||||
$channels = [];
|
||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0 and channel_system = 0");
|
||||
if ($r) {
|
||||
$channels['total'] = [ 'label' => t('Channels'), 'val' => $r[0]['total'] ];
|
||||
$channels['main'] = [ 'label' => t('Primary'), 'val' => $r[0]['main'] ];
|
||||
$channels['clones'] = [ 'label' => t('Clones'), 'val' => $r[0]['clones'] ];
|
||||
}
|
||||
// available channels, primary and clones
|
||||
$channels = [];
|
||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0 and channel_system = 0");
|
||||
if ($r) {
|
||||
$channels['total'] = ['label' => t('Channels'), 'val' => $r[0]['total']];
|
||||
$channels['main'] = ['label' => t('Primary'), 'val' => $r[0]['main']];
|
||||
$channels['clones'] = ['label' => t('Clones'), 'val' => $r[0]['clones']];
|
||||
}
|
||||
|
||||
// We can do better, but this is a quick queue status
|
||||
$r = q("SELECT COUNT(outq_delivered) AS total FROM outq WHERE outq_delivered = 0");
|
||||
$queue = (($r) ? $r[0]['total'] : 0);
|
||||
$queues = [ 'label' => t('Message queues'), 'queue' => $queue ];
|
||||
// We can do better, but this is a quick queue status
|
||||
$r = q("SELECT COUNT(outq_delivered) AS total FROM outq WHERE outq_delivered = 0");
|
||||
$queue = (($r) ? $r[0]['total'] : 0);
|
||||
$queues = ['label' => t('Message queues'), 'queue' => $queue];
|
||||
|
||||
$plugins = [];
|
||||
$plugins = [];
|
||||
|
||||
if (is_array(App::$plugins) && App::$plugins) {
|
||||
foreach (App::$plugins as $p) {
|
||||
if ($p) {
|
||||
$plugins[] = $p;
|
||||
}
|
||||
}
|
||||
sort($plugins);
|
||||
}
|
||||
else {
|
||||
$plugins = 0;
|
||||
}
|
||||
if (is_array(App::$plugins) && App::$plugins) {
|
||||
foreach (App::$plugins as $p) {
|
||||
if ($p) {
|
||||
$plugins[] = $p;
|
||||
}
|
||||
}
|
||||
sort($plugins);
|
||||
} else {
|
||||
$plugins = 0;
|
||||
}
|
||||
|
||||
// Could be extended to provide also other alerts to the admin
|
||||
// Could be extended to provide also other alerts to the admin
|
||||
|
||||
$alertmsg = '';
|
||||
$alertmsg = '';
|
||||
|
||||
$upgrade = EMPTY_STR;
|
||||
$upgrade = EMPTY_STR;
|
||||
|
||||
if((! defined('PLATFORM_ARCHITECTURE')) || (PLATFORM_ARCHITECTURE === 'zap')) {
|
||||
$vrelease = get_repository_version('release');
|
||||
$vdev = get_repository_version('dev');
|
||||
$upgrade = ((version_compare(STD_VERSION,$vrelease) < 0) ? t('Your software should be updated') : '');
|
||||
}
|
||||
|
||||
$t = get_markup_template('admin_summary.tpl');
|
||||
return replace_macros($t, [
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Summary'),
|
||||
'$adminalertmsg' => $alertmsg,
|
||||
'$queues' => $queues,
|
||||
'$accounts' => [ t('Registered accounts'), $accounts ],
|
||||
'$pending' => [ t('Pending registrations'), $pending ],
|
||||
'$channels' => [ t('Registered channels'), $channels ],
|
||||
'$plugins' => (($plugins) ? [ t('Active addons'), $plugins ] : EMPTY_STR),
|
||||
'$version' => [ t('Version'), STD_VERSION ],
|
||||
'$vmaster' => [ t('Repository version (release)'), $vrelease ],
|
||||
'$vdev' => [ t('Repository version (dev)'), $vdev ],
|
||||
'$upgrade' => $upgrade,
|
||||
'$build' => Config::Get('system', 'db_version')
|
||||
]);
|
||||
}
|
||||
if ((!defined('PLATFORM_ARCHITECTURE')) || (PLATFORM_ARCHITECTURE === 'zap')) {
|
||||
$vrelease = get_repository_version('release');
|
||||
$vdev = get_repository_version('dev');
|
||||
$upgrade = ((version_compare(STD_VERSION, $vrelease) < 0) ? t('Your software should be updated') : '');
|
||||
}
|
||||
|
||||
$t = get_markup_template('admin_summary.tpl');
|
||||
return replace_macros($t, [
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Summary'),
|
||||
'$adminalertmsg' => $alertmsg,
|
||||
'$queues' => $queues,
|
||||
'$accounts' => [t('Registered accounts'), $accounts],
|
||||
'$pending' => [t('Pending registrations'), $pending],
|
||||
'$channels' => [t('Registered channels'), $channels],
|
||||
'$plugins' => (($plugins) ? [t('Active addons'), $plugins] : EMPTY_STR),
|
||||
'$version' => [t('Version'), STD_VERSION],
|
||||
'$vmaster' => [t('Repository version (release)'), $vrelease],
|
||||
'$vdev' => [t('Repository version (dev)'), $vdev],
|
||||
'$upgrade' => $upgrade,
|
||||
'$build' => Config::Get('system', 'db_version')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,80 +2,82 @@
|
|||
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
class Account_edit
|
||||
{
|
||||
|
||||
public function post()
|
||||
{
|
||||
|
||||
class Account_edit {
|
||||
$account_id = $_REQUEST['aid'];
|
||||
|
||||
function post() {
|
||||
if (!$account_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$account_id = $_REQUEST['aid'];
|
||||
|
||||
if(! $account_id)
|
||||
return;
|
||||
|
||||
$pass1 = trim($_REQUEST['pass1']);
|
||||
$pass2 = trim($_REQUEST['pass2']);
|
||||
if($pass1 && $pass2 && ($pass1 === $pass2)) {
|
||||
$salt = random_string(32);
|
||||
$password_encoded = hash('whirlpool', $salt . $pass1);
|
||||
$r = q("update account set account_salt = '%s', account_password = '%s',
|
||||
$pass1 = trim($_REQUEST['pass1']);
|
||||
$pass2 = trim($_REQUEST['pass2']);
|
||||
if ($pass1 && $pass2 && ($pass1 === $pass2)) {
|
||||
$salt = random_string(32);
|
||||
$password_encoded = hash('whirlpool', $salt . $pass1);
|
||||
$r = q(
|
||||
"update account set account_salt = '%s', account_password = '%s',
|
||||
account_password_changed = '%s' where account_id = %d",
|
||||
dbesc($salt),
|
||||
dbesc($password_encoded),
|
||||
dbesc(datetime_convert()),
|
||||
intval($account_id)
|
||||
);
|
||||
if($r)
|
||||
info( sprintf( t('Password changed for account %d.'), $account_id). EOL);
|
||||
dbesc($salt),
|
||||
dbesc($password_encoded),
|
||||
dbesc(datetime_convert()),
|
||||
intval($account_id)
|
||||
);
|
||||
if ($r) {
|
||||
info(sprintf(t('Password changed for account %d.'), $account_id) . EOL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$service_class = trim($_REQUEST['service_class']);
|
||||
$account_language = trim($_REQUEST['account_language']);
|
||||
|
||||
$service_class = trim($_REQUEST['service_class']);
|
||||
$account_language = trim($_REQUEST['account_language']);
|
||||
|
||||
$r = q("update account set account_service_class = '%s', account_language = '%s'
|
||||
$r = q(
|
||||
"update account set account_service_class = '%s', account_language = '%s'
|
||||
where account_id = %d",
|
||||
dbesc($service_class),
|
||||
dbesc($account_language),
|
||||
intval($account_id)
|
||||
);
|
||||
dbesc($service_class),
|
||||
dbesc($account_language),
|
||||
intval($account_id)
|
||||
);
|
||||
|
||||
if($r)
|
||||
info( t('Account settings updated.') . EOL);
|
||||
if ($r) {
|
||||
info(t('Account settings updated.') . EOL);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/accounts');
|
||||
}
|
||||
goaway(z_root() . '/admin/accounts');
|
||||
}
|
||||
|
||||
|
||||
function get() {
|
||||
if(argc() > 2)
|
||||
$account_id = argv(2);
|
||||
public function get()
|
||||
{
|
||||
if (argc() > 2) {
|
||||
$account_id = argv(2);
|
||||
}
|
||||
|
||||
$x = q("select * from account where account_id = %d limit 1",
|
||||
intval($account_id)
|
||||
);
|
||||
$x = q(
|
||||
"select * from account where account_id = %d limit 1",
|
||||
intval($account_id)
|
||||
);
|
||||
|
||||
if(! $x) {
|
||||
notice ( t('Account not found.') . EOL);
|
||||
return '';
|
||||
}
|
||||
if (!$x) {
|
||||
notice(t('Account not found.') . EOL);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$a = replace_macros(get_markup_template('admin_account_edit.tpl'), [
|
||||
'$account' => $x[0],
|
||||
'$title' => t('Account Edit'),
|
||||
'$pass1' => [ 'pass1', t('New Password'), ' ','' ],
|
||||
'$pass2' => [ 'pass2', t('New Password again'), ' ','' ],
|
||||
'$account_language' => [ 'account_language' , t('Account language (for emails)'), $x[0]['account_language'], '', language_list() ],
|
||||
'$service_class' => [ 'service_class', t('Service class'), $x[0]['account_service_class'], '' ],
|
||||
'$submit' => t('Submit'),
|
||||
]
|
||||
);
|
||||
|
||||
return $a;
|
||||
|
||||
|
||||
}
|
||||
|
||||
$a = replace_macros(get_markup_template('admin_account_edit.tpl'), [
|
||||
'$account' => $x[0],
|
||||
'$title' => t('Account Edit'),
|
||||
'$pass1' => ['pass1', t('New Password'), ' ', ''],
|
||||
'$pass2' => ['pass2', t('New Password again'), ' ', ''],
|
||||
'$account_language' => ['account_language', t('Account language (for emails)'), $x[0]['account_language'], '', language_list()],
|
||||
'$service_class' => ['service_class', t('Service class'), $x[0]['account_service_class'], ''],
|
||||
'$submit' => t('Submit'),
|
||||
]);
|
||||
|
||||
return $a;
|
||||
}
|
||||
}
|
|
@ -4,199 +4,208 @@ namespace Zotlabs\Module\Admin;
|
|||
|
||||
use App;
|
||||
|
||||
class Accounts {
|
||||
class Accounts
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Handle POST actions on accounts admin page.
|
||||
*
|
||||
* This function is called when on the admin user/account page the form was
|
||||
* submitted to handle multiple operations at once. If one of the icons next
|
||||
* to an entry are pressed the function admin_page_accounts() will handle this.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @brief Handle POST actions on accounts admin page.
|
||||
*
|
||||
* This function is called when on the admin user/account page the form was
|
||||
* submitted to handle multiple operations at once. If one of the icons next
|
||||
* to an entry are pressed the function admin_page_accounts() will handle this.
|
||||
*
|
||||
*/
|
||||
|
||||
function post() {
|
||||
public function post()
|
||||
{
|
||||
|
||||
$pending = ( x($_POST, 'pending') ? $_POST['pending'] : [] );
|
||||
$users = ( x($_POST, 'user') ? $_POST['user'] : [] );
|
||||
$blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : [] );
|
||||
$pending = (x($_POST, 'pending') ? $_POST['pending'] : []);
|
||||
$users = (x($_POST, 'user') ? $_POST['user'] : []);
|
||||
$blocked = (x($_POST, 'blocked') ? $_POST['blocked'] : []);
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
|
||||
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
|
||||
|
||||
|
||||
// account block/unblock button was submitted
|
||||
if (x($_POST, 'page_accounts_block')) {
|
||||
for ($i = 0; $i < count($users); $i++) {
|
||||
// if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
|
||||
$op = ($blocked[$i]) ? '& ~' : '| ';
|
||||
q("UPDATE account SET account_flags = (account_flags $op %d) WHERE account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($users[$i])
|
||||
);
|
||||
}
|
||||
notice( sprintf( tt("%s account blocked/unblocked", "%s accounts blocked/unblocked", count($users)), count($users)) );
|
||||
}
|
||||
// account block/unblock button was submitted
|
||||
if (x($_POST, 'page_accounts_block')) {
|
||||
for ($i = 0; $i < count($users); $i++) {
|
||||
// if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
|
||||
$op = ($blocked[$i]) ? '& ~' : '| ';
|
||||
q(
|
||||
"UPDATE account SET account_flags = (account_flags $op %d) WHERE account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($users[$i])
|
||||
);
|
||||
}
|
||||
notice(sprintf(tt("%s account blocked/unblocked", "%s accounts blocked/unblocked", count($users)), count($users)));
|
||||
}
|
||||
|
||||
// account delete button was submitted
|
||||
if (x($_POST, 'page_accounts_delete')) {
|
||||
foreach ($users as $uid){
|
||||
account_remove($uid, true, false);
|
||||
}
|
||||
notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
|
||||
}
|
||||
// account delete button was submitted
|
||||
if (x($_POST, 'page_accounts_delete')) {
|
||||
foreach ($users as $uid) {
|
||||
account_remove($uid, true, false);
|
||||
}
|
||||
notice(sprintf(tt("%s account deleted", "%s accounts deleted", count($users)), count($users)));
|
||||
}
|
||||
|
||||
// registration approved button was submitted
|
||||
if (x($_POST, 'page_accounts_approve')) {
|
||||
foreach ($pending as $hash) {
|
||||
account_allow($hash);
|
||||
}
|
||||
}
|
||||
// registration approved button was submitted
|
||||
if (x($_POST, 'page_accounts_approve')) {
|
||||
foreach ($pending as $hash) {
|
||||
account_allow($hash);
|
||||
}
|
||||
}
|
||||
|
||||
// registration deny button was submitted
|
||||
if (x($_POST, 'page_accounts_deny')) {
|
||||
foreach ($pending as $hash) {
|
||||
account_deny($hash);
|
||||
}
|
||||
}
|
||||
// registration deny button was submitted
|
||||
if (x($_POST, 'page_accounts_deny')) {
|
||||
foreach ($pending as $hash) {
|
||||
account_deny($hash);
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/accounts' );
|
||||
}
|
||||
goaway(z_root() . '/admin/accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate accounts admin page and handle single item operations.
|
||||
*
|
||||
* This function generates the accounts/account admin page and handles the actions
|
||||
* if an icon next to an entry was clicked. If several items were selected and
|
||||
* the form was submitted it is handled by the function admin_page_accounts_post().
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
/**
|
||||
* @brief Generate accounts admin page and handle single item operations.
|
||||
*
|
||||
* This function generates the accounts/account admin page and handles the actions
|
||||
* if an icon next to an entry was clicked. If several items were selected and
|
||||
* the form was submitted it is handled by the function admin_page_accounts_post().
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
||||
function get(){
|
||||
if (argc() > 2) {
|
||||
$uid = argv(3);
|
||||
$account = q("SELECT * FROM account WHERE account_id = %d",
|
||||
intval($uid)
|
||||
);
|
||||
public function get()
|
||||
{
|
||||
if (argc() > 2) {
|
||||
$uid = argv(3);
|
||||
$account = q(
|
||||
"SELECT * FROM account WHERE account_id = %d",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if (! $account) {
|
||||
notice( t('Account not found') . EOL);
|
||||
goaway(z_root() . '/admin/accounts' );
|
||||
}
|
||||
if (!$account) {
|
||||
notice(t('Account not found') . EOL);
|
||||
goaway(z_root() . '/admin/accounts');
|
||||
}
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts', 't');
|
||||
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts', 't');
|
||||
|
||||
switch (argv(2)) {
|
||||
case 'delete':
|
||||
// delete user
|
||||
account_remove($uid,true,false);
|
||||
switch (argv(2)) {
|
||||
case 'delete':
|
||||
// delete user
|
||||
account_remove($uid, true, false);
|
||||
|
||||
notice( sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
case 'block':
|
||||
q("UPDATE account SET account_flags = ( account_flags | %d ) WHERE account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($uid)
|
||||
);
|
||||
notice(sprintf(t("Account '%s' deleted"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
case 'block':
|
||||
q(
|
||||
"UPDATE account SET account_flags = ( account_flags | %d ) WHERE account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
notice( sprintf( t("Account '%s' blocked") , $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
case 'unblock':
|
||||
q("UPDATE account SET account_flags = ( account_flags & ~ %d ) WHERE account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($uid)
|
||||
);
|
||||
notice(sprintf(t("Account '%s' blocked"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
case 'unblock':
|
||||
q(
|
||||
"UPDATE account SET account_flags = ( account_flags & ~ %d ) WHERE account_id = %d",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
notice( sprintf( t("Account '%s' unblocked"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
}
|
||||
notice(sprintf(t("Account '%s' unblocked"), $account[0]['account_email']) . EOL);
|
||||
break;
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/accounts' );
|
||||
}
|
||||
goaway(z_root() . '/admin/accounts');
|
||||
}
|
||||
|
||||
/* get pending */
|
||||
$pending = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) != 0 ",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
/* get pending */
|
||||
$pending = q(
|
||||
"SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) != 0 ",
|
||||
intval(ACCOUNT_PENDING)
|
||||
);
|
||||
|
||||
/* get accounts */
|
||||
/* get accounts */
|
||||
|
||||
$total = q("SELECT count(*) as total FROM account");
|
||||
if (count($total)) {
|
||||
App::set_pager_total($total[0]['total']);
|
||||
App::set_pager_itemspage(100);
|
||||
}
|
||||
$total = q("SELECT count(*) as total FROM account");
|
||||
if (count($total)) {
|
||||
App::set_pager_total($total[0]['total']);
|
||||
App::set_pager_itemspage(100);
|
||||
}
|
||||
|
||||
$serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
|
||||
$serviceclass = (($_REQUEST['class']) ? " and account_service_class = '" . dbesc($_REQUEST['class']) . "' " : '');
|
||||
|
||||
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id');
|
||||
$dir = 'asc';
|
||||
if (array_key_exists('dir',$_REQUEST)) {
|
||||
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
|
||||
}
|
||||
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'account_id');
|
||||
$dir = 'asc';
|
||||
if (array_key_exists('dir', $_REQUEST)) {
|
||||
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
|
||||
}
|
||||
|
||||
$base = z_root() . '/admin/accounts?f=';
|
||||
$odir = (($dir === 'asc') ? '0' : '1');
|
||||
$base = z_root() . '/admin/accounts?f=';
|
||||
$odir = (($dir === 'asc') ? '0' : '1');
|
||||
|
||||
$users = q("SELECT account_id , account_email, account_lastlog, account_created, account_expires, account_service_class, ( account_flags & %d ) > 0 as blocked,
|
||||
$users = q(
|
||||
"SELECT account_id , account_email, account_lastlog, account_created, account_expires, account_service_class, ( account_flags & %d ) > 0 as blocked,
|
||||
(SELECT %s FROM channel as ch WHERE ch.channel_account_id = ac.account_id and ch.channel_removed = 0 ) as channels FROM account as ac
|
||||
where true $serviceclass and account_flags != %d order by $key $dir limit %d offset %d ",
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
db_concat('ch.channel_address', ' '),
|
||||
intval(ACCOUNT_BLOCKED | ACCOUNT_PENDING),
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
);
|
||||
intval(ACCOUNT_BLOCKED),
|
||||
db_concat('ch.channel_address', ' '),
|
||||
intval(ACCOUNT_BLOCKED | ACCOUNT_PENDING),
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
);
|
||||
|
||||
if ($users) {
|
||||
for($x = 0; $x < count($users); $x ++) {
|
||||
$channel_arr = explode(' ',$users[$x]['channels']);
|
||||
if ($channel_arr) {
|
||||
$linked = [];
|
||||
foreach ( $channel_arr as $c) {
|
||||
$linked[] = '<a href="' . z_root() . '/channel/' . $c . '">' . $c . '</a>';
|
||||
}
|
||||
$users[$x]['channels'] = implode(' ',$linked);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($users) {
|
||||
for ($x = 0; $x < count($users); $x++) {
|
||||
$channel_arr = explode(' ', $users[$x]['channels']);
|
||||
if ($channel_arr) {
|
||||
$linked = [];
|
||||
foreach ($channel_arr as $c) {
|
||||
$linked[] = '<a href="' . z_root() . '/channel/' . $c . '">' . $c . '</a>';
|
||||
}
|
||||
$users[$x]['channels'] = implode(' ', $linked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$t =
|
||||
$o = replace_macros(get_markup_template('admin_accounts.tpl'), [
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Accounts'),
|
||||
'$submit' => t('Submit'),
|
||||
'$select_all' => t('select all'),
|
||||
'$h_pending' => t('Registrations waiting for confirm'),
|
||||
'$th_pending' => array( t('Request date'), t('Email') ),
|
||||
'$no_pending' => t('No registrations.'),
|
||||
'$approve' => t('Approve'),
|
||||
'$deny' => t('Deny'),
|
||||
'$delete' => t('Delete'),
|
||||
'$block' => t('Block'),
|
||||
'$unblock' => t('Unblock'),
|
||||
'$odir' => $odir,
|
||||
'$base' => $base,
|
||||
'$h_users' => t('Accounts'),
|
||||
'$th_users' => [
|
||||
[ t('ID'), 'account_id' ],
|
||||
[ t('Email'), 'account_email' ],
|
||||
[ t('All Channels'), 'channels' ],
|
||||
[ t('Register date'), 'account_created' ],
|
||||
[ t('Last login'), 'account_lastlog' ],
|
||||
[ t('Expires'), 'account_expires' ],
|
||||
[ t('Service Class'), 'account_service_class']
|
||||
],
|
||||
'$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$form_security_token' => get_form_security_token("admin_accounts"),
|
||||
'$baseurl' => z_root(),
|
||||
'$pending' => $pending,
|
||||
'$users' => $users,
|
||||
]);
|
||||
$t =
|
||||
$o = replace_macros(get_markup_template('admin_accounts.tpl'), [
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Accounts'),
|
||||
'$submit' => t('Submit'),
|
||||
'$select_all' => t('select all'),
|
||||
'$h_pending' => t('Registrations waiting for confirm'),
|
||||
'$th_pending' => array(t('Request date'), t('Email')),
|
||||
'$no_pending' => t('No registrations.'),
|
||||
'$approve' => t('Approve'),
|
||||
'$deny' => t('Deny'),
|
||||
'$delete' => t('Delete'),
|
||||
'$block' => t('Block'),
|
||||
'$unblock' => t('Unblock'),
|
||||
'$odir' => $odir,
|
||||
'$base' => $base,
|
||||
'$h_users' => t('Accounts'),
|
||||
'$th_users' => [
|
||||
[t('ID'), 'account_id'],
|
||||
[t('Email'), 'account_email'],
|
||||
[t('All Channels'), 'channels'],
|
||||
[t('Register date'), 'account_created'],
|
||||
[t('Last login'), 'account_lastlog'],
|
||||
[t('Expires'), 'account_expires'],
|
||||
[t('Service Class'), 'account_service_class']
|
||||
],
|
||||
'$confirm_delete_multi' => t('Selected accounts will be deleted!\n\nEverything these accounts had posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$confirm_delete' => t('The account {0} will be deleted!\n\nEverything this account has posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$form_security_token' => get_form_security_token("admin_accounts"),
|
||||
'$baseurl' => z_root(),
|
||||
'$pending' => $pending,
|
||||
'$users' => $users,
|
||||
]);
|
||||
|
||||
$o .= paginate($a);
|
||||
$o .= paginate($a);
|
||||
|
||||
return $o;
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,479 +2,486 @@
|
|||
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
use \Zotlabs\Storage\GitRepo;
|
||||
use \Michelf\MarkdownExtra;
|
||||
use App;
|
||||
use PHPGit\Exception\GitException;
|
||||
use Zotlabs\Storage\GitRepo;
|
||||
use Michelf\MarkdownExtra;
|
||||
|
||||
class Addons {
|
||||
class Addons
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
function post() {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
|
||||
if(argc() > 2 && is_file("addon/" . argv(2) . "/" . argv(2) . ".php")) {
|
||||
@include_once("addon/" . argv(2) . "/" . argv(2) . ".php");
|
||||
if(function_exists(argv(2).'_plugin_admin_post')) {
|
||||
$func = argv(2) . '_plugin_admin_post';
|
||||
$func($a);
|
||||
}
|
||||
if (argc() > 2 && is_file("addon/" . argv(2) . "/" . argv(2) . ".php")) {
|
||||
@include_once("addon/" . argv(2) . "/" . argv(2) . ".php");
|
||||
if (function_exists(argv(2) . '_plugin_admin_post')) {
|
||||
$func = argv(2) . '_plugin_admin_post';
|
||||
$func($a);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/addons/' . argv(2) );
|
||||
}
|
||||
elseif(argc() > 2) {
|
||||
switch(argv(2)) {
|
||||
case 'updaterepo':
|
||||
if (array_key_exists('repoName', $_REQUEST)) {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
}
|
||||
else {
|
||||
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
|
||||
}
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
}
|
||||
else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
$repoDir = 'cache/git/sys/extend/addon/' . $repoName;
|
||||
if (!is_dir($repoDir)) {
|
||||
logger('Repo directory does not exist: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
|
||||
}
|
||||
if (!is_writable($repoDir)) {
|
||||
logger('Repo directory not writable to web server: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
$git = new GitRepo('sys', null, false, $repoName, $repoDir);
|
||||
try {
|
||||
if ($git->pull()) {
|
||||
$files = array_diff(scandir($repoDir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
|
||||
$source = '../extend/addon/' . $repoName . '/' . $file;
|
||||
$target = realpath('addon/') . '/' . $file;
|
||||
unlink($target);
|
||||
if (!symlink($source, $target)) {
|
||||
logger('Error linking addons to /addon');
|
||||
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
json_return_and_die(array('message' => 'Repo updated.', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
|
||||
}
|
||||
} catch (\PHPGit\Exception\GitException $e) {
|
||||
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
|
||||
}
|
||||
case 'removerepo':
|
||||
if (array_key_exists('repoName', $_REQUEST)) {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
|
||||
}
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
$repoDir = 'cache/git/sys/extend/addon/' . $repoName;
|
||||
if (!is_dir($repoDir)) {
|
||||
logger('Repo directory does not exist: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
|
||||
}
|
||||
if (!is_writable($repoDir)) {
|
||||
logger('Repo directory not writable to web server: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
/// @TODO remove directory and unlink /addon/files
|
||||
if (rrmdir($repoDir)) {
|
||||
json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
|
||||
}
|
||||
case 'installrepo':
|
||||
if (array_key_exists('repoURL', $_REQUEST)) {
|
||||
$repoURL = $_REQUEST['repoURL'];
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_writable($extendDir)) {
|
||||
logger('Directory not writable to web server: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
$repoName = null;
|
||||
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
$repoName = GitRepo::getRepoNameFromURL($repoURL);
|
||||
}
|
||||
if (!$repoName) {
|
||||
logger('Invalid git repo');
|
||||
json_return_and_die(array('message' => 'Invalid git repo', 'success' => false));
|
||||
}
|
||||
$repoDir = $addonDir . '/' . $repoName;
|
||||
$tempRepoBaseDir = 'cache/git/sys/temp/';
|
||||
$tempAddonDir = $tempRepoBaseDir . $repoName;
|
||||
goaway(z_root() . '/admin/addons/' . argv(2));
|
||||
} elseif (argc() > 2) {
|
||||
switch (argv(2)) {
|
||||
case 'updaterepo':
|
||||
if (array_key_exists('repoName', $_REQUEST)) {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
|
||||
}
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
$repoDir = 'cache/git/sys/extend/addon/' . $repoName;
|
||||
if (!is_dir($repoDir)) {
|
||||
logger('Repo directory does not exist: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
|
||||
}
|
||||
if (!is_writable($repoDir)) {
|
||||
logger('Repo directory not writable to web server: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
$git = new GitRepo('sys', null, false, $repoName, $repoDir);
|
||||
try {
|
||||
if ($git->pull()) {
|
||||
$files = array_diff(scandir($repoDir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
|
||||
$source = '../extend/addon/' . $repoName . '/' . $file;
|
||||
$target = realpath('addon/') . '/' . $file;
|
||||
unlink($target);
|
||||
if (!symlink($source, $target)) {
|
||||
logger('Error linking addons to /addon');
|
||||
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
json_return_and_die(array('message' => 'Repo updated.', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
|
||||
}
|
||||
} catch (GitException $e) {
|
||||
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
|
||||
}
|
||||
case 'removerepo':
|
||||
if (array_key_exists('repoName', $_REQUEST)) {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
|
||||
}
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
$repoDir = 'cache/git/sys/extend/addon/' . $repoName;
|
||||
if (!is_dir($repoDir)) {
|
||||
logger('Repo directory does not exist: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
|
||||
}
|
||||
if (!is_writable($repoDir)) {
|
||||
logger('Repo directory not writable to web server: ' . $repoDir);
|
||||
json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
/// @TODO remove directory and unlink /addon/files
|
||||
if (rrmdir($repoDir)) {
|
||||
json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
|
||||
}
|
||||
case 'installrepo':
|
||||
if (array_key_exists('repoURL', $_REQUEST)) {
|
||||
$repoURL = $_REQUEST['repoURL'];
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_writable($extendDir)) {
|
||||
logger('Directory not writable to web server: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
$repoName = null;
|
||||
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
$repoName = GitRepo::getRepoNameFromURL($repoURL);
|
||||
}
|
||||
if (!$repoName) {
|
||||
logger('Invalid git repo');
|
||||
json_return_and_die(array('message' => 'Invalid git repo', 'success' => false));
|
||||
}
|
||||
$repoDir = $addonDir . '/' . $repoName;
|
||||
$tempRepoBaseDir = 'cache/git/sys/temp/';
|
||||
$tempAddonDir = $tempRepoBaseDir . $repoName;
|
||||
|
||||
if (!is_writable($addonDir) || !is_writable($tempAddonDir)) {
|
||||
logger('Temp repo directory or /extend/addon not writable to web server: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => 'Temp repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
rename($tempAddonDir, $repoDir);
|
||||
if (!is_writable($addonDir) || !is_writable($tempAddonDir)) {
|
||||
logger('Temp repo directory or /extend/addon not writable to web server: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => 'Temp repo directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
rename($tempAddonDir, $repoDir);
|
||||
|
||||
if (!is_writable(realpath('addon/'))) {
|
||||
logger('/addon directory not writable to web server: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => '/addon directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
$files = array_diff(scandir($repoDir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
|
||||
$source = '../extend/addon/' . $repoName . '/' . $file;
|
||||
$target = realpath('addon/') . '/' . $file;
|
||||
unlink($target);
|
||||
if (!symlink($source, $target)) {
|
||||
logger('Error linking addons to /addon');
|
||||
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
$git = new GitRepo('sys', $repoURL, false, $repoName, $repoDir);
|
||||
$repo = $git->probeRepo();
|
||||
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
|
||||
}
|
||||
case 'addrepo':
|
||||
if (array_key_exists('repoURL', $_REQUEST)) {
|
||||
$repoURL = $_REQUEST['repoURL'];
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
$tempAddonDir = realpath('cache') . '/git/sys/temp';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_dir($tempAddonDir)) {
|
||||
if (!mkdir($tempAddonDir, 0770, true)) {
|
||||
logger('Error creating temp plugin repo folder: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => 'Error creating temp plugin repo folder: ' . $tempAddonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
$repoName = null;
|
||||
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
$repoName = GitRepo::getRepoNameFromURL($repoURL);
|
||||
}
|
||||
if (!$repoName) {
|
||||
logger('Invalid git repo');
|
||||
json_return_and_die(array('message' => 'Invalid git repo: ' . $repoName, 'success' => false));
|
||||
}
|
||||
$repoDir = $tempAddonDir . '/' . $repoName;
|
||||
if (!is_writable($tempAddonDir)) {
|
||||
logger('Temporary directory for new addon repo is not writable to web server: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => 'Temporary directory for new addon repo is not writable to web server.', 'success' => false));
|
||||
}
|
||||
// clone the repo if new automatically
|
||||
$git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
|
||||
if (!is_writable(realpath('addon/'))) {
|
||||
logger('/addon directory not writable to web server: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => '/addon directory not writable to web server.', 'success' => false));
|
||||
}
|
||||
$files = array_diff(scandir($repoDir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
|
||||
$source = '../extend/addon/' . $repoName . '/' . $file;
|
||||
$target = realpath('addon/') . '/' . $file;
|
||||
unlink($target);
|
||||
if (!symlink($source, $target)) {
|
||||
logger('Error linking addons to /addon');
|
||||
json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
$git = new GitRepo('sys', $repoURL, false, $repoName, $repoDir);
|
||||
$repo = $git->probeRepo();
|
||||
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
|
||||
}
|
||||
case 'addrepo':
|
||||
if (array_key_exists('repoURL', $_REQUEST)) {
|
||||
$repoURL = $_REQUEST['repoURL'];
|
||||
$extendDir = 'cache/git/sys/extend';
|
||||
$addonDir = $extendDir . '/addon';
|
||||
$tempAddonDir = realpath('cache') . '/git/sys/temp';
|
||||
if (!file_exists($extendDir)) {
|
||||
if (!mkdir($extendDir, 0770, true)) {
|
||||
logger('Error creating extend folder: ' . $extendDir);
|
||||
json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
|
||||
} else {
|
||||
if (!symlink(realpath('extend/addon'), $addonDir)) {
|
||||
logger('Error creating symlink to addon folder: ' . $addonDir);
|
||||
json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_dir($tempAddonDir)) {
|
||||
if (!mkdir($tempAddonDir, 0770, true)) {
|
||||
logger('Error creating temp plugin repo folder: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => 'Error creating temp plugin repo folder: ' . $tempAddonDir, 'success' => false));
|
||||
}
|
||||
}
|
||||
$repoName = null;
|
||||
if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
|
||||
$repoName = $_REQUEST['repoName'];
|
||||
} else {
|
||||
$repoName = GitRepo::getRepoNameFromURL($repoURL);
|
||||
}
|
||||
if (!$repoName) {
|
||||
logger('Invalid git repo');
|
||||
json_return_and_die(array('message' => 'Invalid git repo: ' . $repoName, 'success' => false));
|
||||
}
|
||||
$repoDir = $tempAddonDir . '/' . $repoName;
|
||||
if (!is_writable($tempAddonDir)) {
|
||||
logger('Temporary directory for new addon repo is not writable to web server: ' . $tempAddonDir);
|
||||
json_return_and_die(array('message' => 'Temporary directory for new addon repo is not writable to web server.', 'success' => false));
|
||||
}
|
||||
// clone the repo if new automatically
|
||||
$git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
|
||||
|
||||
$remotes = $git->git->remote();
|
||||
$fetchURL = $remotes['origin']['fetch'];
|
||||
if ($fetchURL !== $git->url) {
|
||||
if (rrmdir($repoDir)) {
|
||||
$git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error deleting existing addon repo.', 'success' => false));
|
||||
}
|
||||
}
|
||||
$repo = $git->probeRepo();
|
||||
$repo['readme'] = $repo['manifest'] = null;
|
||||
foreach ($git->git->tree('master') as $object) {
|
||||
if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
|
||||
$repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
|
||||
} else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
|
||||
$repo['manifest'] = $git->git->cat->blob($object['hash']);
|
||||
}
|
||||
}
|
||||
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'No repo URL provided', 'success' => false));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$remotes = $git->git->remote();
|
||||
$fetchURL = $remotes['origin']['fetch'];
|
||||
if ($fetchURL !== $git->url) {
|
||||
if (rrmdir($repoDir)) {
|
||||
$git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'Error deleting existing addon repo.', 'success' => false));
|
||||
}
|
||||
}
|
||||
$repo = $git->probeRepo();
|
||||
$repo['readme'] = $repo['manifest'] = null;
|
||||
foreach ($git->git->tree('master') as $object) {
|
||||
if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
|
||||
$repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
|
||||
} elseif ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
|
||||
$repo['manifest'] = $git->git->cat->blob($object['hash']);
|
||||
}
|
||||
}
|
||||
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
|
||||
} else {
|
||||
json_return_and_die(array('message' => 'No repo URL provided', 'success' => false));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Addons admin page.
|
||||
*
|
||||
* @return string with parsed HTML
|
||||
*/
|
||||
function get() {
|
||||
/**
|
||||
* @brief Addons admin page.
|
||||
*
|
||||
* @return string with parsed HTML
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
|
||||
/*
|
||||
* Single plugin
|
||||
*/
|
||||
/*
|
||||
* Single plugin
|
||||
*/
|
||||
|
||||
if (\App::$argc == 3){
|
||||
$plugin = \App::$argv[2];
|
||||
if (!is_file("addon/$plugin/$plugin.php")){
|
||||
notice( t("Item not found.") );
|
||||
return '';
|
||||
}
|
||||
if (App::$argc == 3) {
|
||||
$plugin = App::$argv[2];
|
||||
if (!is_file("addon/$plugin/$plugin.php")) {
|
||||
notice(t("Item not found."));
|
||||
return '';
|
||||
}
|
||||
|
||||
$enabled = in_array($plugin,\App::$plugins);
|
||||
$info = get_plugin_info($plugin);
|
||||
$x = check_plugin_versions($info);
|
||||
$enabled = in_array($plugin, App::$plugins);
|
||||
$info = get_plugin_info($plugin);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
// disable plugins which are installed but incompatible versions
|
||||
// disable plugins which are installed but incompatible versions
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($plugin, \App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(\App::$plugins[$idz]);
|
||||
uninstall_plugin($plugin);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
if ($enabled && !$x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($plugin, App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(App::$plugins[$idz]);
|
||||
uninstall_plugin($plugin);
|
||||
set_config("system", "addon", implode(", ", App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1 - intval($x);
|
||||
|
||||
if (x($_GET,"a") && $_GET['a']=="t"){
|
||||
check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't');
|
||||
$pinstalled = false;
|
||||
// Toggle plugin status
|
||||
$idx = array_search($plugin, \App::$plugins);
|
||||
if ($idx !== false){
|
||||
unset(\App::$plugins[$idx]);
|
||||
uninstall_plugin($plugin);
|
||||
$pinstalled = false;
|
||||
info( sprintf( t("Plugin %s disabled."), $plugin ) );
|
||||
} else {
|
||||
\App::$plugins[] = $plugin;
|
||||
install_plugin($plugin);
|
||||
$pinstalled = true;
|
||||
info( sprintf( t("Plugin %s enabled."), $plugin ) );
|
||||
}
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
if (x($_GET, "a") && $_GET['a'] == "t") {
|
||||
check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't');
|
||||
$pinstalled = false;
|
||||
// Toggle plugin status
|
||||
$idx = array_search($plugin, App::$plugins);
|
||||
if ($idx !== false) {
|
||||
unset(App::$plugins[$idx]);
|
||||
uninstall_plugin($plugin);
|
||||
$pinstalled = false;
|
||||
info(sprintf(t("Plugin %s disabled."), $plugin));
|
||||
} else {
|
||||
App::$plugins[] = $plugin;
|
||||
install_plugin($plugin);
|
||||
$pinstalled = true;
|
||||
info(sprintf(t("Plugin %s enabled."), $plugin));
|
||||
}
|
||||
set_config("system", "addon", implode(", ", App::$plugins));
|
||||
|
||||
if($pinstalled) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
if(function_exists($plugin.'_plugin_admin'))
|
||||
goaway(z_root() . '/admin/addons/' . $plugin);
|
||||
}
|
||||
goaway(z_root() . '/admin/addons' );
|
||||
}
|
||||
if ($pinstalled) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
if (function_exists($plugin . '_plugin_admin')) {
|
||||
goaway(z_root() . '/admin/addons/' . $plugin);
|
||||
}
|
||||
}
|
||||
goaway(z_root() . '/admin/addons');
|
||||
}
|
||||
|
||||
// display plugin details
|
||||
// display plugin details
|
||||
|
||||
if (in_array($plugin, \App::$plugins)){
|
||||
$status = 'on';
|
||||
$action = t('Disable');
|
||||
} else {
|
||||
$status = 'off';
|
||||
$action = t('Enable');
|
||||
}
|
||||
if (in_array($plugin, App::$plugins)) {
|
||||
$status = 'on';
|
||||
$action = t('Disable');
|
||||
} else {
|
||||
$status = 'off';
|
||||
$action = t('Enable');
|
||||
}
|
||||
|
||||
$readme = null;
|
||||
if (is_file("addon/$plugin/README.md")){
|
||||
$readme = file_get_contents("addon/$plugin/README.md");
|
||||
$readme = MarkdownExtra::defaultTransform($readme);
|
||||
} else if (is_file("addon/$plugin/README")){
|
||||
$readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
|
||||
}
|
||||
$readme = null;
|
||||
if (is_file("addon/$plugin/README.md")) {
|
||||
$readme = file_get_contents("addon/$plugin/README.md");
|
||||
$readme = MarkdownExtra::defaultTransform($readme);
|
||||
} elseif (is_file("addon/$plugin/README")) {
|
||||
$readme = "<pre>" . file_get_contents("addon/$plugin/README") . "</pre>";
|
||||
}
|
||||
|
||||
$admin_form = '';
|
||||
$admin_form = '';
|
||||
|
||||
$r = q("select * from addon where plugin_admin = 1 and aname = '%s' limit 1",
|
||||
dbesc($plugin)
|
||||
);
|
||||
$r = q(
|
||||
"select * from addon where plugin_admin = 1 and aname = '%s' limit 1",
|
||||
dbesc($plugin)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
if(function_exists($plugin.'_plugin_admin')) {
|
||||
$func = $plugin.'_plugin_admin';
|
||||
$func($a, $admin_form);
|
||||
}
|
||||
}
|
||||
if ($r) {
|
||||
@require_once("addon/$plugin/$plugin.php");
|
||||
if (function_exists($plugin . '_plugin_admin')) {
|
||||
$func = $plugin . '_plugin_admin';
|
||||
$func($a, $admin_form);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$t = get_markup_template('admin_plugins_details.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Addons'),
|
||||
'$toggle' => t('Toggle'),
|
||||
'$settings' => t('Settings'),
|
||||
'$baseurl' => z_root(),
|
||||
$t = get_markup_template('admin_plugins_details.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Addons'),
|
||||
'$toggle' => t('Toggle'),
|
||||
'$settings' => t('Settings'),
|
||||
'$baseurl' => z_root(),
|
||||
|
||||
'$plugin' => $plugin,
|
||||
'$status' => $status,
|
||||
'$action' => $action,
|
||||
'$info' => $info,
|
||||
'$str_author' => t('Author: '),
|
||||
'$str_maintainer' => t('Maintainer: '),
|
||||
'$str_minversion' => t('Minimum project version: '),
|
||||
'$str_maxversion' => t('Maximum project version: '),
|
||||
'$str_minphpversion' => t('Minimum PHP version: '),
|
||||
'$str_serverroles' => t('Compatible Server Roles: '),
|
||||
'$str_requires' => t('Requires: '),
|
||||
'$disabled' => t('Disabled - version incompatibility'),
|
||||
'$plugin' => $plugin,
|
||||
'$status' => $status,
|
||||
'$action' => $action,
|
||||
'$info' => $info,
|
||||
'$str_author' => t('Author: '),
|
||||
'$str_maintainer' => t('Maintainer: '),
|
||||
'$str_minversion' => t('Minimum project version: '),
|
||||
'$str_maxversion' => t('Maximum project version: '),
|
||||
'$str_minphpversion' => t('Minimum PHP version: '),
|
||||
'$str_serverroles' => t('Compatible Server Roles: '),
|
||||
'$str_requires' => t('Requires: '),
|
||||
'$disabled' => t('Disabled - version incompatibility'),
|
||||
|
||||
'$admin_form' => $admin_form,
|
||||
'$function' => 'addons',
|
||||
'$screenshot' => '',
|
||||
'$readme' => $readme,
|
||||
'$admin_form' => $admin_form,
|
||||
'$function' => 'addons',
|
||||
'$screenshot' => '',
|
||||
'$readme' => $readme,
|
||||
|
||||
'$form_security_token' => get_form_security_token('admin_addons'),
|
||||
));
|
||||
}
|
||||
'$form_security_token' => get_form_security_token('admin_addons'),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* List plugins
|
||||
*/
|
||||
$plugins = [];
|
||||
$files = glob('addon/*/');
|
||||
if($files) {
|
||||
foreach($files as $file) {
|
||||
if ($file === 'addon/vendor/') {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($file)){
|
||||
list($tmp, $id) = array_map('trim', explode('/', $file));
|
||||
$info = get_plugin_info($id);
|
||||
$enabled = in_array($id,\App::$plugins);
|
||||
$x = check_plugin_versions($info);
|
||||
/*
|
||||
* List plugins
|
||||
*/
|
||||
$plugins = [];
|
||||
$files = glob('addon/*/');
|
||||
if ($files) {
|
||||
foreach ($files as $file) {
|
||||
if ($file === 'addon/vendor/') {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($file)) {
|
||||
list($tmp, $id) = array_map('trim', explode('/', $file));
|
||||
$info = get_plugin_info($id);
|
||||
$enabled = in_array($id, App::$plugins);
|
||||
$x = check_plugin_versions($info);
|
||||
|
||||
// disable plugins which are installed but incompatible versions
|
||||
// disable plugins which are installed but incompatible versions
|
||||
|
||||
if($enabled && ! $x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($id, \App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(\App::$plugins[$idz]);
|
||||
uninstall_plugin($id);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1-intval($x);
|
||||
if ($enabled && !$x) {
|
||||
$enabled = false;
|
||||
$idz = array_search($id, App::$plugins);
|
||||
if ($idz !== false) {
|
||||
unset(App::$plugins[$idz]);
|
||||
uninstall_plugin($id);
|
||||
set_config("system", "addon", implode(", ", App::$plugins));
|
||||
}
|
||||
}
|
||||
$info['disabled'] = 1 - intval($x);
|
||||
|
||||
$plugins[] = array( $id, (($enabled)?"on":"off") , $info);
|
||||
}
|
||||
}
|
||||
}
|
||||
$plugins[] = array($id, (($enabled) ? "on" : "off"), $info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usort($plugins,'self::plugin_sort');
|
||||
usort($plugins, 'self::plugin_sort');
|
||||
|
||||
$allowManageRepos = false;
|
||||
if(is_writable('extend/addon') && is_writable('cache')) {
|
||||
$allowManageRepos = true;
|
||||
}
|
||||
$allowManageRepos = false;
|
||||
if (is_writable('extend/addon') && is_writable('cache')) {
|
||||
$allowManageRepos = true;
|
||||
}
|
||||
|
||||
$admin_plugins_add_repo_form= replace_macros(
|
||||
get_markup_template('admin_plugins_addrepo.tpl'), array(
|
||||
'$post' => 'admin/addons/addrepo',
|
||||
'$desc' => t('Enter the public git repository URL of the addon repo.'),
|
||||
'$repoURL' => array('repoURL', t('Addon repo git URL'), '', ''),
|
||||
'$repoName' => array('repoName', t('Custom repo name'), '', '', t('(optional)')),
|
||||
'$submit' => t('Download Addon Repo')
|
||||
)
|
||||
);
|
||||
$newRepoModalID = random_string(3);
|
||||
$newRepoModal = replace_macros(
|
||||
get_markup_template('generic_modal.tpl'), array(
|
||||
'$id' => $newRepoModalID,
|
||||
'$title' => t('Install new repo'),
|
||||
'$ok' => t('Install'),
|
||||
'$cancel' => t('Cancel')
|
||||
)
|
||||
);
|
||||
$admin_plugins_add_repo_form = replace_macros(
|
||||
get_markup_template('admin_plugins_addrepo.tpl'),
|
||||
array(
|
||||
'$post' => 'admin/addons/addrepo',
|
||||
'$desc' => t('Enter the public git repository URL of the addon repo.'),
|
||||
'$repoURL' => array('repoURL', t('Addon repo git URL'), '', ''),
|
||||
'$repoName' => array('repoName', t('Custom repo name'), '', '', t('(optional)')),
|
||||
'$submit' => t('Download Addon Repo')
|
||||
)
|
||||
);
|
||||
$newRepoModalID = random_string(3);
|
||||
$newRepoModal = replace_macros(
|
||||
get_markup_template('generic_modal.tpl'),
|
||||
array(
|
||||
'$id' => $newRepoModalID,
|
||||
'$title' => t('Install new repo'),
|
||||
'$ok' => t('Install'),
|
||||
'$cancel' => t('Cancel')
|
||||
)
|
||||
);
|
||||
|
||||
$reponames = $this->listAddonRepos();
|
||||
$addonrepos = [];
|
||||
foreach($reponames as $repo) {
|
||||
$addonrepos[] = array('name' => $repo, 'description' => '');
|
||||
/// @TODO Parse repo info to provide more information about repos
|
||||
}
|
||||
$reponames = $this->listAddonRepos();
|
||||
$addonrepos = [];
|
||||
foreach ($reponames as $repo) {
|
||||
$addonrepos[] = array('name' => $repo, 'description' => '');
|
||||
/// @TODO Parse repo info to provide more information about repos
|
||||
}
|
||||
|
||||
$t = get_markup_template('admin_plugins.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Addons'),
|
||||
'$submit' => t('Submit'),
|
||||
'$baseurl' => z_root(),
|
||||
'$function' => 'addons',
|
||||
'$plugins' => $plugins,
|
||||
'$disabled' => t('Disabled - version incompatibility'),
|
||||
'$form_security_token' => get_form_security_token('admin_addons'),
|
||||
'$allowManageRepos' => $allowManageRepos,
|
||||
'$managerepos' => t('Manage Repos'),
|
||||
'$installedtitle' => t('Installed Addon Repositories'),
|
||||
'$addnewrepotitle' => t('Install a New Addon Repository'),
|
||||
'$expandform' => false,
|
||||
'$form' => $admin_plugins_add_repo_form,
|
||||
'$newRepoModal' => $newRepoModal,
|
||||
'$newRepoModalID' => $newRepoModalID,
|
||||
'$addonrepos' => $addonrepos,
|
||||
'$repoUpdateButton' => t('Update'),
|
||||
'$repoBranchButton' => t('Switch branch'),
|
||||
'$repoRemoveButton' => t('Remove')
|
||||
));
|
||||
}
|
||||
$t = get_markup_template('admin_plugins.tpl');
|
||||
return replace_macros($t, array(
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Addons'),
|
||||
'$submit' => t('Submit'),
|
||||
'$baseurl' => z_root(),
|
||||
'$function' => 'addons',
|
||||
'$plugins' => $plugins,
|
||||
'$disabled' => t('Disabled - version incompatibility'),
|
||||
'$form_security_token' => get_form_security_token('admin_addons'),
|
||||
'$allowManageRepos' => $allowManageRepos,
|
||||
'$managerepos' => t('Manage Repos'),
|
||||
'$installedtitle' => t('Installed Addon Repositories'),
|
||||
'$addnewrepotitle' => t('Install a New Addon Repository'),
|
||||
'$expandform' => false,
|
||||
'$form' => $admin_plugins_add_repo_form,
|
||||
'$newRepoModal' => $newRepoModal,
|
||||
'$newRepoModalID' => $newRepoModalID,
|
||||
'$addonrepos' => $addonrepos,
|
||||
'$repoUpdateButton' => t('Update'),
|
||||
'$repoBranchButton' => t('Switch branch'),
|
||||
'$repoRemoveButton' => t('Remove')
|
||||
));
|
||||
}
|
||||
|
||||
function listAddonRepos() {
|
||||
$addonrepos = [];
|
||||
$addonDir = 'extend/addon/';
|
||||
if(is_dir($addonDir)) {
|
||||
if ($handle = opendir($addonDir)) {
|
||||
while (false !== ($entry = readdir($handle))) {
|
||||
if ($entry != "." && $entry != "..") {
|
||||
$addonrepos[] = $entry;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
}
|
||||
return $addonrepos;
|
||||
}
|
||||
|
||||
static public function plugin_sort($a,$b) {
|
||||
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
|
||||
}
|
||||
public function listAddonRepos()
|
||||
{
|
||||
$addonrepos = [];
|
||||
$addonDir = 'extend/addon/';
|
||||
if (is_dir($addonDir)) {
|
||||
if ($handle = opendir($addonDir)) {
|
||||
while (false !== ($entry = readdir($handle))) {
|
||||
if ($entry != "." && $entry != "..") {
|
||||
$addonrepos[] = $entry;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
}
|
||||
return $addonrepos;
|
||||
}
|
||||
|
||||
public static function plugin_sort($a, $b)
|
||||
{
|
||||
return (strcmp(strtolower($a[2]['name']), strtolower($b[2]['name'])));
|
||||
}
|
||||
}
|
|
@ -9,175 +9,191 @@ use Zotlabs\Daemon\Run;
|
|||
* @brief Admin Module for Channels.
|
||||
*
|
||||
*/
|
||||
class Channels
|
||||
{
|
||||
|
||||
class Channels {
|
||||
/**
|
||||
* @brief Handle POST actions on channels admin page.
|
||||
*
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Handle POST actions on channels admin page.
|
||||
*
|
||||
*/
|
||||
function post() {
|
||||
$channels = (x($_POST, 'channel') ? $_POST['channel'] : array());
|
||||
|
||||
$channels = ( x($_POST, 'channel') ? $_POST['channel'] : Array() );
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels');
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels');
|
||||
$xor = db_getfunc('^');
|
||||
|
||||
$xor = db_getfunc('^');
|
||||
if (x($_POST, 'page_channels_block')) {
|
||||
foreach ($channels as $uid) {
|
||||
q(
|
||||
"UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
|
||||
intval(PAGE_CENSORED),
|
||||
intval($uid)
|
||||
);
|
||||
Run::Summon(['Directory', $uid, 'nopush']);
|
||||
}
|
||||
notice(sprintf(tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)));
|
||||
}
|
||||
if (x($_POST, 'page_channels_code')) {
|
||||
foreach ($channels as $uid) {
|
||||
q(
|
||||
"UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
|
||||
intval(PAGE_ALLOWCODE),
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
notice(sprintf(tt("%s channel code allowed/disallowed", "%s channels code allowed/disallowed", count($channels)), count($channels)));
|
||||
}
|
||||
if (x($_POST, 'page_channels_delete')) {
|
||||
foreach ($channels as $uid) {
|
||||
channel_remove($uid, true);
|
||||
}
|
||||
notice(sprintf(tt("%s channel deleted", "%s channels deleted", count($channels)), count($channels)));
|
||||
}
|
||||
|
||||
if(x($_POST, 'page_channels_block')) {
|
||||
foreach($channels as $uid) {
|
||||
q("UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
|
||||
intval(PAGE_CENSORED),
|
||||
intval( $uid )
|
||||
);
|
||||
Run::Summon( [ 'Directory', $uid, 'nopush' ] );
|
||||
}
|
||||
notice( sprintf( tt("%s channel censored/uncensored", "%s channels censored/uncensored", count($channels)), count($channels)) );
|
||||
}
|
||||
if(x($_POST, 'page_channels_code')) {
|
||||
foreach($channels as $uid) {
|
||||
q("UPDATE channel SET channel_pageflags = ( channel_pageflags $xor %d ) where channel_id = %d",
|
||||
intval(PAGE_ALLOWCODE),
|
||||
intval( $uid )
|
||||
);
|
||||
}
|
||||
notice( sprintf( tt("%s channel code allowed/disallowed", "%s channels code allowed/disallowed", count($channels)), count($channels)) );
|
||||
}
|
||||
if(x($_POST, 'page_channels_delete')) {
|
||||
foreach($channels as $uid) {
|
||||
channel_remove($uid, true);
|
||||
}
|
||||
notice( sprintf( tt("%s channel deleted", "%s channels deleted", count($channels)), count($channels)) );
|
||||
}
|
||||
goaway(z_root() . '/admin/channels');
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin/channels' );
|
||||
}
|
||||
/**
|
||||
* @brief Generate channels admin page and handle single item operations.
|
||||
*
|
||||
* @return string with parsed HTML
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
if (argc() > 2) {
|
||||
$uid = argv(3);
|
||||
$channel = q(
|
||||
"SELECT * FROM channel WHERE channel_id = %d",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Generate channels admin page and handle single item operations.
|
||||
*
|
||||
* @return string with parsed HTML
|
||||
*/
|
||||
function get() {
|
||||
if(argc() > 2) {
|
||||
$uid = argv(3);
|
||||
$channel = q("SELECT * FROM channel WHERE channel_id = %d",
|
||||
intval($uid)
|
||||
);
|
||||
if (!$channel) {
|
||||
notice(t('Channel not found') . EOL);
|
||||
goaway(z_root() . '/admin/channels');
|
||||
}
|
||||
|
||||
if(! $channel) {
|
||||
notice( t('Channel not found') . EOL);
|
||||
goaway(z_root() . '/admin/channels' );
|
||||
}
|
||||
switch (argv(2)) {
|
||||
case "delete":
|
||||
{
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
|
||||
// delete channel
|
||||
channel_remove($uid, true);
|
||||
|
||||
switch(argv(2)) {
|
||||
case "delete":{
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
|
||||
// delete channel
|
||||
channel_remove($uid,true);
|
||||
notice(sprintf(t("Channel '%s' deleted"), $channel[0]['channel_name']) . EOL);
|
||||
}
|
||||
break;
|
||||
|
||||
notice( sprintf(t("Channel '%s' deleted"), $channel[0]['channel_name']) . EOL);
|
||||
}; break;
|
||||
case "block":
|
||||
{
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
|
||||
$pflags = $channel[0]['channel_pageflags'] ^ PAGE_CENSORED;
|
||||
q(
|
||||
"UPDATE channel SET channel_pageflags = %d where channel_id = %d",
|
||||
intval($pflags),
|
||||
intval($uid)
|
||||
);
|
||||
Run::Summon(['Directory', $uid, 'nopush']);
|
||||
|
||||
case "block":{
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
|
||||
$pflags = $channel[0]['channel_pageflags'] ^ PAGE_CENSORED;
|
||||
q("UPDATE channel SET channel_pageflags = %d where channel_id = %d",
|
||||
intval($pflags),
|
||||
intval( $uid )
|
||||
);
|
||||
Run::Summon( [ 'Directory', $uid, 'nopush' ]);
|
||||
notice(sprintf((($pflags & PAGE_CENSORED) ? t("Channel '%s' censored") : t("Channel '%s' uncensored")), $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')') . EOL);
|
||||
}
|
||||
break;
|
||||
|
||||
notice( sprintf( (($pflags & PAGE_CENSORED) ? t("Channel '%s' censored"): t("Channel '%s' uncensored")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
|
||||
}; break;
|
||||
case "code":
|
||||
{
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
|
||||
$pflags = $channel[0]['channel_pageflags'] ^ PAGE_ALLOWCODE;
|
||||
q(
|
||||
"UPDATE channel SET channel_pageflags = %d where channel_id = %d",
|
||||
intval($pflags),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
case "code":{
|
||||
check_form_security_token_redirectOnErr('/admin/channels', 'admin_channels', 't');
|
||||
$pflags = $channel[0]['channel_pageflags'] ^ PAGE_ALLOWCODE;
|
||||
q("UPDATE channel SET channel_pageflags = %d where channel_id = %d",
|
||||
intval($pflags),
|
||||
intval( $uid )
|
||||
);
|
||||
notice(sprintf((($pflags & PAGE_ALLOWCODE) ? t("Channel '%s' code allowed") : t("Channel '%s' code disallowed")), $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')') . EOL);
|
||||
}
|
||||
break;
|
||||
|
||||
notice( sprintf( (($pflags & PAGE_ALLOWCODE) ? t("Channel '%s' code allowed"): t("Channel '%s' code disallowed")) , $channel[0]['channel_name'] . ' (' . $channel[0]['channel_address'] . ')' ) . EOL);
|
||||
}; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
goaway(z_root() . '/admin/channels');
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
goaway(z_root() . '/admin/channels' );
|
||||
}
|
||||
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
|
||||
$dir = 'asc';
|
||||
if (array_key_exists('dir', $_REQUEST)) {
|
||||
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
|
||||
}
|
||||
|
||||
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
|
||||
$dir = 'asc';
|
||||
if(array_key_exists('dir',$_REQUEST))
|
||||
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
|
||||
$base = z_root() . '/admin/channels?f=';
|
||||
$odir = (($dir === 'asc') ? '0' : '1');
|
||||
|
||||
$base = z_root() . '/admin/channels?f=';
|
||||
$odir = (($dir === 'asc') ? '0' : '1');
|
||||
/* get channels */
|
||||
|
||||
/* get channels */
|
||||
$total = q("SELECT count(*) as total FROM channel where channel_removed = 0 and channel_system = 0");
|
||||
if ($total) {
|
||||
App::set_pager_total($total[0]['total']);
|
||||
App::set_pager_itemspage(100);
|
||||
}
|
||||
|
||||
$total = q("SELECT count(*) as total FROM channel where channel_removed = 0 and channel_system = 0");
|
||||
if($total) {
|
||||
App::set_pager_total($total[0]['total']);
|
||||
App::set_pager_itemspage(100);
|
||||
}
|
||||
$channels = q(
|
||||
"SELECT * from channel where channel_removed = 0 and channel_system = 0 order by $key $dir limit %d offset %d ",
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
);
|
||||
|
||||
$channels = q("SELECT * from channel where channel_removed = 0 and channel_system = 0 order by $key $dir limit %d offset %d ",
|
||||
intval(App::$pager['itemspage']),
|
||||
intval(App::$pager['start'])
|
||||
);
|
||||
if ($channels) {
|
||||
for ($x = 0; $x < count($channels); $x++) {
|
||||
if ($channels[$x]['channel_pageflags'] & PAGE_CENSORED) {
|
||||
$channels[$x]['blocked'] = true;
|
||||
} else {
|
||||
$channels[$x]['blocked'] = false;
|
||||
}
|
||||
|
||||
if($channels) {
|
||||
for($x = 0; $x < count($channels); $x ++) {
|
||||
if($channels[$x]['channel_pageflags'] & PAGE_CENSORED)
|
||||
$channels[$x]['blocked'] = true;
|
||||
else
|
||||
$channels[$x]['blocked'] = false;
|
||||
if ($channels[$x]['channel_pageflags'] & PAGE_ALLOWCODE) {
|
||||
$channels[$x]['allowcode'] = true;
|
||||
} else {
|
||||
$channels[$x]['allowcode'] = false;
|
||||
}
|
||||
|
||||
if($channels[$x]['channel_pageflags'] & PAGE_ALLOWCODE)
|
||||
$channels[$x]['allowcode'] = true;
|
||||
else
|
||||
$channels[$x]['allowcode'] = false;
|
||||
$channels[$x]['channel_link'] = z_root() . '/channel/' . $channels[$x]['channel_address'];
|
||||
}
|
||||
}
|
||||
|
||||
$channels[$x]['channel_link'] = z_root() . '/channel/' . $channels[$x]['channel_address'];
|
||||
}
|
||||
}
|
||||
call_hooks('admin_channels', $channels);
|
||||
|
||||
call_hooks('admin_channels',$channels);
|
||||
$o = replace_macros(get_markup_template('admin_channels.tpl'), [
|
||||
// strings //
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Channels'),
|
||||
'$submit' => t('Submit'),
|
||||
'$select_all' => t('select all'),
|
||||
'$delete' => t('Delete'),
|
||||
'$block' => t('Censor'),
|
||||
'$unblock' => t('Uncensor'),
|
||||
'$code' => t('Allow Code'),
|
||||
'$uncode' => t('Disallow Code'),
|
||||
'$h_channels' => t('Channel'),
|
||||
'$base' => $base,
|
||||
'$odir' => $odir,
|
||||
'$th_channels' => array(
|
||||
[t('UID'), 'channel_id'],
|
||||
[t('Name'), 'channel_name'],
|
||||
[t('Address'), 'channel_address']),
|
||||
|
||||
$o = replace_macros(get_markup_template('admin_channels.tpl'), [
|
||||
// strings //
|
||||
'$title' => t('Administration'),
|
||||
'$page' => t('Channels'),
|
||||
'$submit' => t('Submit'),
|
||||
'$select_all' => t('select all'),
|
||||
'$delete' => t('Delete'),
|
||||
'$block' => t('Censor'),
|
||||
'$unblock' => t('Uncensor'),
|
||||
'$code' => t('Allow Code'),
|
||||
'$uncode' => t('Disallow Code'),
|
||||
'$h_channels' => t('Channel'),
|
||||
'$base' => $base,
|
||||
'$odir' => $odir,
|
||||
'$th_channels' => array(
|
||||
[ t('UID'), 'channel_id' ],
|
||||
[ t('Name'), 'channel_name' ],
|
||||
[ t('Address'), 'channel_address' ]),
|
||||
'$confirm_delete_multi' => t('Selected channels will be deleted!\n\nEverything that was posted in these channels on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$confirm_delete' => t('The channel {0} will be deleted!\n\nEverything that was posted in this channel on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
|
||||
'$confirm_delete_multi' => t('Selected channels will be deleted!\n\nEverything that was posted in these channels on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$confirm_delete' => t('The channel {0} will be deleted!\n\nEverything that was posted in this channel on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$form_security_token' => get_form_security_token('admin_channels'),
|
||||
|
||||
'$form_security_token' => get_form_security_token('admin_channels'),
|
||||
|
||||
// values //
|
||||
'$baseurl' => z_root(),
|
||||
'$channels' => $channels,
|
||||
]);
|
||||
$o .= paginate($a);
|
||||
|
||||
return $o;
|
||||
}
|
||||
// values //
|
||||
'$baseurl' => z_root(),
|
||||
'$channels' => $channels,
|
||||
]);
|
||||
$o .= paginate($a);
|
||||
|
||||
return $o;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Zotlabs\Module\Admin;
|
||||
|
||||
use App;
|
||||
|
@ -25,422 +26,419 @@ require_once('include/photos.php');
|
|||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
class Cover_photo {
|
||||
|
||||
function init() {
|
||||
if (! is_site_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = get_sys_channel();
|
||||
Libprofile::load($channel['channel_address']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluate posted values
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
function post() {
|
||||
|
||||
if (! is_site_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = get_sys_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/cover_photo', 'cover_photo');
|
||||
|
||||
if ((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
|
||||
|
||||
// phase 2 - we have finished cropping
|
||||
|
||||
if (argc() != 3) {
|
||||
notice( t('Image uploaded but image cropping failed.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
$image_id = argv(2);
|
||||
|
||||
if (substr($image_id,-2,1) == '-') {
|
||||
$scale = substr($image_id,-1,1);
|
||||
$image_id = substr($image_id,0,-2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
$srcX = intval($_POST['xstart']);
|
||||
$srcY = intval($_POST['ystart']);
|
||||
$srcW = intval($_POST['xfinal']) - $srcX;
|
||||
$srcH = intval($_POST['yfinal']) - $srcY;
|
||||
|
||||
$r = q("select gender from profile where uid = %d and is_default = 1 limit 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if ($r) {
|
||||
$profile = array_shift($r);
|
||||
}
|
||||
|
||||
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale > 0 order by imgscale asc LIMIT 1",
|
||||
dbesc($image_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
|
||||
$max_thumb = intval(get_config('system','max_thumbnail',1600));
|
||||
$iscaled = false;
|
||||
if (intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) {
|
||||
$imagick_path = get_config('system','imagick_convert_path');
|
||||
if ($imagick_path && @file_exists($imagick_path) && intval($r[0]['os_storage'])) {
|
||||
|
||||
$fname = dbunescbin($r[0]['content']);
|
||||
$tmp_name = $fname . '-001';
|
||||
$newsize = photo_calculate_scale(array_merge(getimagesize($fname),['max' => $max_thumb]));
|
||||
$cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $fname) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name);
|
||||
// logger('imagick thumbnail command: ' . $cmd);
|
||||
for ($x = 0; $x < 4; $x ++) {
|
||||
exec($cmd);
|
||||
if (file_exists($tmp_name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (file_exists($tmp_name)) {
|
||||
$base_image = $r[0];
|
||||
$gis = getimagesize($tmp_name);
|
||||
logger('gis: ' . print_r($gis,true));
|
||||
$base_image['width'] = $gis[0];
|
||||
$base_image['height'] = $gis[1];
|
||||
$base_image['content'] = @file_get_contents($tmp_name);
|
||||
$iscaled = true;
|
||||
@unlink($tmp_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! $iscaled) {
|
||||
$base_image = $r[0];
|
||||
$base_image['content'] = (($base_image['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
|
||||
}
|
||||
|
||||
$im = photo_factory($base_image['content'], $base_image['mimetype']);
|
||||
if ($im->is_valid()) {
|
||||
|
||||
// We are scaling and cropping the relative pixel locations to the original photo instead of the
|
||||
// scaled photo we operated on.
|
||||
|
||||
// First load the scaled photo to check its size. (Should probably pass this in the post form and save
|
||||
// a query.)
|
||||
|
||||
$g = q("select width, height from photo where resource_id = '%s' and uid = %d and imgscale = 3",
|
||||
dbesc($image_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
|
||||
$scaled_width = $g[0]['width'];
|
||||
$scaled_height = $g[0]['height'];
|
||||
|
||||
if ((! $scaled_width) || (! $scaled_height)) {
|
||||
logger('potential divide by zero scaling cover photo');
|
||||
return;
|
||||
}
|
||||
|
||||
// unset all other cover photos
|
||||
|
||||
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_COVER),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
$orig_srcx = ( $base_image['width'] / $scaled_width ) * $srcX;
|
||||
$orig_srcy = ( $base_image['height'] / $scaled_height ) * $srcY;
|
||||
$orig_srcw = ( $srcW / $scaled_width ) * $base_image['width'];
|
||||
$orig_srch = ( $srcH / $scaled_height ) * $base_image['height'];
|
||||
|
||||
$im->cropImageRect(1200,435,$orig_srcx, $orig_srcy, $orig_srcw, $orig_srch);
|
||||
|
||||
$aid = get_account_id();
|
||||
|
||||
$p = [
|
||||
'aid' => 0,
|
||||
'uid' => $channel['channel_id'],
|
||||
'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Cover Photos'),
|
||||
'os_path' => $base_image['os_path'],
|
||||
'display_path' => $base_image['display_path'],
|
||||
'created' => $base_image['created'],
|
||||
'edited' => $base_image['edited']
|
||||
];
|
||||
|
||||
$p['imgscale'] = 7;
|
||||
$p['photo_usage'] = PHOTO_COVER;
|
||||
|
||||
$r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
|
||||
|
||||
$im->doScaleImage(850,310);
|
||||
$p['imgscale'] = 8;
|
||||
|
||||
$r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
|
||||
|
||||
$im->doScaleImage(425,160);
|
||||
$p['imgscale'] = 9;
|
||||
|
||||
$r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
|
||||
|
||||
if ($r1 === false || $r2 === false || $r3 === false) {
|
||||
// if one failed, delete them all so we can start over.
|
||||
notice( t('Image resize failed.') . EOL );
|
||||
$x = q("delete from photo where resource_id = '%s' and uid = %d and imgscale >= 7 ",
|
||||
dbesc($base_image['resource_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
notice( t('Unable to process image') . EOL);
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin');
|
||||
|
||||
}
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$smallest = 0;
|
||||
|
||||
$matches = [];
|
||||
$partial = false;
|
||||
|
||||
if (array_key_exists('HTTP_CONTENT_RANGE',$_SERVER)) {
|
||||
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/',$_SERVER['HTTP_CONTENT_RANGE'],$matches);
|
||||
if ($pm) {
|
||||
logger('Content-Range: ' . print_r($matches,true));
|
||||
$partial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($partial) {
|
||||
$x = save_chunk($channel,$matches[1],$matches[2],$matches[3]);
|
||||
|
||||
if ($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
json_return_and_die($x);
|
||||
}
|
||||
else {
|
||||
header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
|
||||
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $x['name'],
|
||||
'type' => $x['type'],
|
||||
'tmp_name' => $x['tmp_name'],
|
||||
'error' => $x['error'],
|
||||
'size' => $x['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (! array_key_exists('userfile',$_FILES)) {
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $_FILES['files']['name'],
|
||||
'type' => $_FILES['files']['type'],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'],
|
||||
'error' => $_FILES['files']['error'],
|
||||
'size' => $_FILES['files']['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$res = attach_store($channel, $channel['channel_hash'], '', array('album' => t('Cover Photos'), 'hash' => $hash));
|
||||
|
||||
logger('attach_store: ' . print_r($res,true),LOGGER_DEBUG);
|
||||
|
||||
json_return_and_die([ 'message' => $hash ]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate content of profile-photo view
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function get() {
|
||||
|
||||
if (! is_site_admin()) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = get_sys_channel();
|
||||
|
||||
$newuser = false;
|
||||
|
||||
if (argc() == 3 && argv(1) === 'new')
|
||||
$newuser = true;
|
||||
|
||||
|
||||
if (argv(2) === 'reset') {
|
||||
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_COVER),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
|
||||
if (argv(2) === 'use') {
|
||||
if (argc() < 4) {
|
||||
notice( t('Permission denied.') . EOL );
|
||||
return;
|
||||
};
|
||||
|
||||
// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
||||
|
||||
$resource_id = argv(3);
|
||||
|
||||
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and imgscale > 0 ORDER BY imgscale ASC",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if (! $r) {
|
||||
notice( t('Photo not available.') . EOL );
|
||||
return;
|
||||
}
|
||||
$havescale = false;
|
||||
foreach ($r as $rr) {
|
||||
if ($rr['imgscale'] == 7) {
|
||||
$havescale = true;
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
|
||||
intval($r[0]['id']),
|
||||
intval($channel['channel_id'])
|
||||
|
||||
);
|
||||
if (! $r) {
|
||||
notice( t('Photo not available.') . EOL );
|
||||
return;
|
||||
}
|
||||
|
||||
if (intval($r[0]['os_storage'])) {
|
||||
$data = @file_get_contents(dbunescbin($r[0]['content']));
|
||||
}
|
||||
else {
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
}
|
||||
|
||||
$ph = photo_factory($data, $r[0]['mimetype']);
|
||||
$smallest = 0;
|
||||
if ($ph->is_valid()) {
|
||||
// go ahead as if we have just uploaded a new photo to crop
|
||||
$i = q("select resource_id, imgscale from photo where resource_id = '%s' and uid = %d and imgscale = 0",
|
||||
dbesc($r[0]['resource_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if ($i) {
|
||||
$hash = $i[0]['resource_id'];
|
||||
foreach ($i as $ii) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->cover_photo_crop_ui_head($ph, $hash, $smallest);
|
||||
}
|
||||
|
||||
|
||||
if(! array_key_exists('imagecrop',App::$data)) {
|
||||
|
||||
$o .= replace_macros(get_markup_template('admin_cover_photo.tpl'), [
|
||||
'$user' => $channel['channel_address'],
|
||||
'$channel_id' => $channel['channel_id'],
|
||||
'$info' => t('Your cover photo may be visible to anybody on the internet'),
|
||||
'$existing' => get_cover_photo($channel['channel_id'],'array',PHOTO_RES_COVER_850),
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => t('Change Cover Photo'),
|
||||
'$submit' => t('Upload'),
|
||||
'$profiles' => $profiles,
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalCancel' => t('Cancel'),
|
||||
'$embedPhotosModalOK' => t('OK'),
|
||||
'$modalchooseimages' => t('Choose images to embed'),
|
||||
'$modalchoosealbum' => t('Choose an album'),
|
||||
'$modaldiffalbum' => t('Choose a different album'),
|
||||
'$modalerrorlist' => t('Error getting album list'),
|
||||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
'$select' => t('Select previously uploaded photo'),
|
||||
|
||||
]);
|
||||
|
||||
call_hooks('cover_photo_content_end', $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
else {
|
||||
$filename = App::$data['imagecrop'] . '-3';
|
||||
$resolution = 3;
|
||||
|
||||
$o .= replace_macros(get_markup_template('admin_cropcover.tpl'), [
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => \App::$data['imagecrop'] . '-3',
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
'$done' => t('Done Editing')
|
||||
]);
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
/* @brief Generate the UI for photo-cropping
|
||||
*
|
||||
* @param $a Current application
|
||||
* @param $ph Photo-Factory
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
function cover_photo_crop_ui_head($ph, $hash, $smallest){
|
||||
|
||||
$max_length = get_config('system','max_image_length', MAX_IMAGE_LENGTH);
|
||||
|
||||
if ($max_length > 0) {
|
||||
$ph->scaleImage($max_length);
|
||||
}
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
|
||||
if ($width < 300 || $height < 300) {
|
||||
$ph->scaleImageUp(240);
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
}
|
||||
|
||||
|
||||
App::$data['imagecrop'] = $hash;
|
||||
App::$data['imagecrop_resolution'] = $smallest;
|
||||
App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
class Cover_photo
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
if (!is_site_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = get_sys_channel();
|
||||
Libprofile::load($channel['channel_address']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Evaluate posted values
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
public function post()
|
||||
{
|
||||
|
||||
if (!is_site_admin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = get_sys_channel();
|
||||
|
||||
check_form_security_token_redirectOnErr('/admin/cover_photo', 'cover_photo');
|
||||
|
||||
if ((array_key_exists('cropfinal', $_POST)) && ($_POST['cropfinal'] == 1)) {
|
||||
// phase 2 - we have finished cropping
|
||||
|
||||
if (argc() != 3) {
|
||||
notice(t('Image uploaded but image cropping failed.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$image_id = argv(2);
|
||||
|
||||
if (substr($image_id, -2, 1) == '-') {
|
||||
$scale = substr($image_id, -1, 1);
|
||||
$image_id = substr($image_id, 0, -2);
|
||||
}
|
||||
|
||||
|
||||
$srcX = intval($_POST['xstart']);
|
||||
$srcY = intval($_POST['ystart']);
|
||||
$srcW = intval($_POST['xfinal']) - $srcX;
|
||||
$srcH = intval($_POST['yfinal']) - $srcY;
|
||||
|
||||
$r = q(
|
||||
"select gender from profile where uid = %d and is_default = 1 limit 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if ($r) {
|
||||
$profile = array_shift($r);
|
||||
}
|
||||
|
||||
$r = q(
|
||||
"SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale > 0 order by imgscale asc LIMIT 1",
|
||||
dbesc($image_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
$max_thumb = intval(get_config('system', 'max_thumbnail', 1600));
|
||||
$iscaled = false;
|
||||
if (intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) {
|
||||
$imagick_path = get_config('system', 'imagick_convert_path');
|
||||
if ($imagick_path && @file_exists($imagick_path) && intval($r[0]['os_storage'])) {
|
||||
$fname = dbunescbin($r[0]['content']);
|
||||
$tmp_name = $fname . '-001';
|
||||
$newsize = photo_calculate_scale(array_merge(getimagesize($fname), ['max' => $max_thumb]));
|
||||
$cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $fname) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name);
|
||||
// logger('imagick thumbnail command: ' . $cmd);
|
||||
for ($x = 0; $x < 4; $x++) {
|
||||
exec($cmd);
|
||||
if (file_exists($tmp_name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (file_exists($tmp_name)) {
|
||||
$base_image = $r[0];
|
||||
$gis = getimagesize($tmp_name);
|
||||
logger('gis: ' . print_r($gis, true));
|
||||
$base_image['width'] = $gis[0];
|
||||
$base_image['height'] = $gis[1];
|
||||
$base_image['content'] = @file_get_contents($tmp_name);
|
||||
$iscaled = true;
|
||||
@unlink($tmp_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$iscaled) {
|
||||
$base_image = $r[0];
|
||||
$base_image['content'] = (($base_image['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content']));
|
||||
}
|
||||
|
||||
$im = photo_factory($base_image['content'], $base_image['mimetype']);
|
||||
if ($im->is_valid()) {
|
||||
// We are scaling and cropping the relative pixel locations to the original photo instead of the
|
||||
// scaled photo we operated on.
|
||||
|
||||
// First load the scaled photo to check its size. (Should probably pass this in the post form and save
|
||||
// a query.)
|
||||
|
||||
$g = q(
|
||||
"select width, height from photo where resource_id = '%s' and uid = %d and imgscale = 3",
|
||||
dbesc($image_id),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
|
||||
$scaled_width = $g[0]['width'];
|
||||
$scaled_height = $g[0]['height'];
|
||||
|
||||
if ((!$scaled_width) || (!$scaled_height)) {
|
||||
logger('potential divide by zero scaling cover photo');
|
||||
return;
|
||||
}
|
||||
|
||||
// unset all other cover photos
|
||||
|
||||
q(
|
||||
"update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_COVER),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
$orig_srcx = ($base_image['width'] / $scaled_width) * $srcX;
|
||||
$orig_srcy = ($base_image['height'] / $scaled_height) * $srcY;
|
||||
$orig_srcw = ($srcW / $scaled_width) * $base_image['width'];
|
||||
$orig_srch = ($srcH / $scaled_height) * $base_image['height'];
|
||||
|
||||
$im->cropImageRect(1200, 435, $orig_srcx, $orig_srcy, $orig_srcw, $orig_srch);
|
||||
|
||||
$aid = get_account_id();
|
||||
|
||||
$p = [
|
||||
'aid' => 0,
|
||||
'uid' => $channel['channel_id'],
|
||||
'resource_id' => $base_image['resource_id'],
|
||||
'filename' => $base_image['filename'],
|
||||
'album' => t('Cover Photos'),
|
||||
'os_path' => $base_image['os_path'],
|
||||
'display_path' => $base_image['display_path'],
|
||||
'created' => $base_image['created'],
|
||||
'edited' => $base_image['edited']
|
||||
];
|
||||
|
||||
$p['imgscale'] = 7;
|
||||
$p['photo_usage'] = PHOTO_COVER;
|
||||
|
||||
$r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
|
||||
|
||||
$im->doScaleImage(850, 310);
|
||||
$p['imgscale'] = 8;
|
||||
|
||||
$r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
|
||||
|
||||
$im->doScaleImage(425, 160);
|
||||
$p['imgscale'] = 9;
|
||||
|
||||
$r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
|
||||
|
||||
if ($r1 === false || $r2 === false || $r3 === false) {
|
||||
// if one failed, delete them all so we can start over.
|
||||
notice(t('Image resize failed.') . EOL);
|
||||
$x = q(
|
||||
"delete from photo where resource_id = '%s' and uid = %d and imgscale >= 7 ",
|
||||
dbesc($base_image['resource_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
notice(t('Unable to process image') . EOL);
|
||||
}
|
||||
}
|
||||
|
||||
goaway(z_root() . '/admin');
|
||||
}
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$smallest = 0;
|
||||
|
||||
$matches = [];
|
||||
$partial = false;
|
||||
|
||||
if (array_key_exists('HTTP_CONTENT_RANGE', $_SERVER)) {
|
||||
$pm = preg_match('/bytes (\d*)\-(\d*)\/(\d*)/', $_SERVER['HTTP_CONTENT_RANGE'], $matches);
|
||||
if ($pm) {
|
||||
logger('Content-Range: ' . print_r($matches, true));
|
||||
$partial = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($partial) {
|
||||
$x = save_chunk($channel, $matches[1], $matches[2], $matches[3]);
|
||||
|
||||
if ($x['partial']) {
|
||||
header('Range: bytes=0-' . (($x['length']) ? $x['length'] - 1 : 0));
|
||||
json_return_and_die($x);
|
||||
} else {
|
||||
header('Range: bytes=0-' . (($x['size']) ? $x['size'] - 1 : 0));
|
||||
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $x['name'],
|
||||
'type' => $x['type'],
|
||||
'tmp_name' => $x['tmp_name'],
|
||||
'error' => $x['error'],
|
||||
'size' => $x['size']
|
||||
];
|
||||
}
|
||||
} else {
|
||||
if (!array_key_exists('userfile', $_FILES)) {
|
||||
$_FILES['userfile'] = [
|
||||
'name' => $_FILES['files']['name'],
|
||||
'type' => $_FILES['files']['type'],
|
||||
'tmp_name' => $_FILES['files']['tmp_name'],
|
||||
'error' => $_FILES['files']['error'],
|
||||
'size' => $_FILES['files']['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$res = attach_store($channel, $channel['channel_hash'], '', array('album' => t('Cover Photos'), 'hash' => $hash));
|
||||
|
||||
logger('attach_store: ' . print_r($res, true), LOGGER_DEBUG);
|
||||
|
||||
json_return_and_die(['message' => $hash]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate content of profile-photo view
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
public function get()
|
||||
{
|
||||
|
||||
if (!is_site_admin()) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = get_sys_channel();
|
||||
|
||||
$newuser = false;
|
||||
|
||||
if (argc() == 3 && argv(1) === 'new') {
|
||||
$newuser = true;
|
||||
}
|
||||
|
||||
|
||||
if (argv(2) === 'reset') {
|
||||
q(
|
||||
"update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||
intval(PHOTO_NORMAL),
|
||||
intval(PHOTO_COVER),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
|
||||
if (argv(2) === 'use') {
|
||||
if (argc() < 4) {
|
||||
notice(t('Permission denied.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
||||
|
||||
$resource_id = argv(3);
|
||||
|
||||
$r = q(
|
||||
"SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and imgscale > 0 ORDER BY imgscale ASC",
|
||||
intval($channel['channel_id']),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
if (!$r) {
|
||||
notice(t('Photo not available.') . EOL);
|
||||
return;
|
||||
}
|
||||
$havescale = false;
|
||||
foreach ($r as $rr) {
|
||||
if ($rr['imgscale'] == 7) {
|
||||
$havescale = true;
|
||||
}
|
||||
}
|
||||
|
||||
$r = q(
|
||||
"SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
|
||||
intval($r[0]['id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if (!$r) {
|
||||
notice(t('Photo not available.') . EOL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intval($r[0]['os_storage'])) {
|
||||
$data = @file_get_contents(dbunescbin($r[0]['content']));
|
||||
} else {
|
||||
$data = dbunescbin($r[0]['content']);
|
||||
}
|
||||
|
||||
$ph = photo_factory($data, $r[0]['mimetype']);
|
||||
$smallest = 0;
|
||||
if ($ph->is_valid()) {
|
||||
// go ahead as if we have just uploaded a new photo to crop
|
||||
$i = q(
|
||||
"select resource_id, imgscale from photo where resource_id = '%s' and uid = %d and imgscale = 0",
|
||||
dbesc($r[0]['resource_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
if ($i) {
|
||||
$hash = $i[0]['resource_id'];
|
||||
foreach ($i as $ii) {
|
||||
$smallest = intval($ii['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->cover_photo_crop_ui_head($ph, $hash, $smallest);
|
||||
}
|
||||
|
||||
|
||||
if (!array_key_exists('imagecrop', App::$data)) {
|
||||
$o .= replace_macros(get_markup_template('admin_cover_photo.tpl'), [
|
||||
'$user' => $channel['channel_address'],
|
||||
'$channel_id' => $channel['channel_id'],
|
||||
'$info' => t('Your cover photo may be visible to anybody on the internet'),
|
||||
'$existing' => get_cover_photo($channel['channel_id'], 'array', PHOTO_RES_COVER_850),
|
||||
'$lbl_upfile' => t('Upload File:'),
|
||||
'$lbl_profiles' => t('Select a profile:'),
|
||||
'$title' => t('Change Cover Photo'),
|
||||
'$submit' => t('Upload'),
|
||||
'$profiles' => $profiles,
|
||||
'$embedPhotos' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||
'$embedPhotosModalCancel' => t('Cancel'),
|
||||
'$embedPhotosModalOK' => t('OK'),
|
||||
'$modalchooseimages' => t('Choose images to embed'),
|
||||
'$modalchoosealbum' => t('Choose an album'),
|
||||
'$modaldiffalbum' => t('Choose a different album'),
|
||||
'$modalerrorlist' => t('Error getting album list'),
|
||||
'$modalerrorlink' => t('Error getting photo link'),
|
||||
'$modalerroralbum' => t('Error getting album'),
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
'$select' => t('Select previously uploaded photo'),
|
||||
|
||||
]);
|
||||
|
||||
call_hooks('cover_photo_content_end', $o);
|
||||
|
||||
return $o;
|
||||
} else {
|
||||
$filename = App::$data['imagecrop'] . '-3';
|
||||
$resolution = 3;
|
||||
|
||||
$o .= replace_macros(get_markup_template('admin_cropcover.tpl'), [
|
||||
'$filename' => $filename,
|
||||
'$profile' => intval($_REQUEST['profile']),
|
||||
'$resource' => App::$data['imagecrop'] . '-3',
|
||||
'$image_url' => z_root() . '/photo/' . $filename,
|
||||
'$title' => t('Crop Image'),
|
||||
'$desc' => t('Please adjust the image cropping for optimum viewing.'),
|
||||
'$form_security_token' => get_form_security_token("cover_photo"),
|
||||
'$done' => t('Done Editing')
|
||||
]);
|
||||
return $o;
|
||||
}
|
||||
}
|
||||
|
||||
/* @brief Generate the UI for photo-cropping
|
||||
*
|
||||
* @param $a Current application
|
||||
* @param $ph Photo-Factory
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
|
||||
public function cover_photo_crop_ui_head($ph, $hash, $smallest)
|
||||
{
|
||||
|
||||
$max_length = get_config('system', 'max_image_length', MAX_IMAGE_LENGTH);
|
||||
|
||||
if ($max_length > 0) {
|
||||
$ph->scaleImage($max_length);
|
||||
}
|
||||
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
|
||||
if ($width < 300 || $height < 300) {
|
||||
$ph->scaleImageUp(240);
|
||||
$width = $ph->getWidth();
|
||||
$height = $ph->getHeight();
|
||||
}
|
||||
|
||||
|
||||
App::$data['imagecrop'] = $hash;
|
||||
App::$data['imagecrop_resolution'] = $smallest;
|
||||
App::$page['htmlhead'] .= replace_macros(get_markup_template('crophead.tpl'), []);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue