diff options
author | Mario <mario@mariovavti.com> | 2021-07-29 06:59:13 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2021-07-29 06:59:13 +0000 |
commit | 9722d157bf138753bc168f68c56b4963db6da4e9 (patch) | |
tree | a15bb81c35a2367fe4628614471d471ed86d2712 /include | |
parent | 219d47f04c7bb04dcc241b9ed6ca411fc9653f09 (diff) | |
parent | c6133d2558ce29e44342fa7be8bb65e0059aea02 (diff) | |
download | volse-hubzilla-9722d157bf138753bc168f68c56b4963db6da4e9.tar.gz volse-hubzilla-9722d157bf138753bc168f68c56b4963db6da4e9.tar.bz2 volse-hubzilla-9722d157bf138753bc168f68c56b4963db6da4e9.zip |
Merge branch 'dev' into bs5
Diffstat (limited to 'include')
-rw-r--r-- | include/attach.php | 4 | ||||
-rw-r--r-- | include/bbcode.php | 21 | ||||
-rw-r--r-- | include/conversation.php | 32 | ||||
-rw-r--r-- | include/dir_fns.php | 437 | ||||
-rw-r--r-- | include/html2plain.php | 10 | ||||
-rw-r--r-- | include/items.php | 4 | ||||
-rw-r--r-- | include/photos.php | 100 | ||||
-rw-r--r-- | include/queue_fn.php | 314 | ||||
-rw-r--r-- | include/text.php | 87 |
9 files changed, 187 insertions, 822 deletions
diff --git a/include/attach.php b/include/attach.php index db7046ef0..09d4005e8 100644 --- a/include/attach.php +++ b/include/attach.php @@ -668,8 +668,8 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $def_extension = '.jpg'; if($gis[2] === IMAGETYPE_PNG) $def_extension = '.png'; - if($gis[2] === IMAGETYPE_WEBP) - $def_extension = '.webp'; + if($gis[2] === IMAGETYPE_WEBP) + $def_extension = '.webp'; } // If we know it's a photo, over-ride the type in case the source system could not determine what it was diff --git a/include/bbcode.php b/include/bbcode.php index a362e9ce9..87a7e6af6 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1099,6 +1099,27 @@ function bbcode($Text, $options = []) { call_hooks('bbcode_filter', $Text); + if(isset($options['drop_media'])) { + if (strpos($Text,'[/img]') !== false) { + $Text = preg_replace('/\[img(.*?)\[\/(img)\]/ism', '', $Text); + } + if (strpos($Text,'[/audio]') !== false) { + $Text = preg_replace('/\[audio(.*?)\[\/(audio)\]/ism', '', $Text); + } + if (strpos($Text,'[/video]') !== false) { + $Text = preg_replace('/\[video(.*?)\[\/(video)\]/ism', '', $Text); + } + if (strpos($Text,'[/zmg]') !== false) { + $Text = preg_replace('/\[zmg(.*?)\[\/(zmg)\]/ism', '', $Text); + } + if (strpos($Text,'[/zaudio]') !== false) { + $Text = preg_replace('/\[zaudio(.*?)\[\/(zaudio)\]/ism', '', $Text); + } + if (strpos($Text,'[/zvideo]') !== false) { + $Text = preg_replace('/\[zvideo(.*?)\[\/(zvideo)\]/ism', '', $Text); + } + } + // Hide all [noparse] contained bbtags by spacefying them if (strpos($Text,'[noparse]') !== false) { $Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_spacefy',$Text); diff --git a/include/conversation.php b/include/conversation.php index 39ff8d7ad..c5a0df79a 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -730,10 +730,13 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa 'delete' => t('Delete'), ); - $star = array( - 'toggle' => t("Toggle Star Status"), - 'isstarred' => ((intval($item['item_starred'])) ? true : false), - ); + $star = []; + if ((local_channel() && local_channel() === intval($item['uid'])) && intval($item['item_thread_top']) && feature_enabled(local_channel(), 'star_posts')) { + $star = [ + 'toggle' => t("Toggle Star Status"), + 'isstarred' => ((intval($item['item_starred'])) ? true : false), + ]; + } $lock = (($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) ? t('Private Message') @@ -765,8 +768,12 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa $conv_link_mid = (($mode == 'moderate') ? $item['parent_mid'] : $item['mid']); - $conv_link = ((in_array($item['item_type'],[ ITEM_TYPE_CARD, ITEM_TYPE_ARTICLE] )) ? $item['plink'] : z_root() . '/display/' . gen_link_id($conv_link_mid)); + $conv_link_module = 'display'; + if(local_channel()) { + $conv_link_module = 'hq'; + } + $conv_link = ((in_array($item['item_type'],[ ITEM_TYPE_CARD, ITEM_TYPE_ARTICLE] )) ? $item['plink'] : z_root() . '/' . $conv_link_module . '/' . gen_link_id($conv_link_mid)); $tmp_item = array( 'template' => $tpl, @@ -777,7 +784,8 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa 'delete' => t('Delete'), 'preview_lbl' => $preview_lbl, 'id' => (($preview) ? 'P0' : $item['item_id']), - 'mids' => json_encode(['b64.' . base64url_encode($item['mid'])]), + 'mid' => gen_link_id($item['mid']), + 'mids' => json_encode([gen_link_id($item['mid'])]), 'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, $profile_url), 'profile_url' => $profile_link, 'thread_action_menu' => thread_action_menu($item,$mode), @@ -819,7 +827,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa 'owner_photo' => $owner_photo, 'plink' => get_plink($item,false), 'edpost' => false, - 'star' => ((feature_enabled(local_channel(),'star_posts')) ? $star : ''), + 'star' => $star, 'drop' => $drop, 'vote' => $likebuttons, 'like' => '', @@ -932,7 +940,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa '$user' => App::$user, '$threads' => $threads, '$wait' => t('Loading...'), - '$conversation_tools' => t('Conversation Tools'), + '$conversation_tools' => t('Conversation Features'), '$dropping' => ($page_dropping?t('Delete Selected Items'):False), '$preview' => $preview )); @@ -1053,7 +1061,7 @@ function thread_author_menu($item, $mode = '') { } else { $url = (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']); - if($local_channel && $url && (! in_array($item['author']['xchan_network'],[ 'rss', 'anon','unknown' ]))) { + if($local_channel && $url && (! in_array($item['author']['xchan_network'],[ 'rss', 'anon','unknown', 'zot' ]))) { $follow_url = z_root() . '/follow/?f=&url=' . urlencode($url) . '&interactive=0'; } } @@ -1388,7 +1396,8 @@ function hz_status_editor($a, $x, $popup = false) { '$nocomment_enabled' => t('Comments enabled'), '$nocomment_disabled' => t('Comments disabled'), '$auto_save_draft' => $feature_auto_save_draft, - '$reset' => $reset + '$reset' => $reset, + '$popup' => $popup ]; call_hooks('jot_header_tpl_filter',$tplmacros); @@ -1688,7 +1697,8 @@ function prepare_page($item) { // ... other possible options } - $body = prepare_body($item, [ 'newwin' => false ]); + $body = prepare_body($item, true, [ 'newwin' => false ]); + if(App::$page['template'] == 'none') { $tpl = 'page_display_empty.tpl'; diff --git a/include/dir_fns.php b/include/dir_fns.php deleted file mode 100644 index 84b0e6d93..000000000 --- a/include/dir_fns.php +++ /dev/null @@ -1,437 +0,0 @@ -<?php -/** - * @file include/dir_fns.php - */ - -use Zotlabs\Lib\Crypto; -use Zotlabs\Lib\Libzot; -use Zotlabs\Lib\Webfinger; -use Zotlabs\Lib\Zotfinger; - -require_once('include/permissions.php'); - -/** - * @brief - * - * @param int $dirmode - * @return array - */ -function find_upstream_directory($dirmode) { - - $preferred = get_config('system','directory_server'); - - // Thwart attempts to use a private directory - - if(($preferred) && ($preferred != z_root())) { - $r = q("select * from site where site_url = '%s' limit 1", - dbesc($preferred) - ); - if(($r) && ($r[0]['site_flags'] & DIRECTORY_MODE_STANDALONE)) { - $preferred = ''; - } - } - - - if (! $preferred) { - - /* - * No directory has yet been set. For most sites, pick one at random - * from our list of directory servers. However, if we're a directory - * server ourself, point at the local instance - * We will then set this value so this should only ever happen once. - * Ideally there will be an admin setting to change to a different - * directory server if you don't like our choice or if circumstances change. - */ - - $directory_fallback_servers = get_directory_fallback_servers(); - - $dirmode = intval(get_config('system','directory_mode')); - if ($dirmode == DIRECTORY_MODE_NORMAL) { - $toss = mt_rand(0,count($directory_fallback_servers)); - $preferred = $directory_fallback_servers[$toss]; - set_config('system','directory_server',$preferred); - } else{ - set_config('system','directory_server',z_root()); - } - } - - return array('url' => $preferred); -} - -/** - * Directories may come and go over time. We will need to check that our - * directory server is still valid occasionally, and reset to something that - * is if our directory has gone offline for any reason - */ -function check_upstream_directory() { - - $directory = get_config('system', 'directory_server'); - - // it's possible there is no directory server configured and the local hub is being used. - // If so, default to preserving the absence of a specific server setting. - - $isadir = true; - - if ($directory) { - $j = Zotfinger::exec($directory); - if (array_path_exists('data/directory_mode',$j)) { - if ($j['data']['directory_mode'] === 'normal') { - $isadir = false; - } - } - } - - if (! $isadir) - set_config('system', 'directory_server', ''); -} - -function get_directory_setting($observer, $setting) { - - if ($observer) - $ret = get_xconfig($observer, 'directory', $setting); - else - $ret = ((array_key_exists($setting,$_SESSION)) ? intval($_SESSION[$setting]) : false); - - if($ret === false) - $ret = get_config('directory', $setting); - - - // 'safemode' is the default if there is no observer or no established preference. - - if($setting == 'safemode' && $ret === false) - $ret = 1; - - return $ret; -} - -/** - * @brief Called by the directory_sort widget. - */ -function dir_sort_links() { - - $safe_mode = 1; - - $observer = get_observer_hash(); - - $safe_mode = get_directory_setting($observer, 'safemode'); - $globaldir = get_directory_setting($observer, 'globaldir'); - $pubforums = get_directory_setting($observer, 'pubforums'); - - // Build urls without order and pubforums so it's easy to tack on the changed value - // Probably there's an easier way to do this - - $directory_sort_order = get_config('system','directory_sort_order'); - if(! $directory_sort_order) - $directory_sort_order = 'date'; - - $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order); - $suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : ''); - - $url = 'directory?f='; - - $tmp = array_merge($_GET,$_POST); - unset($tmp['suggest']); - unset($tmp['pubforums']); - unset($tmp['global']); - unset($tmp['safe']); - unset($tmp['q']); - unset($tmp['f']); - $forumsurl = $url . http_build_query($tmp) . $suggest; - - $o = replace_macros(get_markup_template('dir_sort_links.tpl'), array( - '$header' => t('Directory Options'), - '$forumsurl' => $forumsurl, - '$safemode' => array('safemode', t('Safe Mode'),$safe_mode,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''), - '$pubforums' => array('pubforums', t('Public Forums Only'),$pubforums,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''), - '$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''), - )); - - return $o; -} - -/** - * @brief Checks the directory mode of this hub. - * - * Checks the directory mode of this hub to see if it is some form of directory server. If it is, - * get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request - * a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB. - * In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored - * directly if the rater's signature matches. - * - * @param int $dirmode; - */ -function sync_directories($dirmode) { - - if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL) - return; - - $realm = get_directory_realm(); - if ($realm == DIRECTORY_REALM) { - $r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') ", - intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), - dbesc(z_root()), - intval(SITE_TYPE_ZOT), - dbesc($realm) - ); - } else { - $r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d ", - intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), - dbesc(z_root()), - dbesc(protect_sprintf('%' . $realm . '%')), - intval(SITE_TYPE_ZOT) - ); - } - - // If there are no directory servers, setup the fallback master - /** @FIXME What to do if we're in a different realm? */ - - if ((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) { - - $x = site_store_lowlevel( - [ - 'site_url' => DIRECTORY_FALLBACK_MASTER, - 'site_flags' => DIRECTORY_MODE_PRIMARY, - 'site_update' => NULL_DATE, - 'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch', - 'site_realm' => DIRECTORY_REALM, - 'site_valid' => 1, - 'site_crypto' => 'aes256cbc' - ] - ); - - $r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ", - intval(DIRECTORY_MODE_PRIMARY), - intval(DIRECTORY_MODE_SECONDARY), - dbesc(z_root()), - intval(SITE_TYPE_ZOT) - ); - } - if (! $r) - return; - - foreach ($r as $rr) { - if (! $rr['site_directory']) - continue; - - logger('sync directories: ' . $rr['site_directory']); - - // for brand new directory servers, only load the last couple of days. - // It will take about a month for a new directory to obtain the full current repertoire of channels. - /** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */ - - $token = get_config('system','realm_token'); - - $syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']); - $x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : '')); - - if (! $x['success']) - continue; - - $j = json_decode($x['body'],true); - if (!($j['transactions']) || ($j['ratings'])) - continue; - - q("update site set site_sync = '%s' where site_url = '%s'", - dbesc(datetime_convert()), - dbesc($rr['site_url']) - ); - - logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA); - - if (is_array($j['transactions']) && count($j['transactions'])) { - foreach ($j['transactions'] as $t) { - $r = q("select * from updates where ud_guid = '%s' limit 1", - dbesc($t['transaction_id']) - ); - if($r) - continue; - - $ud_flags = 0; - if (is_array($t['flags']) && in_array('deleted',$t['flags'])) - $ud_flags |= UPDATE_FLAGS_DELETED; - if (is_array($t['flags']) && in_array('forced',$t['flags'])) - $ud_flags |= UPDATE_FLAGS_FORCED; - - $z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) - values ( '%s', '%s', '%s', %d, '%s' ) ", - dbesc($t['hash']), - dbesc($t['transaction_id']), - dbesc($t['timestamp']), - intval($ud_flags), - dbesc($t['address']) - ); - } - } - if (is_array($j['ratings']) && count($j['ratings'])) { - foreach ($j['ratings'] as $rr) { - $x = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", - dbesc($rr['channel']), - dbesc($rr['target']) - ); - if ($x && $x[0]['xlink_updated'] >= $rr['edited']) - continue; - - // Ratings are signed by the rater. We need to verify before we can accept it. - /** @TODO Queue or defer if the xchan is not yet present on our site */ - - $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", - dbesc($rr['channel']) - ); - if (! $y) { - logger('key unavailable on this site for ' . $rr['channel']); - continue; - } - if (! Crypto::verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) { - logger('failed to verify rating'); - continue; - } - - if ($x) { - $z = q("update xlink set xlink_rating = %d, xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' where xlink_id = %d", - intval($rr['rating']), - dbesc($rr['rating_text']), - dbesc($rr['signature']), - dbesc(datetime_convert()), - intval($x[0]['xlink_id']) - ); - logger('rating updated'); - } else { - $z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", - dbesc($rr['channel']), - dbesc($rr['target']), - intval($rr['rating']), - dbesc($rr['rating_text']), - dbesc($rr['signature']), - dbesc(datetime_convert()) - ); - logger('rating created'); - } - } - } - } -} - - -/** - * @brief - * - * Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data. - * - * Ignore updating records marked as deleted. - * - * If successful, sets ud_last in the DB to the current datetime for this - * reddress/webbie. - * - * @param array $ud Entry from update table - */ -function update_directory_entry($ud) { - - logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA); - - if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) { - $success = false; - $uri = Webfinger::zot_url($ud['ud_addr']); - - if($uri) { - $record = Zotfinger::exec($uri); - - // Check the HTTP signature - $hsig = $record['signature']; - if($hsig && $hsig['signer'] === $uri && $hsig['header_valid'] === true && $hsig['content_valid'] === true) { - $x = Libzot::import_xchan($record['data'], 0, $ud); - if($x['success']) { - $success = true; - } - } - } - } -} - - -/** - * @brief Push local channel updates to a local directory server. - * - * This is called from include/directory.php if a profile is to be pushed to the - * directory and the local hub in this case is any kind of directory server. - * - * @param int $uid - * @param boolean $force - */ -function local_dir_update($uid, $force) { - - logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG); - - $p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1", - intval($uid) - ); - - $profile = array(); - $profile['encoding'] = 'zot'; - - if ($p) { - $hash = $p[0]['channel_hash']; - - $profile['description'] = $p[0]['pdesc']; - $profile['birthday'] = $p[0]['dob']; - if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],'')) - $profile['age'] = $age; - - $profile['gender'] = $p[0]['gender']; - $profile['marital'] = $p[0]['marital']; - $profile['sexual'] = $p[0]['sexual']; - $profile['locale'] = $p[0]['locality']; - $profile['region'] = $p[0]['region']; - $profile['postcode'] = $p[0]['postal_code']; - $profile['country'] = $p[0]['country_name']; - $profile['about'] = $p[0]['about']; - $profile['homepage'] = $p[0]['homepage']; - $profile['hometown'] = $p[0]['hometown']; - - if ($p[0]['keywords']) { - $tags = array(); - $k = explode(' ', $p[0]['keywords']); - if ($k) - foreach ($k as $kk) - if (trim($kk)) - $tags[] = trim($kk); - - if ($tags) - $profile['keywords'] = $tags; - } - - $hidden = (1 - intval($p[0]['publish'])); - - logger('hidden: ' . $hidden); - - $r = q("select xchan_hidden from xchan where xchan_hash = '%s' limit 1", - dbesc($p[0]['channel_hash']) - ); - - if(intval($r[0]['xchan_hidden']) != $hidden) { - $r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'", - intval($hidden), - dbesc($p[0]['channel_hash']) - ); - } - - $arr = array('channel_id' => $uid, 'hash' => $hash, 'profile' => $profile); - call_hooks('local_dir_update', $arr); - - $address = channel_reddress($p[0]); - - if (perm_is_allowed($uid, '', 'view_profile')) { - import_directory_profile($hash, $arr['profile'], $address, 0); - } else { - // they may have made it private - $r = q("delete from xprof where xprof_hash = '%s'", - dbesc($hash) - ); - $r = q("delete from xtag where xtag_hash = '%s'", - dbesc($hash) - ); - } - } - - $ud_hash = random_string() . '@' . App::get_hostname(); - update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); -} diff --git a/include/html2plain.php b/include/html2plain.php index bf8581bdb..48bbe3d9e 100644 --- a/include/html2plain.php +++ b/include/html2plain.php @@ -78,10 +78,10 @@ function quotelevel($message, $wraplength = 75) function collecturls($message) { - + $pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is'; preg_match_all($pattern, $message, $result, PREG_SET_ORDER); - + $urls = []; if ($result) { $ignore = false; @@ -104,15 +104,15 @@ function collecturls($message) { foreach ($list as $listitem) if (strpos($treffer[1], $listitem) !== false) $ignore = true; - + if ((strpos($treffer[1], "//plus.google.com/") !== false) and (strpos($treffer[1], "/posts") !== false)) $ignore = false; - + if (! $ignore) $urls[$treffer[1]] = $treffer[1]; } } - + return($urls); } diff --git a/include/items.php b/include/items.php index 15de6c730..f451358f8 100644 --- a/include/items.php +++ b/include/items.php @@ -2494,7 +2494,7 @@ function send_status_notifications($post_id,$item) { Enotify::submit(array( - 'type' => NOTIFY_COMMENT, + 'type' => ((intval($item['item_private']) === 2) ? NOTIFY_MAIL : NOTIFY_COMMENT), 'from_xchan' => $item['author_xchan'], 'to_xchan' => $r[0]['channel_hash'], 'item' => $item, @@ -3177,7 +3177,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false "' portable_id='" . $item['author']['xchan_hash'] . "' avatar='" . $item['author']['xchan_photo_s'] . "' link='" . $item['plink'] . - "' auth='" . ((in_array($item['author']['xchan_network'], ['zot6','zot'])) ? 'true' : 'false') . + "' auth='" . (($item['author']['xchan_network'] === 'zot6') ? 'true' : 'false') . "' posted='" . $item['created'] . "' message_id='" . $item['mid'] . "']"; diff --git a/include/photos.php b/include/photos.php index 11dd07586..967acf955 100644 --- a/include/photos.php +++ b/include/photos.php @@ -4,6 +4,9 @@ * @brief Functions related to photo handling. */ +use Zotlabs\Lib\Activity; + + require_once('include/permissions.php'); require_once('include/items.php'); require_once('include/photo/photo_driver.php'); @@ -256,10 +259,10 @@ function photo_upload($channel, $observer, $args) { if($args['description']) $p['description'] = $args['description']; - $link = array(); + $url = []; $r0 = $ph->save($p); - $link[0] = array( + $url[0] = array( 'rel' => 'alternate', 'type' => $type, 'href' => z_root() . '/photo/' . $photo_hash . '-0.' . $ph->getExt(), @@ -278,7 +281,7 @@ function photo_upload($channel, $observer, $args) { $ph->scaleImage(1024); $r1 = $ph->storeThumbnail($p, PHOTO_RES_1024); - $link[1] = array( + $url[1] = array( 'rel' => 'alternate', 'type' => $type, 'href' => z_root() . '/photo/' . $photo_hash . '-1.' . $ph->getExt(), @@ -292,7 +295,7 @@ function photo_upload($channel, $observer, $args) { $ph->scaleImage(640); $r2 = $ph->storeThumbnail($p, PHOTO_RES_640); - $link[2] = array( + $url[2] = array( 'rel' => 'alternate', 'type' => $type, 'href' => z_root() . '/photo/' . $photo_hash . '-2.' . $ph->getExt(), @@ -306,7 +309,7 @@ function photo_upload($channel, $observer, $args) { $ph->scaleImage(320); $r3 = $ph->storeThumbnail($p, PHOTO_RES_320); - $link[3] = array( + $url[3] = array( 'rel' => 'alternate', 'type' => $type, 'href' => z_root() . '/photo/' . $photo_hash . '-3.' . $ph->getExt(), @@ -353,18 +356,18 @@ function photo_upload($channel, $observer, $args) { $large_photos = feature_enabled($channel['channel_id'], 'large_photos'); - linkify_tags($args['body'], $channel_id); + $found_tags = linkify_tags($args['body'], $channel_id); if($large_photos) { $scale = 1; - $width = $link[1]['width']; - $height = $link[1]['height']; + $width = $url[1]['width']; + $height = $url[1]['height']; $tag = (($r1) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]'); } else { $scale = 2; - $width = $link[2]['width']; - $height = $link[2]['height']; + $width = $url[2]['width']; + $height = $url[2]['height']; $tag = (($r2) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]'); } @@ -382,22 +385,61 @@ function photo_upload($channel, $observer, $args) { . $tag . z_root() . "/photo/{$photo_hash}-{$scale}." . $ph->getExt() . '[/zmg]' . '[/zrl]'; - // Create item object - $object = array( - 'type' => ACTIVITY_OBJ_PHOTO, - 'title' => $title, - 'created' => $p['created'], - 'edited' => $p['edited'], - 'id' => z_root() . '/item/' . $photo_hash, - 'link' => $link, - 'body' => $summary - ); + $url[] = [ + 'type' => 'Link', + 'mediaType' => 'text/html', + 'href' => z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash + ]; + + $post_tags = []; + + if($found_tags) { + foreach($found_tags as $result) { + $success = $result['success']; + if($success['replaced']) { + $post_tags[] = array( + 'uid' => $channel['channel_id'], + 'ttype' => $success['termtype'], + 'otype' => TERM_OBJ_POST, + 'term' => $success['term'], + 'url' => $success['url'] + ); + } + } + } - $target = array( - 'type' => ACTIVITY_OBJ_ALBUM, - 'title' => (($album) ? $album : '/'), - 'id' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album) - ); + //// Create item object + $object = [ + 'type' => 'Image', + 'name' => $title, + 'published' => datetime_convert('UTC','UTC',$p['created'],ATOM_TIME), + 'updated' => datetime_convert('UTC','UTC',$p['edited'],ATOM_TIME), + // This is a placeholder and will get over-ridden by the item mid, which is critical for sharing as a conversational item over activitypub + 'id' => z_root() . '/photo/' . $photo_hash, + 'url' => $url, + 'source' => [ 'content' => $summary, 'mediaType' => 'text/bbcode' ], + 'content' => bbcode($summary) + ]; + + if ($post_tags) { + $object['tag'] = Activity::encode_taxonomy(['term' => $post_tags]); + } + + $public = (($ac['allow_cid'] || $ac['allow_gid'] || $ac['deny_cid'] || $ac['deny_gid']) ? false : true); + + if ($public) { + $object['to'] = [ ACTIVITY_PUBLIC_INBOX ]; + $object['cc'] = [ z_root() . '/followers/' . $channel['channel_address'] ]; + } + else { + $object['to'] = Activity::map_acl(array_merge($ac, ['item_private' => 1 - intval($public) ])); + } + + $target = [ + 'type' => 'orderedCollection', + 'name' => ((strlen($album)) ? $album : '/'), + 'id' => z_root() . '/album/' . $channel['channel_address'] . ((isset($args['folder'])) ? '/' . $args['folder'] : EMPTY_STR) + ]; // Create item container if($args['item']) { @@ -415,7 +457,9 @@ function photo_upload($channel, $observer, $args) { $item['tgt_type'] = ACTIVITY_OBJ_ALBUM; $item['target'] = json_encode($target); - + if ($post_tags) { + $arr['term'] = $post_tags; + } $force = true; } $r = q("select id, edited from item where mid = '%s' and uid = %d limit 1", @@ -469,6 +513,10 @@ function photo_upload($channel, $observer, $args) { 'body' => $summary ]; + if ($post_tags) { + $arr['term'] = $post_tags; + } + $arr['plink'] = $mid; if($lat && $lon) diff --git a/include/queue_fn.php b/include/queue_fn.php deleted file mode 100644 index 1e8171b1d..000000000 --- a/include/queue_fn.php +++ /dev/null @@ -1,314 +0,0 @@ -<?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", - dbesc($id) - ); - if(! $x) - return; - - - $y = q("select outq_created as earliest from outq where outq_posturl = '%s' order by earliest limit 1", - dbesc($x[0]['outq_posturl']) - ); - - // look for the oldest queue entry with this destination URL. If it's older than a couple of days, - // the destination is considered to be down and only scheduled once an hour, regardless of the - // age of the current queue item. - - $might_be_down = false; - - if($y) - $might_be_down = ((datetime_convert('UTC','UTC',$y[0]['earliest']) < datetime_convert('UTC','UTC','now - 2 days')) ? true : false); - - - // Set all other records for this destination way into the future. - // The queue delivers by destination. We'll keep one queue item for - // this destination (this one) with a shorter delivery. If we succeed - // once, we'll try to deliver everything for that destination. - // The delivery will be set to at most once per hour, and if the - // queue item is less than 12 hours old, we'll schedule for fifteen - // minutes. - - $r = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'", - dbesc(datetime_convert('UTC','UTC','now + 5 days')), - dbesc($x[0]['outq_posturl']) - ); - - $since = datetime_convert('UTC','UTC',$x[0]['outq_created']); - - if(($might_be_down) || ($since < datetime_convert('UTC','UTC','now - 12 hour'))) { - $next = datetime_convert('UTC','UTC','now + 1 hour'); - } - else { - $next = datetime_convert('UTC','UTC','now + ' . intval($add_priority) . ' minutes'); - } - - q("UPDATE outq SET outq_updated = '%s', - outq_priority = outq_priority + %d, - outq_scheduled = '%s' - WHERE outq_hash = '%s'", - - dbesc(datetime_convert()), - intval($add_priority), - dbesc($next), - dbesc($id) - ); -} - -function remove_queue_item($id,$channel_id = 0) { - logger('queue: remove queue item ' . $id,LOGGER_DEBUG); - $sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : ''); - - q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra", - dbesc($id) - ); -} - - -function remove_queue_by_posturl($posturl) { - logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG); - - q("DELETE FROM outq WHERE outq_posturl = '%s' ", - dbesc($posturl) - ); -} - - - -function queue_set_delivered($id,$channel = 0) { - logger('queue: set delivered ' . $id,LOGGER_DEBUG); - $sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : ''); - - // Set the next scheduled run date so far in the future that it will be expired - // long before it ever makes it back into the delivery chain. - - q("update outq set outq_delivered = 1, outq_updated = '%s', outq_scheduled = '%s' where outq_hash = '%s' $sql_extra ", - dbesc(datetime_convert()), - dbesc(datetime_convert('UTC','UTC','now + 5 days')), - dbesc($id) - ); -} - - - -function queue_insert($arr) { - - // do not queue anything with no destination - - if(! (array_key_exists('posturl',$arr) && trim($arr['posturl']))) { - return false; - } - - $x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority, - outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg ) - values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' )", - dbesc($arr['hash']), - intval($arr['account_id']), - intval($arr['channel_id']), - dbesc(($arr['driver']) ? $arr['driver'] : 'zot'), - dbesc($arr['posturl']), - intval(1), - intval(($arr['priority']) ? $arr['priority'] : 0), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($arr['notify']), - dbesc(($arr['msg']) ? $arr['msg'] : '') - ); - return $x; - -} - - - -function queue_deliver($outq, $immediate = false) { - - $base = null; - $h = parse_url($outq['outq_posturl']); - if($h !== false) - $base = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : ''); - - if(($base) && ($base !== z_root()) && ($immediate)) { - $y = q("select site_update, site_dead from site where site_url = '%s' ", - dbesc($base) - ); - if($y) { - if(intval($y[0]['site_dead'])) { - remove_queue_by_posturl($outq['outq_posturl']); - logger('dead site ignored ' . $base); - return; - } - if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) { - update_queue_item($outq['outq_hash'],10); - logger('immediate delivery deferred for site ' . $base); - return; - } - } - else { - - // zot sites should all have a site record, unless they've been dead for as long as - // your site has existed. Since we don't know for sure what these sites are, - // call them unknown - - site_store_lowlevel( - [ - 'site_url' => $base, - 'site_update' => datetime_convert(), - 'site_dead' => 0, - 'site_type' => intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN), - 'site_crypto' => '' - ] - ); - } - } - - - - - - - $arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate); - call_hooks('queue_deliver',$arr); - if($arr['handled']) - return; - - // "post" queue driver - used for diaspora and friendica-over-diaspora communications. - - if($outq['outq_driver'] === 'post') { - $result = z_post_url($outq['outq_posturl'],$outq['outq_msg']); - if($result['success'] && $result['return_code'] < 300) { - logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG); - if($base) { - q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ", - dbesc(datetime_convert()), - dbesc($base) - ); - } - q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'", - dbesc('accepted for delivery'), - dbesc(datetime_convert()), - dbesc($outq['outq_hash']) - ); - remove_queue_item($outq['outq_hash']); - - // server is responding - see if anything else is going to this destination and is piled up - // and try to send some more. We're relying on the fact that do_delivery() results in an - // immediate delivery otherwise we could get into a queue loop. - - if(! $immediate) { - $x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0", - dbesc($outq['outq_posturl']) - ); - - $piled_up = array(); - if($x) { - foreach($x as $xx) { - $piled_up[] = $xx['outq_hash']; - } - } - if($piled_up) { - // call do_delivery() with the force flag - do_delivery($piled_up, true); - } - } - } - else { - logger('deliver: queue post returned ' . $result['return_code'] - . ' from ' . $outq['outq_posturl'],LOGGER_DEBUG); - update_queue_item($outq['outq_hash'],10); - } - return; - } - - // normal zot delivery - - logger('deliver: dest: ' . $outq['outq_posturl'] . ' driver: ' . $outq['outq_driver'], LOGGER_DEBUG); - - if($outq['outq_driver'] === 'zot6') { - - 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; - - 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); - } - - } - return; - } - else { - - $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' and hubloc_sitekey != '' 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; - } - -} diff --git a/include/text.php b/include/text.php index 8dc5ee188..841abdbd3 100644 --- a/include/text.php +++ b/include/text.php @@ -11,6 +11,7 @@ use Ramsey\Uuid\Exception\UnableToBuildUuidException; use Zotlabs\Lib\Crypto; use Zotlabs\Lib\SvgSanitizer; +use Zotlabs\Lib\Libzot; require_once("include/bbcode.php"); @@ -1714,19 +1715,33 @@ function prepare_body(&$item,$attach = false,$opts = false) { $photo = ''; $is_photo = ((($item['verb'] === ACTIVITY_POST) && ($item['obj_type'] === ACTIVITY_OBJ_PHOTO)) ? true : false); - if($is_photo) { - + if ($is_photo) { $object = json_decode($item['obj'],true); + $ptr = null; + if (array_key_exists('url',$object) && is_array($object['url'])) { + if (array_key_exists(0,$object['url'])) { + foreach ($object['url'] as $link) { + if(array_key_exists('width',$link) && $link['width'] >= 640 && $link['width'] <= 1024) { + $ptr = $link; + } + } + if (! $ptr) { + $ptr = $object['url'][0]; + } + } + else { + $ptr = $object['url']; + } - // if original photo width is <= 640px prepend it to item body - if($object['link'][0]['width'] && $object['link'][0]['width'] <= 640) { - $s .= '<div class="inline-photo-item-wrapper"><a href="' . zid(rawurldecode($object['id'])) . '" target="_blank" rel="nofollow noopener" ><img class="inline-photo-item" style="max-width:' . $object['link'][0]['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($object['link'][0]['href'])) . '"></a></div>' . $s; - } - - // if original photo width is > 640px make it a cover photo - if($object['link'][0]['width'] && $object['link'][0]['width'] > 640) { - $scale = ((($object['link'][1]['width'] == 1024) || ($object['link'][1]['height'] == 1024)) ? 1 : 0); - $photo = '<a href="' . zid(rawurldecode($object['id'])) . '" target="_blank" rel="nofollow noopener"><img style="max-width:' . $object['link'][$scale]['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($object['link'][$scale]['href'])) . '"></a>'; + // if original photo width is > 640px make it a cover photo + if ($ptr) { + if (array_key_exists('width',$ptr) && $ptr['width'] > 640) { + $photo = '<a href="' . zid(rawurldecode($object['id'])) . '" target="_blank" rel="nofollow noopener"><img style="max-width:' . $ptr['width'] . 'px; width:100%; height:auto;" src="' . zid(rawurldecode($ptr['href'])) . '"></a>'; + } + else { + $item['body'] = '[zmg]' . $ptr['href'] . '[/zmg]' . "\n\n" . $item['body']; + } + } } } @@ -2837,7 +2852,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true) // BEGIN mentions - if ( in_array($termtype, [ TERM_MENTION, TERM_FORUM ] )) { + if ($termtype === TERM_MENTION) { // The @! tag will alter permissions @@ -2864,14 +2879,13 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true) $newname = substr($name,1); $newname = substr($newname,0,-1); - $r = q("SELECT * FROM xchan WHERE xchan_addr = '%s' OR xchan_url = '%s' AND xchan_deleted = 0", + $r = q("SELECT * FROM xchan WHERE ( xchan_addr = '%s' OR xchan_url = '%s' ) AND xchan_deleted = 0", dbesc($newname), dbesc($newname) ); } if(! $r) { - // look for matching names in the address book // Double quote the entire mentioned term to include special characters @@ -2926,7 +2940,10 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true) // $r is set if we found something if($r) { - foreach($r as $xc) { + + $xchan[0] = Libzot::zot_record_preferred($r, 'xchan_network'); + + foreach($xchan as $xc) { $profile = $xc['xchan_url']; $newname = $xc['xchan_name']; // add the channel's xchan_hash to $access_tag if exclusive @@ -2941,16 +2958,9 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = 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); - } -*/ - if ($termtype === TERM_MENTION) { - $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]'; - $body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body); - } + + $newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]'; + $body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body); // append tag to str_tags if(! stristr($str_tags,$newtag)) { @@ -3880,3 +3890,30 @@ function sanitize_text_field($str) { return preg_replace('/\s+/S', ' ', $str); } +/** + * @brief shortens a string to $max_length without cutting off words + * @param string $str + * @param intval $max_length + * @param string $suffix (optional) + + * @return string + */ +function substr_words($str, $max_length, $suffix = '...') { + + if (strlen($str) > $max_length) { + $words = preg_split('/\s/', $str); + $ret = ''; + $i = 0; + while (true) { + $length = (strlen($ret) + strlen($words[$i])); + if ($length > $max_length) { + break; + } + $ret .= " " . $words[$i]; + ++$i; + } + $ret .= $suffix; + } + + return (($ret) ? $ret : $str); +} |