Merge branch 'origin' into 'develop'
marge from origin 4.0 See merge request harukin/core!40
This commit is contained in:
@@ -16,7 +16,8 @@ function profile_activity($changed, $value) {
|
||||
return;
|
||||
|
||||
$arr = array();
|
||||
$arr['mid'] = $arr['parent_mid'] = item_message_id();
|
||||
$arr['uuid'] = item_message_id();
|
||||
$arr['mid'] = $arr['parent_mid'] = z_root() . '/item/' . $arr['uuid'];
|
||||
$arr['uid'] = local_channel();
|
||||
$arr['aid'] = $self['channel_account_id'];
|
||||
$arr['owner_xchan'] = $arr['author_xchan'] = $self['xchan_hash'];
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
api_register_func('api/export/basic','api_export_basic', true);
|
||||
api_register_func('api/red/channel/export/basic','api_export_basic', true);
|
||||
api_register_func('api/z/1.0/channel/export/basic','api_export_basic', true);
|
||||
api_register_func('api/red/item/export/page','api_item_export_page', true);
|
||||
api_register_func('api/z/1.0/item/export/page','api_item_export_page', true);
|
||||
api_register_func('api/red/channel/list','api_channel_list', true);
|
||||
api_register_func('api/z/1.0/channel/list','api_channel_list', true);
|
||||
api_register_func('api/red/channel/stream','api_channel_stream', true);
|
||||
@@ -80,6 +82,26 @@
|
||||
json_return_and_die(identity_basic_export(api_user(),$sections));
|
||||
}
|
||||
|
||||
function api_item_export_page($type) {
|
||||
if(api_user() === false) {
|
||||
logger('api_item_export_page: no user');
|
||||
return false;
|
||||
}
|
||||
$page = intval($_REQUEST['page']);
|
||||
$records = intval($_REQUEST['records']);
|
||||
if(! $records) {
|
||||
$records = 50;
|
||||
}
|
||||
if(! $_REQUEST['since'])
|
||||
$start = NULL_DATE;
|
||||
else {
|
||||
$start = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['since']);
|
||||
}
|
||||
$finish = datetime_convert(date_default_timezone_get(),'UTC', (($_REQUEST['until']) ? $_REQUEST['until'] : 'now'));
|
||||
|
||||
json_return_and_die(channel_export_items_page(api_user(),$start,$finish,$page,$records));
|
||||
}
|
||||
|
||||
|
||||
function api_network_stream($type) {
|
||||
if(api_user() === false) {
|
||||
|
||||
+50
-28
@@ -137,7 +137,7 @@ function z_mime_content_type($filename) {
|
||||
* @param string $hash (optional)
|
||||
* @param string $filename (optional)
|
||||
* @param string $filetype (optional)
|
||||
* @return associative array with:
|
||||
* @return array Associative array with:
|
||||
* * \e boolean \b success
|
||||
* * \e int|boolean \b results amount of found results, or false
|
||||
* * \e string \b message with error messages if any
|
||||
@@ -176,15 +176,17 @@ function attach_count_files($channel_id, $observer, $hash = '', $filename = '',
|
||||
/**
|
||||
* @brief Returns a list of files/attachments.
|
||||
*
|
||||
* @param $channel_id
|
||||
* @param $observer
|
||||
* @param $hash (optional)
|
||||
* @param $filename (optional)
|
||||
* @param $filetype (optional)
|
||||
* @param $orderby
|
||||
* @param $start
|
||||
* @param $entries
|
||||
* @return associative array with:
|
||||
* @param int $channel_id
|
||||
* @param string $observer
|
||||
* @param string $hash (optional)
|
||||
* @param string $filename (optional)
|
||||
* @param string $filetype (optional)
|
||||
* @param string $orderby (optional)
|
||||
* @param int $start (optional)
|
||||
* @param int $entries (optional)
|
||||
* @param string $since (optional)
|
||||
* @param string $until (optional)
|
||||
* @return array an associative array with:
|
||||
* * \e boolean \b success
|
||||
* * \e array|boolean \b results array with results, or false
|
||||
* * \e string \b message with error messages if any
|
||||
@@ -739,7 +741,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
}
|
||||
|
||||
if(! $hash)
|
||||
$hash = random_string();
|
||||
$hash = new_uuid();
|
||||
|
||||
// Check storage limits
|
||||
if($options !== 'update') {
|
||||
@@ -1122,7 +1124,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$arr['hash'] = (($arr['hash']) ? $arr['hash'] : random_string());
|
||||
$arr['hash'] = (($arr['hash']) ? $arr['hash'] : new_uuid());
|
||||
|
||||
// Check for duplicate name.
|
||||
// Check both the filename and the hash as we will be making use of both.
|
||||
@@ -1428,8 +1430,17 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
|
||||
|
||||
if(! $r) {
|
||||
attach_drop_photo($channel_id,$resource);
|
||||
$arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo'=>$is_photo];
|
||||
call_hooks("attach_delete",$arr);
|
||||
$arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo' => $is_photo];
|
||||
|
||||
/**
|
||||
* @hooks attach_delete
|
||||
* Called when deleting an attachment from channel.
|
||||
* * \e int \b channel_id - the channel_id
|
||||
* * \e string \b resource
|
||||
* * \e int \b is_photo
|
||||
*/
|
||||
call_hooks('attach_delete', $arr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1488,8 +1499,15 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
$arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo'=>$is_photo];
|
||||
call_hooks("attach_delete",$arr);
|
||||
$arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo' => $is_photo];
|
||||
/**
|
||||
* @hooks attach_delete
|
||||
* Called when deleting an attachment from channel.
|
||||
* * \e int \b channel_id - the channel_id
|
||||
* * \e string \b resource
|
||||
* * \e int \b is_photo
|
||||
*/
|
||||
call_hooks('attach_delete', $arr);
|
||||
|
||||
file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', true);
|
||||
|
||||
@@ -1759,16 +1777,18 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
|
||||
$arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage');
|
||||
}
|
||||
|
||||
$mid = item_message_id();
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$objtype = ACTIVITY_OBJ_FILE;
|
||||
|
||||
$arr = array();
|
||||
$arr['aid'] = get_account_id();
|
||||
$arr['uid'] = $channel_id;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['item_wall'] = 1;
|
||||
$arr['item_origin'] = 1;
|
||||
$arr['item_unseen'] = 1;
|
||||
$arr['author_xchan'] = $poster['xchan_hash'];
|
||||
$arr['owner_xchan'] = $poster['xchan_hash'];
|
||||
$arr['title'] = '';
|
||||
@@ -1813,8 +1833,10 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
|
||||
|
||||
$private = (($u_arr_allow_cid[0] || $u_arr_allow_gid[0] || $u_arr_deny_cid[0] || $u_arr_deny_gid[0]) ? 1 : 0);
|
||||
|
||||
$u_mid = item_message_id();
|
||||
$uuid = item_message_id();
|
||||
$u_mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $u_mid;
|
||||
$arr['parent_mid'] = $u_mid;
|
||||
$arr['allow_cid'] = perms2str($u_arr_allow_cid);
|
||||
@@ -1864,7 +1886,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
|
||||
* @param int $channel_id
|
||||
* @param string $hash
|
||||
* @param string $url
|
||||
* @return array An associative array for the specified file.
|
||||
* @return array Associative array for the specified file.
|
||||
*/
|
||||
function get_file_activity_object($channel_id, $hash, $url) {
|
||||
|
||||
@@ -2106,7 +2128,7 @@ function attach_export_data($channel, $resource_id, $deleted = false) {
|
||||
|
||||
if($attach_ptr['is_photo']) {
|
||||
|
||||
// This query could potentially result in a few megabytes of data use.
|
||||
// This query could potentially result in a few megabytes of data use.
|
||||
|
||||
$r = q("select * from photo where resource_id = '%s' and uid = %d order by imgscale asc",
|
||||
dbesc($resource_id),
|
||||
@@ -2348,7 +2370,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
|
||||
$filename = $r[0]['filename'];
|
||||
|
||||
// don't do duplicate check unless our parent folder has changed.
|
||||
// don't do duplicate check unless our parent folder has changed.
|
||||
|
||||
if($r[0]['folder'] !== $new_folder_hash) {
|
||||
|
||||
@@ -2464,7 +2486,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
|
||||
|
||||
|
||||
/**
|
||||
* Used to generate a select input box of all your folders
|
||||
* Used to generate a select input box of all your folders
|
||||
*/
|
||||
|
||||
|
||||
@@ -2547,10 +2569,10 @@ function attach_syspaths($channel_id,$attach_hash) {
|
||||
|
||||
/**
|
||||
* in earlier releases we did not fill in os_path and display_path in the attach DB structure.
|
||||
* (It was not needed or used). Going forward we intend to make use of these fields.
|
||||
* (It was not needed or used). Going forward we intend to make use of these fields.
|
||||
* A cron task checks for empty values (as older attachments may have arrived at our site
|
||||
* in a clone operation) and executes attach_syspaths() to generate these field values and correct
|
||||
* the attach table entry. The operation is limited to 100 DB entries at a time so as not to
|
||||
* in a clone operation) and executes attach_syspaths() to generate these field values and correct
|
||||
* the attach table entry. The operation is limited to 100 DB entries at a time so as not to
|
||||
* overload the system in any cron run. Eventually it will catch up with old attach structures
|
||||
* and switch into maintenance mode to correct any that might arrive in clone packets from older
|
||||
* sites.
|
||||
|
||||
+3
-14
@@ -326,22 +326,11 @@ function bb_ShareAttributes($match) {
|
||||
$auth = is_matrix_url($profile);
|
||||
}
|
||||
|
||||
// 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(! $message_id) {
|
||||
preg_match("/guid='(.*?)'/ism", $attributes, $matches);
|
||||
if ($matches[1] != "")
|
||||
$message_id = $matches[1];
|
||||
}
|
||||
|
||||
$rnd = mt_rand();
|
||||
|
||||
$reldate = '<span class="autotime" title="' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'c') . '" >' . datetime_convert('UTC', date_default_timezone_get(), $posted, 'r') . '</span>';
|
||||
|
||||
$headline = '<div class="shared_container"> <div class="shared_header">';
|
||||
$headline = '<div id="shared_container_' . $rnd . '" class="shared_container"> <div id="shared_header_' . $rnd . '" class="shared_header">';
|
||||
|
||||
if ($avatar != "")
|
||||
$headline .= '<a href="' . (($auth) ? zid($profile) : $profile) . '" ><img src="' . $avatar . '" alt="' . $author . '" height="32" width="32" /></a>';
|
||||
@@ -363,7 +352,7 @@ function bb_ShareAttributes($match) {
|
||||
|
||||
$headline .= '<span>' . $fmt . '</span></div>';
|
||||
|
||||
$text = $headline . '<div class="reshared-content">' . trim($match[2]) . '</div></div>';
|
||||
$text = $headline . '<div id="reshared-content-' . $rnd . '" class="reshared-content">' . trim($match[2]) . '</div></div>';
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
+151
-38
@@ -10,6 +10,7 @@ use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\System;
|
||||
use Zotlabs\Render\Comanche;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/crypto.php');
|
||||
@@ -232,6 +233,7 @@ function create_identity($arr) {
|
||||
|
||||
$sig = base64url_encode(rsa_sign($guid,$key['prvkey']));
|
||||
$hash = make_xchan_hash($guid,$sig);
|
||||
$zhash = Libzot::make_xchan_hash($guid,$key['pubkey']);
|
||||
|
||||
// Force a few things on the short term until we can provide a theme or app with choice
|
||||
|
||||
@@ -265,6 +267,7 @@ function create_identity($arr) {
|
||||
'channel_guid' => $guid,
|
||||
'channel_guid_sig' => $sig,
|
||||
'channel_hash' => $hash,
|
||||
'channel_portable_id' => $zhash,
|
||||
'channel_prvkey' => $key['prvkey'],
|
||||
'channel_pubkey' => $key['pubkey'],
|
||||
'channel_pageflags' => intval($pageflags),
|
||||
@@ -345,30 +348,76 @@ function create_identity($arr) {
|
||||
if(! $r)
|
||||
logger('Unable to store hub location');
|
||||
|
||||
$r = hubloc_store_lowlevel(
|
||||
[
|
||||
'hubloc_guid' => $guid,
|
||||
'hubloc_guid_sig' => 'sha256.' . $sig,
|
||||
'hubloc_hash' => $zhash,
|
||||
'hubloc_id_url' => channel_url($ret['channel']),
|
||||
'hubloc_addr' => channel_reddress($ret['channel']),
|
||||
'hubloc_primary' => intval($primary),
|
||||
'hubloc_url' => z_root(),
|
||||
'hubloc_url_sig' => 'sha256.' . base64url_encode(rsa_sign(z_root(),$ret['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' => 'zot6',
|
||||
'hubloc_updated' => datetime_convert()
|
||||
]
|
||||
);
|
||||
if(! $r)
|
||||
logger('Unable to store hub location');
|
||||
|
||||
|
||||
$newuid = $ret['channel']['channel_id'];
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $hash,
|
||||
'xchan_guid' => $guid,
|
||||
'xchan_guid_sig' => $sig,
|
||||
'xchan_pubkey' => $key['pubkey'],
|
||||
'xchan_hash' => $hash,
|
||||
'xchan_guid' => $guid,
|
||||
'xchan_guid_sig' => $sig,
|
||||
'xchan_pubkey' => $key['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($ret['channel']),
|
||||
'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
|
||||
'xchan_name' => $ret['channel']['channel_name'],
|
||||
'xchan_network' => 'zot',
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert(),
|
||||
'xchan_system' => $system
|
||||
'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($ret['channel']),
|
||||
'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
|
||||
'xchan_name' => $ret['channel']['channel_name'],
|
||||
'xchan_network' => 'zot',
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert(),
|
||||
'xchan_system' => $system
|
||||
]
|
||||
);
|
||||
|
||||
$r = xchan_store_lowlevel(
|
||||
[
|
||||
'xchan_hash' => $zhash,
|
||||
'xchan_guid' => $guid,
|
||||
'xchan_guid_sig' => 'sha256.' . $sig,
|
||||
'xchan_pubkey' => $key['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($ret['channel']),
|
||||
'xchan_url' => z_root() . '/channel/' . $ret['channel']['channel_address'],
|
||||
'xchan_follow' => z_root() . '/follow?f=&url=%s',
|
||||
'xchan_connurl' => z_root() . '/poco/' . $ret['channel']['channel_address'],
|
||||
'xchan_name' => $ret['channel']['channel_name'],
|
||||
'xchan_network' => 'zot6',
|
||||
'xchan_photo_date' => datetime_convert(),
|
||||
'xchan_name_date' => datetime_convert(),
|
||||
'xchan_system' => $system
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Not checking return value.
|
||||
// It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate
|
||||
|
||||
@@ -1031,6 +1080,7 @@ function identity_basic_export($channel_id, $sections = null) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Export items for a year, or a month of a year.
|
||||
*
|
||||
@@ -1053,34 +1103,14 @@ function identity_export_year($channel_id, $year, $month = 0) {
|
||||
else
|
||||
$target_month = '01';
|
||||
|
||||
$ret = array();
|
||||
|
||||
$ch = channelx_by_n($channel_id);
|
||||
if($ch) {
|
||||
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
|
||||
}
|
||||
$mindate = datetime_convert('UTC', 'UTC', $year . '-' . $target_month . '-01 00:00:00');
|
||||
if($month && $month < 12)
|
||||
$maxdate = datetime_convert('UTC', 'UTC', $year . '-' . $target_month_plus . '-01 00:00:00');
|
||||
else
|
||||
$maxdate = datetime_convert('UTC', 'UTC', $year+1 . '-01-01 00:00:00');
|
||||
|
||||
$r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created",
|
||||
intval(ITEM_TYPE_POST),
|
||||
intval($channel_id),
|
||||
dbesc($mindate),
|
||||
dbesc($maxdate)
|
||||
);
|
||||
return channel_export_items_date($channel_id,$mindate,$maxdate);
|
||||
|
||||
if($r) {
|
||||
$ret['item'] = array();
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r, true);
|
||||
foreach($r as $rr)
|
||||
$ret['item'][] = encode_item($rr, true);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1093,7 +1123,8 @@ function identity_export_year($channel_id, $year, $month = 0) {
|
||||
* @param string $finish
|
||||
* @return array
|
||||
*/
|
||||
function channel_export_items($channel_id, $start, $finish) {
|
||||
|
||||
function channel_export_items_date($channel_id, $start, $finish) {
|
||||
|
||||
if(! $start)
|
||||
return array();
|
||||
@@ -1130,6 +1161,71 @@ function channel_export_items($channel_id, $start, $finish) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Export items with pagination
|
||||
*
|
||||
*
|
||||
* @param int $channel_id The channel ID
|
||||
* @param int $page
|
||||
* @param int $limit (default 50)
|
||||
* @return array
|
||||
*/
|
||||
|
||||
function channel_export_items_page($channel_id, $start, $finish, $page = 0, $limit = 50) {
|
||||
|
||||
if(intval($page) < 1) {
|
||||
$page = 0;
|
||||
}
|
||||
|
||||
if(intval($limit) < 1) {
|
||||
$limit = 1;
|
||||
}
|
||||
|
||||
if(intval($limit) > 5000) {
|
||||
$limit = 5000;
|
||||
}
|
||||
|
||||
if(! $start)
|
||||
$start = NULL_DATE;
|
||||
else
|
||||
$start = datetime_convert('UTC', 'UTC', $start);
|
||||
|
||||
$finish = datetime_convert('UTC', 'UTC', (($finish) ? $finish : 'now'));
|
||||
if($finish < $start)
|
||||
return [];
|
||||
|
||||
$offset = intval($limit) * intval($page);
|
||||
|
||||
$ret = [];
|
||||
|
||||
$ch = channelx_by_n($channel_id);
|
||||
if($ch) {
|
||||
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
|
||||
}
|
||||
|
||||
$r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and resource_type = '' and created >= '%s' and created <= '%s' order by created limit %d offset %d",
|
||||
intval(ITEM_TYPE_POST),
|
||||
intval($channel_id),
|
||||
dbesc($start),
|
||||
dbesc($finish),
|
||||
intval($limit),
|
||||
intval($offset)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$ret['item'] = array();
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r, true);
|
||||
foreach($r as $rr)
|
||||
$ret['item'][] = encode_item($rr, true);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Loads a profile into the App structure.
|
||||
*
|
||||
@@ -1740,6 +1836,7 @@ function zat_init() {
|
||||
);
|
||||
if($r) {
|
||||
$xchan = atoken_xchan($r[0]);
|
||||
atoken_create_xchan($xchan);
|
||||
atoken_login($xchan);
|
||||
}
|
||||
}
|
||||
@@ -2284,6 +2381,21 @@ function channelx_by_hash($hash) {
|
||||
return(($r) ? $r[0] : false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a channel array by a channel_hash.
|
||||
*
|
||||
* @param string $hash
|
||||
* @return array|boolean false if channel ID not found, otherwise the channel array
|
||||
*/
|
||||
function channelx_by_portid($hash) {
|
||||
$r = q("SELECT * FROM channel left join xchan on channel_portable_id = xchan_hash WHERE channel_portable_id = '%s' and channel_removed = 0 LIMIT 1",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
return(($r) ? $r[0] : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a channel array by a channel ID.
|
||||
*
|
||||
@@ -2355,6 +2467,7 @@ function channel_store_lowlevel($arr) {
|
||||
'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''),
|
||||
'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''),
|
||||
'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''),
|
||||
'channel_portable_id' => ((array_key_exists('channel_portable_id',$arr)) ? $arr['channel_portable_id'] : ''),
|
||||
'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'),
|
||||
'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''),
|
||||
'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''),
|
||||
|
||||
+16
-24
@@ -7,14 +7,14 @@ function findpeople_widget() {
|
||||
if(get_config('system','invitation_only')) {
|
||||
$x = get_pconfig(local_channel(),'system','invites_remaining');
|
||||
if($x || is_site_admin()) {
|
||||
App::$page['aside'] .= '<div class="side-link" id="side-invite-remain">'
|
||||
. sprintf( tt('%d invitation available','%d invitations available',$x), $x)
|
||||
. '</div>' . $inv;
|
||||
App::$page['aside'] .= '<div class="side-link" id="side-invite-remain">'
|
||||
. sprintf( tt('%d invitation available','%d invitations available',$x), $x)
|
||||
. '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
$advanced_search = ((local_channel() && feature_enabled(local_channel(),'advanced_dirsearch')) ? t('Advanced') : false);
|
||||
|
||||
|
||||
return replace_macros(get_markup_template('peoplefind.tpl'),array(
|
||||
'$findpeople' => t('Find Channels'),
|
||||
'$desc' => t('Enter name or interest'),
|
||||
@@ -22,7 +22,7 @@ function findpeople_widget() {
|
||||
'$hint' => t('Examples: Robert Morgenstein, Fishing'),
|
||||
'$findthem' => t('Find'),
|
||||
'$suggest' => t('Channel Suggestions'),
|
||||
'$similar' => '', // FIXME and uncomment when mod/match working // t('Similar Interests'),
|
||||
'$similar' => '', /// @FIXME fixme and uncomment when mod/match working // t('Similar Interests'),
|
||||
'$random' => t('Random Profile'),
|
||||
'$inv' => t('Invite Friends'),
|
||||
'$advanced_search' => $advanced_search,
|
||||
@@ -56,12 +56,11 @@ function fileas_widget($baseurl,$selected = '') {
|
||||
'$all' => t('Everything'),
|
||||
'$terms' => $terms,
|
||||
'$base' => $baseurl,
|
||||
|
||||
));
|
||||
}
|
||||
|
||||
function categories_widget($baseurl,$selected = '') {
|
||||
|
||||
|
||||
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
|
||||
return '';
|
||||
|
||||
@@ -100,14 +99,13 @@ function categories_widget($baseurl,$selected = '') {
|
||||
'$all' => t('Everything'),
|
||||
'$terms' => $terms,
|
||||
'$base' => $baseurl,
|
||||
|
||||
));
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function cardcategories_widget($baseurl,$selected = '') {
|
||||
|
||||
|
||||
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
|
||||
return '';
|
||||
|
||||
@@ -128,7 +126,7 @@ function cardcategories_widget($baseurl,$selected = '') {
|
||||
$item_normal
|
||||
$sql_extra
|
||||
order by term.term asc",
|
||||
intval(App::$profile['profile_uid']),
|
||||
intval(App::$profile['profile_uid']),
|
||||
intval(TERM_CATEGORY),
|
||||
intval(TERM_OBJ_POST),
|
||||
dbesc(App::$profile['channel_hash'])
|
||||
@@ -144,15 +142,15 @@ function cardcategories_widget($baseurl,$selected = '') {
|
||||
'$all' => t('Everything'),
|
||||
'$terms' => $terms,
|
||||
'$base' => $baseurl,
|
||||
|
||||
));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
function articlecategories_widget($baseurl,$selected = '') {
|
||||
|
||||
|
||||
if(! feature_enabled(App::$profile['profile_uid'],'categories'))
|
||||
return '';
|
||||
|
||||
@@ -173,7 +171,7 @@ function articlecategories_widget($baseurl,$selected = '') {
|
||||
$item_normal
|
||||
$sql_extra
|
||||
order by term.term asc",
|
||||
intval(App::$profile['profile_uid']),
|
||||
intval(App::$profile['profile_uid']),
|
||||
intval(TERM_CATEGORY),
|
||||
intval(TERM_OBJ_POST),
|
||||
dbesc(App::$profile['channel_hash'])
|
||||
@@ -189,17 +187,14 @@ function articlecategories_widget($baseurl,$selected = '') {
|
||||
'$all' => t('Everything'),
|
||||
'$terms' => $terms,
|
||||
'$base' => $baseurl,
|
||||
|
||||
));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function common_friends_visitor_widget($profile_uid,$cnt = 25) {
|
||||
|
||||
if(local_channel() == $profile_uid)
|
||||
@@ -218,17 +213,14 @@ function common_friends_visitor_widget($profile_uid,$cnt = 25) {
|
||||
return;
|
||||
|
||||
$r = common_friends($profile_uid,$observer_hash,0,$cnt,true);
|
||||
|
||||
return replace_macros(get_markup_template('remote_friends_common.tpl'), array(
|
||||
|
||||
return replace_macros(get_markup_template('remote_friends_common.tpl'), [
|
||||
'$desc' => t('Common Connections'),
|
||||
'$base' => z_root(),
|
||||
'$uid' => $profile_uid,
|
||||
'$cid' => $observer,
|
||||
'$linkmore' => (($t > $cnt) ? 'true' : ''),
|
||||
'$more' => sprintf( t('View all %d common connections'), $t),
|
||||
'$items' => $r
|
||||
));
|
||||
'$items' => $r,
|
||||
]);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1328,7 +1328,7 @@ function hz_status_editor($a, $x, $popup = false) {
|
||||
|
||||
$tpl = get_markup_template('jot-header.tpl');
|
||||
|
||||
App::$page['htmlhead'] .= replace_macros($tpl, array(
|
||||
$tplmacros = [
|
||||
'$baseurl' => z_root(),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$pretext' => ((x($x,'pretext')) ? $x['pretext'] : ''),
|
||||
@@ -1349,7 +1349,10 @@ function hz_status_editor($a, $x, $popup = false) {
|
||||
'$nocomment_disabled' => t('Comments disabled'),
|
||||
'$auto_save_draft' => $feature_auto_save_draft,
|
||||
'$reset' => $reset
|
||||
));
|
||||
];
|
||||
|
||||
call_hooks('jot_header_tpl_filter',$tplmacros);
|
||||
App::$page['htmlhead'] .= replace_macros($tpl, $tplmacros);
|
||||
|
||||
$tpl = get_markup_template('jot.tpl');
|
||||
|
||||
@@ -1389,7 +1392,7 @@ function hz_status_editor($a, $x, $popup = false) {
|
||||
$sharebutton = (x($x,'button') ? $x['button'] : t('Share'));
|
||||
$placeholdtext = (x($x,'content_label') ? $x['content_label'] : $sharebutton);
|
||||
|
||||
$o .= replace_macros($tpl, array(
|
||||
$tplmacros = [
|
||||
'$return_path' => ((x($x, 'return_path')) ? $x['return_path'] : App::$query_string),
|
||||
'$action' => z_root() . '/item',
|
||||
'$share' => $sharebutton,
|
||||
@@ -1463,9 +1466,15 @@ function hz_status_editor($a, $x, $popup = false) {
|
||||
'$bbcode' => ((x($x, 'bbcode')) ? $x['bbcode'] : false),
|
||||
'$parent' => ((array_key_exists('parent',$x) && $x['parent']) ? $x['parent'] : 0),
|
||||
'$reset' => $reset,
|
||||
'$is_owner' => ((local_channel() && (local_channel() == $x['profile_uid'])) ? true : false)
|
||||
));
|
||||
'$is_owner' => ((local_channel() && (local_channel() == $x['profile_uid'])) ? true : false),
|
||||
'$custommoretoolsdropdown' => '',
|
||||
'$custommoretoolsbuttons' => '',
|
||||
'$customsubmitright' => []
|
||||
];
|
||||
|
||||
call_hooks('jot_tpl_filter',$tplmacros);
|
||||
|
||||
$o .= replace_macros($tpl, $tplmacros);
|
||||
if ($popup === true) {
|
||||
$o = '<div id="jot-popup" style="display:none">' . $o . '</div>';
|
||||
}
|
||||
|
||||
+7
-2
@@ -225,9 +225,14 @@ function crypto_unencapsulate($data,$prvkey) {
|
||||
if(! $data)
|
||||
return;
|
||||
|
||||
$alg = ((array_key_exists('alg',$data)) ? $data['alg'] : 'aes256cbc');
|
||||
if($alg === 'aes256cbc')
|
||||
$alg = ((is_array($data) && (array_key_exists('encrypted',$data) || array_key_exists('iv',$data))) ? $data['alg'] : '');
|
||||
if(! $alg) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if($alg === 'aes256cbc') {
|
||||
return aes_unencapsulate($data,$prvkey);
|
||||
}
|
||||
|
||||
return other_unencapsulate($data,$prvkey,$alg);
|
||||
|
||||
|
||||
+16
-4
@@ -6,6 +6,10 @@
|
||||
|
||||
use Sabre\VObject;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
|
||||
|
||||
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
/**
|
||||
@@ -463,8 +467,13 @@ function event_store_event($arr) {
|
||||
$hash = $arr['external_id'];
|
||||
elseif(array_key_exists('event_hash',$arr))
|
||||
$hash = $arr['event_hash'];
|
||||
else
|
||||
$hash = random_string() . '@' . App::get_hostname();
|
||||
else {
|
||||
try {
|
||||
$hash = Uuid::uuid4()->toString();
|
||||
} catch (UnsatisfiedDependencyException $e) {
|
||||
$hash = random_string(48);
|
||||
}
|
||||
}
|
||||
|
||||
$r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,dtstart,dtend,summary,description,location,etype,
|
||||
adjust,nofinish, event_status, event_status_date, event_percent, event_repeat, event_sequence, event_priority, event_vdata, allow_cid,allow_gid,deny_cid,deny_gid)
|
||||
@@ -1125,11 +1134,14 @@ function event_store_item($arr, $event) {
|
||||
}
|
||||
}
|
||||
|
||||
if(! $arr['mid'])
|
||||
$arr['mid'] = item_message_id();
|
||||
if(! $arr['mid']) {
|
||||
$arr['uuid'] = $event['event_hash'];
|
||||
$arr['mid'] = z_root() . '/event/' . $event['event_hash'];
|
||||
}
|
||||
|
||||
$item_arr['aid'] = $z[0]['channel_account_id'];
|
||||
$item_arr['uid'] = $arr['uid'];
|
||||
$item_arr['uuid'] = $arr['uuid'];
|
||||
$item_arr['author_xchan'] = $arr['event_xchan'];
|
||||
$item_arr['mid'] = $arr['mid'];
|
||||
$item_arr['parent_mid'] = $arr['mid'];
|
||||
|
||||
@@ -360,14 +360,6 @@ function get_features($filtered = true, $level = (-1)) {
|
||||
get_config('feature_lock','personal_tab')
|
||||
],
|
||||
|
||||
[
|
||||
'affinity',
|
||||
t('Affinity Tool'),
|
||||
t('Filter stream activity by depth of relationships'),
|
||||
false,
|
||||
get_config('feature_lock','affinity')
|
||||
],
|
||||
|
||||
[
|
||||
'suggest',
|
||||
t('Suggest Channels'),
|
||||
|
||||
+9
-11
@@ -261,13 +261,13 @@ function construct_activity_target($item) {
|
||||
* @param SimplePie $item
|
||||
* @return array $author
|
||||
*/
|
||||
|
||||
function get_atom_author($feed, $item) {
|
||||
|
||||
$author = [];
|
||||
|
||||
$found_author = $item->get_author();
|
||||
if($found_author) {
|
||||
/// @FIXME $rawauthor is undefined here
|
||||
if($rawauthor) {
|
||||
if($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data'])
|
||||
$author['full_name'] = unxmlify($rawauthor[0]['child'][NAMESPACE_POCO]['displayName'][0]['data']);
|
||||
@@ -398,10 +398,10 @@ function get_atom_author($feed, $item) {
|
||||
'author' => $author
|
||||
];
|
||||
/**
|
||||
* @hooks parse_atom
|
||||
* @hooks parse_atom_author
|
||||
* * \e SimplePie \b feed - The original SimplePie feed
|
||||
* * \e SimplePie \b item
|
||||
* * \e array \b result - the result array that will also get returned
|
||||
* * \e array \b author - the result array that will also get returned
|
||||
*/
|
||||
call_hooks('parse_atom_author', $arr);
|
||||
|
||||
@@ -416,10 +416,8 @@ function get_atom_author($feed, $item) {
|
||||
*
|
||||
* @param SimplePie $feed
|
||||
* @param SimplePie $item
|
||||
* @param[out] array $author
|
||||
* @return array Associative array with the parsed item data
|
||||
*/
|
||||
|
||||
function get_atom_elements($feed, $item) {
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
@@ -669,10 +667,10 @@ function get_atom_elements($feed, $item) {
|
||||
$termterm = notags(trim(unxmlify($term)));
|
||||
|
||||
// Mastodon auto generates an nsfw category tag for any 'content-warning' message.
|
||||
// Most people use CW and use both summary/content as a spoiler and we honour that
|
||||
// construct so the post will already be collapsed. The generated tag is almost
|
||||
// Most people use CW and use both summary/content as a spoiler and we honour that
|
||||
// construct so the post will already be collapsed. The generated tag is almost
|
||||
// always wrong and even if it isn't we would already be doing the right thing.
|
||||
|
||||
|
||||
if($mastodon && $termterm === 'nsfw' && $summary && $res['body'])
|
||||
continue;
|
||||
|
||||
@@ -1336,7 +1334,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
|
||||
if( ! \Zotlabs\Lib\MessageFilter::evaluate($datarray,get_config('system','pubstream_incl'),get_config('system','pubstream_excl'))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! post_is_importable($datarray, $contact))
|
||||
continue;
|
||||
@@ -1492,7 +1490,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
|
||||
if( ! \Zotlabs\Lib\MessageFilter::evaluate($datarray,get_config('system','pubstream_incl'),get_config('system','pubstream_excl'))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(! post_is_importable($datarray, $contact))
|
||||
continue;
|
||||
@@ -1900,7 +1898,7 @@ function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0, $
|
||||
|
||||
$body = $item['body'];
|
||||
|
||||
if($summary)
|
||||
if($summary)
|
||||
$body = preg_replace('|^(.*?)\[summary\](.*?)\[/summary\](.*?)$|ism','$1$3',$item['body']);
|
||||
|
||||
if($compat)
|
||||
|
||||
+2
-4
@@ -190,7 +190,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
return $result;
|
||||
}
|
||||
|
||||
$allowed = (($is_zot || $r[0]['xchan_network'] === 'rss') ? 1 : 0);
|
||||
$allowed = (($is_zot || in_array($r[0]['xchan_network'],['rss','zot6'])) ? 1 : 0);
|
||||
|
||||
$x = array('channel_id' => $uid, 'follow_address' => $url, 'xchan' => $r[0], 'allowed' => $allowed, 'singleton' => 0);
|
||||
|
||||
@@ -266,9 +266,7 @@ function new_contact($uid,$url,$channel,$interactive = false, $confirm = false)
|
||||
}
|
||||
}
|
||||
else {
|
||||
$closeness = get_pconfig($uid,'system','new_abook_closeness');
|
||||
if($closeness === false)
|
||||
$closeness = 80;
|
||||
$closeness = get_pconfig($uid,'system','new_abook_closeness',80);
|
||||
|
||||
$r = abook_store_lowlevel(
|
||||
[
|
||||
|
||||
+30
-27
@@ -7,17 +7,18 @@ use \Michelf\MarkdownExtra;
|
||||
* @brief
|
||||
*
|
||||
* @param string $path
|
||||
* @return string|unknown
|
||||
* @param string $suffix (optional) default null
|
||||
* @return string
|
||||
*/
|
||||
function get_help_fullpath($path,$suffix=null) {
|
||||
function get_help_fullpath($path, $suffix = null) {
|
||||
|
||||
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
|
||||
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
|
||||
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
|
||||
|
||||
// Determine the language and modify the path accordingly
|
||||
$x = determine_help_language();
|
||||
$lang = $x['language'];
|
||||
$url_idx = ($x['from_url'] ? 1 : 0);
|
||||
|
||||
// The English translation is at the root of /doc/. Other languages are in
|
||||
// subfolders named by the language code such as "de", "es", etc.
|
||||
if($lang !== 'en') {
|
||||
@@ -49,19 +50,18 @@ function get_help_fullpath($path,$suffix=null) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param string $tocpath
|
||||
* @return string|unknown
|
||||
* @param string $tocpath (optional) default false
|
||||
* @return string
|
||||
*/
|
||||
function get_help_content($tocpath = false) {
|
||||
global $lang;
|
||||
|
||||
$doctype = 'markdown';
|
||||
|
||||
$text = '';
|
||||
|
||||
$path = (($tocpath !== false) ? $tocpath : '');
|
||||
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
|
||||
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
|
||||
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
|
||||
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
|
||||
|
||||
if($tocpath === false && argc() > 1) {
|
||||
$path = '';
|
||||
@@ -74,7 +74,7 @@ function get_help_content($tocpath = false) {
|
||||
|
||||
|
||||
if($path) {
|
||||
$fullpath = get_help_fullpath($path);
|
||||
$fullpath = get_help_fullpath($path);
|
||||
$title = basename($path);
|
||||
if(! $tocpath)
|
||||
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
|
||||
@@ -88,10 +88,10 @@ function get_help_content($tocpath = false) {
|
||||
load_doc_file($fullpath . '.md') === '' &&
|
||||
load_doc_file($fullpath . '.bb') === '' &&
|
||||
load_doc_file($fullpath . '.html') === ''
|
||||
) {
|
||||
) {
|
||||
$path = $title;
|
||||
}
|
||||
$fullpath = get_help_fullpath($path);
|
||||
$fullpath = get_help_fullpath($path);
|
||||
$text = load_doc_file($fullpath . '.md');
|
||||
|
||||
if(! $text) {
|
||||
@@ -111,15 +111,15 @@ function get_help_content($tocpath = false) {
|
||||
|
||||
if($tocpath === false) {
|
||||
if(! $text) {
|
||||
$path = 'Site';
|
||||
$fullpath = get_help_fullpath($path,'.md');
|
||||
$path = 'Site';
|
||||
$fullpath = get_help_fullpath($path,'.md');
|
||||
$text = load_doc_file($fullpath . '.md');
|
||||
\App::$page['title'] = t('Help');
|
||||
}
|
||||
if(! $text) {
|
||||
$doctype = 'bbcode';
|
||||
$path = 'main';
|
||||
$fullpath = get_help_fullpath($path,'.md');
|
||||
$path = 'main';
|
||||
$fullpath = get_help_fullpath($path,'.md');
|
||||
$text = load_doc_file($fullpath . '.bb');
|
||||
goaway('/help/about/about');
|
||||
\App::$page['title'] = t('Help');
|
||||
@@ -172,16 +172,20 @@ function preg_callback_help_include($matches) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief Determines help language.
|
||||
*
|
||||
* @return boolean|array
|
||||
* If the language was specified in the URL, override the language preference
|
||||
* of the browser. Default to English if both of these are absent.
|
||||
*
|
||||
* @return array Associative array with:
|
||||
* * \e string \b language - 2-letter ISO 639-1 code ("en")
|
||||
* * \e boolean \b from_url - true if language from URL overrides browser default
|
||||
*/
|
||||
function determine_help_language() {
|
||||
$lang_detect = new Text_LanguageDetect();
|
||||
// Set this mode to recognize language by the short code like "en", "ru", etc.
|
||||
$lang_detect->setNameMode(2);
|
||||
// If the language was specified in the URL, override the language preference
|
||||
// of the browser. Default to English if both of these are absent.
|
||||
|
||||
if($lang_detect->languageExists(argv(1))) {
|
||||
$lang = argv(1);
|
||||
$from_url = true;
|
||||
@@ -212,14 +216,13 @@ function find_doc_file($s) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief Search in doc files.
|
||||
*
|
||||
* @param string $s
|
||||
* @return number|mixed|unknown|boolean
|
||||
* @param string $s The search string to search for
|
||||
* @return array
|
||||
*/
|
||||
function search_doc_files($s) {
|
||||
|
||||
|
||||
\App::set_pager_itemspage(60);
|
||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
||||
|
||||
@@ -277,7 +280,6 @@ function doc_rank_sort($s1, $s2) {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
||||
function load_context_help() {
|
||||
|
||||
$path = App::$cmd;
|
||||
@@ -307,7 +309,7 @@ function load_context_help() {
|
||||
* @brief
|
||||
*
|
||||
* @param string $s
|
||||
* @return void|boolean[]|number[]|string[]|unknown[]
|
||||
* @return void|array
|
||||
*/
|
||||
function store_doc_file($s) {
|
||||
|
||||
@@ -351,7 +353,8 @@ function store_doc_file($s) {
|
||||
$x = item_store_update($item);
|
||||
}
|
||||
else {
|
||||
$item['mid'] = $item['parent_mid'] = item_message_id();
|
||||
$item['uuid'] = item_message_id();
|
||||
$item['mid'] = $item['parent_mid'] = z_root() . '/item/' . $item['uuid'];
|
||||
$x = item_store($item);
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -12,6 +12,7 @@ require_once('include/perm_upgrade.php');
|
||||
* @param array $channel
|
||||
* @param int $account_id
|
||||
* @param int $seize
|
||||
* @param string $newname (optional)
|
||||
* @return boolean|array
|
||||
*/
|
||||
function import_channel($channel, $account_id, $seize, $newname = '') {
|
||||
@@ -650,7 +651,7 @@ function import_items($channel, $items, $sync = false, $relocate = null) {
|
||||
// preserve conversations you've been involved in from being expired
|
||||
|
||||
$stored = $item_result['item'];
|
||||
if((is_array($stored)) && ($stored['id'] != $stored['parent'])
|
||||
if((is_array($stored)) && ($stored['id'] != $stored['parent'])
|
||||
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
|
||||
retain_item($stored['item']['parent']);
|
||||
}
|
||||
@@ -672,7 +673,7 @@ function import_items($channel, $items, $sync = false, $relocate = null) {
|
||||
/**
|
||||
* @brief Sync items to channel.
|
||||
*
|
||||
* @see import_items
|
||||
* @see import_items()
|
||||
*
|
||||
* @param array $channel where to import to
|
||||
* @param array $items
|
||||
@@ -1049,7 +1050,7 @@ function import_mail($channel, $mails, $sync = false) {
|
||||
/**
|
||||
* @brief Synchronise mails.
|
||||
*
|
||||
* @see import_mail
|
||||
* @see import_mail()
|
||||
* @param array $channel
|
||||
* @param array $mails
|
||||
*/
|
||||
@@ -1337,7 +1338,7 @@ function sync_files($channel, $files) {
|
||||
|
||||
if($str)
|
||||
$str .= ",";
|
||||
|
||||
|
||||
$str .= " " . TQUOT . $k . TQUOT . " = '" . (($k === 'content') ? dbescbin($v) : dbesc($v)) . "' ";
|
||||
}
|
||||
$r = dbq("update photo set " . $str . " where id = " . intval($exists[0]['id']) );
|
||||
@@ -1521,7 +1522,8 @@ function import_webpage_element($element, $channel, $type) {
|
||||
}
|
||||
else { // otherwise, generate the creation times and unique id
|
||||
$arr['created'] = datetime_convert('UTC', 'UTC');
|
||||
$arr['mid'] = $arr['parent_mid'] = item_message_id();
|
||||
$arr['uuid'] = item_message_id();
|
||||
$arr['mid'] = $arr['parent_mid'] = z_root() . '/item/' . $arr['uuid'];
|
||||
}
|
||||
// Update the edited time whether or not the element already exists
|
||||
$arr['edited'] = datetime_convert('UTC', 'UTC');
|
||||
|
||||
+119
-19
@@ -7,6 +7,7 @@
|
||||
use Zotlabs\Lib\Enotify;
|
||||
use Zotlabs\Lib\MarkdownSoap;
|
||||
use Zotlabs\Lib\MessageFilter;
|
||||
use Zotlabs\Lib\ThreadListener;
|
||||
use Zotlabs\Lib\IConfig;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\AccessList;
|
||||
@@ -25,7 +26,7 @@ require_once('include/permissions.php');
|
||||
*
|
||||
* @param array $item
|
||||
* @param[out] boolean $private_envelope
|
||||
* @param boolean $include_groups
|
||||
* @param boolean $include_groups
|
||||
* @return array containing the recipients
|
||||
*/
|
||||
function collect_recipients($item, &$private_envelope,$include_groups = true) {
|
||||
@@ -95,9 +96,24 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
|
||||
//$sys = get_sys_channel();
|
||||
|
||||
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
|
||||
$r = q("select abook_xchan, xchan_network 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 ",
|
||||
|
||||
$hookinfo = [
|
||||
'recipients' => [],
|
||||
'item' => $item,
|
||||
'private_envelope' => $private_envelope,
|
||||
'include_groups' => $include_groups
|
||||
];
|
||||
|
||||
call_hooks('collect_public_recipients',$hookinfo);
|
||||
|
||||
if ($hookinfo['recipients']) {
|
||||
$r = $hookinfo['recipients'];
|
||||
} else {
|
||||
$r = q("select abook_xchan, xchan_network 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 ",
|
||||
intval($item['uid'])
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if($r) {
|
||||
|
||||
// filter out restrictive public_policy settings from remote networks
|
||||
@@ -126,6 +142,22 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
|
||||
// $recipients[] = $sys['xchan_hash'];
|
||||
}
|
||||
|
||||
|
||||
// Forward to thread listeners, *unless* there is even a remote hint that the item
|
||||
// might have some privacy attached. This could be (for instance) an ActivityPub DM
|
||||
// in the middle of a public thread. Unless we can guarantee beyond all doubt that
|
||||
// this is public, don't allow it to go to thread listeners.
|
||||
|
||||
if(! intval($item['item_private'])) {
|
||||
$r = ThreadListener::fetch_by_target($item['parent_mid']);
|
||||
if($r) {
|
||||
foreach($r as $rv) {
|
||||
$recipients[] = $rv['portable_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add the authors of any posts in this thread, if they are known to us.
|
||||
// This is specifically designed to forward wall-to-wall posts to the original author,
|
||||
// in case they aren't a connection but have permission to write on our wall.
|
||||
@@ -393,7 +425,11 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
|
||||
if(! array_key_exists('mimetype',$arr))
|
||||
$arr['mimetype'] = 'text/bbcode';
|
||||
|
||||
$arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : item_message_id());
|
||||
|
||||
if(! $arr['mid']) {
|
||||
$arr['uuid'] = ((x($arr,'uuid')) ? $arr['uuid'] : item_message_id());
|
||||
}
|
||||
$arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : z_root() . '/item/' . $arr['uuid']);
|
||||
$arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']);
|
||||
$arr['thr_parent'] = ((x($arr,'thr_parent')) ? $arr['thr_parent'] : $arr['mid']);
|
||||
|
||||
@@ -416,7 +452,7 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
|
||||
$arr['comment_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'],'post_comments'));
|
||||
|
||||
if ((! $arr['plink']) && (intval($arr['item_thread_top']))) {
|
||||
$arr['plink'] = substr(z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']),0,190);
|
||||
$arr['plink'] = substr(z_root() . '/channel/' . $channel['channel_address'] . '/' . (filter_var($arr['mid'], FILTER_VALIDATE_URL) === false ? '?f=&mid=' : '') . urlencode($arr['mid']),0,190);
|
||||
}
|
||||
|
||||
|
||||
@@ -450,6 +486,8 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
|
||||
*/
|
||||
call_hooks('post_local_end', $ret['activity']);
|
||||
}
|
||||
else
|
||||
return $ret;
|
||||
|
||||
if($post_id && $deliver) {
|
||||
Master::Summon([ 'Notifier','activity',$post_id ]);
|
||||
@@ -597,6 +635,7 @@ function get_item_elements($x,$allow_code = false) {
|
||||
$arr = array();
|
||||
|
||||
$arr['body'] = $x['body'];
|
||||
$arr['summary'] = $x['summary'];
|
||||
|
||||
$maxlen = get_max_import_size();
|
||||
|
||||
@@ -605,6 +644,11 @@ function get_item_elements($x,$allow_code = false) {
|
||||
logger('get_item_elements: message length exceeds max_import_size: truncated');
|
||||
}
|
||||
|
||||
if($maxlen && mb_strlen($arr['summary']) > $maxlen) {
|
||||
$arr['summary'] = mb_substr($arr['summary'],0,$maxlen,'UTF-8');
|
||||
logger('get_item_elements: message summary length exceeds max_import_size: truncated');
|
||||
}
|
||||
|
||||
$arr['created'] = datetime_convert('UTC','UTC',$x['created']);
|
||||
$arr['edited'] = datetime_convert('UTC','UTC',$x['edited']);
|
||||
|
||||
@@ -627,6 +671,7 @@ function get_item_elements($x,$allow_code = false) {
|
||||
if(mb_strlen($arr['title']) > 255)
|
||||
$arr['title'] = mb_substr($arr['title'],0,255);
|
||||
|
||||
$arr['uuid'] = (($x['uuid']) ? htmlspecialchars($x['uuid'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['app'] = (($x['app']) ? htmlspecialchars($x['app'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['route'] = (($x['route']) ? htmlspecialchars($x['route'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
$arr['mid'] = (($x['message_id']) ? htmlspecialchars($x['message_id'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
@@ -747,9 +792,10 @@ function get_item_elements($x,$allow_code = false) {
|
||||
// Do this after signature checking as the original signature
|
||||
// was generated on the escaped content.
|
||||
|
||||
if($arr['mimetype'] === 'text/markdown')
|
||||
if($arr['mimetype'] === 'text/markdown') {
|
||||
$arr['summary'] = MarkdownSoap::unescape($arr['summary']);
|
||||
$arr['body'] = MarkdownSoap::unescape($arr['body']);
|
||||
|
||||
}
|
||||
if(array_key_exists('revision',$x)) {
|
||||
|
||||
// extended export encoding
|
||||
@@ -1061,6 +1107,7 @@ function encode_item($item,$mirror = false) {
|
||||
$x['item_blocked'] = $item['item_blocked'];
|
||||
}
|
||||
|
||||
$x['uuid'] = $item['uuid'];
|
||||
$x['message_id'] = $item['mid'];
|
||||
$x['message_top'] = $item['parent_mid'];
|
||||
$x['message_parent'] = $item['thr_parent'];
|
||||
@@ -1071,6 +1118,7 @@ function encode_item($item,$mirror = false) {
|
||||
$x['commented'] = $item['commented'];
|
||||
$x['mimetype'] = $item['mimetype'];
|
||||
$x['title'] = $item['title'];
|
||||
$x['summary'] = $item['summary'];
|
||||
$x['body'] = $item['body'];
|
||||
$x['app'] = $item['app'];
|
||||
$x['verb'] = $item['verb'];
|
||||
@@ -1577,6 +1625,14 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
|
||||
'item' => $arr,
|
||||
'allow_exec' => $allow_exec
|
||||
];
|
||||
|
||||
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
|
||||
/* Custom items are not stored by default
|
||||
because they require an addon to process. */
|
||||
$d['item']['cancel']=true;
|
||||
|
||||
call_hooks('item_custom',$d);
|
||||
}
|
||||
/**
|
||||
* @hooks item_store
|
||||
* Called when item_store() stores a record of type item.
|
||||
@@ -1629,6 +1685,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
|
||||
}
|
||||
|
||||
$arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : '');
|
||||
$arr['summary'] = ((array_key_exists('summary',$arr) && strlen($arr['summary'])) ? trim($arr['summary']) : '');
|
||||
$arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : '');
|
||||
|
||||
$arr['allow_cid'] = ((x($arr,'allow_cid')) ? trim($arr['allow_cid']) : '');
|
||||
@@ -1637,6 +1694,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
|
||||
$arr['deny_gid'] = ((x($arr,'deny_gid')) ? trim($arr['deny_gid']) : '');
|
||||
$arr['postopts'] = ((x($arr,'postopts')) ? trim($arr['postopts']) : '');
|
||||
$arr['route'] = ((x($arr,'route')) ? trim($arr['route']) : '');
|
||||
$arr['uuid'] = ((x($arr,'uuid')) ? trim($arr['uuid']) : '');
|
||||
$arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : 0 );
|
||||
$arr['item_wall'] = ((x($arr,'item_wall')) ? intval($arr['item_wall']) : 0 );
|
||||
$arr['item_type'] = ((x($arr,'item_type')) ? intval($arr['item_type']) : 0 );
|
||||
@@ -1649,6 +1707,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
|
||||
|
||||
// apply the input filter here
|
||||
|
||||
$arr['summary'] = trim(z_input_filter($arr['summary'],$arr['mimetype'],$allow_exec));
|
||||
$arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec));
|
||||
|
||||
item_sign($arr);
|
||||
@@ -1999,8 +2058,20 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
|
||||
*/
|
||||
call_hooks('post_remote_end', $arr);
|
||||
|
||||
/**
|
||||
* @hooks item_stored
|
||||
* Called after new item is stored in the database.
|
||||
* (By this time we have an item_id and other frequently needed info.)
|
||||
*/
|
||||
call_hooks('item_stored',$arr);
|
||||
|
||||
item_update_parent_commented($arr);
|
||||
|
||||
|
||||
if(strpos($arr['body'],'[embed]') !== false) {
|
||||
Master::Summon([ 'Cache_embeds', $current_post ]);
|
||||
}
|
||||
|
||||
// If _creating_ a deleted item, don't propagate it further or send out notifications.
|
||||
// We need to store the item details just in case the delete came in before the original post,
|
||||
// so that we have an item in the DB that's marked deleted and won't store a fresh post
|
||||
@@ -2032,6 +2103,15 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
|
||||
'item' => $arr,
|
||||
'allow_exec' => $allow_exec
|
||||
];
|
||||
|
||||
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
|
||||
/* Custom items are not stored by default
|
||||
because they require an addon to process. */
|
||||
$d['item']['cancel']=true;
|
||||
|
||||
call_hooks('item_custom_update',$d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hooks item_store_update
|
||||
* Called when item_store_update() is called to update a stored item. It
|
||||
@@ -2094,6 +2174,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
|
||||
|
||||
// apply the input filter here
|
||||
|
||||
$arr['summary'] = trim(z_input_filter($arr['summary'],$arr['mimetype'],$allow_exec));
|
||||
$arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec));
|
||||
|
||||
item_sign($arr);
|
||||
@@ -2170,6 +2251,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
|
||||
$arr['route'] = ((array_key_exists('route',$arr)) ? trim($arr['route']) : $orig[0]['route']);
|
||||
|
||||
$arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : $orig[0]['location']);
|
||||
$arr['uuid'] = ((x($arr,'uuid')) ? notags(trim($arr['uuid'])) : $orig[0]['uuid']);
|
||||
$arr['coord'] = ((x($arr,'coord')) ? notags(trim($arr['coord'])) : $orig[0]['coord']);
|
||||
$arr['verb'] = ((x($arr,'verb')) ? notags(trim($arr['verb'])) : $orig[0]['verb']);
|
||||
$arr['obj_type'] = ((x($arr,'obj_type')) ? notags(trim($arr['obj_type'])) : $orig[0]['obj_type']);
|
||||
@@ -2320,6 +2402,19 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
|
||||
*/
|
||||
call_hooks('post_remote_update_end', $arr);
|
||||
|
||||
/**
|
||||
* @hooks item_stored_update
|
||||
* Called after updated item is stored in the database.
|
||||
*/
|
||||
call_hooks('item_stored_update',$arr);
|
||||
|
||||
if(strpos($arr['body'],'[embed]') !== false) {
|
||||
Master::Summon([ 'Cache_embeds', $orig_post_id ]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if($deliver) {
|
||||
send_status_notifications($orig_post_id,$arr);
|
||||
tag_deliver($uid,$orig_post_id);
|
||||
@@ -2336,15 +2431,15 @@ function item_update_parent_commented($item) {
|
||||
|
||||
$update_parent = true;
|
||||
|
||||
// update the commented timestamp on the parent
|
||||
// update the commented timestamp on the parent
|
||||
// - unless this is a moderated comment or a potential clone of an older item
|
||||
// which we don't wish to bring to the surface. As the queue only holds deliveries
|
||||
// for 3 days, it's suspected of being an older cloned item if the creation time
|
||||
// which we don't wish to bring to the surface. As the queue only holds deliveries
|
||||
// for 3 days, it's suspected of being an older cloned item if the creation time
|
||||
//is older than that.
|
||||
|
||||
if(intval($item['item_blocked']) === ITEM_MODERATED)
|
||||
$update_parent = false;
|
||||
|
||||
|
||||
if($item['created'] < datetime_convert('','','now - 4 days'))
|
||||
$update_parent = false;
|
||||
|
||||
@@ -2940,7 +3035,9 @@ function tgroup_check($uid, $item) {
|
||||
* @param array $channel
|
||||
* @param array $item
|
||||
* @param int $item_id
|
||||
* @param boolean $parent
|
||||
* @param array $parent
|
||||
* @param boolean $edit (optional) default false
|
||||
* @return void
|
||||
*/
|
||||
function start_delivery_chain($channel, $item, $item_id, $parent, $edit = false) {
|
||||
|
||||
@@ -2975,7 +3072,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $edit = false)
|
||||
}
|
||||
|
||||
// This will change the author to the post owner. Useful for RSS feeds which are to be syndicated
|
||||
// to federated platforms which can't verify the identity of the author.
|
||||
// to federated platforms which can't verify the identity of the author.
|
||||
// This MAY cause you to run afoul of copyright law.
|
||||
|
||||
$rewrite_author = intval(get_abconfig($channel['channel_id'],$item['owner_xchan'],'system','rself'));
|
||||
@@ -3488,7 +3585,7 @@ function item_expire($uid,$days,$comment_days = 7) {
|
||||
|
||||
if(! $comment_days)
|
||||
$comment_days = 7;
|
||||
|
||||
|
||||
// $expire_network_only = save your own wall posts
|
||||
// and just expire conversations started by others
|
||||
// do not enable this until we can pass bulk delete messages through zot
|
||||
@@ -3789,6 +3886,8 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
|
||||
intval(TERM_OBJ_POST)
|
||||
);
|
||||
|
||||
ThreadListener::delete_by_target($item['mid']);
|
||||
|
||||
/** @FIXME remove notifications for this item */
|
||||
|
||||
return true;
|
||||
@@ -4483,7 +4582,7 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow,
|
||||
$first_access_tag = true;
|
||||
|
||||
foreach($linkified as $x) {
|
||||
$access_tag = $x['access_tag'];
|
||||
$access_tag = $x['success']['access_tag'];
|
||||
if(($access_tag) && (! $parent_item)) {
|
||||
logger('access_tag: ' . $tag . ' ' . print_r($access_tag,true), LOGGER_DATA);
|
||||
if ($first_access_tag && (! get_pconfig($profile_uid,'system','no_private_mention_acl_override'))) {
|
||||
@@ -4589,7 +4688,7 @@ function sync_an_item($channel_id,$item_id) {
|
||||
if($r) {
|
||||
xchan_query($r);
|
||||
$sync_item = fetch_post_tags($r);
|
||||
build_sync_packet($channel_d,array('item' => array(encode_item($sync_item[0],true))));
|
||||
build_sync_packet($channel_id, array('item' => array(encode_item($sync_item[0],true))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4746,7 +4845,8 @@ function item_create_edit_activity($post) {
|
||||
|
||||
$new_item['id'] = 0;
|
||||
$new_item['parent'] = 0;
|
||||
$new_item['mid'] = item_message_id();
|
||||
$new_item['uuid'] = item_message_id();
|
||||
$new_item['mid'] = z_root() . '/item/' . $new_item['uuid'];
|
||||
|
||||
$new_item['body'] = sprintf( t('[Edited %s]'), (($update_item['item_thread_top']) ? t('Post','edit_activity') : t('Comment','edit_activity')));
|
||||
|
||||
@@ -4827,7 +4927,7 @@ function copy_of_pubitem($channel,$mid) {
|
||||
dbesc($mid),
|
||||
intval($syschan['channel_id'])
|
||||
);
|
||||
|
||||
|
||||
if($r) {
|
||||
$items = fetch_post_tags($r,true);
|
||||
foreach($items as $rv) {
|
||||
@@ -4853,5 +4953,5 @@ function copy_of_pubitem($channel,$mid) {
|
||||
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $rep
|
||||
|
||||
|
||||
$body = cleanup_bbcode($body);
|
||||
$results = linkify_tags($a, $body, $uid);
|
||||
$results = linkify_tags($body, $uid);
|
||||
|
||||
if(! $raw) {
|
||||
if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$match)) {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
/**
|
||||
* @file include/network.php
|
||||
* @brief Network related functions.
|
||||
@@ -110,6 +114,13 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
|
||||
@curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
|
||||
}
|
||||
|
||||
if(x($opts,'connecttimeout') && intval($opts['connecttimeout'])) {
|
||||
@curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($opts['connecttimeout']));
|
||||
}
|
||||
else {
|
||||
$curl_contime = intval(@get_config('system','curl_connecttimeout'));
|
||||
@curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (($curl_contime !== false) ? $curl_contime : 30));
|
||||
}
|
||||
|
||||
if(x($opts,'http_auth')) {
|
||||
// "username" . ':' . "password"
|
||||
@@ -324,6 +335,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
|
||||
|
||||
// Pull out multiple headers, e.g. proxy and continuation headers
|
||||
// allow for HTTP/2.x without fixing code
|
||||
|
||||
while(preg_match('/^HTTP\/[1-3](\.\d)? [1-5][0-9][0-9]/',$base)) {
|
||||
$chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
|
||||
$header .= $chunk;
|
||||
@@ -1108,6 +1120,31 @@ function discover_by_webbie($webbie, $protocol = '') {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($x['links'] as $link) {
|
||||
if(array_key_exists('rel',$link)) {
|
||||
if($link['rel'] === PROTOCOL_ZOT6 && ((! $protocol) || (strtolower($protocol) === 'zot6'))) {
|
||||
logger('zot6 found for ' . $webbie, LOGGER_DEBUG);
|
||||
$record = Zotfinger::exec($link['href']);
|
||||
|
||||
// Check the HTTP signature
|
||||
|
||||
$hsig = $record['signature'];
|
||||
if($hsig && ($hsig['signer'] === $url || $hsig['signer'] === $link['href']) && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
|
||||
$hsig_valid = true;
|
||||
|
||||
if(! $hsig_valid) {
|
||||
logger('http signature not valid: ' . print_r($hsig,true));
|
||||
continue;
|
||||
}
|
||||
|
||||
$x = Libzot::import_xchan($record['data']);
|
||||
if($x['success']) {
|
||||
return $x['hash'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger('webfinger: ' . print_r($x,true), LOGGER_DATA, LOG_INFO);
|
||||
|
||||
+227
-636
@@ -1,18 +1,34 @@
|
||||
<?php /** @file */
|
||||
<?php
|
||||
|
||||
use Zotlabs\Photo\PhotoDriver;
|
||||
use Zotlabs\Photo\PhotoGd;
|
||||
use Zotlabs\Photo\PhotoImagick;
|
||||
|
||||
/**
|
||||
* @brief Return a PhotoDriver object.
|
||||
*
|
||||
* Use this factory when manipulating images.
|
||||
*
|
||||
* Return a photo driver object implementing ImageMagick or GD.
|
||||
*
|
||||
* @param string $data Image data
|
||||
* @param string $type Mimetype
|
||||
* @return null|PhotoDriver
|
||||
* NULL if unsupported image type or failure, otherwise photo driver object
|
||||
*/
|
||||
function photo_factory($data, $type = null) {
|
||||
$ph = null;
|
||||
$m = null;
|
||||
|
||||
|
||||
$unsupported_types = array(
|
||||
$unsupported_types = [
|
||||
'image/bmp',
|
||||
'image/vnd.microsoft.icon',
|
||||
'image/tiff',
|
||||
'image/svg+xml'
|
||||
);
|
||||
'image/svg+xml',
|
||||
];
|
||||
|
||||
if($type && in_array(strtolower($type),$unsupported_types)) {
|
||||
logger('photo_factory: unsupported image type');
|
||||
if($type && in_array(strtolower($type), $unsupported_types)) {
|
||||
logger('Unsupported image type ' . $type);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -21,481 +37,62 @@ function photo_factory($data, $type = null) {
|
||||
if(class_exists('Imagick') && !$ignore_imagick) {
|
||||
$v = Imagick::getVersion();
|
||||
preg_match('/ImageMagick ([0-9]+\.[0-9]+\.[0-9]+)/', $v['versionString'], $m);
|
||||
if(version_compare($m[1],'6.6.7') >= 0) {
|
||||
require_once('include/photo/photo_imagick.php');
|
||||
$ph = new photo_imagick($data,$type);
|
||||
}
|
||||
else {
|
||||
if(version_compare($m[1], '6.6.7') >= 0) {
|
||||
$ph = new PhotoImagick($data, $type);
|
||||
} else {
|
||||
// earlier imagick versions have issues with scaling png's
|
||||
// don't log this because it will just fill the logfile.
|
||||
// leave this note here so those who are looking for why
|
||||
// leave this note here so those who are looking for why
|
||||
// we aren't using imagick can find it
|
||||
}
|
||||
}
|
||||
|
||||
if(! $ph) {
|
||||
require_once('include/photo/photo_gd.php');
|
||||
$ph = new photo_gd($data,$type);
|
||||
$ph = new PhotoGd($data, $type);
|
||||
}
|
||||
|
||||
return $ph;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
abstract class photo_driver {
|
||||
|
||||
protected $image;
|
||||
protected $width;
|
||||
protected $height;
|
||||
protected $valid;
|
||||
protected $type;
|
||||
protected $types;
|
||||
|
||||
abstract function supportedTypes();
|
||||
|
||||
abstract function load($data,$type);
|
||||
|
||||
abstract function destroy();
|
||||
|
||||
abstract function setDimensions();
|
||||
|
||||
abstract function getImage();
|
||||
|
||||
abstract function doScaleImage($new_width,$new_height);
|
||||
|
||||
abstract function rotate($degrees);
|
||||
|
||||
abstract function flip($horiz = true, $vert = false);
|
||||
|
||||
abstract function cropImage($max,$x,$y,$w,$h);
|
||||
|
||||
abstract function cropImageRect($maxx,$maxy,$x,$y,$w,$h);
|
||||
|
||||
abstract function imageString();
|
||||
|
||||
abstract function clearexif();
|
||||
|
||||
public function __construct($data, $type='') {
|
||||
$this->types = $this->supportedTypes();
|
||||
if (! array_key_exists($type,$this->types)){
|
||||
$type='image/jpeg';
|
||||
}
|
||||
$this->type = $type;
|
||||
$this->valid = false;
|
||||
$this->load($data,$type);
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if($this->is_valid())
|
||||
$this->destroy();
|
||||
}
|
||||
|
||||
public function is_valid() {
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
public function getWidth() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
public function getHeight() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
|
||||
public function saveImage($path) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
file_put_contents($path, $this->imageString());
|
||||
}
|
||||
|
||||
|
||||
public function getType() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getExt() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
return $this->types[$this->getType()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief scale image
|
||||
* int $max maximum pixel size in either dimension
|
||||
* boolean $float_height - if true allow height to float to any length on tall images,
|
||||
* constraining only the width
|
||||
*/
|
||||
|
||||
public function scaleImage($max, $float_height = true) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$width = $this->width;
|
||||
$height = $this->height;
|
||||
|
||||
$dest_width = $dest_height = 0;
|
||||
|
||||
if((! $width)|| (! $height))
|
||||
return FALSE;
|
||||
|
||||
if($width > $max && $height > $max) {
|
||||
|
||||
// very tall image (greater than 16:9)
|
||||
// constrain the width - let the height float.
|
||||
|
||||
if(((($height * 9) / 16) > $width) && ($float_height)) {
|
||||
$dest_width = $max;
|
||||
$dest_height = intval(( $height * $max ) / $width);
|
||||
}
|
||||
|
||||
// else constrain both dimensions
|
||||
|
||||
elseif($width > $height) {
|
||||
$dest_width = $max;
|
||||
$dest_height = intval(( $height * $max ) / $width);
|
||||
}
|
||||
else {
|
||||
$dest_width = intval(( $width * $max ) / $height);
|
||||
$dest_height = $max;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( $width > $max ) {
|
||||
$dest_width = $max;
|
||||
$dest_height = intval(( $height * $max ) / $width);
|
||||
}
|
||||
else {
|
||||
if( $height > $max ) {
|
||||
|
||||
// very tall image (greater than 16:9)
|
||||
// but width is OK - don't do anything
|
||||
|
||||
if(((($height * 9) / 16) > $width) && ($float_height)) {
|
||||
$dest_width = $width;
|
||||
$dest_height = $height;
|
||||
}
|
||||
else {
|
||||
$dest_width = intval(( $width * $max ) / $height);
|
||||
$dest_height = $max;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$dest_width = $width;
|
||||
$dest_height = $height;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->doScaleImage($dest_width,$dest_height);
|
||||
}
|
||||
|
||||
public function scaleImageUp($min) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
|
||||
$width = $this->width;
|
||||
$height = $this->height;
|
||||
|
||||
$dest_width = $dest_height = 0;
|
||||
|
||||
if((! $width)|| (! $height))
|
||||
return FALSE;
|
||||
|
||||
if($width < $min && $height < $min) {
|
||||
if($width > $height) {
|
||||
$dest_width = $min;
|
||||
$dest_height = intval(( $height * $min ) / $width);
|
||||
}
|
||||
else {
|
||||
$dest_width = intval(( $width * $min ) / $height);
|
||||
$dest_height = $min;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( $width < $min ) {
|
||||
$dest_width = $min;
|
||||
$dest_height = intval(( $height * $min ) / $width);
|
||||
}
|
||||
else {
|
||||
if( $height < $min ) {
|
||||
$dest_width = intval(( $width * $min ) / $height);
|
||||
$dest_height = $min;
|
||||
}
|
||||
else {
|
||||
$dest_width = $width;
|
||||
$dest_height = $height;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->doScaleImage($dest_width,$dest_height);
|
||||
}
|
||||
|
||||
|
||||
public function scaleImageSquare($dim) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
$this->doScaleImage($dim,$dim);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief reads exif data from filename
|
||||
*/
|
||||
|
||||
public function exif($filename) {
|
||||
|
||||
|
||||
if((! function_exists('exif_read_data'))
|
||||
|| (! in_array($this->getType(), [ 'image/jpeg' , 'image/tiff'] ))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* PHP 7.2 allows you to use a stream resource, which should reduce/avoid
|
||||
* memory exhaustion on large images.
|
||||
*/
|
||||
|
||||
if(version_compare(PHP_VERSION,'7.2.0') >= 0) {
|
||||
$f = @fopen($filename,'rb');
|
||||
}
|
||||
else {
|
||||
$f = $filename;
|
||||
}
|
||||
|
||||
if($f) {
|
||||
return @exif_read_data($f,null,true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief orients current image based on exif orientation information
|
||||
*/
|
||||
|
||||
public function orient($exif) {
|
||||
|
||||
if(! ($this->is_valid() && $exif)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ort = ((array_key_exists('IFD0',$exif)) ? $exif['IFD0']['Orientation'] : $exif['Orientation']);
|
||||
|
||||
if(! $ort) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($ort) {
|
||||
case 1: // nothing
|
||||
break;
|
||||
case 2: // horizontal flip
|
||||
$this->flip();
|
||||
break;
|
||||
case 3: // 180 rotate left
|
||||
$this->rotate(180);
|
||||
break;
|
||||
case 4: // vertical flip
|
||||
$this->flip(false, true);
|
||||
break;
|
||||
case 5: // vertical flip + 90 rotate right
|
||||
$this->flip(false, true);
|
||||
$this->rotate(-90);
|
||||
break;
|
||||
case 6: // 90 rotate right
|
||||
$this->rotate(-90);
|
||||
break;
|
||||
case 7: // horizontal flip + 90 rotate right
|
||||
$this->flip();
|
||||
$this->rotate(-90);
|
||||
break;
|
||||
case 8: // 90 rotate left
|
||||
$this->rotate(90);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function save($arr) {
|
||||
|
||||
if(! $this->is_valid()) {
|
||||
logger('attempt to store invalid photo.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$p = array();
|
||||
|
||||
$p['aid'] = ((intval($arr['aid'])) ? intval($arr['aid']) : 0);
|
||||
$p['uid'] = ((intval($arr['uid'])) ? intval($arr['uid']) : 0);
|
||||
$p['xchan'] = (($arr['xchan']) ? $arr['xchan'] : '');
|
||||
$p['resource_id'] = (($arr['resource_id']) ? $arr['resource_id'] : '');
|
||||
$p['filename'] = (($arr['filename']) ? $arr['filename'] : '');
|
||||
$p['album'] = (($arr['album']) ? $arr['album'] : '');
|
||||
$p['imgscale'] = ((intval($arr['imgscale'])) ? intval($arr['imgscale']) : 0);
|
||||
$p['allow_cid'] = (($arr['allow_cid']) ? $arr['allow_cid'] : '');
|
||||
$p['allow_gid'] = (($arr['allow_gid']) ? $arr['allow_gid'] : '');
|
||||
$p['deny_cid'] = (($arr['deny_cid']) ? $arr['deny_cid'] : '');
|
||||
$p['deny_gid'] = (($arr['deny_gid']) ? $arr['deny_gid'] : '');
|
||||
$p['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
|
||||
$p['title'] = (($arr['title']) ? $arr['title'] : '');
|
||||
$p['description'] = (($arr['description']) ? $arr['description'] : '');
|
||||
$p['photo_usage'] = intval($arr['photo_usage']);
|
||||
$p['os_storage'] = intval($arr['os_storage']);
|
||||
$p['os_path'] = $arr['os_path'];
|
||||
$p['os_syspath'] = ((array_key_exists('os_syspath',$arr)) ? $arr['os_syspath'] : '');
|
||||
$p['display_path'] = (($arr['display_path']) ? $arr['display_path'] : '');
|
||||
$p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth());
|
||||
$p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight());
|
||||
|
||||
if(! intval($p['imgscale']))
|
||||
logger('save: ' . print_r($arr,true), LOGGER_DATA);
|
||||
|
||||
$x = q("select id, created from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1",
|
||||
dbesc($p['resource_id']),
|
||||
intval($p['uid']),
|
||||
dbesc($p['xchan']),
|
||||
intval($p['imgscale'])
|
||||
);
|
||||
|
||||
if($x) {
|
||||
$p['created'] = (($x['created']) ? $x['created'] : $p['edited']);
|
||||
$r = q("UPDATE photo set
|
||||
aid = %d,
|
||||
uid = %d,
|
||||
xchan = '%s',
|
||||
resource_id = '%s',
|
||||
created = '%s',
|
||||
edited = '%s',
|
||||
filename = '%s',
|
||||
mimetype = '%s',
|
||||
album = '%s',
|
||||
height = %d,
|
||||
width = %d,
|
||||
content = '%s',
|
||||
os_storage = %d,
|
||||
filesize = %d,
|
||||
imgscale = %d,
|
||||
photo_usage = %d,
|
||||
title = '%s',
|
||||
description = '%s',
|
||||
os_path = '%s',
|
||||
display_path = '%s',
|
||||
allow_cid = '%s',
|
||||
allow_gid = '%s',
|
||||
deny_cid = '%s',
|
||||
deny_gid = '%s'
|
||||
where id = %d",
|
||||
|
||||
intval($p['aid']),
|
||||
intval($p['uid']),
|
||||
dbesc($p['xchan']),
|
||||
dbesc($p['resource_id']),
|
||||
dbesc($p['created']),
|
||||
dbesc($p['edited']),
|
||||
dbesc(basename($p['filename'])),
|
||||
dbesc($this->getType()),
|
||||
dbesc($p['album']),
|
||||
intval($p['height']),
|
||||
intval($p['width']),
|
||||
(intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())),
|
||||
intval($p['os_storage']),
|
||||
(intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())),
|
||||
intval($p['imgscale']),
|
||||
intval($p['photo_usage']),
|
||||
dbesc($p['title']),
|
||||
dbesc($p['description']),
|
||||
dbesc($p['os_path']),
|
||||
dbesc($p['display_path']),
|
||||
dbesc($p['allow_cid']),
|
||||
dbesc($p['allow_gid']),
|
||||
dbesc($p['deny_cid']),
|
||||
dbesc($p['deny_gid']),
|
||||
intval($x[0]['id'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
$p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']);
|
||||
$r = q("INSERT INTO photo
|
||||
( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid )
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
|
||||
intval($p['aid']),
|
||||
intval($p['uid']),
|
||||
dbesc($p['xchan']),
|
||||
dbesc($p['resource_id']),
|
||||
dbesc($p['created']),
|
||||
dbesc($p['edited']),
|
||||
dbesc(basename($p['filename'])),
|
||||
dbesc($this->getType()),
|
||||
dbesc($p['album']),
|
||||
intval($p['height']),
|
||||
intval($p['width']),
|
||||
(intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())),
|
||||
intval($p['os_storage']),
|
||||
(intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())),
|
||||
intval($p['imgscale']),
|
||||
intval($p['photo_usage']),
|
||||
dbesc($p['title']),
|
||||
dbesc($p['description']),
|
||||
dbesc($p['os_path']),
|
||||
dbesc($p['display_path']),
|
||||
dbesc($p['allow_cid']),
|
||||
dbesc($p['allow_gid']),
|
||||
dbesc($p['deny_cid']),
|
||||
dbesc($p['deny_gid'])
|
||||
);
|
||||
}
|
||||
logger('photo save ' . $p['imgscale'] . ' returned ' . intval($r));
|
||||
return $r;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Guess image mimetype from filename or from Content-Type header
|
||||
* @brief Guess image mimetype from filename or from Content-Type header.
|
||||
*
|
||||
* @arg $filename string Image filename
|
||||
* @arg $headers string Headers to check for Content-Type (from curl request)
|
||||
* @param string $filename
|
||||
* Image filename
|
||||
* @param string $headers (optional)
|
||||
* Headers to check for Content-Type (from curl request)
|
||||
* @return null|string Guessed mimetype
|
||||
*/
|
||||
|
||||
function guess_image_type($filename, $headers = '') {
|
||||
// logger('Photo: guess_image_type: '.$filename . ($headers?' from curl headers':''), LOGGER_DEBUG);
|
||||
$type = null;
|
||||
if ($headers) {
|
||||
$m = null;
|
||||
|
||||
$hdrs=array();
|
||||
$h = explode("\n",$headers);
|
||||
if($headers) {
|
||||
$hdrs = [];
|
||||
$h = explode("\n", $headers);
|
||||
foreach ($h as $l) {
|
||||
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
|
||||
list($k, $v) = array_map('trim', explode(':', trim($l), 2));
|
||||
$hdrs[strtolower($k)] = $v;
|
||||
}
|
||||
logger('Curl headers: '.var_export($hdrs, true), LOGGER_DEBUG);
|
||||
if (array_key_exists('content-type', $hdrs))
|
||||
$type = $hdrs['content-type'];
|
||||
}
|
||||
if (is_null($type)){
|
||||
logger('Curl headers: ' .var_export($hdrs, true), LOGGER_DEBUG);
|
||||
if(array_key_exists('content-type', $hdrs)) {
|
||||
$ph = photo_factory('');
|
||||
$types = $ph->supportedTypes();
|
||||
|
||||
if(array_key_exists($hdrs['content-type'], $types))
|
||||
$type = $hdrs['content-type'];
|
||||
}
|
||||
}
|
||||
|
||||
if(is_null($type)){
|
||||
$ignore_imagick = get_config('system', 'ignore_imagick');
|
||||
// Guessing from extension? Isn't that... dangerous?
|
||||
if(class_exists('Imagick') && file_exists($filename) && is_readable($filename) && !$ignore_imagick) {
|
||||
$v = Imagick::getVersion();
|
||||
preg_match('/ImageMagick ([0-9]+\.[0-9]+\.[0-9]+)/', $v['versionString'], $m);
|
||||
if(version_compare($m[1],'6.6.7') >= 0) {
|
||||
if(version_compare($m[1], '6.6.7') >= 0) {
|
||||
/**
|
||||
* Well, this not much better,
|
||||
* but at least it comes from the data inside the image,
|
||||
@@ -507,7 +104,7 @@ function guess_image_type($filename, $headers = '') {
|
||||
else {
|
||||
// earlier imagick versions have issues with scaling png's
|
||||
// don't log this because it will just fill the logfile.
|
||||
// leave this note here so those who are looking for why
|
||||
// leave this note here so those who are looking for why
|
||||
// we aren't using imagick can find it
|
||||
}
|
||||
}
|
||||
@@ -523,7 +120,7 @@ function guess_image_type($filename, $headers = '') {
|
||||
}
|
||||
}
|
||||
|
||||
if(is_null($type) && (strpos($filename,'http') === false)) {
|
||||
if(is_null($type) && (strpos($filename, 'http') === false)) {
|
||||
$size = getimagesize($filename);
|
||||
$ph = photo_factory('');
|
||||
$types = $ph->supportedTypes();
|
||||
@@ -542,33 +139,36 @@ function guess_image_type($filename, $headers = '') {
|
||||
|
||||
}
|
||||
logger('Photo: guess_image_type: filename = ' . $filename . ' type = ' . $type, LOGGER_DEBUG);
|
||||
return $type;
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
function delete_thing_photo($url,$ob_hash) {
|
||||
/**
|
||||
* @brief Delete thing photo from database.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $ob_hash
|
||||
* @return void
|
||||
*/
|
||||
function delete_thing_photo($url, $ob_hash) {
|
||||
|
||||
$hash = basename($url);
|
||||
$hash = substr($hash,0,strpos($hash,'-'));
|
||||
$hash = substr($hash, 0, strpos($hash, '-'));
|
||||
|
||||
// hashes should be 32 bytes.
|
||||
// hashes should be 32 bytes.
|
||||
|
||||
if((! $ob_hash) || (strlen($hash) < 16))
|
||||
return;
|
||||
return;
|
||||
|
||||
$r = q("delete from photo where xchan = '%s' and photo_usage = %d and resource_id = '%s'",
|
||||
q("delete from photo where xchan = '%s' and photo_usage = %d and resource_id = '%s'",
|
||||
dbesc($ob_hash),
|
||||
intval(PHOTO_THING),
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief fetches an photo from external site and prepares its miniatures.
|
||||
* @brief Fetches a photo from external site and prepares its miniatures.
|
||||
*
|
||||
* @param string $photo
|
||||
* external URL to fetch base image
|
||||
@@ -587,224 +187,215 @@ function delete_thing_photo($url,$ob_hash) {
|
||||
* * \e boolean \b 4 => TRUE if fetch failure
|
||||
* * \e string \b 5 => modification date
|
||||
*/
|
||||
function import_xchan_photo($photo, $xchan, $thing = false, $force = false) {
|
||||
$modified = '';
|
||||
$o = null;
|
||||
|
||||
function import_xchan_photo($photo,$xchan,$thing = false,$force = false) {
|
||||
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
|
||||
$album = (($thing) ? 'Things' : 'Contact Photos');
|
||||
|
||||
$modified = '';
|
||||
logger('Updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
|
||||
|
||||
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
|
||||
$album = (($thing) ? 'Things' : 'Contact Photos');
|
||||
if($thing) {
|
||||
$hash = photo_new_resource();
|
||||
} else {
|
||||
$r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1", dbesc($xchan), intval(PHOTO_XCHAN));
|
||||
if($r) {
|
||||
$hash = $r[0]['resource_id'];
|
||||
$modified = $r[0]['edited'];
|
||||
$type = $r[0]['mimetype'];
|
||||
} else {
|
||||
$hash = photo_new_resource();
|
||||
}
|
||||
}
|
||||
|
||||
logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
|
||||
|
||||
if($thing) {
|
||||
$hash = photo_new_resource();
|
||||
}
|
||||
else {
|
||||
$r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
|
||||
dbesc($xchan),
|
||||
intval(PHOTO_XCHAN)
|
||||
);
|
||||
if($r) {
|
||||
$hash = $r[0]['resource_id'];
|
||||
$modified = $r[0]['edited'];
|
||||
$type = $r[0]['mimetype'];
|
||||
}
|
||||
else {
|
||||
$hash = photo_new_resource();
|
||||
}
|
||||
}
|
||||
|
||||
$photo_failure = false;
|
||||
$img_str = '';
|
||||
|
||||
if($photo) {
|
||||
$filename = basename($photo);
|
||||
|
||||
if($force || $modified == '') {
|
||||
$result = z_fetch_url($photo,true);
|
||||
}
|
||||
else {
|
||||
$h = array('headers' => array("If-Modified-Since: " . gmdate("D, d M Y H:i:s", strtotime($modified . "Z")) . " GMT"));
|
||||
$result = z_fetch_url($photo,true,0,$h);
|
||||
}
|
||||
|
||||
if($result['success']) {
|
||||
$img_str = $result['body'];
|
||||
$type = guess_image_type($photo, $result['header']);
|
||||
$modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time()));
|
||||
|
||||
if(is_null($type))
|
||||
$photo_failure = true;
|
||||
}
|
||||
elseif($result['return_code'] == 304) {
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
}
|
||||
else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
$photo_failure = true;
|
||||
|
||||
if(! $photo_failure && $result['return_code'] != 304) {
|
||||
$img = photo_factory($img_str, $type);
|
||||
if($img->is_valid()) {
|
||||
$width = $img->getWidth();
|
||||
$height = $img->getHeight();
|
||||
|
||||
if($width && $height) {
|
||||
if(($width / $height) > 1.2) {
|
||||
// crop out the sides
|
||||
$margin = $width - $height;
|
||||
$img->cropImage(300,($margin / 2),0,$height,$height);
|
||||
}
|
||||
elseif(($height / $width) > 1.2) {
|
||||
// crop out the bottom
|
||||
$margin = $height - $width;
|
||||
$img->cropImage(300,0,0,$width,$width);
|
||||
|
||||
}
|
||||
else {
|
||||
$img->scaleImageSquare(300);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
$photo_failure = true;
|
||||
|
||||
$p = array(
|
||||
'xchan' => $xchan,
|
||||
'resource_id' => $hash,
|
||||
'filename' => basename($photo),
|
||||
'album' => $album,
|
||||
'photo_usage' => $flags,
|
||||
'imgscale' => 4,
|
||||
'edited' => $modified
|
||||
);
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$img->scaleImage(80);
|
||||
$p['imgscale'] = 5;
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$img->scaleImage(48);
|
||||
$p['imgscale'] = 6;
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
}
|
||||
else {
|
||||
logger('import_xchan_photo: invalid image from ' . $photo);
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
if($photo_failure) {
|
||||
$default = get_default_profile_photo();
|
||||
$photo = z_root() . '/' . $default;
|
||||
$thumb = z_root() . '/' . get_default_profile_photo(80);
|
||||
$micro = z_root() . '/' . get_default_profile_photo(48);
|
||||
$type = 'image/png';
|
||||
$modified = gmdate('Y-m-d H:i:s', filemtime($default));
|
||||
}
|
||||
|
||||
logger('HTTP code: ' . $result['return_code'] . '; modified: ' . $modified . '; failure: ' . ($photo_failure ? 'yes' : 'no') . '; URL: ' . $photo, LOGGER_DEBUG);
|
||||
return(array($photo,$thumb,$micro,$type,$photo_failure,$modified));
|
||||
|
||||
}
|
||||
|
||||
function import_channel_photo_from_url($photo,$aid,$uid) {
|
||||
$photo_failure = false;
|
||||
$img_str = '';
|
||||
|
||||
if($photo) {
|
||||
$filename = basename($photo);
|
||||
|
||||
$result = z_fetch_url($photo,true);
|
||||
if($force || $modified == '') {
|
||||
$result = z_fetch_url($photo, true);
|
||||
} else {
|
||||
$h = [
|
||||
'headers' => [
|
||||
'If-Modified-Since: ' . gmdate('D, d M Y H:i:s', strtotime($modified . 'Z')) . ' GMT'
|
||||
]
|
||||
];
|
||||
$result = z_fetch_url($photo, true, 0, $h);
|
||||
}
|
||||
|
||||
if($result['success']) {
|
||||
$img_str = $result['body'];
|
||||
$type = guess_image_type($photo, $result['header']);
|
||||
$modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time()));
|
||||
if(is_null($type))
|
||||
$photo_failure = true;
|
||||
} elseif($result['return_code'] == 304) {
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
} else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
} else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
||||
if(!$photo_failure && $result['return_code'] != 304) {
|
||||
$img = photo_factory($img_str, $type);
|
||||
if($img->is_valid()) {
|
||||
$width = $img->getWidth();
|
||||
$height = $img->getHeight();
|
||||
|
||||
if($width && $height) {
|
||||
if(($width / $height) > 1.2) {
|
||||
// crop out the sides
|
||||
$margin = $width - $height;
|
||||
$img->cropImage(300, ($margin / 2), 0, $height, $height);
|
||||
} elseif(($height / $width) > 1.2) {
|
||||
// crop out the bottom
|
||||
$margin = $height - $width;
|
||||
$img->cropImage(300, 0, 0, $width, $width);
|
||||
} else {
|
||||
$img->scaleImageSquare(300);
|
||||
}
|
||||
} else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
||||
$p = [
|
||||
'xchan' => $xchan,
|
||||
'resource_id' => $hash,
|
||||
'filename' => basename($photo),
|
||||
'album' => $album,
|
||||
'photo_usage' => $flags,
|
||||
'imgscale' => 4,
|
||||
'edited' => $modified,
|
||||
];
|
||||
|
||||
$r = $img->save($p);
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$img->scaleImage(80);
|
||||
$p['imgscale'] = 5;
|
||||
$r = $img->save($p);
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$img->scaleImage(48);
|
||||
$p['imgscale'] = 6;
|
||||
$r = $img->save($p);
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
$photo = z_root() . '/photo/' . $hash . '-4';
|
||||
$thumb = z_root() . '/photo/' . $hash . '-5';
|
||||
$micro = z_root() . '/photo/' . $hash . '-6';
|
||||
} else {
|
||||
logger('Invalid image from ' . $photo);
|
||||
$photo_failure = true;
|
||||
}
|
||||
}
|
||||
if($photo_failure) {
|
||||
$default = get_default_profile_photo();
|
||||
$photo = z_root() . '/' . $default;
|
||||
$thumb = z_root() . '/' . get_default_profile_photo(80);
|
||||
$micro = z_root() . '/' . get_default_profile_photo(48);
|
||||
$type = 'image/png';
|
||||
$modified = gmdate('Y-m-d H:i:s', filemtime($default));
|
||||
}
|
||||
|
||||
logger('HTTP code: ' . $result['return_code'] . '; modified: ' . $modified
|
||||
. '; failure: ' . ($photo_failure ? 'yes' : 'no') . '; URL: ' . $photo, LOGGER_DEBUG);
|
||||
|
||||
return([$photo, $thumb, $micro, $type, $photo_failure, $modified]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Import channel photo from a URL.
|
||||
*
|
||||
* @param string $photo URL to a photo
|
||||
* @param int $aid
|
||||
* @param int $uid channel_id
|
||||
* @return null|string Guessed image mimetype or null.
|
||||
*/
|
||||
function import_channel_photo_from_url($photo, $aid, $uid) {
|
||||
$type = null;
|
||||
|
||||
if($photo) {
|
||||
$result = z_fetch_url($photo, true);
|
||||
|
||||
if($result['success']) {
|
||||
$img_str = $result['body'];
|
||||
$type = guess_image_type($photo, $result['header']);
|
||||
|
||||
if(is_null($type))
|
||||
$photo_failure = true;
|
||||
import_channel_photo($img_str, $type, $aid, $uid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
||||
import_channel_photo($img_str,$type,$aid,$uid);
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Import a channel photo and prepare its miniatures.
|
||||
*
|
||||
* @param string $photo Image data
|
||||
* @param string $type
|
||||
* @param int $aid
|
||||
* @param int $uid channel_id
|
||||
* @return boolean|string false on failure, otherwise resource_id of photo
|
||||
*/
|
||||
function import_channel_photo($photo, $type, $aid, $uid) {
|
||||
|
||||
function import_channel_photo($photo,$type,$aid,$uid) {
|
||||
|
||||
logger('import_channel_photo: importing channel photo for ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$hash = photo_new_resource();
|
||||
logger('Importing channel photo for ' . $uid, LOGGER_DEBUG);
|
||||
|
||||
$photo_failure = false;
|
||||
|
||||
|
||||
$hash = photo_new_resource();
|
||||
$filename = $hash;
|
||||
|
||||
$img = photo_factory($photo, $type);
|
||||
if($img->is_valid()) {
|
||||
|
||||
// config array for image save method
|
||||
$p = [
|
||||
'aid' => $aid,
|
||||
'uid' => $uid,
|
||||
'resource_id' => $hash,
|
||||
'filename' => $filename,
|
||||
'album' => t('Profile Photos'),
|
||||
'photo_usage' => PHOTO_PROFILE,
|
||||
'imgscale' => 4,
|
||||
];
|
||||
|
||||
// photo size
|
||||
$img->scaleImageSquare(300);
|
||||
|
||||
$p = array('aid' => $aid, 'uid' => $uid, 'resource_id' => $hash, 'filename' => $filename, 'album' => t('Profile Photos'), 'photo_usage' => PHOTO_PROFILE, 'imgscale' => 4);
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
// thumb size
|
||||
$img->scaleImage(80);
|
||||
$p['imgscale'] = 5;
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
// micro size
|
||||
$img->scaleImage(48);
|
||||
$p['imgscale'] = 6;
|
||||
|
||||
$r = $img->save($p);
|
||||
|
||||
if($r === false)
|
||||
$photo_failure = true;
|
||||
|
||||
}
|
||||
else {
|
||||
logger('import_channel_photo: invalid image.');
|
||||
} else {
|
||||
logger('Invalid image.');
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
||||
//return(($photo_failure)? false : true);
|
||||
|
||||
if($photo_failure)
|
||||
return false;
|
||||
else
|
||||
return $hash;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
<?php /** @file */
|
||||
|
||||
|
||||
require_once('include/photo/photo_driver.php');
|
||||
|
||||
|
||||
class photo_gd extends photo_driver {
|
||||
|
||||
function supportedTypes() {
|
||||
$t = array();
|
||||
$t['image/jpeg'] ='jpg';
|
||||
if (imagetypes() & IMG_PNG) $t['image/png'] = 'png';
|
||||
if (imagetypes() & IMG_GIF) $t['image/gif'] = 'gif';
|
||||
return $t;
|
||||
|
||||
}
|
||||
|
||||
function load($data, $type) {
|
||||
$this->valid = false;
|
||||
if(! $data)
|
||||
return;
|
||||
|
||||
$this->image = @imagecreatefromstring($data);
|
||||
if($this->image !== FALSE) {
|
||||
$this->valid = true;
|
||||
$this->setDimensions();
|
||||
imagealphablending($this->image, false);
|
||||
imagesavealpha($this->image, true);
|
||||
}
|
||||
}
|
||||
|
||||
function setDimensions() {
|
||||
$this->width = imagesx($this->image);
|
||||
$this->height = imagesy($this->image);
|
||||
}
|
||||
|
||||
|
||||
public function clearexif() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public function destroy() {
|
||||
if($this->is_valid()) {
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
}
|
||||
|
||||
public function getImage() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function doScaleImage($dest_width,$dest_height) {
|
||||
|
||||
$dest = imagecreatetruecolor( $dest_width, $dest_height );
|
||||
$width = imagesx($this->image);
|
||||
$height = imagesy($this->image);
|
||||
|
||||
imagealphablending($dest, false);
|
||||
imagesavealpha($dest, true);
|
||||
if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha
|
||||
imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height);
|
||||
if($this->image)
|
||||
imagedestroy($this->image);
|
||||
$this->image = $dest;
|
||||
$this->setDimensions();
|
||||
}
|
||||
|
||||
public function rotate($degrees) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$this->image = imagerotate($this->image,$degrees,0);
|
||||
$this->setDimensions();
|
||||
}
|
||||
|
||||
public function flip($horiz = true, $vert = false) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$w = imagesx($this->image);
|
||||
$h = imagesy($this->image);
|
||||
$flipped = imagecreate($w, $h);
|
||||
if($horiz) {
|
||||
for ($x = 0; $x < $w; $x++) {
|
||||
imagecopy($flipped, $this->image, $x, 0, $w - $x - 1, 0, 1, $h);
|
||||
}
|
||||
}
|
||||
if($vert) {
|
||||
for ($y = 0; $y < $h; $y++) {
|
||||
imagecopy($flipped, $this->image, 0, $y, 0, $h - $y - 1, $w, 1);
|
||||
}
|
||||
}
|
||||
$this->image = $flipped;
|
||||
$this->setDimensions(); // Shouldn't really be necessary
|
||||
}
|
||||
|
||||
public function cropImage($max,$x,$y,$w,$h) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$dest = imagecreatetruecolor( $max, $max );
|
||||
imagealphablending($dest, false);
|
||||
imagesavealpha($dest, true);
|
||||
if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha
|
||||
imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h);
|
||||
if($this->image)
|
||||
imagedestroy($this->image);
|
||||
$this->image = $dest;
|
||||
$this->setDimensions();
|
||||
}
|
||||
|
||||
public function cropImageRect($maxx,$maxy,$x,$y,$w,$h) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$dest = imagecreatetruecolor( $maxx, $maxy );
|
||||
imagealphablending($dest, false);
|
||||
imagesavealpha($dest, true);
|
||||
if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha
|
||||
imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $maxx, $maxy, $w, $h);
|
||||
if($this->image)
|
||||
imagedestroy($this->image);
|
||||
$this->image = $dest;
|
||||
$this->setDimensions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function imageString() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$quality = FALSE;
|
||||
|
||||
ob_start();
|
||||
|
||||
switch($this->getType()){
|
||||
case "image/png":
|
||||
$quality = get_config('system','png_quality');
|
||||
if((! $quality) || ($quality > 9))
|
||||
$quality = PNG_QUALITY;
|
||||
imagepng($this->image,NULL, $quality);
|
||||
break;
|
||||
case "image/jpeg":
|
||||
default:
|
||||
$quality = get_config('system','jpeg_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
$quality = JPEG_QUALITY;
|
||||
imagejpeg($this->image,NULL,$quality);
|
||||
break;
|
||||
}
|
||||
$string = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
<?php /** @file */
|
||||
|
||||
|
||||
require_once('include/photo/photo_driver.php');
|
||||
|
||||
|
||||
class photo_imagick extends photo_driver {
|
||||
|
||||
|
||||
function supportedTypes() {
|
||||
return array(
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif'
|
||||
);
|
||||
}
|
||||
|
||||
public function get_FormatsMap() {
|
||||
return array(
|
||||
'image/jpeg' => 'JPG',
|
||||
'image/png' => 'PNG',
|
||||
'image/gif' => 'GIF'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function load($data, $type) {
|
||||
$this->valid = false;
|
||||
$this->image = new Imagick();
|
||||
|
||||
if(! $data)
|
||||
return;
|
||||
|
||||
try {
|
||||
$this->image->readImageBlob($data);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
logger('imagick readImageBlob() exception:' . print_r($e,true));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the image to the format it will be saved to
|
||||
*/
|
||||
|
||||
$map = $this->get_FormatsMap();
|
||||
$format = $map[$type];
|
||||
|
||||
if($this->image) {
|
||||
$this->image->setFormat($format);
|
||||
|
||||
// Always coalesce, if it is not a multi-frame image it won't hurt anyway
|
||||
$this->image = $this->image->coalesceImages();
|
||||
|
||||
|
||||
$this->valid = true;
|
||||
$this->setDimensions();
|
||||
|
||||
/**
|
||||
* setup the compression here, so we'll do it only once
|
||||
*/
|
||||
switch($this->getType()) {
|
||||
case "image/png":
|
||||
$quality = get_config('system','png_quality');
|
||||
if((! $quality) || ($quality > 9))
|
||||
$quality = PNG_QUALITY;
|
||||
/**
|
||||
* From http://www.imagemagick.org/script/command-line-options.php#quality:
|
||||
*
|
||||
* 'For the MNG and PNG image formats, the quality value sets
|
||||
* the zlib compression level (quality / 10) and filter-type (quality % 10).
|
||||
* The default PNG "quality" is 75, which means compression level 7 with adaptive PNG filtering,
|
||||
* unless the image has a color map, in which case it means compression level 7 with no PNG filtering'
|
||||
*/
|
||||
$quality = $quality * 10;
|
||||
$this->image->setCompressionQuality($quality);
|
||||
break;
|
||||
case "image/jpeg":
|
||||
$quality = get_config('system','jpeg_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
$quality = JPEG_QUALITY;
|
||||
$this->image->setCompressionQuality($quality);
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy() {
|
||||
if($this->is_valid()) {
|
||||
$this->image->clear();
|
||||
$this->image->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function setDimensions() {
|
||||
$this->width = $this->image->getImageWidth();
|
||||
$this->height = $this->image->getImageHeight();
|
||||
}
|
||||
|
||||
|
||||
public function clearexif() {
|
||||
|
||||
$profiles = $this->image->getImageProfiles("icc", true);
|
||||
|
||||
$this->image->stripImage();
|
||||
|
||||
if(!empty($profiles)) {
|
||||
$this->image->profileImage("icc", $profiles['icc']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getImage() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$this->image = $this->image->deconstructImages();
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function doScaleImage($dest_width,$dest_height) {
|
||||
|
||||
/**
|
||||
* If it is not animated, there will be only one iteration here,
|
||||
* so don't bother checking
|
||||
*/
|
||||
// Don't forget to go back to the first frame
|
||||
$this->image->setFirstIterator();
|
||||
do {
|
||||
$this->image->scaleImage($dest_width, $dest_height);
|
||||
} while ($this->image->nextImage());
|
||||
|
||||
$this->setDimensions();
|
||||
}
|
||||
|
||||
public function rotate($degrees) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$this->image->setFirstIterator();
|
||||
do {
|
||||
// ImageMagick rotates in the opposite direction of imagerotate()
|
||||
$this->image->rotateImage(new ImagickPixel(), -$degrees);
|
||||
} while ($this->image->nextImage());
|
||||
|
||||
$this->setDimensions();
|
||||
}
|
||||
|
||||
public function flip($horiz = true, $vert = false) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$this->image->setFirstIterator();
|
||||
do {
|
||||
if($horiz) $this->image->flipImage();
|
||||
if($vert) $this->image->flopImage();
|
||||
} while ($this->image->nextImage());
|
||||
|
||||
$this->setDimensions(); // Shouldn't really be necessary
|
||||
}
|
||||
|
||||
public function cropImage($max,$x,$y,$w,$h) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$this->image->setFirstIterator();
|
||||
do {
|
||||
$this->image->cropImage($w, $h, $x, $y);
|
||||
/**
|
||||
* We need to remove the canvas,
|
||||
* or the image is not resized to the crop:
|
||||
* http://php.net/manual/en/imagick.cropimage.php#97232
|
||||
*/
|
||||
$this->image->setImagePage(0, 0, 0, 0);
|
||||
} while ($this->image->nextImage());
|
||||
|
||||
$this->doScaleImage($max,$max);
|
||||
}
|
||||
|
||||
public function cropImageRect($maxx,$maxy,$x,$y,$w,$h) {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
$this->image->setFirstIterator();
|
||||
do {
|
||||
$this->image->cropImage($w, $h, $x, $y);
|
||||
/**
|
||||
* We need to remove the canvas,
|
||||
* or the image is not resized to the crop:
|
||||
* http://php.net/manual/en/imagick.cropimage.php#97232
|
||||
*/
|
||||
$this->image->setImagePage(0, 0, 0, 0);
|
||||
} while ($this->image->nextImage());
|
||||
|
||||
$this->doScaleImage($maxx,$maxy);
|
||||
}
|
||||
|
||||
public function imageString() {
|
||||
if(!$this->is_valid())
|
||||
return FALSE;
|
||||
|
||||
/* Clean it */
|
||||
$this->image = $this->image->deconstructImages();
|
||||
return $this->image->getImagesBlob();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+7
-3
@@ -356,7 +356,7 @@ function photo_upload($channel, $observer, $args) {
|
||||
|
||||
$large_photos = feature_enabled($channel['channel_id'], 'large_photos');
|
||||
|
||||
linkify_tags($a, $args['body'], $channel_id);
|
||||
linkify_tags($args['body'], $channel_id);
|
||||
|
||||
if($large_photos) {
|
||||
$scale = 1;
|
||||
@@ -441,11 +441,13 @@ function photo_upload($channel, $observer, $args) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
$mid = item_message_id();
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$arr = [
|
||||
'aid' => $account_id,
|
||||
'uid' => $channel_id,
|
||||
'uuid' => $uuid,
|
||||
'mid' => $mid,
|
||||
'parent_mid' => $mid,
|
||||
'item_hidden' => $item_hidden,
|
||||
@@ -827,12 +829,14 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
|
||||
|
||||
$item_hidden = (($visible) ? 0 : 1 );
|
||||
|
||||
$mid = item_message_id();
|
||||
$uuid = item_message_id();
|
||||
$mid = z_root() . '/item/' . $uuid;
|
||||
|
||||
$arr = array();
|
||||
|
||||
$arr['aid'] = $channel['channel_account_id'];
|
||||
$arr['uid'] = $channel['channel_id'];
|
||||
$arr['uuid'] = $uuid;
|
||||
$arr['mid'] = $mid;
|
||||
$arr['parent_mid'] = $mid;
|
||||
$arr['item_wall'] = 1;
|
||||
|
||||
+47
-46
@@ -7,13 +7,15 @@
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle errors in plugin calls
|
||||
* @brief Handle errors in plugin calls.
|
||||
*
|
||||
* @param string $plugin name of the addon
|
||||
* @param string $error_text text of error
|
||||
* @param bool $uninstall uninstall plugin
|
||||
* @param string $notice UI visible text of error
|
||||
* @param string $log technical error message for logging
|
||||
* @param bool $uninstall (optional) default false
|
||||
* uninstall plugin on error
|
||||
*/
|
||||
function handleerrors_plugin($plugin,$notice,$log,$uninstall=false){
|
||||
function handleerrors_plugin($plugin, $notice, $log, $uninstall = false){
|
||||
logger("Addons: [" . $plugin . "] Error: ".$log, LOGGER_ERROR);
|
||||
if ($notice != '') {
|
||||
notice("[" . $plugin . "] Error: ".$notice, LOGGER_ERROR);
|
||||
@@ -23,7 +25,7 @@ function handleerrors_plugin($plugin,$notice,$log,$uninstall=false){
|
||||
$idx = array_search($plugin, \App::$plugins);
|
||||
unset(\App::$plugins[$idx]);
|
||||
uninstall_plugin($plugin);
|
||||
set_config("system","addon", implode(", ",\App::$plugins));
|
||||
set_config("system", "addon", implode(", ", \App::$plugins));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,8 +215,8 @@ function reload_plugins() {
|
||||
try {
|
||||
$func();
|
||||
} catch (Exception $e) {
|
||||
handleerrors_plugin($plugin,"","UNLOAD FAILED (uninstalling) : ".$e->getMessage(),true);
|
||||
continue;
|
||||
handleerrors_plugin($pl, '', 'UNLOAD FAILED (uninstalling) : ' . $e->getMessage(),true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(function_exists($pl . '_load')) {
|
||||
@@ -222,8 +224,8 @@ function reload_plugins() {
|
||||
try {
|
||||
$func();
|
||||
} catch (Exception $e) {
|
||||
handleerrors_plugin($plugin,"","LOAD FAILED (uninstalling): ".$e->getMessage(),true);
|
||||
continue;
|
||||
handleerrors_plugin($pl, '', 'LOAD FAILED (uninstalling): ' . $e->getMessage(),true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
q("UPDATE addon SET tstamp = %d WHERE id = %d",
|
||||
@@ -305,7 +307,7 @@ function plugins_sync() {
|
||||
* @return array
|
||||
*/
|
||||
function visible_plugin_list() {
|
||||
|
||||
|
||||
$r = q("select * from addon where hidden = 0 order by aname asc");
|
||||
$x = (($r) ? ids_to_array($r,'aname') : array());
|
||||
$y = [];
|
||||
@@ -315,7 +317,7 @@ function visible_plugin_list() {
|
||||
$y[] = $xv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $y;
|
||||
}
|
||||
|
||||
@@ -381,8 +383,6 @@ function unregister_hook($hook, $file, $function) {
|
||||
* array in their theme_init() and use this to customise the app behaviour.
|
||||
* use insert_hook($hookname,$function_name) to do this.
|
||||
*/
|
||||
|
||||
|
||||
function load_hooks() {
|
||||
|
||||
App::$hooks = [];
|
||||
@@ -456,21 +456,21 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) {
|
||||
function call_hooks($name, &$data = null) {
|
||||
$a = 0;
|
||||
|
||||
if (isset(App::$hooks[$name])) {
|
||||
if (isset(App::$hooks[$name])) {
|
||||
foreach(App::$hooks[$name] as $hook) {
|
||||
|
||||
if ($name != 'permit_hook') { // avoid looping
|
||||
$checkhook = [
|
||||
'name'=>$name,
|
||||
'hook'=>$hook,
|
||||
'data'=>$data,
|
||||
'name'=>$name,
|
||||
'hook'=>$hook,
|
||||
'data'=>$data,
|
||||
// Note: Since PHP uses COPY-ON-WRITE
|
||||
// for variables, there is no cost to
|
||||
// for variables, there is no cost to
|
||||
// passing the $data structure (unless
|
||||
// the permit_hook processors change the
|
||||
// information it contains.
|
||||
'permit'=>true
|
||||
];
|
||||
'permit'=>true
|
||||
];
|
||||
call_hooks('permit_hook',$checkhook);
|
||||
if (!$checkhook['permit']) {
|
||||
continue;
|
||||
@@ -618,7 +618,7 @@ function get_widget_info($widget){
|
||||
}
|
||||
}
|
||||
|
||||
if(! ($widget_found && $f))
|
||||
if(! ($widget_found && $f))
|
||||
return $info;
|
||||
|
||||
$f = escape_tags($f);
|
||||
@@ -736,8 +736,8 @@ function get_theme_info($theme){
|
||||
'description' => '',
|
||||
'author' => array(),
|
||||
'version' => '',
|
||||
'minversion' => '',
|
||||
'maxversion' => '',
|
||||
'minversion' => STD_VERSION,
|
||||
'maxversion' => STD_VERSION,
|
||||
'compat' => '',
|
||||
'credits' => '',
|
||||
'maintainer' => array(),
|
||||
@@ -1041,7 +1041,7 @@ function get_intltext_template($s, $root = '') {
|
||||
if (isset(\App::$override_intltext_templates[$testroot][$s]["content"])) {
|
||||
return \App::$override_intltext_templates[$testroot][$s]["content"];
|
||||
} else {
|
||||
if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) &&
|
||||
if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) &&
|
||||
isset(\App::$override_intltext_templates[$testroot][$s]["file"])) {
|
||||
$s = \App::$override_intltext_templates[$testroot][$s]["file"];
|
||||
$root = \App::$override_intltext_templates[$testroot][$s]["root"];
|
||||
@@ -1058,37 +1058,38 @@ function get_intltext_template($s, $root = '') {
|
||||
}
|
||||
|
||||
function get_markup_template($s, $root = '') {
|
||||
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
|
||||
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
|
||||
|
||||
$t = App::template_engine();
|
||||
$t = App::template_engine();
|
||||
|
||||
if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) {
|
||||
return \App::$override_markup_templates[$testroot][$s]["content"];
|
||||
} else {
|
||||
if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) &&
|
||||
isset(\App::$override_markup_templates[$testroot][$s]["file"])) {
|
||||
$root = \App::$override_markup_templates[$testroot][$s]["root"];
|
||||
$s = \App::$override_markup_templates[$testroot][$s]["file"];
|
||||
$template = $t->get_markup_template($s, $root);
|
||||
} elseif (\App::$override_templateroot) {
|
||||
$newroot = \App::$override_templateroot;
|
||||
if ($newroot != '' && substr($newroot,-1) != '/' ) {
|
||||
$newroot .= '/';
|
||||
}
|
||||
$newroot .= $root;
|
||||
$template = $t->get_markup_template($s, $newroot);
|
||||
} else {
|
||||
$template = $t->get_markup_template($s, $root);
|
||||
if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) {
|
||||
return \App::$override_markup_templates[$testroot][$s]["content"];
|
||||
} else {
|
||||
if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) &&
|
||||
isset(\App::$override_markup_templates[$testroot][$s]["file"])) {
|
||||
$root = \App::$override_markup_templates[$testroot][$s]["root"];
|
||||
$s = \App::$override_markup_templates[$testroot][$s]["file"];
|
||||
$template = $t->get_markup_template($s, $root);
|
||||
} elseif (\App::$override_templateroot) {
|
||||
$newroot = \App::$override_templateroot;
|
||||
if ($newroot != '' && substr($newroot,-1) != '/' ) {
|
||||
$newroot .= '/';
|
||||
}
|
||||
$newroot .= $root;
|
||||
$template = $t->get_markup_template($s, $newroot);
|
||||
} else {
|
||||
$template = $t->get_markup_template($s, $root);
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief Test if a folder exists.
|
||||
*
|
||||
* @param string $folder
|
||||
* @return boolean|string
|
||||
* False if folder does not exist, or canonicalized absolute pathname
|
||||
*/
|
||||
function folder_exists($folder) {
|
||||
// Get canonicalized absolute pathname
|
||||
|
||||
+80
-28
@@ -1,5 +1,9 @@
|
||||
<?php /** @file */
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Zot6\Receiver;
|
||||
use Zotlabs\Zot6\Zot6Handler;
|
||||
|
||||
function update_queue_item($id, $add_priority = 0) {
|
||||
logger('queue: requeue item ' . $id,LOGGER_DEBUG);
|
||||
$x = q("select outq_created, outq_posturl from outq where outq_hash = '%s' limit 1",
|
||||
@@ -9,7 +13,7 @@ function update_queue_item($id, $add_priority = 0) {
|
||||
return;
|
||||
|
||||
|
||||
$y = q("select min(outq_created) as earliest from outq where outq_posturl = '%s'",
|
||||
$y = q("select outq_created as earliest from outq where outq_posturl = '%s' order by earliest limit 1",
|
||||
dbesc($x[0]['outq_posturl'])
|
||||
);
|
||||
|
||||
@@ -226,37 +230,85 @@ function queue_deliver($outq, $immediate = false) {
|
||||
|
||||
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||
|
||||
$channel = null;
|
||||
if($outq['outq_driver'] === 'zot6') {
|
||||
|
||||
if($outq['outq_msg'] && $outq['outq_channel']) {
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
}
|
||||
if($outq['outq_posturl'] === z_root() . '/zot') {
|
||||
// local delivery
|
||||
$zot = new Receiver(new Zot6Handler(),$outq['outq_notify']);
|
||||
$result = $zot->run(true);
|
||||
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
|
||||
logger('deliver: local zot6 delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'],[ 'success' => true, 'body' => json_encode($result) ], $outq);
|
||||
}
|
||||
else {
|
||||
logger('remote');
|
||||
$channel = null;
|
||||
|
||||
$host_crypto = null;
|
||||
if($outq['outq_channel']) {
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
}
|
||||
|
||||
$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 = 'zot6' order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if($h) {
|
||||
$host_crypto = $h[0];
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $outq['outq_notify'];
|
||||
|
||||
$result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
|
||||
|
||||
if($result['success']) {
|
||||
logger('deliver: remote zot6 delivery succeeded to ' . $outq['outq_posturl']);
|
||||
Libzot::process_response($outq['outq_posturl'],$result, $outq);
|
||||
}
|
||||
else {
|
||||
logger('deliver: remote zot6 delivery failed to ' . $outq['outq_posturl']);
|
||||
logger('deliver: remote zot6 delivery fail data: ' . print_r($result,true), LOGGER_DATA);
|
||||
update_queue_item($outq['outq_hash'],10);
|
||||
}
|
||||
|
||||
if($channel && $base) {
|
||||
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if($h) {
|
||||
$host_crypto = $h[0];
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $outq['outq_notify'];
|
||||
|
||||
$result = zot_zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
|
||||
|
||||
|
||||
if($result['success']) {
|
||||
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
zot_process_response($outq['outq_posturl'],$result, $outq);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
|
||||
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
|
||||
update_queue_item($outq['outq_hash'],10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$channel = null;
|
||||
|
||||
if($outq['outq_msg'] && $outq['outq_channel']) {
|
||||
$channel = channelx_by_n($outq['outq_channel']);
|
||||
}
|
||||
|
||||
$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' order by hubloc_id desc limit 1",
|
||||
dbesc($base)
|
||||
);
|
||||
if($h) {
|
||||
$host_crypto = $h[0];
|
||||
}
|
||||
}
|
||||
|
||||
$msg = $outq['outq_notify'];
|
||||
|
||||
$result = zot_zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
|
||||
|
||||
|
||||
if($result['success']) {
|
||||
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||
zot_process_response($outq['outq_posturl'],$result, $outq);
|
||||
}
|
||||
else {
|
||||
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
|
||||
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
|
||||
update_queue_item($outq['outq_hash'],10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+298
-165
@@ -3,8 +3,11 @@
|
||||
* @file include/text.php
|
||||
*/
|
||||
|
||||
use \Zotlabs\Lib as Zlib;
|
||||
use \Michelf\MarkdownExtra;
|
||||
use Zotlabs\Lib as Zlib;
|
||||
|
||||
use Michelf\MarkdownExtra;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
|
||||
|
||||
require_once("include/bbcode.php");
|
||||
|
||||
@@ -38,12 +41,12 @@ function replace_macros($s, $r) {
|
||||
|
||||
$t = App::template_engine();
|
||||
|
||||
try {
|
||||
$output = $t->replace_macros($arr['template'], $arr['params']);
|
||||
} catch (Exception $e) {
|
||||
logger("Unable to render template: ".$e->getMessage());
|
||||
$output = "<h3>ERROR: there was an error creating the output.</h3>";
|
||||
}
|
||||
try {
|
||||
$output = $t->replace_macros($arr['template'], $arr['params']);
|
||||
} catch (Exception $e) {
|
||||
logger('Unable to render template: ' . $e->getMessage());
|
||||
$output = '<h3>ERROR: there was an error creating the output.</h3>';
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
@@ -536,7 +539,14 @@ function paginate(&$a) {
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param int $i
|
||||
* @param string $more
|
||||
* @param string $less
|
||||
* @return string Parsed HTML from template 'alt_pager.tpl'
|
||||
*/
|
||||
function alt_pager($i, $more = '', $less = '') {
|
||||
|
||||
if(! $more)
|
||||
@@ -571,18 +581,9 @@ function alt_pager($i, $more = '', $less = '') {
|
||||
* @return string a unique id
|
||||
*/
|
||||
function item_message_id() {
|
||||
do {
|
||||
$dups = false;
|
||||
$hash = random_string();
|
||||
$mid = $hash . '@' . App::get_hostname();
|
||||
|
||||
$r = q("SELECT id FROM item WHERE mid = '%s' LIMIT 1",
|
||||
dbesc($mid));
|
||||
if($r)
|
||||
$dups = true;
|
||||
} while($dups == true);
|
||||
return new_uuid();
|
||||
|
||||
return $mid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -593,17 +594,9 @@ function item_message_id() {
|
||||
* @return string a uniqe hash
|
||||
*/
|
||||
function photo_new_resource() {
|
||||
do {
|
||||
$found = false;
|
||||
$resource = hash('md5', uniqid(mt_rand(), true));
|
||||
|
||||
$r = q("SELECT id FROM photo WHERE resource_id = '%s' LIMIT 1",
|
||||
dbesc($resource));
|
||||
if($r)
|
||||
$found = true;
|
||||
} while($found === true);
|
||||
return new_uuid();
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -824,7 +817,7 @@ function activity_match($haystack,$needle) {
|
||||
* and strip the period from any tags which end with one.
|
||||
*
|
||||
* @param string $s
|
||||
* @return Returns array of tags found, or empty array.
|
||||
* @return array Returns an array of tags found, or empty array.
|
||||
*/
|
||||
function get_tags($s) {
|
||||
$ret = array();
|
||||
@@ -840,6 +833,9 @@ function get_tags($s) {
|
||||
// ignore anything in [color= ], because it may contain color codes which are mistaken for tags
|
||||
$s = preg_replace('/\[color=(.*?)\]/sm','',$s);
|
||||
|
||||
// skip anchors in URL
|
||||
$s = preg_replace('/\[url=(.*?)\]/sm','',$s);
|
||||
|
||||
// match any double quoted tags
|
||||
|
||||
if(preg_match_all('/([@#\!]\"\;.*?\"\;)/',$s,$match)) {
|
||||
@@ -911,6 +907,7 @@ function tag_sort_length($a,$b) {
|
||||
function total_sort($a,$b) {
|
||||
if($a['total'] == $b['total'])
|
||||
return 0;
|
||||
|
||||
return(($b['total'] > $a['total']) ? 1 : (-1));
|
||||
}
|
||||
|
||||
@@ -997,7 +994,7 @@ function contact_block() {
|
||||
|
||||
// There is no setting to discover if you are bi-directionally connected
|
||||
// Use the ability to post comments as an indication that this relationship is more
|
||||
// than wishful thinking; even though soapbox channels and feeds will disable it.
|
||||
// than wishful thinking; even though soapbox channels and feeds will disable it.
|
||||
|
||||
if(! intval(get_abconfig(App::$profile['uid'],$rr['xchan_hash'],'their_perms','post_comments'))) {
|
||||
$rr['oneway'] = true;
|
||||
@@ -1015,9 +1012,15 @@ function contact_block() {
|
||||
'$micropro' => $micropro,
|
||||
));
|
||||
|
||||
$arr = array('contacts' => $r, 'output' => $o);
|
||||
|
||||
$arr = ['contacts' => $r, 'output' => $o];
|
||||
/**
|
||||
* @hooks contact_block_end
|
||||
* Called at the end of contact_block(), but can not manipulate the output.
|
||||
* * \e array \b contacts - Result array from database
|
||||
* * \e string \b output - the generated output
|
||||
*/
|
||||
call_hooks('contact_block_end', $arr);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
@@ -1104,7 +1107,7 @@ function searchbox($s,$id='search-box',$url='/search',$save = false) {
|
||||
* @return string
|
||||
*/
|
||||
function linkify($s, $me = false) {
|
||||
$s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+\,\@]*)/u", (($me) ? ' <a href="$1" rel="me" >$1</a>' : ' <a href="$1" >$1</a>'), $s);
|
||||
$s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+\,\@]*)/u", (($me) ? ' <a href="$1" rel="me nofollow" >$1</a>' : ' <a href="$1" >$1</a>'), $s);
|
||||
$s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$s);
|
||||
|
||||
return($s);
|
||||
@@ -1122,6 +1125,21 @@ function linkify($s, $me = false) {
|
||||
* @returns string
|
||||
*/
|
||||
function sslify($s) {
|
||||
|
||||
// Local photo cache
|
||||
$str = [
|
||||
'body' => $s,
|
||||
'uid' => local_channel()
|
||||
];
|
||||
/**
|
||||
* @hooks cache_body_hook
|
||||
* * \e string \b body The content to parse and also the return value
|
||||
* * \e int|bool \b uid
|
||||
*/
|
||||
call_hooks('cache_body_hook', $str);
|
||||
|
||||
$s = $str['body'];
|
||||
|
||||
if (strpos(z_root(),'https:') === false)
|
||||
return $s;
|
||||
|
||||
@@ -1131,11 +1149,10 @@ function sslify($s) {
|
||||
// Complain to your browser maker
|
||||
|
||||
$allow = get_config('system','sslify_everything');
|
||||
|
||||
$pattern = (($allow) ? "/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/" : "/\<img(.*?)src=\"(http\:.*?)\"(.*?)\>/" );
|
||||
$pattern = (($allow) ? "/\<(.*?)src=[\"|'](http\:.*?)[\"|'](.*?)\>/" : "/\<img(.*?)src=[\"|'](http\:.*?)[\"|'](.*?)\>/" );
|
||||
|
||||
$matches = null;
|
||||
$cnt = preg_match_all($pattern,$s,$matches,PREG_SET_ORDER);
|
||||
$cnt = preg_match_all($pattern, $s, $matches, PREG_SET_ORDER);
|
||||
if ($cnt) {
|
||||
foreach ($matches as $match) {
|
||||
$filename = basename( parse_url($match[2], PHP_URL_PATH) );
|
||||
@@ -1223,7 +1240,11 @@ function get_mood_verbs() {
|
||||
/**
|
||||
* @brief Function to list all smilies, both internal and from addons.
|
||||
*
|
||||
* @return Returns array with keys 'texts' and 'icons'
|
||||
* @param boolean $default_only (optional) default false
|
||||
* true will prevent that plugins can add smilies
|
||||
* @return array Returns an associative array with:
|
||||
* * \e array \b texts
|
||||
* * \e array \b icons
|
||||
*/
|
||||
function list_smilies($default_only = false) {
|
||||
|
||||
@@ -1309,6 +1330,11 @@ function list_smilies($default_only = false) {
|
||||
if($default_only)
|
||||
return $params;
|
||||
|
||||
/**
|
||||
* @hooks smile
|
||||
* * \e array \b texts - default values and also return value
|
||||
* * \e array \b icons - default values and also return value
|
||||
*/
|
||||
call_hooks('smilie', $params);
|
||||
|
||||
return $params;
|
||||
@@ -1464,7 +1490,7 @@ function theme_attachments(&$item) {
|
||||
foreach($arr as $r) {
|
||||
|
||||
$icon = getIconFromType($r['type']);
|
||||
|
||||
|
||||
if($r['title'])
|
||||
$label = urldecode(htmlspecialchars($r['title'], ENT_COMPAT, 'UTF-8'));
|
||||
|
||||
@@ -1634,6 +1660,10 @@ function generate_named_map($location) {
|
||||
|
||||
function prepare_body(&$item,$attach = false,$opts = false) {
|
||||
|
||||
/**
|
||||
* @hooks prepare_body_init
|
||||
* * \e array \b item
|
||||
*/
|
||||
call_hooks('prepare_body_init', $item);
|
||||
|
||||
$s = '';
|
||||
@@ -1660,18 +1690,29 @@ function prepare_body(&$item,$attach = false,$opts = false) {
|
||||
$s .= prepare_binary($item);
|
||||
}
|
||||
else {
|
||||
$s .= prepare_text($item['body'],$item['mimetype'], $opts);
|
||||
if($item['summary']) {
|
||||
$s .= prepare_text('[summary]' . $item['summary'] . '[/summary]' . $item['body'],$item['mimetype'],$opts);
|
||||
}
|
||||
else {
|
||||
$s .= prepare_text($item['body'],$item['mimetype'], $opts);
|
||||
}
|
||||
}
|
||||
|
||||
$event = (($item['obj_type'] === ACTIVITY_OBJ_EVENT) ? format_event_obj($item['obj']) : false);
|
||||
|
||||
$prep_arr = array(
|
||||
$prep_arr = [
|
||||
'item' => $item,
|
||||
'html' => $event ? $event['content'] : $s,
|
||||
'event' => $event['header'],
|
||||
'photo' => $photo
|
||||
);
|
||||
|
||||
];
|
||||
/**
|
||||
* @hooks prepare_body
|
||||
* * \e array \b item
|
||||
* * \e string \b html - the parsed HTML to return
|
||||
* * \e string \b event - the event header to return
|
||||
* * \e string \b photo - the photo to return
|
||||
*/
|
||||
call_hooks('prepare_body', $prep_arr);
|
||||
|
||||
$s = $prep_arr['html'];
|
||||
@@ -1703,7 +1744,14 @@ function prepare_body(&$item,$attach = false,$opts = false) {
|
||||
if(local_channel() == $item['uid'])
|
||||
$filer = format_filer($item);
|
||||
|
||||
$s = sslify($s);
|
||||
if($s)
|
||||
$s = sslify($s);
|
||||
|
||||
if($photo)
|
||||
$photo = sslify($photo);
|
||||
|
||||
if($event)
|
||||
$event = sslify($event);
|
||||
|
||||
$prep_arr = array(
|
||||
'item' => $item,
|
||||
@@ -1734,17 +1782,24 @@ function prepare_binary($item) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Given a text string, convert from bbcode to html and add smilie icons.
|
||||
* @brief Given a text string, convert from content_type to HTML.
|
||||
*
|
||||
* Take a text in plain text, html, markdown, bbcode, PDL or PHP and prepare
|
||||
* it to return HTML.
|
||||
*
|
||||
* In bbcode this function will add smilie icons.
|
||||
*
|
||||
* @param string $text
|
||||
* @param string $content_type (optional) default text/bbcode
|
||||
* @param boolean $cache (optional) default false
|
||||
*
|
||||
* @param string $content_type (optional)
|
||||
* default 'text/bbcode', other values are 'text/plain', 'text/html',
|
||||
* 'text/markdown', 'application/x-pdl', 'application/x-php'
|
||||
* @param boolean|array $opts (optional)
|
||||
* default false, otherwise configuration array for bbcode()
|
||||
* @return string
|
||||
* The parsed $text as prepared HTML.
|
||||
*/
|
||||
function prepare_text($text, $content_type = 'text/bbcode', $opts = false) {
|
||||
|
||||
|
||||
switch($content_type) {
|
||||
case 'text/plain':
|
||||
$s = escape_tags($text);
|
||||
@@ -1784,8 +1839,8 @@ function prepare_text($text, $content_type = 'text/bbcode', $opts = false) {
|
||||
default:
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
if(stristr($text,'[nosmile]'))
|
||||
$s = bbcode($text, [ 'cache' => $cache ]);
|
||||
if(stristr($text, '[nosmile]'))
|
||||
$s = bbcode($text, ((is_array($opts)) ? $opts : [] ));
|
||||
else
|
||||
$s = smilies(bbcode($text, ((is_array($opts)) ? $opts : [] )));
|
||||
|
||||
@@ -2145,7 +2200,7 @@ function legal_webbie($s) {
|
||||
return '';
|
||||
|
||||
// WARNING: This regex may not work in a federated environment.
|
||||
// You will probably want something like
|
||||
// You will probably want something like
|
||||
// preg_replace('/([^a-z0-9\_])/','',strtolower($s));
|
||||
|
||||
$r = preg_replace('/([^a-z0-9\-\_])/','',strtolower($s));
|
||||
@@ -2244,19 +2299,24 @@ function ids_to_querystr($arr,$idx = 'id',$quote = false) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief array_elm_to_str($arr,$elm,$delim = ',') extract unique individual elements from an array of arrays and return them as a string separated by a delimiter
|
||||
* similar to ids_to_querystr, but allows a different delimiter instead of a db-quote option
|
||||
* empty elements (evaluated after trim()) are ignored.
|
||||
* @param $arr array
|
||||
* @param $elm array key to extract from sub-array
|
||||
* @param $delim string default ','
|
||||
* @param $each filter function to apply to each element before evaluation, default is 'trim'.
|
||||
* @brief Extract unique individual elements from an array of arrays and return
|
||||
* them as a string separated by a delimiter.
|
||||
*
|
||||
* Similar to ids_to_querystr, but allows a different delimiter instead of a
|
||||
* db-quote option empty elements (evaluated after trim()) are ignored.
|
||||
*
|
||||
* @see ids_to_querystr()
|
||||
*
|
||||
* @param array $arr
|
||||
* @param string $elm key to extract from sub-array
|
||||
* @param string $delim (optional) default ','
|
||||
* @param string $each (optional) default is 'trim'
|
||||
* Filter function to apply to each element before evaluation.
|
||||
* @returns string
|
||||
*/
|
||||
|
||||
function array_elm_to_str($arr,$elm,$delim = ',',$each = 'trim') {
|
||||
|
||||
function array_elm_to_str($arr, $elm, $delim = ',', $each = 'trim') {
|
||||
$tmp = [];
|
||||
|
||||
if($arr && is_array($arr)) {
|
||||
foreach($arr as $x) {
|
||||
if(is_array($x) && array_key_exists($elm,$x)) {
|
||||
@@ -2267,7 +2327,8 @@ function array_elm_to_str($arr,$elm,$delim = ',',$each = 'trim') {
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode($delim,$tmp);
|
||||
|
||||
return implode($delim, $tmp);
|
||||
}
|
||||
|
||||
function trim_and_unpunify($s) {
|
||||
@@ -2491,9 +2552,9 @@ function design_tools() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates website portation tools menu
|
||||
* @brief Creates website portation tools menu.
|
||||
*
|
||||
* @return string
|
||||
* @return string Parsed HTML code from template 'website_portation_tools.tpl'
|
||||
*/
|
||||
function website_portation_tools() {
|
||||
|
||||
@@ -2506,7 +2567,7 @@ function website_portation_tools() {
|
||||
$sys = true;
|
||||
}
|
||||
|
||||
return replace_macros(get_markup_template('website_portation_tools.tpl'), array(
|
||||
return replace_macros(get_markup_template('website_portation_tools.tpl'), [
|
||||
'$title' => t('Import'),
|
||||
'$import_label' => t('Import website...'),
|
||||
'$import_placeholder' => t('Select folder to import'),
|
||||
@@ -2523,7 +2584,7 @@ function website_portation_tools() {
|
||||
'$cloud_export_desc' => t('/path/to/export/folder'),
|
||||
'$cloud_export_hint' => t('Enter a path to a cloud files destination.'),
|
||||
'$cloud_export_select' => t('Specify folder'),
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2583,8 +2644,9 @@ function extra_query_args() {
|
||||
* @param boolean $in_network default true
|
||||
* @return boolean true if replaced, false if not replaced
|
||||
*/
|
||||
function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $in_network = true) {
|
||||
function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true) {
|
||||
|
||||
$channel = App::get_channel();
|
||||
$replaced = false;
|
||||
$r = null;
|
||||
$match = array();
|
||||
@@ -2640,21 +2702,20 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
|
||||
$str_tags .= $newtag;
|
||||
}
|
||||
return [
|
||||
'replaced' => $replaced,
|
||||
'termtype' => $termtype,
|
||||
'term' => $basetag,
|
||||
'url' => $url,
|
||||
'contact' => []
|
||||
];
|
||||
|
||||
return [ [
|
||||
'replaced' => $replaced,
|
||||
'termtype' => $termtype,
|
||||
'term' => $basetag,
|
||||
'url' => $url,
|
||||
'contact' => [],
|
||||
'access_tag' => '',
|
||||
]];
|
||||
}
|
||||
|
||||
// END hashtags
|
||||
|
||||
// BEGIN mentions
|
||||
|
||||
|
||||
if ( in_array($termtype, [ TERM_MENTION, TERM_FORUM ] )) {
|
||||
|
||||
// The @! tag and !! tag will alter permissions
|
||||
@@ -2665,13 +2726,13 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
$exclusive = (((strpos(substr($tag,1), '!') === 0) && $in_network) ? true : false);
|
||||
|
||||
//is it already replaced?
|
||||
if(strpos($tag,'[zrl=') || strpos($tag,'[url='))
|
||||
if(strpos($tag,"[zrl=") || strpos($tag,"[url="))
|
||||
return $replaced;
|
||||
|
||||
// get the channel name
|
||||
// First extract the name or name fragment we are going to replace
|
||||
|
||||
$name = substr($tag,(($exclusive) ? 2 : 1));
|
||||
$name = substr($tag,(($exclusive) ? 2 : 1));
|
||||
$newname = $name; // make a copy that we can mess with
|
||||
$tagcid = 0;
|
||||
|
||||
@@ -2683,7 +2744,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
$newname = substr($name,1);
|
||||
$newname = substr($newname,0,-1);
|
||||
|
||||
$r = q("select * from xchan where xchan_addr = '%s' or xchan_url = '%s' limit 1",
|
||||
$r = q("select * from xchan where xchan_addr = '%s' or xchan_url = '%s'",
|
||||
dbesc($newname),
|
||||
dbesc($newname)
|
||||
);
|
||||
@@ -2706,7 +2767,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
// select someone from this user's contacts by name
|
||||
|
||||
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1",
|
||||
WHERE xchan_name = '%s' AND abook_channel = %d ",
|
||||
dbesc($newname),
|
||||
intval($profile_uid)
|
||||
);
|
||||
@@ -2714,8 +2775,8 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
// select anybody by full hubloc_addr
|
||||
|
||||
if((! $r) && strpos($newname,'@')) {
|
||||
$r = q("SELECT * FROM xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
WHERE hubloc_addr = '%s' LIMIT 1",
|
||||
$r = q("SELECT * FROM xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
WHERE hubloc_addr = '%s' ",
|
||||
dbesc($newname)
|
||||
);
|
||||
}
|
||||
@@ -2724,7 +2785,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
|
||||
if(! $r) {
|
||||
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
|
||||
WHERE xchan_addr like ('%s') AND abook_channel = %d LIMIT 1",
|
||||
WHERE xchan_addr like ('%s') AND abook_channel = %d ",
|
||||
dbesc(((strpos($newname,'@')) ? $newname : $newname . '@%')),
|
||||
intval($profile_uid)
|
||||
);
|
||||
@@ -2732,17 +2793,62 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$fn_results = [];
|
||||
$access_tag = EMPTY_STR;
|
||||
|
||||
|
||||
// $r is set if we found something
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if($r) {
|
||||
$profile = $r[0]['xchan_url'];
|
||||
$newname = $r[0]['xchan_name'];
|
||||
// add the channel's xchan_hash to $access_tag if exclusive
|
||||
if($exclusive) {
|
||||
$access_tag .= 'cid:' . $r[0]['xchan_hash'];
|
||||
foreach($r as $xc) {
|
||||
$profile = $xc['xchan_url'];
|
||||
$newname = $xc['xchan_name'];
|
||||
// add the channel's xchan_hash to $access_tag if exclusive
|
||||
if($exclusive) {
|
||||
$access_tag = 'cid:' . $xc['xchan_hash'];
|
||||
}
|
||||
|
||||
// if there is a url for this channel
|
||||
|
||||
if(isset($profile)) {
|
||||
$replaced = true;
|
||||
//create profile link
|
||||
$profile = str_replace(',','%2c',$profile);
|
||||
$url = $profile;
|
||||
if($termtype === TERM_FORUM) {
|
||||
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
else {
|
||||
// ( $termtype === TERM_MENTION )
|
||||
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
|
||||
// append tag to str_tags
|
||||
if(! stristr($str_tags,$newtag)) {
|
||||
if(strlen($str_tags))
|
||||
$str_tags .= ',';
|
||||
$str_tags .= $newtag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$fn_results[] = [
|
||||
'replaced' => $replaced,
|
||||
'termtype' => $termtype,
|
||||
'term' => $newname,
|
||||
'url' => $url,
|
||||
'access_tag' => $access_tag,
|
||||
'contact' => (($r) ? $xc : []),
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -2754,7 +2860,6 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
// weird - as all the other tags are linked to something.
|
||||
|
||||
if(local_channel() && local_channel() == $profile_uid) {
|
||||
require_once('include/group.php');
|
||||
$grp = group_byname($profile_uid,$name);
|
||||
|
||||
if($grp) {
|
||||
@@ -2771,58 +2876,62 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a url for this channel
|
||||
|
||||
if(isset($profile)) {
|
||||
$replaced = true;
|
||||
//create profile link
|
||||
$profile = str_replace(',','%2c',$profile);
|
||||
$url = $profile;
|
||||
if($termtype === TERM_FORUM) {
|
||||
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
else {
|
||||
// ( $termtype === TERM_MENTION )
|
||||
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
// if there is a url for this channel
|
||||
|
||||
if(isset($profile)) {
|
||||
$replaced = true;
|
||||
//create profile link
|
||||
$profile = str_replace(',','%2c',$profile);
|
||||
$url = $profile;
|
||||
if($termtype === TERM_FORUM) {
|
||||
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
else {
|
||||
// ( $termtype === TERM_MENTION )
|
||||
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
|
||||
$body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
|
||||
}
|
||||
|
||||
// append tag to str_tags
|
||||
if(! stristr($str_tags,$newtag)) {
|
||||
if(strlen($str_tags))
|
||||
$str_tags .= ',';
|
||||
$str_tags .= $newtag;
|
||||
}
|
||||
}
|
||||
|
||||
// append tag to str_tags
|
||||
if(! stristr($str_tags,$newtag)) {
|
||||
if(strlen($str_tags))
|
||||
$str_tags .= ',';
|
||||
$str_tags .= $newtag;
|
||||
}
|
||||
$fn_results[] = [
|
||||
'replaced' => $replaced,
|
||||
'termtype' => $termtype,
|
||||
'term' => $newname,
|
||||
'url' => $url,
|
||||
'access_tag' => $access_tag,
|
||||
'contact' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $fn_results;
|
||||
|
||||
return [
|
||||
'replaced' => $replaced,
|
||||
'termtype' => $termtype,
|
||||
'term' => $newname,
|
||||
'url' => $url,
|
||||
'contact' => (($r) ? $r[0] : [])
|
||||
];
|
||||
}
|
||||
|
||||
function linkify_tags($a, &$body, $uid, $in_network = true) {
|
||||
function linkify_tags(&$body, $uid, $in_network = true) {
|
||||
$str_tags = EMPTY_STR;
|
||||
$tagged = [];
|
||||
$results = [];
|
||||
|
||||
$tags = get_tags($body);
|
||||
|
||||
if(count($tags)) {
|
||||
foreach($tags as $tag) {
|
||||
$access_tag = '';
|
||||
|
||||
$success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : App::$profile_uid , $tag, $in_network);
|
||||
$success = handle_tag($body, $str_tags, ($uid) ? $uid : App::$profile_uid , $tag, $in_network);
|
||||
|
||||
$results[] = array('success' => $success, 'access_tag' => $access_tag);
|
||||
if($success['replaced']) $tagged[] = $tag;
|
||||
foreach($success as $handled_tag) {
|
||||
$results[] = [ 'success' => $handled_tag ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2880,7 +2989,7 @@ function getIconFromType($type) {
|
||||
'video/x-matroska' => 'fa-file-video-o'
|
||||
);
|
||||
|
||||
$catMap = [
|
||||
$catMap = [
|
||||
'application' => 'fa-file-code-o',
|
||||
'multipart' => 'fa-folder',
|
||||
'audio' => 'fa-file-audio-o',
|
||||
@@ -2888,7 +2997,7 @@ function getIconFromType($type) {
|
||||
'text' => 'fa-file-text-o',
|
||||
'image' => 'fa=file-picture-o',
|
||||
'message' => 'fa-file-text-o'
|
||||
];
|
||||
];
|
||||
|
||||
|
||||
$iconFromType = '';
|
||||
@@ -2898,7 +3007,7 @@ function getIconFromType($type) {
|
||||
}
|
||||
else {
|
||||
$parts = explode('/',$type);
|
||||
if($parts[0] && $catMap[$parts[0]]) {
|
||||
if($parts[0] && $catMap[$parts[0]]) {
|
||||
$iconFromType = $catMap[$parts[0]];
|
||||
}
|
||||
}
|
||||
@@ -2986,9 +3095,9 @@ function item_url_replace($channel,&$item,$old,$new,$oldnick = '') {
|
||||
json_url_replace('/' . $oldnick . '/' ,'/' . $channel['channel_address'] . '/' ,$item['target']);
|
||||
}
|
||||
|
||||
$x = preg_replace("/".preg_quote($old,'/')."\/(search|\w+\/".$channel['channel_address'].")/", $new.'/${1}', $item['body']);
|
||||
if($x) {
|
||||
$item['body'] = $x;
|
||||
$x = preg_replace("/".preg_quote($old,'/')."\/(search|\w+\/".$channel['channel_address'].")/", $new.'/${1}', $item['body']);
|
||||
if($x) {
|
||||
$item['body'] = $x;
|
||||
$item['sig'] = base64url_encode(rsa_sign($item['body'],$channel['channel_prvkey']));
|
||||
$item['item_verified'] = 1;
|
||||
}
|
||||
@@ -3098,7 +3207,13 @@ function pdl_selector($uid, $current='') {
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$arr = array('channel_id' => $uid, 'current' => $current, 'entries' => $r);
|
||||
$arr = ['channel_id' => $uid, 'current' => $current, 'entries' => $r];
|
||||
/**
|
||||
* @hooks pdl_selector
|
||||
* * \e int \b channel_id
|
||||
* * \e string \b current
|
||||
* * \e array \b entries - Result from database query
|
||||
*/
|
||||
call_hooks('pdl_selector', $arr);
|
||||
|
||||
$entries = $arr['entries'];
|
||||
@@ -3139,7 +3254,7 @@ function flatten_array_recursive($arr) {
|
||||
$ret = array_merge($ret, $tmp);
|
||||
}
|
||||
}
|
||||
elseif($a) {
|
||||
elseif(isset($a)) {
|
||||
$ret[] = $a;
|
||||
}
|
||||
}
|
||||
@@ -3154,7 +3269,7 @@ function flatten_array_recursive($arr) {
|
||||
* @param string $lang Which language should be highlighted
|
||||
* @return string
|
||||
* Important: The returned text has the text pattern 'http' translated to '%eY9-!' which should be converted back
|
||||
* after further processing. This was done to prevent oembed links from occurring inside code blocks.
|
||||
* after further processing. This was done to prevent oembed links from occurring inside code blocks.
|
||||
* See include/bbcode.php
|
||||
*/
|
||||
function text_highlight($s, $lang) {
|
||||
@@ -3173,7 +3288,6 @@ function text_highlight($s, $lang) {
|
||||
'language' => $lang,
|
||||
'success' => false
|
||||
];
|
||||
|
||||
/**
|
||||
* @hooks text_highlight
|
||||
* * \e string \b text
|
||||
@@ -3225,28 +3339,6 @@ function array2XML($obj, $array) {
|
||||
}
|
||||
}
|
||||
|
||||
function array_path_exists($str,$arr) {
|
||||
|
||||
$ptr = $arr;
|
||||
$search = explode('/', $str);
|
||||
|
||||
if($search) {
|
||||
foreach($search as $s) {
|
||||
if(array_key_exists($s,$ptr)) {
|
||||
$ptr = $ptr[$s];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Inserts an array into $table.
|
||||
*
|
||||
@@ -3396,13 +3488,17 @@ function punify($s) {
|
||||
|
||||
}
|
||||
|
||||
// Be aware that unpunify will only convert domain names and not pathnames
|
||||
|
||||
/**
|
||||
* Be aware that unpunify() will only convert domain names and not pathnames.
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
function unpunify($s) {
|
||||
require_once('vendor/simplepie/simplepie/idn/idna_convert.class.php');
|
||||
$x = new idna_convert(['encoding' => 'utf8']);
|
||||
return $x->decode($s);
|
||||
|
||||
return $x->decode($s);
|
||||
}
|
||||
|
||||
|
||||
@@ -3410,7 +3506,7 @@ function unique_multidim_array($array, $key) {
|
||||
$temp_array = array();
|
||||
$i = 0;
|
||||
$key_array = array();
|
||||
|
||||
|
||||
foreach($array as $val) {
|
||||
if (!in_array($val[$key], $key_array)) {
|
||||
$key_array[$i] = $val[$key];
|
||||
@@ -3438,7 +3534,7 @@ function get_forum_channels($uid) {
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if($x2) {
|
||||
if($x2) {
|
||||
$xf = ids_to_querystr($x2,'xchan',true);
|
||||
|
||||
// private forums
|
||||
@@ -3451,7 +3547,7 @@ function get_forum_channels($uid) {
|
||||
}
|
||||
}
|
||||
|
||||
$sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
|
||||
$sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
|
||||
|
||||
$r = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_addr, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name",
|
||||
intval($uid)
|
||||
@@ -3487,14 +3583,14 @@ function print_array($arr, $level = 0) {
|
||||
$o .= $tabs . '[' . $k . '] => ' . print_array($v, $level + 1) . "\n";
|
||||
}
|
||||
else {
|
||||
$o .= $tabs . '[' . $k . '] => ' . print_val($v) . ",\n";
|
||||
$o .= $tabs . '[' . $k . '] => ' . print_val($v) . ",\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$o .= substr($tabs,0,-1) . ']' . (($level) ? ',' : ';' ). "\n";
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function print_val($v) {
|
||||
@@ -3509,3 +3605,40 @@ function print_val($v) {
|
||||
|
||||
}
|
||||
|
||||
function array_path_exists($str,$arr) {
|
||||
|
||||
$ptr = $arr;
|
||||
$search = explode('/', $str);
|
||||
|
||||
if($search) {
|
||||
foreach($search as $s) {
|
||||
if(array_key_exists($s,$ptr)) {
|
||||
$ptr = $ptr[$s];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate a unique ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function new_uuid() {
|
||||
|
||||
try {
|
||||
$hash = Uuid::uuid4()->toString();
|
||||
} catch (UnsatisfiedDependencyException $e) {
|
||||
$hash = random_string(48);
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ use Zotlabs\Zot6\HTTPSig;
|
||||
|
||||
function xchan_store_lowlevel($arr) {
|
||||
|
||||
if(! $arr['xchan_hash']) {
|
||||
logger('No xchan_hash');
|
||||
return false;
|
||||
}
|
||||
|
||||
$store = [
|
||||
'xchan_hash' => ((array_key_exists('xchan_hash',$arr)) ? $arr['xchan_hash'] : ''),
|
||||
'xchan_guid' => ((array_key_exists('xchan_guid',$arr)) ? $arr['xchan_guid'] : ''),
|
||||
|
||||
+3
-3
@@ -70,9 +70,9 @@ function zid($s, $address = '') {
|
||||
$zurl .= '#' . $fragment;
|
||||
|
||||
$arr = [
|
||||
'url' => $s,
|
||||
'zid' => urlencode($myaddr),
|
||||
'result' => $zurl
|
||||
'url' => $s,
|
||||
'zid' => urlencode($myaddr),
|
||||
'result' => $zurl
|
||||
];
|
||||
/**
|
||||
* @hooks zid
|
||||
|
||||
+71
-33
@@ -8,6 +8,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
use Zotlabs\Lib\DReport;
|
||||
|
||||
require_once('include/crypto.php');
|
||||
require_once('include/items.php');
|
||||
require_once('include/queue_fn.php');
|
||||
@@ -81,7 +83,7 @@ function zot_get_hublocs($hash) {
|
||||
|
||||
/* Only search for active hublocs - e.g. those that haven't been marked deleted */
|
||||
|
||||
$ret = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 order by hubloc_url ",
|
||||
$ret = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 and hubloc_network = 'zot' order by hubloc_url ",
|
||||
dbesc($hash)
|
||||
);
|
||||
|
||||
@@ -172,7 +174,7 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot
|
||||
* packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'keychange', 'force_refresh', 'notify', 'auth_check'
|
||||
* @param array $recipients
|
||||
* envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts
|
||||
* @param string msg
|
||||
* @param string $msg
|
||||
* optional message
|
||||
* @param string $remote_key
|
||||
* optional public site key of target hub used to encrypt entire packet
|
||||
@@ -654,7 +656,7 @@ function zot_gethub($arr, $multiple = false) {
|
||||
|
||||
$r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url
|
||||
where hubloc_guid = '%s' and hubloc_guid_sig = '%s'
|
||||
and hubloc_url = '%s' and hubloc_url_sig = '%s'
|
||||
and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_network = 'zot'
|
||||
$sitekey $limit",
|
||||
dbesc($arr['guid']),
|
||||
dbesc($arr['guid_sig']),
|
||||
@@ -1098,6 +1100,8 @@ function zot_process_response($hub, $arr, $outq) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dreport = true;
|
||||
|
||||
$x = json_decode($arr['body'], true);
|
||||
|
||||
if(! $x) {
|
||||
@@ -1114,30 +1118,44 @@ function zot_process_response($hub, $arr, $outq) {
|
||||
}
|
||||
if(! (is_array($x['delivery_report']) && count($x['delivery_report']))) {
|
||||
logger('encrypted delivery report could not be decrypted');
|
||||
return;
|
||||
$dreport = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($x['delivery_report'] as $xx) {
|
||||
call_hooks('dreport_process',$xx);
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx) && delivery_report_is_storable($xx)) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($xx['message_id']),
|
||||
dbesc($xx['location']),
|
||||
dbesc($xx['recipient']),
|
||||
dbesc($xx['status']),
|
||||
dbesc(datetime_convert($xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
if($dreport) {
|
||||
foreach($x['delivery_report'] as $xx) {
|
||||
call_hooks('dreport_process',$xx);
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
|
||||
|
||||
// legacy zot recipients add a space and their name to the xchan. split those if true.
|
||||
$legacy_recipient = strpos($xx['recipient'], ' ');
|
||||
if($legacy_recipient !== false) {
|
||||
$legacy_recipient_parts = explode(' ', $xx['recipient'], 2);
|
||||
$xx['recipient'] = $legacy_recipient_parts[0];
|
||||
$xx['name'] = $legacy_recipient_parts[1];
|
||||
}
|
||||
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($xx['message_id']),
|
||||
dbesc($xx['location']),
|
||||
dbesc($xx['recipient']),
|
||||
dbesc($xx['name']),
|
||||
dbesc($xx['status']),
|
||||
dbesc(datetime_convert('UTC','UTC',$xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have a more descriptive delivery report, so discard the per hub 'queued' report.
|
||||
|
||||
q("delete from dreport where dreport_queue = '%s' ",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
if($dreport) {
|
||||
// we have a more descriptive delivery report, so discard the per hub 'queued' report.
|
||||
q("delete from dreport where dreport_queue = '%s' ",
|
||||
dbesc($outq['outq_hash'])
|
||||
);
|
||||
}
|
||||
|
||||
// update the timestamp for this site
|
||||
|
||||
@@ -1188,6 +1206,7 @@ function zot_fetch($arr) {
|
||||
$zret = zot6_check_sig();
|
||||
|
||||
if($zret['success'] && $zret['hubloc'] && $zret['hubloc']['hubloc_guid'] === $arr['sender']['guid'] && $arr['msg']) {
|
||||
|
||||
logger('zot6_delivery',LOGGER_DEBUG);
|
||||
logger('zot6_data: ' . print_r($arr,true),LOGGER_DATA);
|
||||
|
||||
@@ -1228,6 +1247,7 @@ function zot_fetch($arr) {
|
||||
$datatosend = json_encode(crypto_encapsulate(json_encode($data),$hub['hubloc_sitekey'], $algorithm));
|
||||
|
||||
$import = zot_zot($url,$datatosend);
|
||||
|
||||
}
|
||||
else {
|
||||
$algorithm = zot_best_algorithm($hub['site_crypto']);
|
||||
@@ -1748,7 +1768,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
|
||||
}
|
||||
|
||||
$channel = $r[0];
|
||||
$DR->addto_recipient($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
|
||||
/* blacklisted channels get a permission denied, no special message to tip them off */
|
||||
|
||||
@@ -1809,7 +1829,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
|
||||
else {
|
||||
$arr['item_wall'] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((! $tag_delivery) && (! $local_public)) {
|
||||
$allowed = (perm_is_allowed($channel['channel_id'],$sender['hash'],$perm));
|
||||
@@ -1820,10 +1840,10 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if ($parent) {
|
||||
$allowed = can_comment_on_post($d['hash'],$parent[0]);
|
||||
$allowed = can_comment_on_post($sender['hash'],$parent[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (! $allowed) {
|
||||
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
|
||||
$DR->update('permission denied');
|
||||
@@ -2297,7 +2317,7 @@ function process_mail_delivery($sender, $arr, $deliveries) {
|
||||
}
|
||||
|
||||
$channel = $r[0];
|
||||
$DR->addto_recipient($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
|
||||
/* blacklisted channels get a permission denied, no special message to tip them off */
|
||||
|
||||
@@ -2310,7 +2330,7 @@ function process_mail_delivery($sender, $arr, $deliveries) {
|
||||
|
||||
if(! perm_is_allowed($channel['channel_id'],$sender['hash'],'post_mail')) {
|
||||
|
||||
/*
|
||||
/*
|
||||
* Always allow somebody to reply if you initiated the conversation. It's anti-social
|
||||
* and a bit rude to send a private message to somebody and block their ability to respond.
|
||||
* If you are being harrassed and want to put an end to it, delete the conversation.
|
||||
@@ -2338,7 +2358,7 @@ function process_mail_delivery($sender, $arr, $deliveries) {
|
||||
);
|
||||
if($r) {
|
||||
if(intval($arr['mail_recalled'])) {
|
||||
msg_drop($r[0]['id'], $channel['channel_id'], $r[0]['conv_guid']);
|
||||
msg_drop($r[0]['id'], $channel['channel_id'], $r[0]['conv_guid']);
|
||||
$DR->update('mail recalled');
|
||||
$result[] = $DR->get();
|
||||
logger('mail_recalled');
|
||||
@@ -3227,7 +3247,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
|
||||
|
||||
$channel = $r[0];
|
||||
|
||||
// don't provide these in the export
|
||||
// don't provide these in the export
|
||||
|
||||
unset($channel['channel_active']);
|
||||
unset($channel['channel_password']);
|
||||
@@ -3596,7 +3616,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
|
||||
|
||||
if(array_key_exists('channel_pageflags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
|
||||
// Several pageflags are site-specific and cannot be sync'd.
|
||||
// Only allow those bits which are shareable from the remote and then
|
||||
// Only allow those bits which are shareable from the remote and then
|
||||
// logically OR with the local flags
|
||||
|
||||
$arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] & (PAGE_HIDDEN|PAGE_AUTOCONNECT|PAGE_APPLICATION|PAGE_PREMIUM|PAGE_ADULT);
|
||||
@@ -3987,7 +4007,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
|
||||
|
||||
if(array_key_exists('item',$arr) && is_array($arr['item'][0])) {
|
||||
$DR = new Zotlabs\Lib\DReport(z_root(),$d['hash'],$d['hash'],$arr['item'][0]['message_id'],'channel sync processed');
|
||||
$DR->addto_recipient($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
|
||||
}
|
||||
else
|
||||
$DR = new Zotlabs\Lib\DReport(z_root(),$d['hash'],$d['hash'],'sync packet','channel sync delivered');
|
||||
@@ -4909,6 +4929,7 @@ function zot_reply_pickup($data) {
|
||||
dbesc($data['secret']),
|
||||
dbesc($data['callback'])
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
$ret['message'] = 'nothing to pick up';
|
||||
logger('mod_zot: pickup: ' . $ret['message']);
|
||||
@@ -4918,12 +4939,13 @@ function zot_reply_pickup($data) {
|
||||
|
||||
/*
|
||||
* Everything is good if we made it here, so find all messages that are going to this location
|
||||
* and send them all.
|
||||
* and send them all - or a reasonable number if there are a lot so we don't overflow memory.
|
||||
*/
|
||||
|
||||
$r = q("select * from outq where outq_posturl = '%s'",
|
||||
$r = q("select * from outq where outq_posturl = '%s' limit 100",
|
||||
dbesc($data['callback'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
logger('mod_zot: successful pickup message received from ' . $data['callback'] . ' ' . count($r) . ' message(s) picked up', LOGGER_DEBUG);
|
||||
|
||||
@@ -4949,6 +4971,19 @@ function zot_reply_pickup($data) {
|
||||
}
|
||||
}
|
||||
|
||||
// It's possible that we have more than 100 messages waiting to be sent.
|
||||
|
||||
// See if there are any more messages in the queue.
|
||||
$x = q("select * from outq where outq_posturl = '%s' order by outq_created limit 1",
|
||||
dbesc($data['callback'])
|
||||
);
|
||||
|
||||
// If so, kick off a new delivery notification for the next batch
|
||||
if ($x) {
|
||||
logger("Send additional pickup request.", LOGGER_DEBUG);
|
||||
queue_deliver($x[0],true);
|
||||
}
|
||||
|
||||
// this is a bit of a hack because we don't have the hubloc_url here, only the callback url.
|
||||
// worst case is we'll end up using aes256cbc if they've got a different post endpoint
|
||||
|
||||
@@ -4960,6 +4995,8 @@ function zot_reply_pickup($data) {
|
||||
$encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm);
|
||||
|
||||
json_return_and_die($encrypted);
|
||||
// @FIXME: There is a possibility that the transmission will get interrupted
|
||||
// and fail - in which case this packet of messages will be lost.
|
||||
/* pickup: end */
|
||||
}
|
||||
|
||||
@@ -5020,7 +5057,7 @@ function zot_reply_auth_check($data,$encrypted_packet) {
|
||||
}
|
||||
|
||||
// There should be exactly one recipient, the original auth requestor
|
||||
|
||||
/// @FIXME $recipients is undefined here.
|
||||
$ret['message'] .= 'recipients ' . print_r($recipients,true) . EOL;
|
||||
|
||||
if ($data['recipients']) {
|
||||
@@ -5185,7 +5222,7 @@ function zot6_check_sig() {
|
||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER['HTTP_SIGNATURE']);
|
||||
if($sigblock) {
|
||||
$keyId = $sigblock['keyId'];
|
||||
|
||||
logger('keyID: ' . $keyId);
|
||||
if($keyId) {
|
||||
$r = q("select hubloc.*, site_crypto from hubloc left join site on hubloc_url = site_url
|
||||
where hubloc_addr = '%s' ",
|
||||
@@ -5195,6 +5232,7 @@ function zot6_check_sig() {
|
||||
foreach($r as $hubloc) {
|
||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||
if($verified && $verified['header_signed'] && $verified['header_valid'] && $verified['content_signed'] && $verified['content_valid']) {
|
||||
logger('zot6 verified');
|
||||
$ret['hubloc'] = $hubloc;
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
|
||||
Reference in New Issue
Block a user