Compare commits

...

28 Commits
9.4 ... 9.4.3

Author SHA1 Message Date
Mario Vavti
69109a558b version 9.4.3 2024-10-10 12:16:33 +02:00
Mario
4aff6d19d6 changelog
(cherry picked from commit a5c1b669b4)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-10 10:11:31 +00:00
Mario
3cb5d14037 also discard Add/Remove at the AP side
(cherry picked from commit 2aee659cbd)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-10 10:04:17 +00:00
Mario
5f685bcf63 also dismiss add/remove collection activities in fetch_conversation()
(cherry picked from commit 44232677c8)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-10 10:03:51 +00:00
Mario
cb44f7e360 dismiss add/remove collection activities until we support themÃ
(cherry picked from commit 16603ca854)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-10 10:03:32 +00:00
Mario
8f74ee67e3 css fixes
(cherry picked from commit 2693e9e990)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 11:27:56 +00:00
Mario
b0a11537de remove bogus icon id
(cherry picked from commit 04741c761a)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 11:27:40 +00:00
Mario
4de9cb1142 more fa2bi fixes
(cherry picked from commit 8f890fb6fa)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 11:07:50 +00:00
Mario
158ddfb009 changelog
(cherry picked from commit 1afb2a4ce8)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 07:09:21 +00:00
Mario
2b4f344181 Version 9.4.2 2024-10-04 07:07:31 +00:00
Mario
2e5f922561 due to popular demand: indicate reacted state via icon color
(cherry picked from commit afbeb58c16)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:59:50 +00:00
Mario
a6498a0cfc Reflect change to btn-link in js template
(cherry picked from commit 8ffab25f5d)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:59:16 +00:00
Mario
1073392398 Fix modal backdrop not removed when like/unlike from the modal
(cherry picked from commit 7d41deebce)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:51:15 +00:00
Mario
76064dbb33 Fix missing handle icon in mod pdledit_gui
(cherry picked from commit 7e48caae6b)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-04 06:27:37 +00:00
Mario
1ab4f36a1b Merge branch 'master' of https://framagit.org/hubzilla/core 2024-10-03 04:52:40 +00:00
Mario
cea9c88b9e version 9.4.1 2024-10-03 04:52:18 +00:00
Mario
babe118383 Tests: Unbreak help test.
(cherry picked from commit 5b93aa1148)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:27:26 +00:00
Mario
2b140e53cc changelog
(cherry picked from commit 9008760aa6)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-02 20:21:51 +00:00
Mario
fb1514a782 Help: Drop language specifier in URL when redirecting
This finally fixes the help for languages other than english.


(cherry picked from commit 4daa03f025)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:09:36 +00:00
Mario
7679894684 Replace drop shadow in help toc with brighter color.
The drop shadow looked terrible in dark mode. While that could be fixed,
I think it looks better with just using the link hover color and making
the selected item bold.


(cherry picked from commit 8ae9df3bb7)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:08:55 +00:00
Mario
520cf1015c Move some help related styling from redbasic to module css.
(cherry picked from commit 25d9d3ba1b)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:08:33 +00:00
Mario
64bd8eef4b Use html details element for toc on top of help pages.
This allows us to get rid of some more unneccessary JavaScript that just
implements stuff that web browsers now do anyways.


(cherry picked from commit 26ce231951)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:08:04 +00:00
Mario
aa42f6a6b2 Remove link to "Contents" from the help table of contect sidebar.
Changes the element where the jQuery.toc plugin looks for headings to
only include the actual help contents, not the toc itself.


(cherry picked from commit fb9464437e)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:07:31 +00:00
Mario
13345d3cbe deps: Upgrade smarty/smarty to version 4.5.4
This eliminates a potential vulnerability where an template author could
inject arbitrary PHP files to be run via the 'extends' tag.

See:
  - https://github.com/smarty-php/smarty/security/advisories/GHSA-4rmg-292m-wg3w
  - 0be92bc8a6

Impact assessment:

In our case I would consider this a low severity issue as we don't
allow users to dynamically add or edit smarty templates. Templates has
to be updated via merge requests, or by installing a theme. In both
cases a malicious attacker already has easier ways to inject whatever
code they want.

Further, the extend tag is not in use in any of our core templates.


(cherry picked from commit 4dff1a1e5b)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:06:10 +00:00
Mario
888ee16d52 fix german about page title
(cherry picked from commit 1c45030c58)

Co-authored-by: Mario <mario@mariovavti.com>
2024-10-02 20:05:06 +00:00
Mario
0f3e01f343 markdown: Don't link URLs in code blocks.
When passing a content throught the `markdown_to_bb` function
to convert any markdown in the content, any recognized URLs in the
content would be converted to BBCode links as a post processing step
after the main conversion.

After commit a1ccacb825 this did no longer
consider content within code blocks, and would thus convert them as
to BBCode links.

Example: The following content

	[code]
	example url: https://example.com
	[/code]

