Skip to content

Commit

Permalink
feat(PdfIframeHandler): create it
Browse files Browse the repository at this point in the history
  • Loading branch information
J9rem committed Dec 15, 2022
1 parent 50342e8 commit 230df7c
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 45 deletions.
2 changes: 1 addition & 1 deletion actions/Bazar2PublicationAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function run()
if (array_key_exists('wiki', $queries)) {
unset($queries['wiki']);
}
$href = $this->wiki->Href('pdf', null, $queries// merge GET with wiki and following params
$href = $this->wiki->Href('pdf'.testUrlInIframe(), null, $queries// merge GET with wiki and following params
+[
'via' => 'bazarliste',
'template-page' => $this->arguments['templatepage'],
Expand Down
3 changes: 3 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,6 @@ services:

YesWiki\Publication\Service\:
resource: 'services/*'

YesWiki\Publication\Controller\:
resource: 'controllers/*'
66 changes: 66 additions & 0 deletions controllers/PdfController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace YesWiki\Publication\Controller;

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use YesWiki\Core\YesWikiController;
use YesWiki\Publication\Service\PdfHelper;
use YesWiki\Publication\Service\SessionManager;
use YesWiki\Wiki;

class PdfController extends YesWikiController
{
protected $params;
protected $pdfHelper;

public function __construct(
ParameterBagInterface $params,
PdfHelper $pdfHelper,
Wiki $wiki,
) {
$this->params = $params;
$this->pdfHelper = $pdfHelper;
$this->wiki = $wiki;
}

public function run(bool $inIframe = false)
{
if (!empty($_GET['url']) && is_string($_GET['url']) &&
!empty($_GET['urlPageTag']) && is_string($_GET['urlPageTag']) &&
!empty($_GET['hash']) && is_string($_GET['hash'])) {
// redirect to api
if (!method_exists($this->wiki, 'isCli') || !$this->wiki->isCli()) {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Expose-Headers: Location, Slug, Accept, Content-Type');
}
$filteredParams = array_filter($_GET, function ($v, $k) {
return in_array($k, ['url','urlPageTag','hash','refresh','forceNewFormat','via','template-page'], true) && is_scalar($v);
}, ARRAY_FILTER8USE_BOTH);
$this->wiki->redirect($this->wiki->href('', 'api/pdf/getPdf', $filteredParams + [
'fromOldPath' => '1'
], false));
}

list(
'pageTag'=>$pageTag,
'sourceUrl'=>$sourceUrl,
'hash'=>$hash,
) =
$this->pdfHelper->getSourceUrl($_GET ?? [], $_SERVER ?? []);

$method = $inIframe ? 'render' : 'renderInSquelette';

return $this->$method('@publication/handler-pdf.twig', [
'isAdmin' => $this->wiki->UserIsAdmin(),
'isIframe' => $inIframe,
'pageTag' => $pageTag,
'sourceUrl' => $sourceUrl,
'hash' => $hash,
'urls' => [
'local' => $this->pdfHelper->canExecChromium() ? $this->wiki->href('', 'api/pdf/getPdf') : '',
'external' => empty($this->params->get('htmltopdf_service_url')) ? '' : $this->params->get('htmltopdf_service_url'),
],
'refresh' => in_array($_GET['refresh'] ?? false, [1,"1",true,"true"], true),
]);
}
}
6 changes: 6 additions & 0 deletions docs/en/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ For this:
2. contact administrator of the concerned website to ask to add the current ueswiki's domain to the list of authorized domains.
- the concerned adminsitrator will have to modify the parameter `htmltopdf_service_authorized_domains` into page [GererConfig](?GererConfig 'Page config :ignore'), part `publication` (examples of possibles values : `['example.com']` or `['example.com','wiki.example.com','example.net']`)

### What do if print page does not display in `iframe` ?

If print page does not display in `iframe`, it is possible that server constraints of security prevent its display.

To authorize it, go as admin in page page [GererConfig](?GererConfig 'Page config :ignore') in part `Main parameters` and add `'pdf','pdfiframe'` to possible values in parameter `allowed_methods_in_iframe`.

## More precise usage

See french help at this [address](/tools/publication/docs/fr/?id=utilisation-d%c3%a9taill%c3%a9e)
Expand Down
6 changes: 6 additions & 0 deletions docs/fr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ Pour ceci:
2. contacter l'administrateurice du site concerné pour lui demander d'ajouter votre nom de domaine aux domaines autorisés.
- l'administrateurice concernée devra alors modifier le paramètre `htmltopdf_service_authorized_domains` dans la page [GererConfig](?GererConfig 'Page config :ignore') dans la partie `publication` (quelques exemples de valeurs possibles : `['example.com']` ou `['example.com','wiki.example.com','example.net']`)

### Que faire si la page d'impression ne s'affiche pas un cadre de type `iframe` ?

Si la page d'impression est affichée dans un cadre de type `iframe`, il est possible qu'elle ne s'affiche pas en raison des contraintes de sécurité de certains serveurs.

Pour en autoriser l'affichage, rendez-vous en temps qu'administrateurice sur la page [GererConfig](?GererConfig 'Page config :ignore') dans la partie `Paramètres principaux` et ajouter `'pdf','pdfiframe'` aux valeurs possibles pour le paramètre `allowed_methods_in_iframe`.

## Utilisation détaillée

Cette partie décrit de façon détaillée les paramètres pour les actions et handlers utilisés. Pour les explications de prise en main, veuillez vous rendre [en haut de ce fichier](?id=prise-en-main).
Expand Down
41 changes: 2 additions & 39 deletions handlers/PdfHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,12 @@
namespace YesWiki\Publication;

use YesWiki\Core\YesWikiHandler;
use YesWiki\Publication\Service\PdfHelper;
use YesWiki\Publication\Controller\PdfController;

class PdfHandler extends YesWikiHandler
{
public function run()
{
// get service
$pdfHelper = $this->getService(PdfHelper::class);

if (!empty($_GET['url']) && is_string($_GET['url']) &&
!empty($_GET['urlPageTag']) && is_string($_GET['urlPageTag']) &&
!empty($_GET['hash']) && is_string($_GET['hash'])) {
// redirect to api
if (!method_exists($this->wiki, 'isCli') || !$this->wiki->isCli()) {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Expose-Headers: Location, Slug, Accept, Content-Type');
}
$filteredParams = array_filter($_GET, function ($v, $k) {
return in_array($k, ['url','urlPageTag','hash','refresh','forceNewFormat','via','template-page'], true) && is_scalar($v);
}, ARRAY_FILTER8USE_BOTH);
$this->wiki->redirect($this->wiki->href('', 'api/pdf/getPdf', $filteredParams + [
'fromOldPath' => '1'
], false));
}


list(
'pageTag'=>$pageTag,
'sourceUrl'=>$sourceUrl,
'hash'=>$hash,
) =
$pdfHelper->getSourceUrl($_GET ?? [], $_SERVER ?? []);

return $this->renderInSquelette('@publication/handler-pdf.twig', [
'isAdmin' => $this->wiki->UserIsAdmin(),
'pageTag' => $pageTag,
'sourceUrl' => $sourceUrl,
'hash' => $hash,
'urls' => [
'local' => $pdfHelper->canExecChromium() ? $this->wiki->href('', 'api/pdf/getPdf') : '',
'external' => empty($this->params->get('htmltopdf_service_url')) ? '' : $this->params->get('htmltopdf_service_url'),
],
'refresh' => in_array($_GET['refresh'] ?? false, [1,"1",true,"true"], true),
]);
return $this->getService(PdfController::class)->run();
}
}
55 changes: 55 additions & 0 deletions handlers/PdfIframeHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace YesWiki\Publication;

use YesWiki\Core\YesWikiHandler;
use YesWiki\Publication\Controller\PdfController;

class PdfIframeHandler extends YesWikiHandler
{
public function run()
{
if ($this->wiki->UserIsAdmin() &&
!in_array(
'pdfiframe',
is_array($this->params->get('allowed_methods_in_iframe')) ? $this->params->get('allowed_methods_in_iframe') : []
)
) {
// allow local ('self') and everyone (*) to allow display error message
if (!$this->wiki->isCli() && !headers_sent()) {
header("Content-Security-Policy: frame-ancestors 'self' *;");
}

return $this->displayInIframe($this->render('@templates/alert-message.twig', [
'type' => 'danger',
'message' => _t('PUBLICATION_IFRAME_NOT_SET', [
'gererConfigLink' => "<a href=\"{$this->wiki->href('iframe', 'GererConfig')}\">GererConfig</a>"
])
]));
}
return $this->displayInIframe($this->getService(PdfController::class)->run(true));
}

protected function displayInIframe(string $content)
{
$output = <<<HTML
<body class="yeswiki-iframe-body login-body">
<div class="container">
<div class="yeswiki-page-widget page-widget page" {$this->wiki->Format('{{doubleclic iframe="1"}}')}>
$content
</div><!-- end .page-widget -->
</div><!-- end .container -->
HTML;
// common footer for all iframe page

$this->wiki->AddJavascriptFile('tools/templates/libs/vendor/iframeResizer.contentWindow.min.js');

// on recupere les entetes html mais pas ce qu'il y a dans le body
$header = explode('<body', $this->wiki->Header());
$output = $header[0].$output;
// on recupere juste les javascripts et la fin des balises body et html
$output .= preg_replace('/^.+<script/Us', '<script', $this->wiki->Footer());

return $output;
}
}
4 changes: 3 additions & 1 deletion javascripts/handler-pdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ let appParams = {
finish: false,
hash: '',
isAdmin: null,
isIframe: null,
message: '',
messageType: 'danger',
pageTag:'',
Expand Down Expand Up @@ -349,7 +350,7 @@ let appParams = {
},
returnToPage: function(){
this.stopFetch();
window.location = wiki.url(wiki.pageTag);
window.location = wiki.url(wiki.pageTag+(this.isIframe ? '/iframe' : ''));
},
stopFetch: function(){
if (this.abortController !== null){
Expand Down Expand Up @@ -445,6 +446,7 @@ let appParams = {
return false;
});
this.isAdmin = (baseEl.dataset.isAdmin === true || baseEl.dataset.isAdmin === "true");
this.isIframe = (baseEl.dataset.isIframe === true || baseEl.dataset.isIframe === "true");
this.hash = baseEl.dataset.hash ?? '';
this.pageTag = baseEl.dataset.pageTag ?? '';
this.sourceUrl = baseEl.dataset.sourceUrl ?? '';
Expand Down
1 change: 1 addition & 0 deletions lang/publication_en.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
'PUBLICATION_ERROR_FOR_USER' => 'Connexion not possible<br/>Pdf creation by altenative way.<br/><i>If a new window does not open in this browser in few seconds, click on button bellow.</i>.',
'PUBLICATION_ERROR_RELOADING' => 'This website uses an external service to print pdf. You will be redirected to this service.',
'PUBLICATION_ERROR_WHILE_GENERATING_PDF' => 'Error while generating pdf for \'{url}\' : {error}',
'PUBLICATION_IFRAME_NOT_SET' => 'The handler `pdfiframe` is not allowed to display in iframe!<br/>Go to page page %{gererConfigLink}, part \'Main parameters\' to add \'pdfiframe\' in parameter `allowed_methods_in_iframe` ',
'PUBLICATION_GET_PDF_SERVICE_URL' => 'Get pdf server address',
'PUBLICATION_LOADING_BROWSER' => 'Loading browser on server',
'PUBLICATION_LOADING_PAGE' => 'Loading page on server',
Expand Down
1 change: 1 addition & 0 deletions lang/publication_fr.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
'PUBLICATION_ERROR_FOR_USER' => 'Connexion impossible<br/>Génération du pdf par un moyen alternatif.<br/><i>Si une fenêtre ne s\'ouvre pas dans ce navigateur dans quelques secondes, vous pouvez cliquer sur le bouton ci-dessous.</i>.',
'PUBLICATION_ERROR_RELOADING' => 'Ce site utilise un service externe pour imprimer les pages. Vous allez être redirigé vers ce service.',
'PUBLICATION_ERROR_WHILE_GENERATING_PDF' => 'Erreur en générant le pdf pour \'{url}\' : {error}',
'PUBLICATION_IFRAME_NOT_SET' => 'Le handler `pdfiframe` n\'est pas autorisé à s\'afficher dans les iframes !<br/>Veuiller vous rendre dans la page %{gererConfigLink}, partie \'Paramètres principaux\' pour ajouter \'pdfiframe\' au paramètre `allowed_methods_in_iframe` !',
'PUBLICATION_GET_PDF_SERVICE_URL' => 'Récupération de l\'adresse du serveur pdf',
'PUBLICATION_LOADING_BROWSER' => 'Chargement du navigateur sur le serveur',
'PUBLICATION_LOADING_PAGE' => 'Chargement de la page sur le serveur',
Expand Down
1 change: 1 addition & 0 deletions lang/publication_pt.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
// 'PUBLICATION_ERROR_FOR_USER' => 'Connexion impossible<br/>Génération du pdf par un moyen alternatif.<br/><i>Si une fenêtre ne s\'ouvre pas dans ce navigateur dans quelques secondes, vous pouvez cliquer sur le bouton ci-dessous.</i>.',
// 'PUBLICATION_ERROR_RELOADING' => 'Ce site utilise un service externe pour imprimer les pages. Vous allez être redirigé vers ce service.',
// 'PUBLICATION_ERROR_WHILE_GENERATING_PDF' => 'Erreur en générant le pdf pour \'{url}\' : {error}',
// 'PUBLICATION_IFRAME_NOT_SET' => 'Le handler `pdfiframe` n\'est pas autorisé à s\'afficher dans les iframes !<br/>Veuiller vous rendre dans la page %{gererConfigLink}, partie \'Paramètres principaux\' pour ajouter \'pdfiframe\' au paramètre `allowed_methods_in_iframe` !',
// 'PUBLICATION_GET_PDF_SERVICE_URL' => 'Récupération de l\'adresse du serveur pdf',
// 'PUBLICATION_LOADING_BROWSER' => 'Chargement du navigateur sur le serveur',
// 'PUBLICATION_LOADING_PAGE' => 'Chargement de la page sur le serveur',
Expand Down
6 changes: 3 additions & 3 deletions services/PdfHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ protected function getData(array $get, array $server, string $pagedjs_hash): arr
$hash = substr(sha1($pagedjs_hash . strtolower($queryString)), 0, 10);
} else {
$pageTag = $this->wiki->GetPageTag();
$pdfTag = $this->wiki->MiniHref('pdf', $pageTag);
$pdfTag = $this->wiki->MiniHref('pdf'.testUrlInIframe(), $pageTag);
$queryString = preg_replace('#^'. $pdfTag .'&?#', '', $server['QUERY_STRING'] ?? '');
$queryString = preg_replace('/refresh=[A-Za-z0-9\-]+(&|$)/', '', $queryString);
$sourceUrl = $this->wiki->href('preview', $pageTag, $queryString, false);
Expand Down Expand Up @@ -308,11 +308,11 @@ public function useBrowserToCreatePdfFromPage(
$this->setValueInSession($uuid, PdfHelper::SESSION_BROWSER_READY, 1);

$timeout = (
empty($options['sendSyncDefaultTimeout']) ||
empty($options['sendSyncDefaultTimeout']) ||
!is_scalar($options['sendSyncDefaultTimeout']) ||
intval($options['sendSyncDefaultTimeout']) < 10000 // in ms
) ? 20 // in sec
: ceil(intval($options['sendSyncDefaultTimeout'])*2/1000); // in s
: ceil(intval($options['sendSyncDefaultTimeout'])*2/1000); // in s
// (twice to be sure that Browser manages timeout and not php)
set_time_limit($timeout);

Expand Down
3 changes: 2 additions & 1 deletion templates/bazar/entries/_publication_button.twig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% set curretHandler = url({params:{}}) matches '/.*iframe$/' ? 'pdfiframe' : 'pdf' %}
<a class="{{ forPage ? 'link-pdf' : 'btn btn-entry-action btn-sm btn-default'}}"
href="{{ forPage ? url({handler: 'pdf' }) : (urlentry['external-data'] ? entry.url ~ '/pdf' : url({ tag: entryId, handler: 'pdf' })) }}"
href="{{ forPage ? url({handler: curretHandler }) : (urlentry['external-data'] ? entry.url ~ '/' ~ curretHandler : url({ tag: entryId, handler: 'pdf' })) }}"
onclick="toastMessage(_t('PUBLICATION_PDF_GENERATION_LANCHED'),7000,'alert alert-primary');"
title="{{ _t('PUBLICATION_EXPORT_PAGE_TO_PDF') }}">
<i class="{{ forPage ? 'glyphicon glyphicon-book' : 'fas fa-book' }}"></i>
Expand Down
1 change: 1 addition & 0 deletions templates/handler-pdf.twig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<div class="pdf-handler-container"
data-is-admin="{{ (isAdmin == true)|json_encode }}"
data-is-iframe="{{ (isIframe == true)|json_encode }}"
data-urls="{{ urls|json_encode }}"
data-source-url="{{ sourceUrl }}"
data-hash="{{ hash }}"
Expand Down

0 comments on commit 230df7c

Please sign in to comment.