Overview
Comment:Fix image tag in file preview, as reported by @Eric. Also fix URL prefix for links in specific contexts in admin.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | stable
Files: files | file ages | folders
SHA3-256: 9e33c7cafd555a27393b31974d9b6c0a11b776204b9dc2f36f28c4037b03b16d
User & Date: bohwaz on 2021-09-16 17:41:59
Other Links: manifest | tags
Context
2021-09-16
17:49
Fix user_prefix argument in markdown passed to skriv check-in: 01df610025 user: bohwaz tags: trunk, stable
17:41
Fix image tag in file preview, as reported by @Eric. Also fix URL prefix for links in specific contexts in admin. check-in: 9e33c7cafd user: bohwaz tags: trunk, stable
16:56
Add pagination to virtual documents view, fix [63cd9cc9b96d2eb3340827098de6be5c5dae7e48] check-in: 3d283a05a5 user: bohwaz tags: trunk, stable
Changes

Modified src/include/lib/Garradin/Entities/Files/File.php from [211bafd088] to [2f3a044bb4].

687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
	}

	public function fetch()
	{
		return Files::callStorage('fetch', $this);
	}

	public function render(array $options = [])
	{
		$editor_type = $this->renderFormat();

		if ($editor_type == 'text') {
			return sprintf('<pre>%s</pre>', htmlspecialchars($this->fetch()));
		}
		elseif (!$editor_type) {
			throw new \LogicException('Cannot render file of this type');
		}
		else {
			return Render::render($editor_type, $this, $this->fetch(), $options);
		}
	}

	public function checkReadAccess(?Session $session): bool
	{
		// Web pages and config files are always public
		if ($this->isPublic()) {







|










|







687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
	}

	public function fetch()
	{
		return Files::callStorage('fetch', $this);
	}

	public function render(?string $user_prefix = null)
	{
		$editor_type = $this->renderFormat();

		if ($editor_type == 'text') {
			return sprintf('<pre>%s</pre>', htmlspecialchars($this->fetch()));
		}
		elseif (!$editor_type) {
			throw new \LogicException('Cannot render file of this type');
		}
		else {
			return Render::render($editor_type, $this, $this->fetch(), $user_prefix);
		}
	}

	public function checkReadAccess(?Session $session): bool
	{
		// Web pages and config files are always public
		if ($this->isPublic()) {

Modified src/include/lib/Garradin/Entities/Web/Page.php from [00abd9dd36] to [da90d06a42].

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	{
		$out = $this->asArray();
		$out['url'] = $this->url();
		$out['html'] = $this->render();
		return $out;
	}

	public function render(array $options = []): string
	{
		if (!$this->file()) {
			throw new \LogicException('File does not exist: '  . $this->file_path);
		}

		return Render::render($this->format, $this->file(), $this->content, $options);
	}

	public function preview(string $content): string
	{
		return Render::render($this->format, $this->file(), $content, ['prefix' => '#']);
	}

	public function filepath(bool $stored = true): string
	{
		return $stored && isset($this->file_path) ? $this->file_path : File::CONTEXT_WEB . '/' . $this->path . '/' . $this->_name;
	}








|





|




|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	{
		$out = $this->asArray();
		$out['url'] = $this->url();
		$out['html'] = $this->render();
		return $out;
	}

	public function render(?string $user_prefix = null): string
	{
		if (!$this->file()) {
			throw new \LogicException('File does not exist: '  . $this->file_path);
		}

		return Render::render($this->format, $this->file(), $this->content, $user_prefix);
	}

	public function preview(string $content): string
	{
		return Render::render($this->format, $this->file(), $content, '#');
	}

	public function filepath(bool $stored = true): string
	{
		return $stored && isset($this->file_path) ? $this->file_path : File::CONTEXT_WEB . '/' . $this->path . '/' . $this->_name;
	}

Modified src/include/lib/Garradin/Web/Render/AbstractRender.php from [c4980b1d31] to [4ca4df51b9].

9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26

27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

abstract class AbstractRender
{
	protected $current_path;
	protected $context;
	protected $link_prefix;
	protected $link_suffix;


	protected $file;

	public function __construct(?File $file)
	{
		$this->file = $file;

		if ($file) {
			$this->isRelativeTo($file);
		}
	}



	abstract public function render(?string $content = null, array $options = []): string;

	protected function resolveAttachment(string $uri) {
		$prefix = $this->current_path;
		$pos = strpos($uri, '/');

		// "Image.jpg"
		if ($pos === false) {
			return WWW_URL . $prefix . '/' . $uri;
		}
		// "bla/Image.jpg" outside of web context
		elseif ($this->context !== File::CONTEXT_WEB && $pos !== 0) {
			return WWW_URL . $this->context . '/' . $uri;
		}
		// "bla/Image.jpg" in web context or absolute link, eg. "/transactions/2442/42.jpg"
		else {
			return WWW_URL . ltrim($uri, '/');
		}
	}

	protected function resolveLink(string $uri) {
		$first = substr($uri, 0, 1);
		if ($first == '/' || $first == '!') {
			return Utils::getLocalURL($uri);
		}

		if (strpos(Utils::basename($uri), '.') === false) {
			$uri .= $this->link_suffix;
		}

		return $this->link_prefix . $uri;
	}

	public function isRelativeTo(File $file) {
		$this->current_path = Utils::dirname($file->path);
		$this->context = strtok($this->current_path, '/');
		$this->link_suffix = '';

		if ($this->context === File::CONTEXT_WEB) {
			$this->link_prefix = WWW_URL;
			$this->current_path = Utils::basename(Utils::dirname($file->path));
		}
		else {
			$this->link_prefix = $options['prefix'] ?? sprintf(ADMIN_URL . 'common/files/preview.php?p=%s/', $this->context);
			$this->link_suffix = '.skriv';
		}
	}
}







>



|






|
>
|
>
|





|
|
|

<
<
<
|
<
|
|
<
















|
|



|



|




9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40



41

42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

abstract class AbstractRender
{
	protected $current_path;
	protected $context;
	protected $link_prefix;
	protected $link_suffix;
	protected $user_prefix;

	protected $file;

	public function __construct(?File $file, ?string $user_prefix)
	{
		$this->file = $file;

		if ($file) {
			$this->isRelativeTo($file);
		}

		$this->user_prefix = $user_prefix;
	}

	abstract public function render(?string $content = null): string;

	protected function resolveAttachment(string $uri) {
		$prefix = $this->current_path;
		$pos = strpos($uri, '/');

		// Absolute URL: treat it as absolute!
		if ($pos === 0) {
			return WWW_URL . ltrim($uri, '/');
		}





		// Handle relative URIs
		return WWW_URL . $prefix . '/' . $uri;

	}

	protected function resolveLink(string $uri) {
		$first = substr($uri, 0, 1);
		if ($first == '/' || $first == '!') {
			return Utils::getLocalURL($uri);
		}

		if (strpos(Utils::basename($uri), '.') === false) {
			$uri .= $this->link_suffix;
		}

		return $this->link_prefix . $uri;
	}

	public function isRelativeTo(File $file) {
		$this->current_path = $file->parent;
		$this->context = $file->context();
		$this->link_suffix = '';

		if ($this->context === File::CONTEXT_WEB) {
			$this->link_prefix = $this->user_prefix ?? WWW_URL;
			$this->current_path = Utils::basename(Utils::dirname($file->path));
		}
		else {
			$this->link_prefix = $this->user_prefix ?? sprintf(ADMIN_URL . 'common/files/preview.php?p=%s/', $this->context);
			$this->link_suffix = '.skriv';
		}
	}
}

Modified src/include/lib/Garradin/Web/Render/EncryptedSkriv.php from [ef852896e7] to [42fbb7e0fc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;
use Garradin\Template;
use const Garradin\ADMIN_URL;

class EncryptedSkriv extends AbstractRender
{
	public function render(?string $content = null, array $options = []): string
	{
		$tpl = Template::getInstance();
		$file = $this->file;
		$content = $content ?? $file->fetch();
		$tpl->assign('admin_url', ADMIN_URL);
		$tpl->assign(compact('file', 'content'));
		return $tpl->fetch('common/files/_file_render_encrypted.tpl');
	}
}










|









1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;
use Garradin\Template;
use const Garradin\ADMIN_URL;

class EncryptedSkriv extends AbstractRender
{
	public function render(?string $content = null): string
	{
		$tpl = Template::getInstance();
		$file = $this->file;
		$content = $content ?? $file->fetch();
		$tpl->assign('admin_url', ADMIN_URL);
		$tpl->assign(compact('file', 'content'));
		return $tpl->fetch('common/files/_file_render_encrypted.tpl');
	}
}

Modified src/include/lib/Garradin/Web/Render/Render.php from [a31683eb85] to [baee19544e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;

class Render
{

	const FORMAT_SKRIV = 'skriv';
	const FORMAT_ENCRYPTED = 'skriv/encrypted';
	const FORMAT_MARKDOWN = 'markdown';

	static public function render(string $format, File $file, string $content = null, array $options = [])
	{
		if ($format == self::FORMAT_SKRIV) {
			$r = new Skriv($file);
		}
		else if ($format == self::FORMAT_ENCRYPTED) {
			$r = new EncryptedSkriv($file);
		}
		else if ($format == self::FORMAT_MARKDOWN) {
			$r = new Markdown($file);
		}
		else {
			throw new \LogicException('Invalid format: ' . $format);
		}

		return $r->render($content, $options);
	}
}













|


|


|


|





|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;

class Render
{

	const FORMAT_SKRIV = 'skriv';
	const FORMAT_ENCRYPTED = 'skriv/encrypted';
	const FORMAT_MARKDOWN = 'markdown';

	static public function render(string $format, File $file, string $content = null, string $link_prefix = null)
	{
		if ($format == self::FORMAT_SKRIV) {
			$r = new Skriv($file, $link_prefix);
		}
		else if ($format == self::FORMAT_ENCRYPTED) {
			$r = new EncryptedSkriv($file, $link_prefix);
		}
		else if ($format == self::FORMAT_MARKDOWN) {
			$r = new Markdown($file, $link_prefix);
		}
		else {
			throw new \LogicException('Invalid format: ' . $format);
		}

		return $r->render($content);
	}
}

Modified src/include/lib/Garradin/Web/Render/Skriv.php from [c98806af5f] to [f232e4ffa3].

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

use const Garradin\{ADMIN_URL, WWW_URL};

class Skriv extends AbstractRender
{
	protected $skriv;

	public function __construct(?File $file)
	{
		parent::__construct($file);

		$this->skriv = new SkrivLite;
		$this->skriv->registerExtension('file', [$this, 'SkrivFile']);
		$this->skriv->registerExtension('fichier', [$this, 'SkrivFile']);
		$this->skriv->registerExtension('image', [$this, 'SkrivImage']);

		// Enregistrer d'autres extensions éventuellement
		Plugin::fireSignal('skriv.init', ['skriv' => $this->skriv]);
	}

	public function render(?string $content = null, array $options = []): string
	{
		$skriv =& $this->skriv;

		$str = $content ?? $this->file->fetch();

		$str = preg_replace_callback('/#file:\[([^\]\h]+)\]/', function ($match) {
			return $this->resolveAttachment($match[1]);







|

|










|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

use const Garradin\{ADMIN_URL, WWW_URL};

class Skriv extends AbstractRender
{
	protected $skriv;

	public function __construct(?File $file, ?string $user_prefix)
	{
		parent::__construct($file, $user_prefix);

		$this->skriv = new SkrivLite;
		$this->skriv->registerExtension('file', [$this, 'SkrivFile']);
		$this->skriv->registerExtension('fichier', [$this, 'SkrivFile']);
		$this->skriv->registerExtension('image', [$this, 'SkrivImage']);

		// Enregistrer d'autres extensions éventuellement
		Plugin::fireSignal('skriv.init', ['skriv' => $this->skriv]);
	}

	public function render(?string $content = null): string
	{
		$skriv =& $this->skriv;

		$str = $content ?? $this->file->fetch();

		$str = preg_replace_callback('/#file:\[([^\]\h]+)\]/', function ($match) {
			return $this->resolveAttachment($match[1]);
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	 * @param SkrivLite $skriv   Objet SkrivLite
	 */
	public function SkrivFile(array $args, ?string $content, SkrivLite $skriv): string
	{
		$name = $args[0] ?? null;
		$caption = $args[1] ?? null;

		if (!$name || !$this->current_path)
		{
			return $skriv->parseError('/!\ Tag file : aucun nom de fichier indiqué.');
		}

		if (empty($caption))
		{
			$caption = $name;







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	 * @param SkrivLite $skriv   Objet SkrivLite
	 */
	public function SkrivFile(array $args, ?string $content, SkrivLite $skriv): string
	{
		$name = $args[0] ?? null;
		$caption = $args[1] ?? null;

		if (!$name || null === $this->current_path)
		{
			return $skriv->parseError('/!\ Tag file : aucun nom de fichier indiqué.');
		}

		if (empty($caption))
		{
			$caption = $name;
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

		$name = $args[0] ?? null;
		$align = $args[1] ?? null;
		$caption = $args[2] ?? null;

		$align = strtr($align, $align_replace);

		if (!$name || !$this->current_path)
		{
			return $skriv->parseError('/!\ Tag image : aucun nom de fichier indiqué.');
		}

		$url = $this->resolveAttachment($name);
		$thumb_url = sprintf('%s?%dpx', $url, $align == 'center' ? 500 : 200);








|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

		$name = $args[0] ?? null;
		$align = $args[1] ?? null;
		$caption = $args[2] ?? null;

		$align = strtr($align, $align_replace);

		if (!$name || null === $this->current_path)
		{
			return $skriv->parseError('/!\ Tag image : aucun nom de fichier indiqué.');
		}

		$url = $this->resolveAttachment($name);
		$thumb_url = sprintf('%s?%dpx', $url, $align == 'center' ? 500 : 200);

Modified src/templates/common/files/edit_web.tpl from [5e930c6a6c] to [c721ff089b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{include file="admin/_head.tpl" title="Édition de fichier" custom_js=['wiki_editor.js']}

<form method="post" action="{$self_url}">
	<p class="textEditor">
		{input type="textarea" name="content" cols="70" rows="30" default=$content data-preview-url="!common/files/_preview.php?f=%s"|local_url|args:$file.parent data-fullscreen="1" data-attachments="0" data-savebtn="1" data-format=$file->renderFormat()}
	</p>

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
	</p>

</form>

{include file="admin/_foot.tpl"}




|










1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{include file="admin/_head.tpl" title="Édition de fichier" custom_js=['wiki_editor.js']}

<form method="post" action="{$self_url}">
	<p class="textEditor">
		{input type="textarea" name="content" cols="70" rows="30" default=$content data-preview-url="!common/files/_preview.php?f=%s"|local_url|args:$file.path data-fullscreen="1" data-attachments="0" data-savebtn="1" data-format=$file->renderFormat()}
	</p>

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
	</p>

</form>

{include file="admin/_foot.tpl"}

Modified src/www/admin/common/files/_preview.php from [cc03d1dcb7] to [a08e5e24c0].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

	$file = $page->file();
}
else {
	throw new UserException('Fichier inconnu');
}

$prefix = $page ? 'web/page.php?uri=' : 'common/files/_preview.php?p=' . File::CONTEXT_DOCUMENTS . '/';

$content = Render::render(f('format'), $file, f('content'), ['prefix' => ADMIN_URL . $prefix]);

$tpl->assign(compact('file', 'content'));

$tpl->assign('custom_css', ['!web/css.php']);

$tpl->display('common/files/_preview.tpl');







|

|






32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

	$file = $page->file();
}
else {
	throw new UserException('Fichier inconnu');
}

$prefix = $page ? 'web/page.php?uri=' : 'common/files/_preview.php?p=';

$content = Render::render(f('format'), $file, f('content'), ADMIN_URL . $prefix);

$tpl->assign(compact('file', 'content'));

$tpl->assign('custom_css', ['!web/css.php']);

$tpl->display('common/files/_preview.tpl');

Modified src/www/admin/common/files/preview.php from [a192851b45] to [5a776333ed].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
}

if (!$file->checkReadAccess($session)) {
	throw new UserException('Vous n\'avez pas le droit de lire ce fichier.');
}

try {
	$tpl->assign('content', $file->render());
	$tpl->assign('file', $file);
	$tpl->display('common/files/_preview.tpl');
}
catch (\LogicException $e) {
	$file->serve($session);
}







|






13
14
15
16
17
18
19
20
21
22
23
24
25
26
}

if (!$file->checkReadAccess($session)) {
	throw new UserException('Vous n\'avez pas le droit de lire ce fichier.');
}

try {
	$tpl->assign('content', $file->render('common/files/_preview.php?p='));
	$tpl->assign('file', $file);
	$tpl->display('common/files/_preview.tpl');
}
catch (\LogicException $e) {
	$file->serve($session);
}

Modified src/www/admin/web/page.php from [da153abd6b] to [7684223213].

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$membres = new Membres;

$tpl->assign('breadcrumbs', $page->getBreadcrumbs());

$images = $page->getImageGallery(true);
$files = $page->getAttachmentsGallery(true);

$content = $page->render(['prefix' => ADMIN_URL . 'web/page.php?p=']);

$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;

$tpl->assign(compact('page', 'images', 'files', 'content', 'type_page', 'type_category'));

$tpl->assign('custom_js', ['wiki_gallery.js']);
$tpl->assign('custom_css', ['wiki.css', '!web/css.php']);

$tpl->display('web/page.tpl');







|










22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$membres = new Membres;

$tpl->assign('breadcrumbs', $page->getBreadcrumbs());

$images = $page->getImageGallery(true);
$files = $page->getAttachmentsGallery(true);

$content = $page->render(ADMIN_URL . 'web/page.php?p=');

$type_page = Page::TYPE_PAGE;
$type_category = Page::TYPE_CATEGORY;

$tpl->assign(compact('page', 'images', 'files', 'content', 'type_page', 'type_category'));

$tpl->assign('custom_js', ['wiki_gallery.js']);
$tpl->assign('custom_css', ['wiki.css', '!web/css.php']);

$tpl->display('web/page.tpl');