Would be converted to

	[code]
	example url: [url=https://example.com]https://example.com[/url]
	[/code]

Prior to commit a1ccacb825, code blocks
would be protected, so this would not happen.

This patch removes the post processing step for converting plain URLs to
links completely from this routine. This functionality is in any case
covered in the actual BBCode parser where it belongs.

This will have some other side effects as well, such as images and links
created using Markdown, will not be converted to [zmg] or [zrl] tags
where that would be done automatically before. If you intend to use a
[zrl] or [zmg] tag, you now need to do so explicitly.


(cherry picked from commit 803cd74b48)

Co-authored-by: Harald Eilertsen <haraldei@anduin.net>
2024-10-02 20:04:30 +00:00
Mario
79220ede66 rewrite sql logic to rename photos - there are more DB queries involved now but the previous logic was throwing error in postgresql (while the result was correct anyway)
(cherry picked from commit a5f0253aef)

Co-authored-by: Mario Vavti <mario@mariovavti.com>
2024-10-02 20:03:54 +00:00
Mario
b498e50f74 adjust post app icon and remove obsolete arguments
(cherry picked from commit 5cbd42bbc4)

Co-authored-by: Mario <mario@mariovavti.com>
2024-09-27 16:51:57 +00:00
37 changed files with 269 additions and 229 deletions

View File

@@ -1,3 +1,24 @@
Hubzilla 9.4.3 (2024-10-10)
- Discard Add/Remove activities (Hubzilla 10 and (streams) compatibility)
- Fix HQ channel activities icons
- Fix saved search icons
Hubzilla 9.4.2 (2024-10-04)
- Indicate reacted state via icon color (community wish)
- Fix modal backdrop not removed when reacting from the modal
- Fix missing handle icon in mod pdledit_gui
Hubzilla 9.4.1 (2024-10-02)
- Various fixes for the help module
- Update smarty library via composer
- Fix URLs replaced with bbcode in codeblocks if markdown enabled
- Fix unable to move multiple files when using postgresql DB backend
- Adjust icon for post app
- Fix check for while loop in wiki addon
Hubzilla 9.4 (2024-09-25)
- If we got an ocap token try to authenticate with it first
- Hide comment titles

View File

@@ -3054,13 +3054,6 @@ class Activity {
}
$a = new ActivityStreams($n);
if ($a->type === 'Announce' && is_array($a->obj)
&& array_key_exists('object', $a->obj) && array_key_exists('actor', $a->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
logger('relayed activity', LOGGER_DEBUG);
$a = new ActivityStreams($a->obj);
}
logger($a->debug(), LOGGER_DATA);
@@ -3069,6 +3062,24 @@ class Activity {
break;
}
if (in_array($a->type, ['Add', 'Remove'])
&& is_array($a->obj)
&& array_key_exists('object', $a->obj)
&& array_key_exists('actor', $a->obj)
&& !empty($a->tgt)) {
logger('unsupported collection operation', LOGGER_DEBUG);
return;
}
if ($a->type === 'Announce' && is_array($a->obj)
&& array_key_exists('object', $a->obj) && array_key_exists('actor', $a->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
logger('relayed activity', LOGGER_DEBUG);
$a = new ActivityStreams($a->obj);
}
$item = Activity::decode_note($a);
if (!$item) {

View File

@@ -1148,6 +1148,17 @@ class Libzot {
logger('Activity rejected: ' . print_r($data, true));
return;
}
if (in_array($AS->type, ['Add', 'Remove'])
&& is_array($AS->obj)
&& array_key_exists('object', $AS->obj)
&& array_key_exists('actor', $AS->obj)
&& !empty($AS->tgt)) {
logger('unsupported collection operation', LOGGER_DEBUG);
return;
}
if (is_array($AS->obj)) {
$item = Activity::decode_note($AS);
if (!$item) {
@@ -1158,6 +1169,7 @@ class Libzot {
else {
$item = [];
}
logger($AS->debug(), LOGGER_DATA);
}
@@ -2006,7 +2018,13 @@ class Libzot {
foreach ($items as $activity) {
$AS = new ActivityStreams($activity);
if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
if (!$AS->is_valid()) {
logger('Fetched activity rejected: ' . print_r($activity, true));
continue;
}
if ($AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object', $AS->obj) && array_key_exists('actor', $AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
@@ -2014,9 +2032,14 @@ class Libzot {
$AS = new ActivityStreams($AS->obj);
}
if (!$AS->is_valid()) {
logger('Fetched activity rejected: ' . print_r($activity, true));
continue;
if (in_array($AS->type, ['Add', 'Remove'])
&& is_array($AS->obj)
&& array_key_exists('object', $AS->obj)
&& array_key_exists('actor', $AS->obj)
&& !empty($AS->tgt)) {
logger('unsupported collection operation', LOGGER_DEBUG);
return;
}
// logger($AS->debug());

View File

@@ -30,7 +30,7 @@ class Help extends \Zotlabs\Web\Controller {
$this->determine_help_language();
if (empty($_REQUEST['search']) && argc() === 1) {
goaway("/help/{$this->lang['language']}/about/about");
goaway("/help/about/about");
killme();
}
}
@@ -155,7 +155,7 @@ class Help extends \Zotlabs\Web\Controller {
}
if (empty($args)) {
goaway("/help/{$this->lang['language']}/about/about");
goaway("/help/about/about");
}
// Keep the first remaining arg as the heading slug

View File

@@ -91,7 +91,7 @@ class Channel_activities {
self::$activities['photos'] = [
'label' => t('Photos'),
'icon' => 'photo',
'icon' => 'image',
'url' => z_root() . '/photos/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -123,7 +123,7 @@ class Channel_activities {
self::$activities['files'] = [
'label' => t('Files'),
'icon' => 'folder-open',
'icon' => 'folder',
'url' => z_root() . '/cloud/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -166,7 +166,7 @@ class Channel_activities {
self::$activities['webpages'] = [
'label' => t('Webpages'),
'icon' => 'newspaper-o',
'icon' => 'layout-text-sidebar',
'url' => z_root() . '/webpages/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -237,7 +237,7 @@ class Channel_activities {
self::$activities['channels'] = [
'label' => t('Channels'),
'icon' => 'home',
'icon' => 'house',
'url' => z_root() . '/manage',
'date' => datetime_convert(),
'items' => $i,

View File

@@ -1,7 +1,7 @@
version: 3
url: $baseurl/rpost?f=&body=
version: 4
url: $baseurl/rpost
requires: observer
name: Post
photo: icon:pencil-square
photo: icon:pencil-fill
categories: Productivity
desc: A separate post editor.

View File

@@ -66,7 +66,7 @@ require_once('include/security.php');
define('PLATFORM_NAME', 'hubzilla');
define('STD_VERSION', '9.4');
define('STD_VERSION', '9.4.3');
define('ZOT_REVISION', '6.0');
define('DB_UPDATE_VERSION', 1263);

12
composer.lock generated
View File

@@ -1906,16 +1906,16 @@
},
{
"name": "smarty/smarty",
"version": "v4.4.1",
"version": "v4.5.4",
"source": {
"type": "git",
"url": "https://github.com/smarty-php/smarty.git",
"reference": "f4152e9b814ae2369b6e4935c05e1e0c3654318d"
"reference": "c11676e85aa71bc7c3cd9100f1655a9f4d14616e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/f4152e9b814ae2369b6e4935c05e1e0c3654318d",
"reference": "f4152e9b814ae2369b6e4935c05e1e0c3654318d",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/c11676e85aa71bc7c3cd9100f1655a9f4d14616e",
"reference": "c11676e85aa71bc7c3cd9100f1655a9f4d14616e",
"shasum": ""
},
"require": {
@@ -1966,9 +1966,9 @@
"support": {
"forum": "https://github.com/smarty-php/smarty/discussions",
"issues": "https://github.com/smarty-php/smarty/issues",
"source": "https://github.com/smarty-php/smarty/tree/v4.4.1"
"source": "https://github.com/smarty-php/smarty/tree/v4.5.4"
},
"time": "2024-02-26T13:58:37+00:00"
"time": "2024-08-14T20:04:35+00:00"
},
{
"name": "spomky-labs/otphp",

View File

@@ -1,4 +1,4 @@
[size=large][b]Was ist $Projectname?[/b][/size]
[h3]Was ist $Projectname?[/h3]
$Projectname ist ein dezentralisiertes Kommunikationsnetzwerk mit dem Ziel, Kommunikationsmöglichkeiten bereitzustellen, die Zensur umgehen, die Privatsphäre respektieren und somit frei sind von den Einschränkungen, die die heutigen kommerziellen Kommunikationsgiganten uns auferlegen. Diese stellen in erster Linie Spionagenetzwerke für zahlende Kunden aller Art zur Verfügung und monopolisieren und zentralisieren das ganze Internet was ursprünglich eben gerade nicht unter den revolutionären Zielen war, die einst zum World Wide Web führten.

View File

@@ -2599,33 +2599,31 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
intval($r[0]['id'])
);
if($r[0]['is_photo']) {
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s'
where resource_id = '%s' and uid = %d",
dbesc($newalbumname),
dbesc($filename),
dbesc($x['os_path']),
dbesc($x['path']),
dbesc($resource_id),
intval($channel_id)
);
q("update photo set content = CASE imgscale WHEN 0 THEN %s ELSE CONCAT(%s, '-', imgscale) END where resource_id = '%s' and uid = %d and os_storage = 1",
dbescbin($newstorepath),
dbescbin($newstorepath),
dbesc($resource_id),
intval($channel_id)
);
// now rename the thumbnails in os_storage - the original should have been copied before already
$ps = q("SELECT content, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and imgscale > 0 and os_storage = 1",
if ($r[0]['is_photo']) {
// update the photo DB entries and copy the thumbnails
$ps = q("SELECT imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and os_storage = 1",
intval($channel_id),
dbesc($resource_id)
);
if ($recurse) {
foreach($ps as $p) {
rename($oldstorepath . '-' . $p['imgscale'], $p['content']);
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s', content = '%s'
where resource_id = '%s' and imgscale = %d and uid = %d",
dbesc($newalbumname),
dbesc($filename),
dbesc($x['os_path']),
dbesc($x['path']),
dbescbin($newstorepath . ((intval($p['imgscale']) > 0) ? '-' . $p['imgscale'] : '')),
dbesc($resource_id),
intval($p['imgscale']),
intval($channel_id)
);
// the original should have been copied already
if (intval($p['imgscale']) > 0) {
rename($oldstorepath . '-' . $p['imgscale'], $newstorepath . '-' . $p['imgscale']);
}
}
}
}

View File

@@ -80,22 +80,6 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
$s = html2bbcode($s);
// $s = bb_code_protect($s);
// Convert everything that looks like a link to a link
if($use_zrl) {
if (strpos($s,'[/img]') !== false) {
$s = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", 'use_zrl_cb_img', $s);
$s = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", 'use_zrl_cb_img_x', $s);
}
$s = preg_replace_callback("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)([\,\.\:\;]\s|$)/ismu", 'use_zrl_cb_link',$s);
}
else {
$s = preg_replace("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)([\,\.\:\;]\s|$)/ismu", '$1[url=$2$3]$2$3[/url]$4',$s);
}
// $s = bb_code_unprotect($s);
// remove duplicate adjacent code tags
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s);

View File

@@ -81,8 +81,8 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase {
$this->get('help');
}
public function test_getting_locale_with_no_topic_should_redirect_to_about_page_for_locale(): void {
$this->expectRedirectTo('help/de/about/about');
public function test_getting_locale_with_no_topic_should_redirect_to_about_page(): void {
$this->expectRedirectTo('help/about/about');
$this->get('help/de');
}

View File

@@ -138,7 +138,15 @@ class BBCodeTest extends UnitTestCase {
'del tag' => [
'some [s]strike through[/s] text',
'some <del>strike through</del> text'
]
],
'naked url is converted to link' => [
'example url: https://example.com',
'example url: <a href="https://example.com" target="_blank" rel="nofollow noopener">https://example.com</a>'
],
'naked url within code block is not converted to link' => [
"[code]\nhttp://example.com\n[/code]",
"<pre><code>http://example.com</code></pre>"
],
];
}
@@ -223,6 +231,10 @@ class BBCodeTest extends UnitTestCase {
"<pre><code>some\n indented\ncode</code></pre>",
"[code]some\n indented\ncode[/code]"
],
'code block with URL' => [
'<pre><code>\nproxy_pass http://example.com\n</code></pre>',
'[code]\nproxy_pass http://example.com\n[/code]'
],
'paragraph with a mention and some text' => [
'<p><span class="h-card" translate="no"><a href="https://example.org/@profile" class="u-url mention">@<span>profile</span></a></span> some content</p>',
'[url=https://example.org/@profile]@profile[/url] some content'

View File

@@ -93,6 +93,14 @@ class MarkdownTest extends UnitTestCase {
"[code=php]&lt;?php\necho phpinfo();[/code]",
"```php\n<?php\necho phpinfo();\n```"
],
'code block with URL' => [
"[code]an example url https://example.com[/code]",
"```\nan example url https://example.com\n```"
],
'bbcode code block with URL' => [
"[code] proxy_pass http://example.com; [/code]",
"[code]\nproxy_pass http://example.com;\n[/code]"
]
];
}

View File

@@ -1976,17 +1976,17 @@
},
{
"name": "smarty/smarty",
"version": "v4.4.1",
"version_normalized": "4.4.1.0",
"version": "v4.5.4",
"version_normalized": "4.5.4.0",
"source": {
"type": "git",
"url": "https://github.com/smarty-php/smarty.git",
"reference": "f4152e9b814ae2369b6e4935c05e1e0c3654318d"
"reference": "c11676e85aa71bc7c3cd9100f1655a9f4d14616e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/f4152e9b814ae2369b6e4935c05e1e0c3654318d",
"reference": "f4152e9b814ae2369b6e4935c05e1e0c3654318d",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/c11676e85aa71bc7c3cd9100f1655a9f4d14616e",
"reference": "c11676e85aa71bc7c3cd9100f1655a9f4d14616e",
"shasum": ""
},
"require": {
@@ -1996,7 +1996,7 @@
"phpunit/phpunit": "^8.5 || ^7.5",
"smarty/smarty-lexer": "^3.1"
},
"time": "2024-02-26T13:58:37+00:00",
"time": "2024-08-14T20:04:35+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -2039,7 +2039,7 @@
"support": {
"forum": "https://github.com/smarty-php/smarty/discussions",
"issues": "https://github.com/smarty-php/smarty/issues",
"source": "https://github.com/smarty-php/smarty/tree/v4.4.1"
"source": "https://github.com/smarty-php/smarty/tree/v4.5.4"
},
"install-path": "../smarty/smarty"
},

View File

@@ -3,7 +3,7 @@
'name' => 'zotlabs/hubzilla',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '39933052a9eb827afee3965509909ba314de5257',
'reference' => 'c12ef4fbf4b2046e0af68b11e8fe5af2d335f32e',
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -269,9 +269,9 @@
'dev_requirement' => false,
),
'smarty/smarty' => array(
'pretty_version' => 'v4.4.1',
'version' => '4.4.1.0',
'reference' => 'f4152e9b814ae2369b6e4935c05e1e0c3654318d',
'pretty_version' => 'v4.5.4',
'version' => '4.5.4.0',
'reference' => 'c11676e85aa71bc7c3cd9100f1655a9f4d14616e',
'type' => 'library',
'install_path' => __DIR__ . '/../smarty/smarty',
'aliases' => array(),
@@ -349,7 +349,7 @@
'zotlabs/hubzilla' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '39933052a9eb827afee3965509909ba314de5257',
'reference' => 'c12ef4fbf4b2046e0af68b11e8fe5af2d335f32e',
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View File

@@ -6,11 +6,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [4.5.4] - 2024-08-14
- Fixed that using `count()` would trigger a deprecation notice. [#813](https://github.com/smarty-php/smarty/issues/813)
## [4.5.3] - 2024-05-28
- Fixed a code injection vulnerability in extends-tag. This addresses CVE-2024-35226.
## [4.5.2] - 2024-04-06
- Fixed argument must be passed by reference error introduced in v4.5.1 [#964](https://github.com/smarty-php/smarty/issues/964)
## [4.5.1] - 2024-03-18
- Using unregistered static class methods in expressions now also triggers a deprecation notice because we will drop support for this in the next major release [#813](https://github.com/smarty-php/smarty/issues/813)
## [4.5.0] - 2024-03-18
- (this release accidentally didn't contain any changes, fixed in 4.5.1)
## [4.4.1] - 2024-02-26
- Fixed internal release-tooling
## [4.4.0] - 2024-02-26
### Changed
- Using the `|implode`, `|json_encode` and `|substr` modifiers does not generate a deprecation warning anymore as they will continue to be supported in v5 [#939](https://github.com/smarty-php/smarty/issues/939)
### Added

View File

@@ -178,14 +178,14 @@ The above example will output:
</p>
<p>
name: Jack Jones<br />
home phone: 777-555-5555<br />
cell phone: 888-555-5555<br />
home: 777-555-5555<br />
cell: 888-555-5555<br />
e-mail: jack@myexample.com
</p>
<p>
name: Jane Munson<br />
home phone: 000-555-5555<br />
cell phone: 123456<br />
home: 000-555-5555<br />
cell: 123456<br />
e-mail: jane@myexample.com
</p>
```

View File

@@ -785,6 +785,9 @@ value(res) ::= ns1(c)DOUBLECOLON static_class_access(s). {
if (isset($this->smarty->registered_classes[c])) {
res = $this->smarty->registered_classes[c].'::'.s[0].s[1];
} else {
trigger_error('Using unregistered static method "' . c.'::'.s[0] . '" in a template is deprecated and will be ' .
'removed in a future release. Use Smarty::registerClass to explicitly register ' .
'a class for access.', E_USER_DEPRECATED);
res = c.'::'.s[0].s[1];
}
} else {

View File

@@ -107,7 +107,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '4.4.1';
const SMARTY_VERSION = '4.5.4';
/**
* define variable scopes
*/

View File

@@ -30,7 +30,7 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inh
*
* @var array
*/
public $optional_attributes = array('extends_resource');
public $optional_attributes = array();
/**
* Attribute definition: Overwrites base class.
@@ -62,29 +62,7 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inh
}
// add code to initialize inheritance
$this->registerInit($compiler, true);
$file = trim($_attr[ 'file' ], '\'"');
if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') {
// generate code for each template
$files = array_reverse(explode('|', substr($file, 8)));
$i = 0;
foreach ($files as $file) {
if ($file[ 0 ] === '"') {
$file = trim($file, '".');
} else {
$file = "'{$file}'";
}
$i++;
if ($i === count($files) && isset($_attr[ 'extends_resource' ])) {
$this->compileEndChild($compiler);
}
$this->compileInclude($compiler, $file);
}
if (!isset($_attr[ 'extends_resource' ])) {
$this->compileEndChild($compiler);
}
} else {
$this->compileEndChild($compiler, $_attr[ 'file' ]);
}
$this->compileEndChild($compiler, $_attr[ 'file' ]);
$compiler->has_code = false;
return '';
}
@@ -115,44 +93,4 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inh
'') . ");\n?>"
);
}
/**
* Add code for including subtemplate to end of template
*
* @param \Smarty_Internal_TemplateCompilerBase $compiler
* @param string $template subtemplate name
*
* @throws \SmartyCompilerException
* @throws \SmartyException
*/
private function compileInclude(Smarty_Internal_TemplateCompilerBase $compiler, $template)
{
$compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag(
$compiler->parser,
$compiler->compileTag(
'include',
array(
$template,
array('scope' => 'parent')
)
)
);
}
/**
* Create source code for {extends} from source components array
*
* @param \Smarty_Internal_Template $template
*
* @return string
*/
public static function extendsSourceArrayCode(Smarty_Internal_Template $template)
{
$resources = array();
foreach ($template->source->components as $source) {
$resources[] = $source->resource;
}
return $template->smarty->left_delimiter . 'extends file=\'extends:' . join('|', $resources) .
'\' extends_resource=true' . $template->smarty->right_delimiter;
}
}

View File

@@ -109,9 +109,11 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
if (!is_object($compiler->smarty->security_policy)
|| $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)
) {
trigger_error('Using php-function "' . $modifier . '" as a modifier is deprecated and will be ' .
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
'a custom modifier.', E_USER_DEPRECATED);
if (!in_array($modifier, ['time', 'join', 'is_array', 'in_array'])) {
trigger_error('Using unregistered function "' . $modifier . '" in a template is deprecated and will be ' .
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
'a custom modifier.', E_USER_DEPRECATED);
}
$output = "{$modifier}({$params})";
}
$compiler->known_modifier_type[ $modifier ] = $type;

View File

@@ -455,15 +455,29 @@ abstract class Smarty_Internal_TemplateCompilerBase
$this->smarty->_current_file = $this->template->source->filepath;
// get template source
if (!empty($this->template->source->components)) {
// we have array of inheritance templates by extends: resource
// generate corresponding source code sequence
$_content =
Smarty_Internal_Compile_Extends::extendsSourceArrayCode($this->template);
$_compiled_code = '<?php $_smarty_tpl->_loadInheritance(); $_smarty_tpl->inheritance->init($_smarty_tpl, true); ?>';
$i = 0;
$reversed_components = array_reverse($this->template->getSource()->components);
foreach ($reversed_components as $source) {
$i++;
if ($i === count($reversed_components)) {
$_compiled_code .= '<?php $_smarty_tpl->inheritance->endChild($_smarty_tpl); ?>';
}
$_compiled_code .= $this->compileTag(
'include',
[
var_export($source->resource, true),
['scope' => 'parent'],
]
);
}
$_compiled_code = $this->postFilter($_compiled_code, $this->template);
} else {
// get template source
$_content = $this->template->source->getContent();
$_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true));
}
$_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true));
if (!empty($this->required_plugins[ 'compiled' ]) || !empty($this->required_plugins[ 'nocache' ])) {
$_compiled_code = '<?php ' . $this->compileRequiredPlugins() . "?>\n" . $_compiled_code;
}
@@ -640,7 +654,18 @@ abstract class Smarty_Internal_TemplateCompilerBase
return $func_name . '(' . $parameter[ 0 ] . ')';
}
} else {
return $name . '(' . implode(',', $parameter) . ')';
if (
!$this->smarty->loadPlugin('smarty_modifiercompiler_' . $name)
&& !isset($this->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$name])
&& !in_array($name, ['time', 'join', 'is_array', 'in_array', 'count'])
) {
trigger_error('Using unregistered function "' . $name . '" in a template is deprecated and will be ' .
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
'a custom modifier.', E_USER_DEPRECATED);
}
return $name . '(' . implode(',', $parameter) . ')';
}
} else {
$this->trigger_template_error("unknown function '{$name}'");

View File

@@ -2425,6 +2425,9 @@ public static $yy_action = array(
if (isset($this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor])) {
$this->_retvalue = $this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor].'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
} else {
trigger_error('Using unregistered static method "' . $this->yystack[$this->yyidx + -2]->minor.'::'.$this->yystack[$this->yyidx + 0]->minor[0] . '" in a template is deprecated and will be ' .
'removed in a future release. Use Smarty::registerClass to explicitly register ' .
'a class for access.', E_USER_DEPRECATED);
$this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
}
} else {

View File

@@ -253,7 +253,7 @@ class Smarty_Security
*
* @param string $function_name
* @param object $compiler compiler object
*
* @deprecated
* @return boolean true if function is trusted
*/
public function isTrustedPhpFunction($function_name, $compiler)

View File

@@ -5,11 +5,13 @@
# - ./run-tests-for-all-php-versions.sh --group 20221124
# - ./run-tests-for-all-php-versions.sh --exclude-group slow
docker-compose run php71 ./run-tests.sh $@ && \
docker-compose run php72 ./run-tests.sh $@ && \
docker-compose run php73 ./run-tests.sh $@ && \
docker-compose run php74 ./run-tests.sh $@ && \
docker-compose run php80 ./run-tests.sh $@ && \
docker-compose run php81 ./run-tests.sh $@ && \
docker-compose run php82 ./run-tests.sh $@ && \
docker-compose run php83 ./run-tests.sh $@
COMPOSE_CMD="mutagen-compose"
$COMPOSE_CMD run --rm php71 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php72 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php73 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php74 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php80 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php81 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php82 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php83 ./run-tests.sh $@

View File

@@ -11,10 +11,22 @@
padding-bottom: 0.3em;
}
#doco-content img {
width: 100%;
}
#region_1 .widget ul ul {
list-style-type: none;
}
#doco-top-toc-wrapper {
margin-bottom: 1em;
}
#doco-top-toc-wrapper > summary {
font-size: large;
}
.toc-content li,
#doco-top-toc li {
padding: 3px 0px;
@@ -24,3 +36,12 @@
padding-left: 20px;
}
.selected-doco-nav > a {
font-weight: bold;
color: var(--bs-link-hover-color);
}
#help-content pre code {
overflow-x: auto;
white-space: pre;
}

View File

@@ -1209,9 +1209,12 @@ function dolike(ident, verb) {
else {
$('#thread-wrapper-' + data.orig_id).replaceWith(data.html);
}
$('#wall-item-ago-' + data.id + ' .autotime').timeago();
collapseHeight();
liking = 0;
// remove modal backdrop in case the update was triggered from a modal
$('.modal-backdrop').remove();
}
});
liking = 1;
@@ -1363,7 +1366,7 @@ function dostar(ident) {
$('#starred-' + ident).removeClass('bi-star');
$('#star-' + ident).addClass('hidden');
$('#unstar-' + ident).removeClass('hidden');
var btn_tpl = '<div class="" id="star-button-' + ident + '"><button type="button" class="btn btn-outline-secondary border-0 wall-item-star" onclick="dostar(' + ident + ');"><i class="bi bi-star"></i></button></div>'
var btn_tpl = '<div class="" id="star-button-' + ident + '"><button type="button" class="btn btn-sm btn-link link-secondary wall-item-star" onclick="dostar(' + ident + ');"><i class="bi bi-star generic-icons"></i></button></div>'
$('#wall-item-tools-right-' + ident).prepend(btn_tpl);
}
else {

View File

@@ -1,14 +1,3 @@
function docoTocToggle() {
if ($('#doco-top-toc').is(':visible')) {
$('#doco-toc-toggle').removeClass('bi-gear').addClass('bi-caret-right');
} else {
$('#doco-toc-toggle').removeClass('bi-caret-right').addClass('bi-caret-down');
}
$('#doco-top-toc').toggle();
return false;
}
toc = {};
// Generate the table of contents in the side nav menu (see view/tpl/help.tpl)
$(document).ready(function () {

View File

@@ -150,20 +150,6 @@ input[type=text], textarea {
color: var(--bs-body-color);
}
.selected-doco-nav {
font-weight: bold;
text-shadow: 2px 2px 3px lightgray;
}
#doco-content img {
width: 100%;
}
#help-content pre code {
overflow-x: auto;
white-space: pre;
}
.heart {
color: #FF0000;
}

View File

@@ -106,8 +106,8 @@
{{foreach $item.responses as $verb=>$response}}
{{if $item.reactions_allowed || (!$item.reactions_allowed && $response.count)}}
<div class="">
<button type="button" title="{{$response.count}} {{$response.button.label}}" class="btn btn-sm btn-outline-secondary border-0 wall-item-{{$response.button.class}}"{{if $response.modal}} data-bs-toggle="modal" data-bs-target="#{{$verb}}Modal-{{$item.id}}"{{else if $response.count}} data-bs-toggle="dropdown"{{elseif $item.reactions_allowed}} onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;"{{/if}} id="wall-item-{{$verb}}-{{$item.id}}">
<i class="bi bi-{{$response.button.icon}} generic-icons"></i>{{if $response.count}}<span style="display: inline-block; margin-top: -.25rem;" class="align-top{{if $item.my_responses.$verb}} text-decoration-underline{{/if}}">{{$response.count}}</span>{{/if}}
<button type="button" title="{{$response.count}} {{$response.button.label}}" class="btn btn-sm btn-link{{if !$item.my_responses.$verb}} link-secondary{{/if}} wall-item-{{$response.button.class}}"{{if $response.modal}} data-bs-toggle="modal" data-bs-target="#{{$verb}}Modal-{{$item.id}}"{{else if $response.count}} data-bs-toggle="dropdown"{{elseif $item.reactions_allowed}} onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;"{{/if}} id="wall-item-{{$verb}}-{{$item.id}}">
<i class="bi bi-{{$response.button.icon}} generic-icons"></i>{{if $response.count}}<span style="display: inline-block; margin-top: -.25rem;" class="align-top">{{$response.count}}</span>{{/if}}
</button>
{{if $response.modal}}
<div class="modal" id="{{$verb}}Modal-{{$item.id}}">
@@ -151,7 +151,7 @@
{{/foreach}}
{{if $item.toplevel && $item.emojis && $item.reactions}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0" data-bs-toggle="dropdown" id="wall-item-react-{{$item.id}}">
<button type="button" class="btn btn-sm btn-link link-secondary" data-bs-toggle="dropdown" id="wall-item-react-{{$item.id}}">
<i class="bi bi-emoji-smile generic-icons"></i>
</button>
<div class="dropdown-menu dropdown-menu-start container text-center w-25">
@@ -178,22 +178,22 @@
{{else}}
{{if $item.star && $item.star.isstarred}}
<div class="" id="star-button-{{$item.id}}">
<button type="button" class="btn btn-sm btn-outline-secondary border-0 wall-item-star" onclick="dostar({{$item.id}});"><i class="bi bi-star generic-icons"></i></button>
<button type="button" class="btn btn-sm btn-link link-secondary wall-item-star" onclick="dostar({{$item.id}});"><i class="bi bi-star generic-icons"></i></button>
</div>
{{/if}}
{{if $item.attachments}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0 wall-item-attach" data-bs-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="bi bi-paperclip generic-icons"></i></button>
<button type="button" class="btn btn-sm btn-link link-secondary wall-item-attach" data-bs-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="bi bi-paperclip generic-icons"></i></button>
<div class="dropdown-menu dropdown-menu-end">{{$item.attachments}}</div>
</div>
{{/if}}
{{if $item.reply_to}}
<button type="button" title="{{$item.reply_to.0}}" class="btn btn-sm btn-outline-secondary border-0" onclick="doreply({{$item.parent}}, {{$item.id}}, '{{$item.author_id}}', '{{$item.reply_to.2}} {{$item.name|escape:javascript}}');">
<button type="button" title="{{$item.reply_to.0}}" class="btn btn-sm btn-link link-secondary" onclick="doreply({{$item.parent}}, {{$item.id}}, '{{$item.author_id}}', '{{$item.reply_to.2}} {{$item.name|escape:javascript}}');">
<i class="bi bi-arrow-90deg-left generic-icons" ></i>
</button>
{{/if}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0" data-bs-toggle="dropdown" id="wall-item-menu-{{$item.id}}">
<button type="button" class="btn btn-sm btn-link link-secondary" data-bs-toggle="dropdown" id="wall-item-menu-{{$item.id}}">
<i class="bi bi-three-dots-vertical generic-icons"></i>
</button>
<div class="dropdown-menu dropdown-menu-end" role="menu" aria-labelledby="wall-item-menu-{{$item.id}}">

View File

@@ -95,7 +95,7 @@
<div class="p-2 wall-item-tools d-flex justify-content-between">
<div class="wall-item-tools-left hstack gap-1" id="wall-item-tools-left-{{$item.id}}">
<div class="wall-item-list-comments btn-group">
<a class="btn btn-sm btn-outline-secondary border-0 wall-item-comments" href="{{$item.viewthread}}" title="{{$item.comment_count_txt.label}}{{if $item.list_unseen_txt}}, {{$item.list_unseen_txt.label}}{{/if}}">
<a class="btn btn-sm btn-link link-secondary wall-item-comments" href="{{$item.viewthread}}" title="{{$item.comment_count_txt.label}}{{if $item.list_unseen_txt}}, {{$item.list_unseen_txt.label}}{{/if}}">
<i class="bi bi-chat generic-icons"></i>{{if $item.comment_count_txt.count}}<span style="display: inline-block; margin-top: -.25rem;" class="align-top">{{$item.comment_count_txt.count}}</span>{{/if}}{{if $item.unseen_comments}}, <i class="bi bi-eye-slash generic-icons"></i><span class="unseen-wall-indicator-{{$item.id}} align-top" style="display: inline-block; margin-top: -.25rem;">{{$item.list_unseen_txt.count}}</span>{{/if}}
</a>
</div>
@@ -109,9 +109,10 @@
{{foreach $item.responses as $verb=>$response}}
{{if $item.reactions_allowed || (!$item.reactions_allowed && $response.count)}}
<div class="">
<button type="button" title="{{$response.count}} {{$response.button.label}}" class="btn btn-sm btn-outline-secondary border-0 wall-item-{{$response.button.class}}"{{if $response.modal}} data-bs-toggle="modal" data-bs-target="#{{$verb}}Modal-{{$item.id}}"{{else if $response.count}} data-bs-toggle="dropdown"{{elseif $item.reactions_allowed}} onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;"{{/if}} id="wall-item-{{$verb}}-{{$item.id}}">
<i class="bi bi-{{$response.button.icon}} generic-icons"></i>{{if $response.count}}<span style="display: inline-block; margin-top: -.25rem;" class="align-top{{if $item.my_responses.$verb}} text-decoration-underline{{/if}}">{{$response.count}}</span>{{/if}}
</button> {{if $response.modal}}
<button type="button" title="{{$response.count}} {{$response.button.label}}" class="btn btn-sm btn-link{{if !$item.my_responses.$verb}} link-secondary{{/if}} wall-item-{{$response.button.class}}"{{if $response.modal}} data-bs-toggle="modal" data-bs-target="#{{$verb}}Modal-{{$item.id}}"{{else if $response.count}} data-bs-toggle="dropdown"{{elseif $item.reactions_allowed}} onclick="{{$response.button.onclick}}({{$item.id}},'{{$verb}}'); return false;"{{/if}} id="wall-item-{{$verb}}-{{$item.id}}">
<i class="bi bi-{{$response.button.icon}} generic-icons"></i>{{if $response.count}}<span style="display: inline-block; margin-top: -.25rem;" class="align-top">{{$response.count}}</span>{{/if}}
</button>
{{if $response.modal}}
<div class="modal" id="{{$verb}}Modal-{{$item.id}}">
<div class="modal-dialog">
<div class="modal-content">
@@ -153,7 +154,7 @@
{{/foreach}}
{{if $item.toplevel && $item.emojis && $item.reactions}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0" data-bs-toggle="dropdown" id="wall-item-react-{{$item.id}}">
<button type="button" class="btn btn-sm btn-link link-secondary" data-bs-toggle="dropdown" id="wall-item-react-{{$item.id}}">
<i class="bi bi-emoji-smile generic-icons"></i>
</button>
<div class="dropdown-menu dropdown-menu-start container text-center w-25">
@@ -180,17 +181,17 @@
{{else}}
{{if $item.star && $item.star.isstarred}}
<div class="" id="star-button-{{$item.id}}">
<button type="button" class="btn btn-sm btn-outline-secondary border-0 wall-item-star" onclick="dostar({{$item.id}});"><i class="bi bi-star generic-icons"></i></button>
<button type="button" class="btn btn-sm btn-link link-secondary wall-item-star" onclick="dostar({{$item.id}});"><i class="bi bi-star generic-icons"></i></button>
</div>
{{/if}}
{{if $item.attachments}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0 wall-item-attach" data-bs-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="bi bi-paperclip generic-icons"></i></button>
<button type="button" class="btn btn-sm btn-link link-secondary wall-item-attach" data-bs-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="bi bi-paperclip generic-icons"></i></button>
<div class="dropdown-menu dropdown-menu-end">{{$item.attachments}}</div>
</div>
{{/if}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0" data-bs-toggle="dropdown" id="wall-item-menu-{{$item.id}}">
<button type="button" class="btn btn-sm btn-link link-secondary" data-bs-toggle="dropdown" id="wall-item-menu-{{$item.id}}">
<i class="bi bi-three-dots-vertical generic-icons"></i>
</button>
<div class="dropdown-menu dropdown-menu-end" role="menu" aria-labelledby="wall-item-menu-{{$item.id}}">

View File

@@ -7,14 +7,13 @@
{{$module->missing_translation_message()}}
</div>
{{/if}}
<div class="section-content-wrapper" id="doco-content">
<h3 id="doco-top-toc-heading">
<span class="fakelink" onclick="docoTocToggle(); return false;">
<i class="bi bi-caret-right fakelink" id="doco-toc-toggle"></i>
{{$module->get_toc_heading()}}
</span>
</h3>
<ul id="doco-top-toc" style="margin-bottom: 1.5em; display: none;"></ul>
{{$module->render_content()}}
<div class="section-content-wrapper">
<details id="doco-top-toc-wrapper">
<summary id="doco-top-toc-heading">{{$module->get_toc_heading()}}</summary>
<ul id="doco-top-toc"></ul>
</details>
<div id="doco-content">
{{$module->render_content()}}
</div>
</div>
</div>

View File

@@ -12,7 +12,7 @@
{{if $entry.type !== 'content'}}
<button type="button" class="btn btn-sm btn-outline-primary pdledit_gui_item_src{{if $disable_controls}} disabled{{/if}}">Edit</button>
<button type="button" class="btn btn-sm btn-outline-danger pdledit_gui_item_remove{{if $disable_controls}} disabled{{/if}}">Remove</button>
<i class="bi fa-arrows-alt m-2 float-end cursor-pointer pdledit_gui_item_handle"></i>
<i class="bi bi-arrows-move m-2 float-end cursor-pointer pdledit_gui_item_handle"></i>
{{/if}}
</div>
</div>

View File

@@ -4,7 +4,7 @@
<ul id="saved-search-list" class="nav nav-pills flex-column">
{{foreach $saved as $search}}
<li class="nav-item nav-item-hack" id="search-term-{{$search.id}}">
<a class="nav-link widget-nav-pills-icons" title="{{$search.delete}}" onclick="return confirmDelete();" id="drop-saved-search-term-{{$search.id}}" href="{{$search.dellink}}"><i id="dropfa-floppy-od-search-term-{{$search.id}}" class="bi bi-trash drop-icons" ></i></a>
<a class="nav-link widget-nav-pills-icons{{if $search.selected}} active{{/if}}" title="{{$search.delete}}" onclick="return confirmDelete();" id="drop-saved-search-term-{{$search.id}}" href="{{$search.dellink}}"><i class="bi bi-trash"></i></a>
<a id="saved-search-term-{{$search.id}}" class="nav-link{{if $search.selected}} active{{/if}}" href="{{$search.srchlink}}">{{$search.displayterm}}</a>
</li>
{{/foreach}}

View File

@@ -105,22 +105,17 @@
{{else}}
{{if $item.star && $item.star.isstarred}}
<div class="" id="star-button-{{$item.id}}">
<button type="button" class="btn btn-sm btn-outline-secondary border-0 wall-item-star" onclick="dostar({{$item.id}});"><i class="bi bi-star generic-icons"></i></button>
<button type="button" class="btn btn-sm btn-link link-secondary wall-item-star" onclick="dostar({{$item.id}});"><i class="bi bi-star generic-icons"></i></button>
</div>
{{/if}}
{{if $item.attachments}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0 wall-item-attach" data-bs-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="bi bi-paperclip generic-icons"></i></button>
<button type="button" class="btn btn-sm btn-link link-secondary wall-item-attach" data-bs-toggle="dropdown" id="attachment-menu-{{$item.id}}"><i class="bi bi-paperclip generic-icons"></i></button>
<div class="dropdown-menu dropdown-menu-end">{{$item.attachments}}</div>
</div>
{{/if}}
{{if $item.reply_to}}
<button type="button" title="{{$item.reply_to.0}}" class="btn btn-sm btn-outline-secondary border-0" onclick="doreply({{$item.parent}}, {{$item.id}}, '{{$item.author_id}}', '{{$item.reply_to.2}} {{$item.name|escape:javascript}}');">
<i class="bi bi-arrow-90deg-left generic-icons" ></i>
</button>
{{/if}}
<div class="">
<button type="button" class="btn btn-sm btn-outline-secondary border-0" data-bs-toggle="dropdown" id="wall-item-menu-{{$item.id}}">
<button type="button" class="btn btn-sm btn-link link-secondary" data-bs-toggle="dropdown" id="wall-item-menu-{{$item.id}}">
<i class="bi bi-three-dots-vertical generic-icons"></i>
</button>
<div class="dropdown-menu dropdown-menu-end" role="menu" aria-labelledby="wall-item-menu-{{$item.id}}">

View File

@@ -4,7 +4,7 @@
<input class="form-control" type="text" name="search" id="search-text" value="{{$s}}" onclick="this.submit();" />
<button type="submit" name="submit" class="btn btn-outline-secondary" id="search-submit" value="{{$search_label}}"><i class="bi bi-search"></i></button>
{{if $savedsearch}}
<button type="submit" name="searchsave" class="btn btn-outline-secondary" id="search-save" value="{{$save_label}}"><i class="bi fa-floppy-o"></i></button>
<button type="submit" name="searchsave" class="btn btn-outline-secondary" id="search-save" value="{{$save_label}}"><i class="bi bi-save"></i></button>
{{/if}}
</div>
</form>