diff --git a/.puppet/profiles/icinga2_dev/files/constants.conf b/.puppet/profiles/icinga2_dev/files/constants.conf
index 9e6ed51af..fb714b2fb 100644
--- a/.puppet/profiles/icinga2_dev/files/constants.conf
+++ b/.puppet/profiles/icinga2_dev/files/constants.conf
@@ -6,6 +6,16 @@
/* The directory which contains the plugins from the Monitoring Plugins project. */
const PluginDir = "/usr/lib64/nagios/plugins"
+/* The directory which contains the Manubulon plugins.
+ * Check the documentation, chapter "SNMP Manubulon Plugin Check Commands", for details.
+ */
+const ManubulonPluginDir = "/usr/lib64/nagios/plugins"
+
+/* The directory which you use to store additional plugins which ITL provides user contributed command definitions for.
+ * Check the documentation, chapter "Plugins Contribution", for details.
+ */
+const PluginContribDir = "/usr/lib64/nagios/plugins"
+
/* Our local instance name. By default this is the server's hostname as returned by `hostname --fqdn`.
* This should be the common name from the API certificate.
*/
@@ -13,3 +23,4 @@ const NodeName = "localhost"
/* Our local zone name. */
const ZoneName = NodeName
+const TicketSalt = ""
diff --git a/ChangeLog b/ChangeLog
index 8954889e5..132c6e0f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
# Icinga Web 2 Changelog
+## What's New
+
+### What's New in Version 2.3.4/2.3.3
+
+#### Bugfixes
+
+* Bug 11267: Links in plugin output don't behave as expected
+* Bug 11348: Host aliases are not shown in detail area
+* Bug 11728: First non whitespace character after comma stripped from plugin output
+* Bug 11729: Sort by severity depends on state type
+* Bug 11737: Zero width space characters destroy state highlighting in plugin output
+* Bug 11796: Zero width space characters may destroy links in plugin output
+* Bug 11831: module.info parsing fails in case it contains newlines that are not part of the module's description
+* Bug 11850: "Add to menu" tab unnecessarily appears in command forms
+* Bug 11871: Colors used in the timeline are not accessible
+* Bug 11883: Delete action on comments and downtimes in list views not accessible because they lack context
+* Bug 11885: Database: Asterisk filters ignored when combined w/ other filters
+* Bug 11910: Web 2 lacks mobile meta tags
+* Fix remote code execution via remote command transport
+
### What's New in Version 2.3.2
#### Feature
@@ -14,8 +34,6 @@
* Bug 10848: Can't change items per page if filter is in modify state
* Bug 11392: Can't configure monitoring backend via the web interface when no monitoring backend was configured
-## What's New
-
### What's New in Version 2.3.1
#### Bugfixes
diff --git a/VERSION b/VERSION
index f706a60d8..20dd63223 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v2.3.2
+v2.3.4
diff --git a/application/controllers/AccountController.php b/application/controllers/AccountController.php
new file mode 100644
index 000000000..25bc97756
--- /dev/null
+++ b/application/controllers/AccountController.php
@@ -0,0 +1,73 @@
+getTabs()
+ ->add('account', array(
+ 'title' => $this->translate('Update your account'),
+ 'label' => $this->translate('My Account'),
+ 'url' => 'account'
+ ))
+ ->add('navigation', array(
+ 'title' => $this->translate('List and configure your own navigation items'),
+ 'label' => $this->translate('Navigation'),
+ 'url' => 'navigation'
+ ));
+ }
+
+ /**
+ * My account
+ */
+ public function indexAction()
+ {
+ $config = Config::app()->getSection('global');
+ $user = $this->Auth()->getUser();
+ if ($user->getAdditional('backend_type') === 'db') {
+ try {
+ $userBackend = UserBackend::create($user->getAdditional('backend_name'));
+ } catch (ConfigurationError $e) {
+ $userBackend = null;
+ }
+ if ($userBackend !== null) {
+ $changePasswordForm = new ChangePasswordForm();
+ $changePasswordForm
+ ->setBackend($userBackend)
+ ->handleRequest();
+ $this->view->changePasswordForm = $changePasswordForm;
+ }
+ }
+
+ $form = new PreferenceForm();
+ $form->setPreferences($user->getPreferences());
+ if ($config->get('config_backend', 'ini') !== 'none') {
+ $form->setStore(PreferencesStore::create(new ConfigObject(array(
+ 'store' => $config->get('config_backend', 'ini'),
+ 'resource' => $config->config_resource
+ )), $user));
+ }
+ $form->handleRequest();
+
+ $this->view->form = $form;
+ $this->getTabs()->activate('account');
+ }
+}
diff --git a/application/controllers/AnnouncementsController.php b/application/controllers/AnnouncementsController.php
new file mode 100644
index 000000000..458b9a40a
--- /dev/null
+++ b/application/controllers/AnnouncementsController.php
@@ -0,0 +1,100 @@
+getTabs()->add(
+ 'announcements',
+ array(
+ 'active' => true,
+ 'label' => $this->translate('Announcements'),
+ 'title' => $this->translate('List All Announcements'),
+ 'url' => Url::fromPath('announcements')
+ )
+ );
+
+ $repo = new AnnouncementIniRepository();
+ $this->view->announcements = $repo
+ ->select(array('id', 'author', 'message', 'start', 'end'))
+ ->order('start');
+ }
+
+ /**
+ * Create an announcement
+ */
+ public function newAction()
+ {
+ $this->assertPermission('admin');
+
+ $form = $this->prepareForm()->add();
+ $form->handleRequest();
+ $this->renderForm($form, $this->translate('New Announcement'));
+ }
+
+ /**
+ * Update an announcement
+ */
+ public function updateAction()
+ {
+ $this->assertPermission('admin');
+
+ $form = $this->prepareForm()->edit($this->params->getRequired('id'));
+ try {
+ $form->handleRequest();
+ } catch (NotFoundError $_) {
+ $this->httpNotFound($this->translate('Announcement not found'));
+ }
+ $this->renderForm($form, $this->translate('Update Announcement'));
+ }
+
+ /**
+ * Remove an announcement
+ */
+ public function removeAction()
+ {
+ $this->assertPermission('admin');
+
+ $form = $this->prepareForm()->remove($this->params->getRequired('id'));
+ try {
+ $form->handleRequest();
+ } catch (NotFoundError $_) {
+ $this->httpNotFound($this->translate('Announcement not found'));
+ }
+ $this->renderForm($form, $this->translate('Remove Announcement'));
+ }
+
+ public function acknowledgeAction()
+ {
+ $this->assertHttpMethod('POST');
+ $this->getResponse()->setHeader('X-Icinga-Container', 'ignore', true);
+ $form = new AcknowledgeAnnouncementForm();
+ $form->handleRequest();
+ }
+
+ /**
+ * Assert permission admin and return a prepared RepositoryForm
+ *
+ * @return AnnouncementForm
+ */
+ protected function prepareForm()
+ {
+ $form = new AnnouncementForm();
+ return $form
+ ->setRepository(new AnnouncementIniRepository())
+ ->setRedirectUrl(Url::fromPath('announcements'));
+ }
+}
diff --git a/application/controllers/ApplicationStateController.php b/application/controllers/ApplicationStateController.php
index caae26f54..cba019843 100644
--- a/application/controllers/ApplicationStateController.php
+++ b/application/controllers/ApplicationStateController.php
@@ -4,6 +4,8 @@
namespace Icinga\Controllers;
use Icinga\Application\Icinga;
+use Icinga\Web\Announcement\AnnouncementCookie;
+use Icinga\Web\Announcement\AnnouncementIniRepository;
use Icinga\Web\Controller;
use Icinga\Web\Session;
@@ -14,6 +16,7 @@ class ApplicationStateController extends Controller
{
public function indexAction()
{
+ $this->_helper->layout()->disableLayout();
if (isset($_COOKIE['icingaweb2-session'])) {
$last = (int) $_COOKIE['icingaweb2-session'];
} else {
@@ -34,6 +37,23 @@ class ApplicationStateController extends Controller
);
$_COOKIE['icingaweb2-session'] = $now;
}
- Icinga::app()->getResponse()->setHeader('X-Icinga-Container', 'ignore', true);
+ $announcementCookie = new AnnouncementCookie();
+ $announcementRepo = new AnnouncementIniRepository();
+ if ($announcementCookie->getEtag() !== $announcementRepo->getEtag()) {
+ $announcementCookie
+ ->setEtag($announcementRepo->getEtag())
+ ->setNextActive($announcementRepo->findNextActive());
+ $this->getResponse()->setCookie($announcementCookie);
+ $this->getResponse()->setHeader('X-Icinga-Announcements', 'refresh', true);
+ } else {
+ $nextActive = $announcementCookie->getNextActive();
+ if ($nextActive && $nextActive <= $now) {
+ $announcementCookie->setNextActive($announcementRepo->findNextActive());
+ $this->getResponse()->setCookie($announcementCookie);
+ $this->getResponse()->setHeader('X-Icinga-Announcements', 'refresh', true);
+ }
+ }
+
+ $this->getResponse()->setHeader('X-Icinga-Container', 'ignore', true);
}
}
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
index c1d75b711..997c6a708 100644
--- a/application/controllers/ConfigController.php
+++ b/application/controllers/ConfigController.php
@@ -4,6 +4,7 @@
namespace Icinga\Controllers;
use Exception;
+use Icinga\Application\Version;
use InvalidArgumentException;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
@@ -122,6 +123,7 @@ class ConfigController extends Controller
$this->view->module = $module;
$this->view->tabs = $module->getConfigTabs()->activate('info');
+ $this->view->moduleGitCommitId = Version::getGitHead($module->getBaseDir());
} else {
$this->view->module = false;
$this->view->tabs = null;
@@ -213,7 +215,7 @@ class ConfigController extends Controller
$form->setOnSuccess(function (UserBackendConfigForm $form) {
try {
- $form->add(array_filter($form->getValues()));
+ $form->add($form::transformEmptyValuesToNull($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
@@ -244,12 +246,7 @@ class ConfigController extends Controller
$form->setIniConfig(Config::app('authentication'));
$form->setOnSuccess(function (UserBackendConfigForm $form) use ($backendName) {
try {
- $form->edit($backendName, array_map(
- function ($v) {
- return $v !== '' ? $v : null;
- },
- $form->getValues()
- ));
+ $form->edit($backendName, $form::transformEmptyValuesToNull($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
@@ -393,10 +390,10 @@ class ConfigController extends Controller
$authConfig = Config::app('authentication');
foreach ($authConfig as $backendName => $config) {
if ($config->get('resource') === $resource) {
- $form->addDescription(sprintf(
+ $form->warning(sprintf(
$this->translate(
- 'The resource "%s" is currently utilized for authentication by user backend "%s". ' .
- 'Removing the resource can result in noone being able to log in any longer.'
+ 'The resource "%s" is currently utilized for authentication by user backend "%s".'
+ . ' Removing the resource can result in noone being able to log in any longer.'
),
$resource,
$backendName
@@ -404,6 +401,17 @@ class ConfigController extends Controller
}
}
+ // Check if selected resource is currently used as user preferences backend
+ if (Config::app()->get('global', 'config_resource') === $resource) {
+ $form->warning(sprintf(
+ $this->translate(
+ 'The resource "%s" is currently utilized to store user preferences. Removing the'
+ . ' resource causes all current user preferences not being available any longer.'
+ ),
+ $resource
+ ));
+ }
+
$this->view->form = $form;
$this->render('resource/remove');
}
diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php
index 86ee26554..b0010385d 100644
--- a/application/controllers/ErrorController.php
+++ b/application/controllers/ErrorController.php
@@ -32,8 +32,6 @@ class ErrorController extends ActionController
$error = $this->_getParam('error_handler');
$exception = $error->exception;
/** @var \Exception $exception */
- Logger::error($exception);
- Logger::error('Stacktrace: %s', $exception->getTraceAsString());
if (! ($isAuthenticated = $this->Auth()->isAuthenticated())) {
$this->innerLayout = 'guest-error';
@@ -83,6 +81,7 @@ class ErrorController extends ActionController
break;
default:
$this->getResponse()->setHttpResponseCode(500);
+ Logger::error("%s\n%s", $exception, $exception->getTraceAsString());
break;
}
$this->view->message = $exception->getMessage();
diff --git a/application/controllers/LayoutController.php b/application/controllers/LayoutController.php
index f7bbd5102..32295a688 100644
--- a/application/controllers/LayoutController.php
+++ b/application/controllers/LayoutController.php
@@ -20,4 +20,9 @@ class LayoutController extends ActionController
$this->_helper->layout()->disableLayout();
$this->view->menuRenderer = Icinga::app()->getMenu()->getRenderer();
}
+
+ public function announcementsAction()
+ {
+ $this->_helper->layout()->disableLayout();
+ }
}
diff --git a/application/controllers/NavigationController.php b/application/controllers/NavigationController.php
index 51b5dae1c..1d2d39f68 100644
--- a/application/controllers/NavigationController.php
+++ b/application/controllers/NavigationController.php
@@ -128,11 +128,11 @@ class NavigationController extends Controller
$this->getTabs()
->add(
- 'preferences',
+ 'account',
array(
- 'title' => $this->translate('Adjust the preferences of Icinga Web 2 according to your needs'),
- 'label' => $this->translate('Preferences'),
- 'url' => 'preference'
+ 'title' => $this->translate('Update your account'),
+ 'label' => $this->translate('My Account'),
+ 'url' => 'account'
)
)
->add(
@@ -219,7 +219,7 @@ class NavigationController extends Controller
$form->setDefaultUrl(rawurldecode($this->params->get('url', '')));
$form->setOnSuccess(function (NavigationConfigForm $form) {
- $data = array_filter($form->getValues());
+ $data = $form::transformEmptyValuesToNull($form->getValues());
try {
$form->add($data);
@@ -266,12 +266,7 @@ class NavigationController extends Controller
$form->setUserConfig(Config::navigation($itemType, $itemOwner));
$form->setRedirectUrl($referrer === 'shared' ? 'navigation/shared' : 'navigation');
$form->setOnSuccess(function (NavigationConfigForm $form) use ($itemName) {
- $data = array_map(
- function ($v) {
- return $v !== '' ? $v : null;
- },
- $form->getValues()
- );
+ $data = $form::transformEmptyValuesToNull($form->getValues());
try {
$form->edit($itemName, $data);
diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php
deleted file mode 100644
index bb4655c27..000000000
--- a/application/controllers/PreferenceController.php
+++ /dev/null
@@ -1,65 +0,0 @@
- new Tab(array(
- 'title' => t('Adjust the preferences of Icinga Web 2 according to your needs'),
- 'label' => t('Preferences'),
- 'url' => 'preference'
- )),
- 'navigation' => new Tab(array(
- 'title' => t('List and configure your own navigation items'),
- 'label' => t('Navigation'),
- 'url' => 'navigation'
- ))
- );
- }
-
- /**
- * Show form to adjust user preferences
- */
- public function indexAction()
- {
- $config = Config::app()->getSection('global');
- $user = $this->getRequest()->getUser();
-
- $form = new PreferenceForm();
- $form->setPreferences($user->getPreferences());
- if ($config->get('config_backend', 'ini') !== 'none') {
- $form->setStore(PreferencesStore::create(new ConfigObject(array(
- 'store' => $config->get('config_backend', 'ini'),
- 'resource' => $config->config_resource
- )), $user));
- }
- $form->handleRequest();
-
- $this->view->form = $form;
- $this->getTabs()->activate('preferences');
- }
-}
diff --git a/application/controllers/UsergroupbackendController.php b/application/controllers/UsergroupbackendController.php
index 14456fc01..a9e411c54 100644
--- a/application/controllers/UsergroupbackendController.php
+++ b/application/controllers/UsergroupbackendController.php
@@ -43,7 +43,7 @@ class UsergroupbackendController extends Controller
$form->setIniConfig(Config::app('groups'));
$form->setOnSuccess(function (UserGroupBackendForm $form) {
try {
- $form->add(array_filter($form->getValues()));
+ $form->add($form::transformEmptyValuesToNull($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
@@ -73,12 +73,7 @@ class UsergroupbackendController extends Controller
$form->setIniConfig(Config::app('groups'));
$form->setOnSuccess(function (UserGroupBackendForm $form) use ($backendName) {
try {
- $form->edit($backendName, array_map(
- function ($v) {
- return $v !== '' ? $v : null;
- },
- $form->getValues()
- ));
+ $form->edit($backendName, $form::transformEmptyValuesToNull($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
diff --git a/application/fonts/fontello-ifont/LICENSE.txt b/application/fonts/fontello-ifont/LICENSE.txt
old mode 100644
new mode 100755
index 7e9af2aa8..441bc985b
--- a/application/fonts/fontello-ifont/LICENSE.txt
+++ b/application/fonts/fontello-ifont/LICENSE.txt
@@ -3,7 +3,7 @@ Font license info
## Font Awesome
- Copyright (C) 2012 by Dave Gandy
+ Copyright (C) 2016 by Dave Gandy
Author: Dave Gandy
License: SIL ()
@@ -19,15 +19,6 @@ Font license info
Homepage: http://somerandomdude.com/work/iconic/
-## MFG Labs
-
- Copyright (C) 2012 by Daniel Bruce
-
- Author: MFG Labs
- License: SIL (http://scripts.sil.org/OFL)
- Homepage: http://www.mfglabs.com/
-
-
## Entypo
Copyright (C) 2012 by Daniel Bruce
diff --git a/application/fonts/fontello-ifont/README.txt b/application/fonts/fontello-ifont/README.txt
old mode 100644
new mode 100755
index a91438a9a..beaab3366
--- a/application/fonts/fontello-ifont/README.txt
+++ b/application/fonts/fontello-ifont/README.txt
@@ -2,14 +2,14 @@ This webfont is generated by http://fontello.com open source project.
================================================================================
-Please, note, that you should obey original font licences, used to make this
+Please, note, that you should obey original font licenses, used to make this
webfont pack. Details available in LICENSE.txt file.
- Usually, it's enough to publish content of LICENSE.txt file somewhere on your
site in "About" section.
- If your project is open-source, usually, it will be ok to make LICENSE.txt
- file publically available in your repository.
+ file publicly available in your repository.
- Fonts, used in Fontello, don't require a clickable link on your site.
But any kind of additional authors crediting is welcome.
diff --git a/application/fonts/fontello-ifont/config.json b/application/fonts/fontello-ifont/config.json
old mode 100644
new mode 100755
index f68fd5cef..610be9441
--- a/application/fonts/fontello-ifont/config.json
+++ b/application/fonts/fontello-ifont/config.json
@@ -711,7 +711,7 @@
{
"uid": "3bd18d47a12b8709e9f4fe9ead4f7518",
"css": "reschedule",
- "code": 59492,
+ "code": 59524,
"src": "entypo"
},
{
@@ -744,12 +744,6 @@
"code": 59512,
"src": "typicons"
},
- {
- "uid": "b90d80c250a9bbdd6cd3fe00e6351710",
- "css": "ok",
- "code": 59395,
- "src": "iconic"
- },
{
"uid": "11e664deed5b2587456a4f9c01d720b6",
"css": "cancel",
@@ -775,10 +769,52 @@
"src": "iconic"
},
{
- "uid": "9c3b8d8a6d477da4d3e65b92e4e9c290",
+ "uid": "8f28d948aa6379b1a69d2a090e7531d4",
+ "css": "warning-empty",
+ "code": 59525,
+ "src": "typicons"
+ },
+ {
+ "uid": "d4816c0845aa43767213d45574b3b145",
+ "css": "history",
+ "code": 61914,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "b035c28eba2b35c6ffe92aee8b0df507",
+ "css": "attention-circled",
+ "code": 59521,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "73ffeb70554099177620847206c12457",
+ "css": "binoculars",
+ "code": 61925,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "a73c5deb486c8d66249811642e5d719a",
+ "css": "arrows-cw",
+ "code": 59492,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "dd6c6b221a1088ff8a9b9cd32d0b3dd5",
+ "css": "check",
+ "code": 59523,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "b90d80c250a9bbdd6cd3fe00e6351710",
+ "css": "ok",
+ "code": 59395,
+ "src": "iconic"
+ },
+ {
+ "uid": "37c5ab63f10d7ad0b84d0978dcd0c7a8",
"css": "flapping",
"code": 59485,
- "src": "mfglabs"
+ "src": "fontawesome"
}
]
}
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/css/animation.css b/application/fonts/fontello-ifont/css/animation.css
old mode 100644
new mode 100755
diff --git a/application/fonts/fontello-ifont/css/ifont-codes.css b/application/fonts/fontello-ifont/css/ifont-codes.css
old mode 100644
new mode 100755
index 146f097f0..3c9341de5
--- a/application/fonts/fontello-ifont/css/ifont-codes.css
+++ b/application/fonts/fontello-ifont/css/ifont-codes.css
@@ -99,7 +99,7 @@
.icon-bell-off-empty:before { content: '\e861'; } /* '' */
.icon-plug:before { content: '\e862'; } /* '' */
.icon-eye-off:before { content: '\e863'; } /* '' */
-.icon-reschedule:before { content: '\e864'; } /* '' */
+.icon-arrows-cw:before { content: '\e864'; } /* '' */
.icon-cw:before { content: '\e865'; } /* '' */
.icon-host:before { content: '\e866'; } /* '' */
.icon-thumbs-up:before { content: '\e867'; } /* '' */
@@ -127,4 +127,10 @@
.icon-info-circled:before { content: '\e87d'; } /* '' */
.icon-twitter:before { content: '\e87e'; } /* '' */
.icon-facebook-squared:before { content: '\e87f'; } /* '' */
-.icon-gplus-squared:before { content: '\e880'; } /* '' */
\ No newline at end of file
+.icon-gplus-squared:before { content: '\e880'; } /* '' */
+.icon-attention-circled:before { content: '\e881'; } /* '' */
+.icon-check:before { content: '\e883'; } /* '' */
+.icon-reschedule:before { content: '\e884'; } /* '' */
+.icon-warning-empty:before { content: '\e885'; } /* '' */
+.icon-history:before { content: '\f1da'; } /* '' */
+.icon-binoculars:before { content: '\f1e5'; } /* '' */
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/css/ifont-embedded.css b/application/fonts/fontello-ifont/css/ifont-embedded.css
old mode 100644
new mode 100755
index d8330a657..f9fa8b3ea
--- a/application/fonts/fontello-ifont/css/ifont-embedded.css
+++ b/application/fonts/fontello-ifont/css/ifont-embedded.css
@@ -1,15 +1,15 @@
@font-face {
font-family: 'ifont';
- src: url('../font/ifont.eot?36375038');
- src: url('../font/ifont.eot?36375038#iefix') format('embedded-opentype'),
- url('../font/ifont.svg?36375038#ifont') format('svg');
+ src: url('../font/ifont.eot?47279460');
+ src: url('../font/ifont.eot?47279460#iefix') format('embedded-opentype'),
+ url('../font/ifont.svg?47279460#ifont') format('svg');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'ifont';
- src: url('data:application/octet-stream;base64,d09GRgABAAAAAEt8AA4AAAAAe2AAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABRAAAAEQAAABWPilJgGNtYXAAAAGIAAAAOgAAAUrQkRm3Y3Z0IAAAAcQAAAAKAAAACgAAAABmcGdtAAAB0AAABZQAAAtwiJCQWWdhc3AAAAdkAAAACAAAAAgAAAAQZ2x5ZgAAB2wAADyiAABhGvFH6HdoZWFkAABEEAAAADUAAAA2CLYq3mhoZWEAAERIAAAAIAAAACQIbgTbaG10eAAARGgAAACrAAACCLwZAABsb2NhAABFFAAAAQYAAAEGfOlljG1heHAAAEYcAAAAIAAAACABOQ16bmFtZQAARjwAAAF5AAACqcQUfvlwb3N0AABHuAAAA1oAAAV7GXTvb3ByZXAAAEsUAAAAZQAAAHvdawOFeJxjYGTOZpzAwMrAwVTFtIeBgaEHQjM+YDBkZGJgYGJgZWbACgLSXFMYHF4wvGhgDvqfxRDFHMEwHSjMCJIDAO4KDCd4nGNgYGBmgGAZBkYGEHAB8hjBfBYGDSDNBqQZGZgYGF40/P8PUvCCAURLMELVAwEjG8OIBwDyRwcuAAAAAAAAAAAAAAAAAAB4nK1WaXMTRxCd1WHLNj6CDxI2gVnGcox2VpjLCBDG7EoW4BzylexCjl1Ldu6LT/wG/ZpekVSRb/y0vB4d2GAnVVQoSv2m9+1M9+ueXpPQksReWI+k3HwpprY2aWTnSUg3bFqO4kPZ2QspU0z+LoiCaLXUvu04JCISgap1hSWC2PfI0iTjQ48yWrYlvWpSbulJd9kaD+qt+vbT0FGO3QklNZuhQ+uRLanCqBJFMu2RkjYtw9VfSVrh5yvMfNUMJYLoJJLGm2EMj+Rn44xWGa3GdhxFkU2WG0WKRDM8iCKPslpin1wxQUD5oBlSXvk0onyEH5EVe5TTCnHJdprf9yU/6R3OvyTieouyJQf+QHZkB3unK/ki0toK46adbEehivB0fSfEI5uT6p/sUV7TaOB2RaYnzQiWyleQWPkJZfYPyWrhfMqXPBrVkoOcCFovc2Jf8g60HkdMiWsmyILujk6IoO6XnKHYY/q4+OO9XSwXIQTIOJb1jkq4EEYpYbOaJG0EOYiSskWV1HpHTJzyOi3iLWG/Tu3oS2e0Sag7MZ6th46tnKjkeDSp00ymTu2k5tGUBlFKOhM85tcBlB/RJK+2sZrEyqNpbDNjJJFQoIVzaSqIZSeWNAXRPJrRm7thmmvXokWaPFDPPXpPb26Fmzs9p+3AP2v8Z3UqpoO9MJ2eDshKfJp2uUnRun56hn8m8UPWAiqRLTbDlMVDtn4H5eVjS47CawNs957zK+h99kTIpIH4G/AeL9UpBUyFmFVQC9201rUsy9RqVotUZOq7IU0rX9ZpAk05Dn1jX8Y4/q+ZGUtMCd/vxOnZEZeeufYlyDSH3GZdj+Z1arFdgM5sz+k0y/Z9nebYfqDTPNvzOh1ha+t0lO2HOi2w/UinY2wvaEGT7jsEchGBXMAGEoGwdRAI20sIhK1CIGwXEQjbIgJhu4RA2H6MQNguIxC2l7Wsmn4qaRw7E8sARYgDoznuyGVuKldTyaUSrotGpzbkKXKrpKJ4Vv0rA/3ikTesgbVAukTW/IpJrnxUleOPrmh508S5Ao5Vf3tzXJ8TD2W/WPhT8L/amqqkV6x5ZHIVeSPQk+NE1yYVj67p8rmqR9f/i4oOa4F+A6UQC0VZlg2+mZDwUafTUA1c5RAzGzMP1/W6Zc3P4fybGCEL6H78NxQaC9yDTllJWe1gr9XXj2W5twflsCdYkmK+zOtb4YuMzEr7RWYpez7yecAVMCqVYasNXK3gzXsS85DpTfJMELcVZYOkjceZILGBYx4wb76TICRMXbWB2imcsIG8YMwp2O+EQ1RvlOVwe6F9Ho2Uf2tX7MgZFU0Q+G32Rtjrs1DyW6yBhCe/1NdAVSFNxbipgEsj5YZq8GFcrdtGMk6gr6jYDcuyig8fR9x3So5lIPlIEatHRz+tvUKd1Ln9yihu3zv9CIJBaWL+9r6Z4qCUd7WSZVZtA1O3GpVT15rDxasO3c2j7nvH2Sdy1jTddE/c9L6mVbeDg7lZEO3bHJSlTC6o68MOG6jLzaXQ6mVckt52DzAsMKDfoRUb/1f3cfg8V6oKo+NIvZ2oH6PPYgzyDzh/R/UF6OcxTLmGlOd7lxOfbtzD2TJdxV2sn+LfwKy15mbpGnBD0w2Yh6xaHbrKDXynBjo90tyO9BDwse4K8QBgE8Bi8InuWsbzKYDxfMYcH+Bz5jBoMofBFnMYbDNnDWCHOQx2mcNgjzkMvmDOOsCXzGEQModBxBwGT5gTADxlDoOvmMPga+Yw+IY59wG+ZQ6DmDkMEuYw2Nd0ayhzixd0F6htUBXowPQTFvewONRUGbK/44Vhf28Qs38wiKk/aro9pP7EC0P92SCm/mIQU3/VdGdI/Y0Xhvq7QUz9wyCmPtMvxnKZwV9GvkuFA8ouNp/z98T7B8IaQLYAAQAB//8AD3iclXwNYFTVmej9zv2dOzN3/u7cO0kmk/nLTJgMkziZn5CEEEIgMWAMECggIipgBKTWIrAW1ALPh11LLLXVVaumxdZ2tVWgtfV1dd+Wul23a23fLrRbt7T2Z9FurdvaPssj1/edc+8kwZ9qYXLvPfece873feec7+9853AujnvzT/xZ3s35uCaujVvAXcpdwX2Qu4Wb4Mw+/a8P7P3wtqsvG1u2qLujNR0NuQXX3NbmsC7JqWQmWy5VzI6iEcB01klXMQ1vyafpVrDT3WCn36n8fPjz5Wk+LR9y8mma5cfixjEzBng14rMeYfN0woxZ979bDmyZ+XBWqQszZlV+73YDk+HtWE0MpG30Zm6jJax/mZVD0ttoeXqxvvuXFgJl+j3HcQT76Ak+xHuwh1o45auZpEYIdoMupRLJTLnUK5rFGCn2ko5iTOR1KZnpRcj44IpFVmTRCsETjGW6EmImv2x4uD0pJztboroqnbj58VuFPV/f1b9oZGRRrLO/0pmsJ5FYBH9GptTV2wOn1tyMZcheTnrzzTe3Cm38Ci7AFbluboBbjWMk0KddvnZscFHvvHJcl4k0txVYL1ZLCAZUi1UprIMNYhZBxJekFxZApVqMCSZQKEsV7DtdKkAvMUTaxZlspVzKGh3FXjCL2ekiS9d1LZ3bB4uFXH8i08yTAxSxgVEQPP44YialC0OjS+rm+OVUZybu12Dq2bFdY/iD2xn8J26CRb2FpfPWzeWbmxMDLcLiQSd/Az+Qz3/bqAdv2D9iXdY/MtKPlOgsZYxItJ4Y/nqVIC06+6Nkopt+MGb9du3N5Kav7ZEO/p/WAgzwC0f8YW8kAk429hVgX/2RnyDPciInHRc4mNsqQtUEEzZaxx54HO58UIVLHvoyfOIhu+xpvon8knNjWRmwbLOclbPVbNWsmjLfdP8rv77/lVfu//Ur97+y8zO//vVnXnmFXTmnnQf5Cb6Rfevi8VsIJwKpQKKcCHQE+AnriTPWE3DpGXj+jPU4jJ6BS60n7O84jp+A5zkevwMKX7WcCAf5fb89c4Zmzao3wIU59clQ0OtRBR7rTwScERdIiGFspwyBRABegGf6C1NXF/rhaesY+YyF96mryWNTV7f197fx3uvPXP/BqatZ6wLjNZM4jhSsO4u8xtunduYbDZ9H4gVEvlQAKQa9UMUHDQx8oJwhYXOCjoRpFBdAomjwhg+kZBtkqjj9HR4ihzuK5Dk9ZpBg0v8JPR4kRjSyJG6c/2c2d4FfmlidWAa8Ef+aGjynxtRzAZdqThjahGbARGSTTyeR+gjRfbWHO46zaXrciC+L4w9azMA5Fb8yw+d8OhjaOY7h8wTiU2D4zOH6KD49FzWGfW6JMHwyGk7EYqWKD8TAe9iZD4wxxqCb5iHwPLKzaZ6JF5wlxSYw/gw+r3oqqYlkxfsq4uOKTOi+CQRqwgwFGGrBRg2/i+u637l//DhlJ3iBppaWphisMBwk8jZSHCchLlv5f8C+kVASdHOD3DZuJ53jH96xYbi/p5r2qgJIFKdUUu8o8qVMNhnGh1BYkg0Ku4YYxERTTyULpFyqljP0UoAsYlo0i6FUpRwoZTukcEBvDktYiJ8PHYhrNimXO8ospyOczFA6dBQpU0BmYcCy9Ws2jiWS8cWL+z+tR1wrFhtGfaZYyBnknzMDvektmVRLCbaOVAqVP+wlZC8PK1rmpYpRvwBumfeEK8It/BVKXGlrT1r/nu/LQ74/J3Z+GH6aysPypQDXy1LEXLLJK+pmwNBU3Whv+pIW75mzPsEb7fN9vHfD3JFxqLfa6i6CsXIo1GF96aKrdxiRWFc+fZIAvzUX083FW8l3LyapeBHa+9uhiHNIprQUnkFa8vhMJWuIM7l+LtTnr8YMPejXPKoiCYSTkTlUy3TCy+Dcs7U00tQZ5Un7jrTEYbMA2IWOjxg0Ag4GGTafOpV+6aWf8Qvx/rOfvRTB2x//+Ed+lR46p6W1czzh8e49F9Ihov8uEjrnjXnP6ZHf6RGYv+3x9Qs2Xnml9VnnYdH6T61fcO3Wrdaul/Wka5+i7AOgV1dSfzmcVsbPGEl1myRtc6XDZ8ZdSZPNga38ZYirxjVyeW4+nQPluZmEEVTonAY26jVCoY9ByE5B0k5W35KJyEznlnoBHjv4q/4bvvOL53bw/b/6H+/2vPPkLmIndp6Eh9vbrsj0Z0iut+WKtnZrDJPZ/kymP4upUxfkkQP4dtDOpDen357gz5JvsfmcQmzKXC83SvttWf/8zlJba6bJ8Ltlgv2GUzopxUglhHc6yStmtYLcy4d8S0YeVqlWMs21LJguM/2gy5QRZKnwJigYT+W68qSlN3Md/gmFSvuv5/H++ijfmago7vyaYa+rHlbnelpIvrNg3eOU+aNz/8qlqn7+d7p66ejBb37nmwdHvxfLsaJgOA+v/ZtWL3n8/8bnE63LIoXWRF9zrchHnYdLnftPPrE3EPjIkS1fPzQycujrNTnzBNMPV6G86KdypnmW+mV2oPBADmbOUtlq7xrhgnd4SZRTM1qdybS6cMLm3QZ/1tGwytbPy9MamJ2c0cHKORz1F2RDY2Me8M290yxu27aY+S4JLHpBOhfbFuOcMfwgjmGVS2KPj9AxvKyvmK7ziRwdwx04C8spnIYy6M6kRBQCNh7hAEJP5WGITs4UZeUpJACPYyHMBFQI0x3ZlNxB76GOEPmbq1okQgiAYP27dEzU5GOK4t2mKtsUFX/wA+up52VRUiR1/yKY/7ygSIro/usbJ3P1h+pzD2VvXfdRsuOmehdxq6o0tUSSj4nicVeY5xRVVaY4dXh/EbKqJALpu7Vo/VBQUbEg/fCHnp7R0Z4e+JA1Qfv1QpyLqPUjzgOl9hrOzTM4i++K84V48TUayFJ2mgo1IrwH0kSYhZ7bJoDAg0MCD6NAh420S77lbTh/ort7dLS7G26wDpP9+zsQf1HEpmwS/Mgn4WM/6tGoxz7KxnKBK6Ee3d7WahLKogyUX1SGZbKodZg4QwleMtmCUKlShZYpH8VmHLJ8AAsa/GRjLteYj778Yjwj6G7BE4npgfUb64R6VRMUZSCNM74ZPL8HaMzB0Isv/AB+g7MLTmHqH4JqqVcPpaNJIxCPahHvULK/0BcrNW9rLp3OR6d+RPRHzLtNW+f/FuphBW4hymLlq4v7iyqFlc4ZXTYRYuwRWeNTqPKhxMVnFKqZ0gLaacg/Ua0oZ6n23ASJKurQdDBSyypBFWoe1Z59zTtVPebeoYiZZFfdYGNnLqYqW9x+r6F8KL6PKkHefVe6jaj7Sji90R2NCMqV+Nb6g3Xf+F1boQuVpo39N7qjhnuHLESCGrxuebSIrig7PaGY+5YF6/SYDkevVGO6euWV2JB65VEDSsPj43TsSdM2py0fG7hW1DhQ16i2tzSZfls2Ul0Ddcws/jWjogCzNEEzYduAWSddddIzmmLRIN2wxbr3FOmZOgmbT5+GmKGd38h0Hv4hdnvXVN/QqcHTg1NnD7M3h31oogDTEm0lywA/u9FXBvLHN/+E/DGCMkNH/hiQqR5uyBCgDJ7OmXIA5w0CxPtcAes3hiz71AnV+k0wFCHPmeQx02/9xrrKVHn3hOoDH4T8c+k4ncI61+LcbGHjtJj3CqzvNYJdXUWEK4ZpOCoXtftQGGXRiqLaALaMZlM1wPp57cANDz362R3D/LrlkR5/UIlUevKjW/ZsGsvwPZWIkuoxl6+z7kPZA3R8bvjAAzsHBnY+8IEtx3qxrNkTmLNnUdfWZYXCsq1dA7tywa52JTj/BAxZ99LxD1vwyvEM/y9iXy7nruQ+hPbC9s2Xr6pKPKMDj9KQdgrVaBHIMnIHVOormdq9aj+U0GBdwKzDXmKGWf85n0qmgalKNVTJGqJkYM9T5SeDPU+1o+k0LSnznzQ896p9zVNTraM+zYuzXwAh6I2IRBBk1WPwIBCietV6XiDIXF2iJLlF1JHDMnxxTt5zj95Sshp8HlFbRHh/THhEgPDUU0RSYKWiEQ9RZOsxWSNdvCLDSpx5bp6+UTwCGYy3WHK6HXryzUmfVxY1QZLqwz1hyXC7vHqvLkawfa/WHxZ0l0d2B1RdDVKWB2JfiyX1ZyDgywY1kvGGlICsgkdKs+tx59kDquLw67PMdorgjOmk/HpuvKFO98qUX4to+1FWlUJuxciD4tXAiVEJdWTFQG1u0EvAnjDIx6gKGYbH4PWXURaeOqzK1m7WGNwuqxNf+AJ1q0y9jGPK+j4TteQKLOZRfuE3LoUtMfPsZHoGQOsTX3jVup0VWxsPk1fZ05MyFi5FOPnNczhGXmF61TC3htvCfZi7lbuN6lUHPnrr7uvGN12++tLOBoHqw8iMNSiQiikaTP/NNuNEMmSN8bdspkqHTUfRxF7PZrL0FeqKmQp7FwPTkJug2daNZRGHSSaVlHGUGGiw9AJLaUBTIbOMrDIr0yZSTQBZMSw3ESSIWMX2ZBJhdlNQqD8ODX4xMCiHZOuWXoFXiFBpGx5d1t4hC5XC8PJCRlQGBpCHFpYPFyoCb9S1XTI6XOjkcbT0wkfxs8GA6J+6tj46t1TNhfHW0Tmnbm603pjT2YG3cK56dyWo5H0guAD2VODeQWvlWlFABuiDlwatn1wNEmwwogya5E/cLUpaEH7YTKL1raONbfm2xTm8BRWxZY4oB9oaR3OJHiPf1jiSb2jgm38oCmlX1nNJZDia0CNDsYR1Y3TY1BP0ArsTMkqueo1gw/uDsDD9Wl9Z5GURfMdSv7iEEOYmcPiQm/PA/4L/ywWfgZ/AN9HEuYeycGTetLtiwDR2nL1U9S32Qpl2kZnpJQtAypR1uZSRygWB2jHIrzJJWlquZDNyBY2+AsH+k3S0dVFnlu0pTUUbPmDnYSH6V8wgLVN0nmeNKrN9jA6jlC2yApJJC2PtaEhWMimsmKbR6MaxkJSSkiHjADHaAJ9x9JTMrCQXsYoy6usmfi0bMh1BOErkGNGrhozf4ZfZjGR00IqaEKKq1MSjRiDRCstYCoHIoo3bgcMMLQA04+ViTGjiqXOC8uVqks0rHI2VMtaCF4SulEEzuILoIl66FE5VcPhV8L2MI5KnzJumsxQ56hPItIFRwZoQYqMaI0ieStUwqWckU86WqXRnNmC2iCWSCE0vdBjsVjUqyErRFEnRNE6ASrGMJOEr1QwKI1ov/fkAUQsjxfBZolTPVDKU9hUpjF1UgCqbSZhj6pIBj+189oYbnj37nR3STd+EICg88lU+EA7h3Bc8PPaaIKiorIGCQ1UQBCJIIBHFJQqiyIPiATEqo9qn4OggsosXkCcT/ArZn4hSTddCqN8CASK6CIRc+LUoqbwiyCJPJBfWJboEkeeJKIAmu32Cn8dKBYWCoWBrPPJyISjyHg9gIU9dA88rYkjk3YLXjQ1JgiK4hOVFQSQSQhNREQZRQCAEYOqhKstBQXbhxBaIhmmC84EQH1quaDSLIKgqYA2iRya8wrtkQ5JERfELOtaDlfMaL4AqKgGVUM0W5QyohPfg5AeC8PFEdmM7RNF51OoJxRuVUrzjOyHCu3iEgPcSjdJDwCwJgSAUK1kRZQ9SkhBEn0Ei4zVIxZfoIS4UYgpSC0urLq/r2huWgwe8WEMYsBKeAuJBBERQAVtA8FXsI0LFjYdiKLh9QFyY59558pWTO9nF+g9QiITdp/CiGzxYCFk64oy0BSJ5RIlXAXsYKJZIZqDkkgjSHjmVLEiKKguiJHroyMBMjwvpIiISfIDwmizhe95FZJWXQBNUrFFExFRBlmVwiYqsIJ14Sk4cESrPa0TEhkRBJiiJfEhEgshrWICXeRxqAHMvxbGGfSj5VOxfHGaaS3cTkOoJmAgPL+o870dCC4qoCOA2NZEiJHgUTdBAdeuyAiKSHTsiyKuCgGoA4VVKZA/xu0KIlICQqCgoaH8iyf2iTyQ4Gt1IcYH2nObSRBfg0CS0BwUeJ4pIfCrtV6QAjj8T9QvsAR9RVbTCeMHtEukAwU7AknTQ4sDCzxFDTOMQAuxlYnnDq7B/sXEf0PmAY4MgOWilBHUbTSK0FBtZSBMxqgRcmstDBL+MOuibb/5JaOepJi0d15iNbkt8qitmqEaMtgu9hHU5BkLb3nVTk9fcBaN98MiuNYeT2Ur3mDm04Xtr98KR8eGbYj7Xrkc2jaTGunOpwE7qA3jTenMrvIH1x7F+XXB0XCmFfKsacgRzqBeYZajLPJXG8KoqWT+Q/YpLJTteIqKK/X890ZQn3RrZ+B8iUtNwe6du0oD3K/CtTpAVL/yLompIGMuqEE6c9jvMrEv5+jxL6TpUqiHk5sW5rdW3rAO9LR2w0+XAO6dDb0lPMGuUXU7NfpS3yyq7nH7HAoXag9p3nD7Ry/+0nqaP0I/X56fO0mcSwSsY55+jCb6CV67mjyc98BtOQ9qqjLY1e7tmyajn3FH3OTcqRq+jGfJPGj7jL0rND9r3+H03/JP9PbH7HhXAAtS8yN26z/KgRedhvmH1b6kpE3NTv6/baR+uIXs5L37vZusIAd1unola2KzHXaxwNELWoJVnuB1wnG8Xkn2sbfcM7JSivYBtw0KVAYrlVdigOUjYsNi+pf/kv0bmMNuJwe6iKp/TtOmyEdD5v7WuQtCtq9zu9e6YCi3Q4o561rthwrra7YbP4Lv1brf1Q3yNBaKs3r8nO/lFrF5frV6KUtVVqxzrJVuxSlqRG1qsHzqVP6DCtdaVqno5IglzaEvuy1XadtRZO/kaWTJTL2qLyex05U69/N/SmqwfYp127Q/Quh5wb1uPA2COdVpVnZbsah1476nBS21IFzEYJbNOtZQM5OPTKLopLbACijj5ErZ0Gh8RTHhQtSu+XI3VfHcHyH9yMay33j1rbAXs1YZyQL4AdP5AOBfuDh9taRqM5Y7qPXouHIZteg9ewlCKGpg8au1uTEMmCrcfDbPCmBW2PmU4vsJDfJn8xm7PHg8y1AZTwnEZJrLTXcCXdfy0K5wzjM/RetONcPvnDGymy8BmoSumW3fpCERP+HO5GIIER8MMJutT+nR7a7G9RmwvxPBjKyzm24nnYwtHa9ON1m4HblozbMeWKFJwOyK1wUG61cmgmFFQjrbYbX2PP4D8iOIWmsGtNlqbqG+MLuaEA1XWJNKS4WZ9Khyeg/ejiEFj7ii2nAvDfooZ0na73m3MsdvPQT7qADftd12H7S3C9vIu2p6Mil3Nq0pN6qxM1bSai7UJqlmbF9f4nw81wWyGPcph5pDIku8+++yof67uP2e61MByTNBlMLoYlA+MYsqtybJhaOfMEE0uD4Qwz0BmL2tuksb8YChyTjPMMP10eSBsYtFIKMi+5F00a66f5vjn0gwXQk+m8Yhw7Zzy1bkJXSH2OKSavhMmQJmFTTWgCwDUm+UMGurEYjECD4vfGFV1H1u3irpHvyFpUp8IJ5A5Oc/iU8tZvgGiIn5juRpjC1yU12ABaYEEP56V0CSnBOesr3+DX8HznMlgzDeFGIw4ljJvAYWFGziwU8JT36AxDftjCNnyb4h+cYEkfWMUeR0SBB6eedRj6nIKLALThWniWv6UKPZheSyBXBKulSX7SZuVa48F2/YfwLHQEZjhs/MhRd16MwKjG8qp8Gz23chW2WpDlEEdpr54NkLPug+7Y/rpIeTpE8g4JhDModMoGw67Z2Ugt5mVQbn4+yk3u+ZpOcefJYFZOkQNh8RbIE5cCN/USZ3CRkHUSc+FUFzQcq01Ri/4GNKLthX1gOM3DdDAhFmkoh4TZy3NgNsNbXCQDhBGCRxJtDrisisnD2LvUThqmDlw4I/ZyW9i/0zyXrZmtJhTn5zflsvWK7w9hrIpJ36lOrP8Mb0GQjWz2rI3MDLQxVHSK6DFSf28KP3lfbaTZR9zt+xTFep3wcTQXd/9tHD4X++AZK5Hf2bTR0aPjPeRnu2Hj95xfSe/+Jkw3GV/RV069lf7qOqxT6275gj59HP3SHdQR174mcW9W+/87OEdXUL/lk9f8pFNz4Q5B6fH0fb3cy4uiHipT8ZNj4qmCuJUygKN0UBFPZNCo17Wm+kaHk9hJi+2W5ctW9d7/Whx6gfw8NL1K+8YBfIi80Nev4T073zg8ft39cHGdcPW+mJx9IZr4eHi6J2jl1225qEbMHvX/Sfu3dMrDW//PHcBXX3IPS5CGOY0GKj61eg6y937njS0nmbUg/73SzdGsPcmFY2XeJz08h7Oz2W5yxDGNb3xsIfRiXliSxk6/Sp06CGQJKkRWW8ihtlRYb6sqi7jG6o2O39SSiNomuOHVHNnfwXCFgr5GIH7PB6N9DTSfoxW8msyvcuWLevNQCYQGJJvUQYlQ8oMzqtLxvl6TatT0nXuQrHdVZ8GuU7T6kkyXtdVHB0fHx+pkACtoy6q+tVgrrFloBCJFAZa5uWDoVXLl6+S6sX8vA8saMj3NvqadJ8v3Oj3euujdVESN6P1Xq+/Mezz6U2+aF8uuuAD1Y29adLStWnGZ3QF8nudS3AFpEdrc1PEX+uzGfW8NgNoqAdPQ4OqNT8SUgpeV5Vj9mCV04p6dsXHPn/HKBk79KXbVn+k5ot4/ambSfIc1cyxxEks/N2VHxsjo4c/exhLfmzljY5tu/Mk851+n58kv+ZCaEks466jvtPx5YOlXCTA1qgDjNFPR6TRBZMQyiaJRTP18nR5hZpSJvMxTmdUaQ+WmJ+KmVgXZFKHdy9ds88wD2WtABMRTx1hCwhHnkKGdro9K7qQuXgMv19QInJAFXSfS8y2T2y8RJFQmIXj7jmFwhx3PKz7ZGVkw52Hd8kylcl1dfriETI8qNcJQd7Q/bK86zA5PPUQ5VpPGdopbOMpVbf+d27Yx+t+j9/jiaajHklTPPg17xvOrToS5w1kmX5XbN34upjLjzzU4BN3rr71h0XM0L0eTeu450v3dGgaL/FeHTM7TjnyEi8HyBOMnspXKRnJX0jG90+IvwSnmj3zGINNOh6o2TNvhettzb+9FTsW6gle5VdyVAtbimN5aHHvHBlwLIdkOox7gapjwNYOk1kZmWKlSpUZtrbNVrU1oPE+1DQuZ7KzdG0qirNUYzSLxt2dEerh3fXc+HBTrFLtueYI6PEgHP2rwz6DBAPWfdQZ7Z9YMv+w6BcKkkQeRxWiIP7IenjrxfPWw6J5Xb2DbMFuMAZtzw0Oj4O7Ej0y7rzb+zXvsEFNMGNYzhyW8EO/QJ5g98XW56FxeCtdGmVro0+QA4hrluvAPr0oX686OhBFJAY0XqFA3ZNlNPoZkoi2Uaww7c3IBnS6YooIxYAcOHrTBGvcuo/dJv7q86izGYB8l+B9YvzTW4CuIv7TbOC8X9vrQDx+xAH+n6yfD4+T7UMUSLLF1tP+hPr+SZQGfQhjT1S318VkRxeq9TBVytC6qNn7Vaos94JJuyeAEzaVLGWo89V5aZBPua3vo1B3YqJQskOb++SGRcdQDFAvISjKseYSVNInJJWQ2ptFG6gWYr2AqsKkPWgm6QDCF1+19izaoCpul+SVFfwMDuHXAlEE580GrobLNvItpDfDJa/JLKbTYCEkqRmvBCrZ9BVCLckBHQVHEeXALJTtqFgHZdhMatAh/Ir6FvCJRIhEkY0aqGEirjgLENcCCYqaS4ANi+DQBZBbe2zIIf/OmNbiCCZx3PA441LcIOWtpWyT6ZMJXZcyE4EEXZLCfpBwrhjUvd38lnR1Oq7QEQxmh6242k9MSRrkg+dfPY1CmUoFvMCjqpKiz3g5nY+ef5UuSQ6VmtPNpVOVdArBRmPrUtKzbZIWuvCSnyrT0uSfG3MVtlZfcW45DjWNGXxmYrcauCbErYOrct3ME/VhLtUX37hy6UBvT1dnpdTWkozHovWR2bFdPsQdVW/6l511h7fc+TIbkDT+wEA7pwKzyledPEqnasf7pNPk5LePHft27Qr3HT9+6tgxeHRy8tTx4ydrS4v0eh97dWpyMvh+KDk5OZk+duxYenLq5OQ5ekkfg/ZJVtkkWwDMYN7k5LZZr/4cmRlv3cU/hHqCgpoC1ROa6oJuiepN1VrYZPO0XyUGzagnQZZqUtWiwez7sGmvBZ1ygiRhq3UAjfVutKr3GmNwj6dh/6WUlcSX1Llcn9tOcksTPrUWGHnOOqDr89H4hr3Vsf8wmpdugCMv3El0vxSUN+zrIXVzdZVzMf5P+Q0/PQqoJ3IRjnKzT188sLCvt1rINEbrImFdFYBzUZ9kqtw8E/tEJ+cCoIEx+J7eeWaLO+YA9pttm8+Ey9OgmhCWO3kSbqczlEYZaGet2L59/Fpr8z4ajeBnMQl+5gx0YhI0WLhvnxXrGxwccj6hr08NDkJsaGjq5OAgOVD7jF6tl2rf0biGQbuYHZdxg9DGX4x9EkRsP8I9yf2exmX89B8evu3qjrqwHzuIxnnT2DfK+0XaUyZ94lk4HPaZbMctyrSPsMdoDIREl5KYnzXLZCDVhqjum6ExjTaBKlVUouhLuqhWQcWKcT4UkiYKaxO1YlYlXVcD6shgujKLr8DakFvaVWaY56PKPN5YJZ0RVTpGWAUUoMDsbzNZ9u27flopXvAtvO7EjD+W78wDDZlw7j9UxNWSJ9QkCN5+tyT2hQ1JFrzjkuoNmf2CVxoVxLTilVeJChaU3bSgZ0CVpL5QRJJ5WhC8IaNf9IrLhUhA8UpYEjavlNQoGQAx3Oj2uOU8DwN8oyqvXCmrjXzJD0JOCQSipkAWkagLXzulcworLbytsEf1zJSGDXa0+s8b86SlCacoWYuX7lzuX65BYLSQ2dAseYRAv1B0Sz0NXkVaJXmKgrDUJ4pK3hMxvKDIby2pKj31rKT7IrtkLOxtCHmIYn1vxKX4tAUaIS0NzQDuErQQgmmf4hpxufxemhNzlVDStpiQpVlev4t0YJ79VZZmeUpZ+yMXfqTMfISVTn+kTPuaVBy/4yhTl8cluk/CDr/EQdp84djMvuPYtMehPTjtgNv3GJyMGbGxSbpX7FlBVu9cDVFFHlfdoRZJ9I16ZfmSunqXLPj3Kh5/g3mp5JeWGIKotKg+ZQuKWVUcVzSz2S6rXBKpdyl8YC9yUF/UGBV98pAuCN2aawtyVqfn9tBcfyzcUERNMDwKYo9XWRb1q/I1Lk+PKPXFRA27zBdt8IFHZmXr6uNzZY+sj9pFfYrCioqLolj0ElaQs9eR+CDy5FHUneOSs47ENPgC0DV2aspQwjBFntk/HZQCaGfHCA3kRdMW6VBGQ4gRqEpjk1B3pLTC/3zQI7nnlTr80bTSXWkduiffEFIVRZB5aGyKau0+RVB1Sddl4lfimRjwAmi5HcsgKLolWY3F4h7ZHyELQ54sTx7wtWvReFRQ+bDekL9nqLUSNf3BuOYrlTo9EtrfLWpLzEcifsWdrE8qouLmDbhkR85DRB5iLTFQ/KTZLYVUVGAUJvNpvFWIq0c5v467gtvB/RV3KxfuC+77yK4P7rjq8stGqokGZoLhgIpBuBZS40TTmKgk06X1UIAx8kQA2IKbach6yuE2NsMqOTEsyFfoUEJdmo4mttxOI+lxfGkQkswKI29yPmRLWR4fKPHpOmMmhUZGle/wGzFzKmhvbXjdqPiGfyDKX5GePUujdVbCo8HGRHxFwKUA8OmGZcmPbFxVVGS04ohYKSgiUjujexVFCni8siqijig3Wf8da2tsOe2SKdVRx5WXLFsJkqs16ov7YaPWl2tQCLnZX4pM3cxa5ffizfBnfuCXvyKff5z0xMyXz38elmoBocHrBxI2gt7EEbpIKmlmZz3yNGhbsGxJYXXUUDz1PBgD2cus//YuNYrw32ZR0InBU83ao1gfj/lEpXl+e2+TrPlhJlZ1pn+WUx0zm7b7Q3h//REK0xBVJHm5g9rp+IwKVriDRj/QZcwsn+LtZ/yqo/weBO7Orl8zJABdXydkaO1l2S9gnzjJ5QuWE2elvFp8HxR7vduaAJ9bc4ka6IL13/Ch7u4/uDWPB3VyaLde8CqCx6O5/9D9LnSY3/wX0aEapoplL5E7dBpYkqLJbNWmhQbTBMCkKb8HFR75TK6Lxx5GA0EgPa2fy2zbnrl/zjy0FpAUvNSd+2xm63XvTYED3d3rBJUOFEHg13V33/NAd/danNcgSvJamnT2pszg3YEa2EqqlwwPdJUKGRt/6X2OA9tf2OjsTCuLM89UFel4a/o9aDBBo+Wo8mztRpvkvtrT7Leq8j5Gwc8dP5aqrJ2xcSZmHhkNnmC82V4P70YaXENpcMWyvp7KRfaauGQ7O2avaZvvkQ4FEgE9BkiTXoAOFH8pSRaZo84xNrKBVM1lRxlXB2XsdD0m9o5wHnawQANjyPIoCoEXiKJYt59rEMQnJAF+rSqVUrPVjlZFmZZ7NOvKG8eMvJJ9DOn3pPUMo91CRrt3frY2kcDUbz26qupk80JkXuJKbHHqt4WB/gIJMSAuD0chpl+u1tZ2trI9HSY3H3WCrqSbozoB81sjKsh3UcSbzJ9dABrLlkpSTmsr5JlKEuU/DUtdQNWBUi/EqXPyhmd3wujF7T5v/arFkaZsEtNkzz/Arbf96lA2t+OTDWleQQVFILxH8Oqy7pd9azbBbb8C/69uI3tHDi7rvWFOtFKcm+oJ8+LIwXsOjlgvXXl0o3BlRhY9LiCq6BM1Q4lGQ7nikTHM2XiUrWlcy/DIoGxO2mu508BKDNbMhbDS7aDAn50GSqVRNBfCNHrwm5sO/eo22GA3rwjgUYEoAj8bgIsPbuxECGxaPs5gaOaWIi0vriTtmPTZRCujiVZeQCoyMpmqTbOi7RhlekATz1SvjBO9yVxmvVTK0Q2rW09say8uWRVuIJKHBkrxPKB+ogmLR2DriVMntp4aHRA9SoNLEAUeyaQ0hFctKbbffX08sO5o/+Jl4B0ag4cvObjMdZEp0n0PggC8hJXExEjQ37JzEZJ+2cEXF+3KaoaacPOiRJFVQRDNi1zDfLGtdNtway67h3PsUxvXMM61jWifrr84Zbg4fvbYqY0cKCGixRihOuWfoQO8FwV0CW5f9enV0FOuhEK+ulhrbtVda9bctWrr18bJ9mPb3502pPJedBkle7s2zZu7OhYvuNWgpHRtun5L59Cyg/fvH4E/Q66pnX+eVP9zl0OrrfxJfiXnQf7cj7SqJHSvSmPAxRJz/iapd6PYnMgE7CWQsF+kLIYukNA1sXKv4EQq9YIdo2TqMR6mXIl2CHa1uKw7yKlP1ZdWbF9RqiefzzWeQyX4XGMuWmhPB8nBa8V4Pi5u3Q9GvJTbqLQnXK45XfDFR2BOtKczmezsiVqnH2nMoercnWuMFMc23Hbp2BG/6kadNRl2q/4jYyOH1q9ur/EKGw8ad98SUiXyVhz+ErjhH98nrO8HOsdnCO2ODFC+iiyf+j9r2/Fr2+dDPPMWZrJ8xtkeP+MTCPgco98Huu+4Zty7j7kB9lFXAum1VjKXAjzGtjZwAvUJ85Nsn4YH5wHb29ceC/mxWdu3V6b/WdMJuGDPbmp6p2vN0dERsCUvi82mnqpTdM8IvL7WiFv3kQO1Ha4eaV/cmDprxNjCZV9rOh6G3WbFt8oXgdTcXnni1Km4sdbabW/TFfyBs2gWraUbutZ6pLP5PoB2Ix7RVvkrxkQv4iAyP+svEAe6r3Ue18sN0TiyRX09XdGQRyGciASsZhGiMA2MlQzkoaHwjJ8NlQiTLRpnM6mE44FNFCvzWcCuwZuQKoOctdf/dXitb1VfGcIu10lXEP/SGxZZ7dQTCy+kYi5eblBUr4cJv0oaXmguiWklUp20bp8kH+yY7PDn/av8f7dw1cKmChypVWE9vdWuoH8DaEJIiiJzdgRoJb1ExhoUmHjIuv0hKJSwCv+YPz+9Z6+Ny6OsaIlMx6qwFWgNxbupo2GC1q69slitJGr+Y/6s2/o5jfTaV129urczqdMI14AkKBI/GFsHh/fpcRc0uuE3PtV6yY1DSQrG2vvWdTZlBGQqHlXUdP7Byz+49GcTzEP8knv2HsIC14rwpGRmV/oIMkp6NADVyUsFkS01TIfs0D2BcbQYzw5KMjKfoIIsj9eTnb2rV1cpDAikG+GggMLhdbGfXf6gN4DWo0cRdT7T1Lmurz0WlBAGN+opMRUvum/iZ0unz1I4y5c5nevCOdQR9TpziMXH2M2jCihLuimiRUs3CNDwxgo1Ei4oZGIp6hjazDb12AAF8v/hdvMbg/VRxSO4eRQIkZXpXZeFFYnRC6Hxm+FfXbvhj1m65ceBLRAysz9xR92/j48tWeI3kMn6zqxvyct3zC6jusxP+rZfyXjtn1Au7eMCXBI1YfXJ9mwDEpPKpUyWrh/TEyGqVNrG6cZTOSmFUb+rsAXIiogICPE0dWdU8iAggSdX3Zo88sKR5K2rlv4UhJ9a3/C7l2zyG/6BdrcffuQesd6w/t16Y8TtHgEFMqCMuKHr4MKuRdSzuqhr4cEbDh2Ci7HopsUejQTV9gH/d0Ohj95770dDGf3We8kDN+s2zf+Ov4T5ehuR5qZXpn6ZEPPzkkotjsp2BlINEwfiOWdHLFmlW68a3br1oXAs1/hy41AYJnSyJpYjmb601G79KBa2Xg3jy/BQ49nGHGDyQ2FHJv2dkHbaLCGd5iZpu/x7tGvSl5R5QqVEs1LvA5zTCILRqNf7QQrT5oca97GM8HvB2che+gP4XTfNitnQ0/nyJ7YWl6KxZmxPma2510wbtp0W+agTxUedr2aYXMIsDLZlJ24E6Gqb7ktrBvVawsMx03qanWgA/UYcjl9zF7nzWsb7qeQ5breJvN6Dup10PG06sXSOXEGCMZ59AQwJJvb4SUPDRlbsWQHl2e3DbupQDzhu5u4xMjp/+4UwbKexFdNyjdDYOpnJtYhHoDp6CBug/mXxrYg7O4aPQyND7YULcaam2sPbWYOTFzS35a67tmyPOe29wX+SfJvzc0VsL1Wv1davsyk0fWn3B1xgVJkmR8M7U9SGrNgLt07gAtt7zwcN7dQEXRGDhfh/b1KUiSxaN1s346diSiAifCLYHjrEwoNvEgm0WH/wGXDqlO5HmaJYb0B6jgg89FtPY9k5ol+AEZ/vhuuotfPzLaJWk/lbWNxhga61p4xpmZ+YXu+cdZiOSbfm8rNUAqYCbNb91s9ZV6RS7EZhTvmMWcsFmwZZBr2esm+GZj1jkBu3scdttk7AaEfmoV7sY/yzHHXzDjzZ2TqIrvFsf+I0GCxWIik7brAC28YVI3C7ptzm0jTXbYr2uD+SqQ+bMZrwDOcS0dKSiN4iq7J8mUKEtV+au26o8CksjDYKu8LiWCkZD6redq/qB91dX1gR8iXb036t6BKWSH7lrmTXas5Z27bjiBQugTDXuSXW3382ZujAdJRQvusdo4T2v2cUFeVBP8AKX8F221n8wMJqQhWoDTEfbeiqYUopvkzJEKYLoSyGk3JwFI3YnbJUts/SyKSaK2/LTSVxmMqZX0YjTYsGL/3lLxfuXF1c0bNe97xCd5G84g2ihbCqb9dYcQw/HVjxloz6unjyMXVsfgaee6w4tquva6zk97juFF08CtoJl8dXAQDMWNA9dqi54sMsSREkQu5UPL4yqKtsmf4o/yj5KdrVzjk3OM78VDxWqUnjR5Ykd8jZjl4g+pdeffVLh3csGbvq5hMnzp0gh7/+9b3kNfLT16xHX1sz3HMCuBNf3vvd737+lZp8FnbjeBdtHTeAFg3q4GF6qg0dT23AVgXlLJuM4MS3Crv/3+2D/FldHbAelDRp/9ltsITegV/kUry/x0E0xK87/yr5+u88qouWkfa/vB2L2CUM1bZhhA+yWA+TW4B9VWo0Qwqz91AoOEp/1iyWZMpwqTGACh/KiowduHihLWAyW4Bu0+U3J/9HPopGwAo47HLF24NdZI0g/b9f41RvE6RxN7ULdNi/VYgVYiAs3tr4CmUCu//xemYSdF0ZBNtG4Pfh+/O7RSKWJb+wNhh6u6mgDpWew3zHT8hw8SAuWXtv/+JCJhZAo0xwDJqyY9C4qLOARaVNm2TZagL/jJD5PhAkAwwptNH+DV42twx3rC7WA/mCg/JK+Pz6VG/yq23vhfK0KQRBeOSiPqBW2+lzNg2Grr27+o/kbyrvkwCz42VpXLiusv0qNGiX2t1yqlylUZ908YYq9vTO/59w+MzKtZedH39u83OL6y9bO3Ym3NNCjDMHzhhdKPJ7wmfG1l5Wvxhzr7HWrV15JpzrMn66/0zYti++hfrYE5wLbd9eboD7ALUvVi5d1F9JhjySbV8gu6M6mfE2hayqh6Wajkkj/aC20mRS/kjXUGQWQxWiFKc7vlNscSrLtuhBpbW9E1B12wBbZ6ltz3W/0h0VVXnAVTd6W9HtXn3+7mKxSVR5zZ12gyu85uLPCOfcRnbsxb1zdn9n8cLLU+Wr4u5rL01tnU81ujvhmgv0uRsFuNZad23RlZVUOZfec0kgFzxwj1pxSZIugWhNjdwahbr6y0Oh9NyNW4fVg9du6luQ3lQKId+13jzJV8gb7GwY5auGz0X1vgUQaK5mgtVK1aQYgSgbBHHLMjeI/NRO67/W7BR2bbpD2DS0RoDPgk6TG+8kV2Fy9Q137LRe9K++CUb3bPJv8Q+tOQfnMGk9vucqfZwm1+9k/X8SedMbjDcFHd5kUm5UALpyjbzXpEqevwL3PPKqcNPXv36ngIzpxM3jI0t2HH7ktdfIG2c///zzex89YZ3oWbbmNRh7jXPs4T8JbUz2NXE51B3oHuzW5ng0JFF7uGqbjCwelXpPUaFgW7DLAXtLNnQ4UrtaFoulVkjqHWebS6VmcgWz5qYmPBK5gp1oMSmr5M21pebzB9IVwCnmWutyHSo1w+20uLUbi780a682eKZerzBFp1IJBmtxa+vYXvFebgfysk1L54YknsVW0P22aKXTwMVUqZLFG859em4NsaOMaJA0GgbIVMulLMpseiRbhm4tnY5QlZ1jXTIzfmS6lNVLmEinC/Q4cifssC5yIB89WYFkVdN00xvzurWIanh0NRiUDS3qiZJdFy/aRvy62qi6gpHBBjEMiY0jQ5XxxQs97JSNv9HnxaNejxExom3DLQ1Xda2ePqoLRlGPjt8Qr5bA1z8c8WYCmj/uCqkesO4jkqRIZM7lPr8r1xKMZr1pBYrh4pyg3prxeDpbR9bVm2auETbHct6LczGtf5kRTo8s7Ogcm/ZnrWW2wwJ2psHVF5frGP1Cs+iXYl67SomdWkeJgfMYhbNNQtFeFi0yCuNEL3dQBckI277SAs/8fzNRXo5rvRGmI4GnCRgJKh5oVHU/qVw0ePEuv1eeE1SVYNBl4D+/zse8pq5plTSU4GQ0PzjWfVVDdlkhaoQMSVMbEvP0v6F0nPQsHNratWBkYwLCYgNZUyOi9XyopCa92WiwJefy+9oKcySReAQC1r2qHoz7Y5DxRob7fZUKUjrfMG81crL+S9LhYKW94I22XuzNxWBzY86oi8C6pXxrp9edadWDc9ia6mH+pHPWW/30aUpDdE11ycKezo72XCbRGGFnpSlsodk+7Q+lEI0zjDFfvPPAsqYf6A4MDdgZhzDrK8pjaV6GhjJ05UF3zkeydjonJ5H7aU5Py9R/loZL+CMfd4w66zO963rxBy3D1wzD0PjwkB0P8YnGHCsBW2OsAilpfcd5RbzNtIqS9e1aFlwzl9bR+1AJqyh3DNuxqG+e4H28wlXoGX3O3jzbgWDvFGMOj6RELUwqDNDizKSSbD+8vSPCDhtGI8u3ZuHSTmtkwd7H+2CFmPRL1pfzO1dADp5IFdIFSFvf1EJ+Q/ullPaJv0z1zb0oCYurlyxcU4VjfV/Zu8D6suhPirCydezGVutS+kkKBjQj6fuFhO9/mbyo0IdVVDg7/o3yuL1MD0qxlaZBbiV3BbeN280d4Ca4B7nPccdp/NtXvjD50P1H7rjt1pt27hi/av3q0eGB3s5iPhOv1zWF+Nj+TJwVqPzTAT7rOTvrGdlFKkGf6Qk771LGfB/vzQvrfK8yZZqma18wK6aOMu5TrrILf0OufS78Ddkp0uOyYi4XvOSy7nNVXPhzMk4pNKUMOin7dtouYr1k3ydqN6yxFx8Gz1/Bn801nr+CTkt+MtbyLPvqNvtqf/qjt726523P9hXC7JXzO8kKuayVtm/V8rCDWl6P5XK1NY0/8evISWcNUX2yNd0Q8tCzHS+wJxO2AVnbX2E66dnH7/Brdf/539pn5gRYXNm7pmbZlQb4h5iHmV1Bq+VgwlnnxwvdO6BycbQuV1D5urS7I1HvZvLVPkkUqOuymqSS3EfFEOpLxKBhWvgyWwA5qfFMva1SBjHzPm0HomPxStpjvyfd7lFYkh+CFXdAbmhoiWGoYyDl9+/fP1ccOyxJy/avatu4pDNOXGPSxT849YNhCd/Km069yf3rZllyYdlxiEMekteIYyvcwQiJ+t0r7o5Go5o2pspSazspzZFkdewesasTIsl0BN+KwyvIyDIR394trllD1q8WadHxG8iOrbQo05me4CtIgyDbi5YI++hetGYWgoNKJF16ihF6cB4VJPQ0ICp32QEpOjt1tWLGgPx9rGnLo1ug6/rD0LXhtqHROx8u/+veDzx0/RDp23HvWF0o2F5EpFf0zzcDivARcdOXN29bn3h698UHN/SQges+dIieArTq/huW8FAItO7sW/mxMZRAAcWg+zsofJSvuzk/Z9DzQQN++3xQFw1cZjs4OkIJqrMmAnQrx2PQ3v3AB2589nphz9N/NQ5f6Z+/3qK7M+BK64X5/WAfQLByzQPdsAceu+HZt9iAKIO/qsqzbUCsNgS2vbfu8PmN52ChY9t145Dvh4XWM5zj97froHG8XnaWKerloaBPc7tEAaheDoFUgP3ZFeNTM01tnoDNh8lz2AD55wma2mC9hEMpNnWS9EztY23h1FoJj52a2kcOTPuUP8xTjhlDeKN1zJ/UbNjKHlD3TC9dYo8B3X7ngwRfToX5saZM99S+7pY41KVZiD/EWAB8+t674eOfG8wVl8DQRfDUGVsRONP8GsDvf187P+vv2TmqPKdzUS6NsrVEYwFK7fmWdDwa8Svs/Cy6IbR5egOus+2g2fRBGyyAJrDvYF54J/cc7TkKZXWqQ42pH1RV8jzed6hTqAEEAtVq4F+vuy6ZuO66BJmDiQC+tB6lOfhHtM/1HB33qVNFFT+M0S/xfpmffuWvfoJ9lbzOOoSJKr6EgpPDztD6CP8Gv4b5HpvYObhSOpshLFKKHnxC3UbENNLUQsik5XIFNVTUWvkP3G1tvWtC+6gSUKN9dYaiSeq10jU3Qef20bnti6xfPPgkDI6U5qz0uz6u3fEpOPiAGpQCshnpiXrUXdZPtn+ocdeG3+769E1F6P7YY7dY57caM3vyFTKJY0Y6rgk1+9E5UI2drcV2+cKffL4//MEXy/v2xHLxPb4crPPl6Zt8zLcb/pr5c2/c7Zup8zZylb3HWwXn3LlswjnLje5KwTbIytpXsZmaPhnPxWE3fbZb21Xb90/rozBKlGasf+maCttrTU+JoTutYciX8+NnrTHfHutGAy1lHf56j4+srIG+O5aPwS5ffjbebD8+s5sc6AJUv2K7xelAEvDDnG9PPBfbQ4EikwxOrD4cJ1GTVo/12vrP3/FDvIj6H9phTjwh1iaG6IoKWmHU5KOH/7D+nR9r9X/R+vZ/PRLxaMnPfGjdfFfFfCGs1d0yt7PZjPm/+F/Q/UUzEZ839+aIP/x9s+JasHaHsxepRJYjHVpx7iXrPcw/+g4bwFEjf8e3sEGiUZDWeXoCiugXopL04x9Lp8SoVHuJD1FRfPFFcYVMH9gLvOCzX3jxx5L8jm9r+6SS07Bl6wMz+1Wm9xQ7W+HNd3wLyxAEBM6GiVWNTZwSES4G049/LDI4EXDokmlZlvzxi/Y3mFbe8S2On9o+Pc/0+dGzNuDxa2dts4MNszbTsT1+59+8k7+Xz6NuH+LmoAyI6ZpLpPuioIJyS0DMzaQUlqhSWy7xKKxoqAOiRDc60LhI7AZ49mlANfaP1kHrVQk8v8sVSDKeKZyIbS8F2yOamqtvj+3q9JcMjyddz+eI9YZdUoW9EPx0e300no93TX25VIqkMw9t7CrUJ5P3jNtj7v/yh9BGb6NrnwqwY8nR7OKzLNaCuljs23ykeQFK1JNC9exq0axUJbnCH2ou51bveeTKu/eFIjdf1b0+GPJFIgtWZPLN+bqBv79e3Dp8aXl+We8ukR2VrHnxnbdt6iPL+UvIQJVI3qv6SZjUjWzMrdwkhvWl4zDPE+9LS7U1UGpTpulZ345PgoWrob1YTdlH+1Lt3wynwh2B2vIz+Tpd/h3/oP+W+sxAauHS9XD99dZp+o53b1w4dbZ/A8Cy/SubUNB+WFy3/Ir91omNC0kEXzsykLVpImddyc71Rxm4fdOGNQuyiXoPPUOFBvhip9vhQk0Qk3idqRple8vqAqA7fJmjkJ7nbjqHDvI0XKpcKvClXraBhe5WoQsn4Y5wR8hZrnFWzw34Xv9cM98SgWihEHFLXo8UVD2SMCediOV1ejHmFe9qH+saKnndsnFloT6uJ/M5IzHQlTGSsUgwUu+PNH5/cDCNv1MbFk29TJEn5qINX8q1gCeYM+syugIuBa1dvycI2US+vasp2V7s25lOD7eXlgDxa3VRqdFfjEYykaDkT3c2R/NxPRaMacl4LJFvPJcaGkqtgzFGTYd6G/8/A/2PawAAeJxjYGRgYADiZ+yP98bz23xl4GZ+ARRhuJTfsQVCx7X8//k/k2U/cwSQy8HABBIFAI5lDk0AAAB4nGNgZGBgDvqfxRDFysrA8P8ly34GoAgKaAIAdw0FUnicY37BwMAMwoIMDCz6QHoBEBtCaXQMVMfKCqQjoXpeoMrBaUGomgVI6iIh5jN+gfCZrCGYMRWCwWKnkOgFUDMi0dhIdjOuQZJbADEPzm6CygtC2HBzkDHUTWA5QTQ7YGIvsGOwmxfgkIeaC7Z3AYIG6QG7EchmkQPSQPexlCEwXL8JVE6fAdXPgggxsHqoOFw/UlwwcQBxGxQD2cxOiDAH65uBGq4AVQxGkQAAAAAAANIBEgGoAb4B3AH4AggCNgKeAwQDqgQgBIYFEAWCBfwGdgbMBzoHoAfKCCAI1AkyCg4M4g0SDUwNwA3gDgAOHg4+DmoOlg7CDu4PJg9eD5QPzBAwEIIQ0hE0EWoRohIMEk4SoBMoE3IUGhRoFI4VBBVWFbwWIBaIFzwXjhgGGWYaBhqCG1Ib1hxSHNQdcB3UHhYejB8iH4Yf1iAOIHAg6iEyIXgh2CIyImwiyiMEI0IjeiPQJBgkciSuJRwlSCWEJeomaiagJy4naieWJ+ooiiksKa4qCCr2K0YryCwYLEosbCyiLNotQi2KLbQt3C4GLi4uYC6uLvwvGi9oL7Qv7jCNAAAAAQAAAIIB+AAPAAAAAAACAAAAEABzAAAANAtwAAAAAHicdZI5TsNAGIXfZEMkggIkGpq/AQUhOYtEkwoUEQoKJIo0VI7xFjmeaDxBygW4AwfgWpyF58mwFdjy+HvvX+YfywCO8AGF3XXFZ8cKbaodN7CHiecm/RvPLfLMcxs93HvuUM09d3GJJ889HOOVHVRrn2qJN88KXdX03MChOvDcpH/quUU+89zGiRp47tC/9dzFXD147uFcvU/1emvyNLPSn17IeDi6ksVWNK28DAsJNzbTppJrSXRp46LQQaRXeS0e43RThMaxW+axqXJdyigYOn0Xl7EJbfxcd6xe0rG1iSRGr2Tme8na6GUc2SCzdj0ZDH7vgSk01tjCIEeKDBaCPt0LvscYYsSPL1gwQ5i5y8pRIkRBJ8SGFZmLVNTXfBKqkm7MjIIcIOK6YtVX5JGxlJUF680v/4fmzKg75k4Lpwg4y0/8jvHS5YRup+fvGSu8sPeYrmV2PY1xuwt/kL9zCc9dx5Z0IvqBO72lO8GA9z/n+AR+3XkDAAAAeJxtVIeS2zYQ1Tuxn3T2Ob33HqbH6dVO770XEFySiECCBkDpdOn+8gAUlTITzgh4u7OLXex70Oxgtvuy2f9/l2czHGCOACEixEiQIsMhFljiCGdwFsc4hytwJa7C1bgG1+I6XI8bcCNuws24BbfiNtyOO3An7sLduAf34j7cjwfwIHI8hIfxCB7FY3gcT+BJnMdTeBrP4Fk8h+fxAl7ES3gZr+BVXMBFvIbX8QbexFt4G+/gXbyH9/EBPsRH+Bif4FN8hs/xBb7EV/ga3+BbfIfv8QN+BEMBjhKECjUaCPyEFSRadFDocQkaBhYD1tjgBFuc4mf8gl/xG37HH/gTl9OSmaZQTJfBYEiHfjEHahVx1nGSQS8HE7aiG8yiUrIknVPb221Sqk0nFSujoffbvBY25ENBJimZZQUzFNZsqCk2wlLL+oVR2uYdaykf+qN/DH9O2lLN+kZ1NC+GOrTMrExUCWlJz1VVBYVSq7BnxlJiuDAu2YS1VAWFXKqhDCvp7pAUTPOGaTu2lpdCu9b8lkiqrAepFnWzQ2OI6qnLdj4PYxfu93SM98gfUIh6ynNod5QH4wEOnNFkxCnl1SBlzqQ9/Je9mLBpmZRBq9Z0PHkapcWp6iyT+/w1aSs4k/GpUm0uurCQiq+S0VKDTaVvoRhk4a/MV+layWEc5eGEfEPZhP3M2sHSvBU8pq60oqXUWDcbj45cGedkeyb3ZrTR1PEmNlI4mk3ihLAWnEw8gXBkKHG8UN6XVTqCjdJlNiI6cXJxc+G5pRMbWu04WXLVttTZXaV4sgJHk838svMHBUmZ+MVPcMmsdUFCdd4Key1cBpXCxpXSG6fTUFMvt+m4uhA5py3NLasD9zNLP52RPJ+d/m0FHgWNaikQXaWChmQfGfKSSZx8+l50daRpI7oyG1WUS+EuOzblxnm0B1PH7lXUsavrXZmjkDdUDpIO+MbVMDa1zdAWxtMzIU9PbFyVjnTkbshc3RVtdw/PDWUINqISTiSqS3f1e0FTJ0wTm5xO41FBbOUeastqwUN/5PlsVOMos2xU6AgPd7IdceKUPIK5iz9mXS29YobCbT7h3H88Y17EheaSFn5a+Q6Xsd0IR44+WzFO/lHm5tLguiuXtf+b2Fuz2V/x+7GtAAB4nGPw3sFwIihiIyNjX+QGxp0cDBwMyQUbGVidNjIwaEFoDhR6JwMDAycyi5nBZaMKY0dgxAaHjoiNzCkuG9VAvF0cDQyMLA4dySERICWRQLCRgUdrB+P/1g0svRuZGFwAB9MiuAAAAA==') format('woff'),
- url('data:application/octet-stream;base64,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BjYGFQ4BFS4BNx4BFxYHBgcGFxQGFgGtdMZycsboyG4GerwBEgEIAwECBAMRFRMKAQwEDAMBBwYEBAoFBgQBCAEGAQQEBAIEBgEGAggJBQQFBQMBCAwBBRwHAgIBCAEOAQIHCQMEBAEEAgMBBwoCBAUNBAIUDhMECAYBAgECBQkCARMJAgQGBQYKAwgEBwUDAgYJBAYBBQkEBQMDAgUEAQ4HCw8EEAMDAQgECAEIAwEIBAQEAwMEAgQSBQMMDAEDAwIMGRsDAwgFEwUDCwQNCwEEAgYECAQJBFEyBAUCBgUDARgKAQIHBQQDBAQEAQIBAQECCgcHEgQHCQQDCAQCDgEBAgIOAgQCAg8IAwQDAgMFAQQKCgEECAQFDAcCAwgDCQcWBgYFCAgQBBQKAQIEAgYDDgMEAQoFCBEKAgICAgEFAgQBCgIDDAMCCAECCAMBAwIHCwQBAgIIFAMICgECAQQCAwUCAQIBBAECAgQYAwkDAQEBAw0CDgQCAwEEAwUCBggEAgIBCAQEBwgFBwwEBAICAgYBBQQDAgMFBwQDAhIBBAICBQwCCQICCggFCQIIBAIKCQ0JaXJRAQwBDQEEAxUBAwUCAwICAQUMCAMEBQEKAQMBAQQIBAoBBwYCCgIEAQwBAQICBAsPAQIJCgEDC3TE6sR0dMTqxHT+3QEIAgYGAQQIAwULAQwCAgQMAQoHAgMEAgQBAgYMBQYDCgEGBAEBAgICAQMDAgEDCAQCBgIDAwQFBAYHBAYICgcEBQYFDAMBAgQCAQMMCQ4DBAUHCAUDEQIDDgcGDAMBAwkCBwoDBgEOBAoEAQIFAgIGCgQHBwcBCQUIBwgDAgcDAgQCBgIEBQoDAw4CBQEBAgUEBwIBCggPAQMCAgcEAw4DAgQDBwMGBAQBAS1PBAEIBAMEBg8KAgYEBQQFDgkUCwIBBhoCARcFBAYDBRQDAxAFAgEECAUIBAELFw4FDAICBAQMCA4EDgEKCxQHCAEFAw0CAQIBEgMKBAQJBQYCAwoDAgMFDAIQCRMDAwQEBgIECgcOAQUCBAEEAgIQBQ8FAgUDAgsCCAQEAgIEGA4JDgUJAQQGAQIDAQEBBAMGBwYFAg8KAQQBAgMBAgMIBRcEAggIAwQPAgoKBQECAwQLCQUCAgICBgIKBwYFBAQEAwEECgQGAQcCAQcGBQMEAQEBBQQC/g0VVQIC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IABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAggAAAQIBAwEEAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARcBGAEZARoBGwEcAR0BHgEfASABIQEiASMBJAElASYBJwEoASkBKgErASwBLQEuAS8BMAExATIBMwE0ATUBNgE3ATgBOQE6ATsBPAE9AT4BPwFAAUEBQgFDAUQBRQFGAUcBSAFJAUoBSwFMAU0BTgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXQFeAV8BYAFhAWIBYwFkAWUBZgFnAWgBaQFqAWsBbAFtAW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AYABgQGCCWRhc2hib2FyZAR1c2VyBXVzZXJzAm9rBmNhbmNlbARwbHVzBW1pbnVzDGZvbGRlci1lbXB0eQhkb3dubG9hZAZ1cGxvYWQDZ2l0BWN1YmVzCGRhdGFiYXNlBWdhdWdlB3NpdGVtYXAMc29ydC1uYW1lLXVwDnNvcnQtbmFtZS1kb3duCW1lZ2FwaG9uZQNidWcFdGFza3MGZmlsdGVyA29mZgRib29rBXBhc3RlCHNjaXNzb3JzBWdsb2JlBWNsb3VkBWZsYXNoCGJhcmNoYXJ0CGRvd24tZGlyBnVwLWRpcghsZWZ0LWRpcglyaWdodC1kaXIJZG93bi1vcGVuCnJpZ2h0LW9wZW4HdXAtb3BlbglsZWZ0LW9wZW4GdXAtYmlnCXJpZ2h0LWJpZwhsZWZ0LWJpZwhkb3duLWJpZw9yZXNpemUtZnVsbC1hbHQLcmVzaXplLWZ1bGwMcmVzaXplLXNtYWxsBG1vdmURcmVzaXplLWhvcml6b250YWwPcmVzaXplLXZlcnRpY2FsB3pvb20taW4FYmxvY2sIem9vbS1vdXQJbGlnaHRidWxiBWNsb2NrCXZvbHVtZS11cAt2b2x1bWUtZG93bgp2b2x1bWUtb2ZmBG11dGUDbWljB2VuZHRpbWUJc3RhcnR0aW1lDmNhbGVuZGFyLWVtcHR5CGNhbGVuZGFyBndyZW5jaAdzbGlkZXJzCHNlcnZpY2VzB3NlcnZpY2UFcGhvbmUIZmlsZS1wZGYJZmlsZS13b3JkCmZpbGUtZXhjZWwIZG9jLXRleHQFdHJhc2gNY29tbWVudC1lbXB0eQdjb21tZW50BGNoYXQKY2hhdC1lbXB0eQRiZWxsCGJlbGwtYWx0DWF0dGVudGlvbi1hbHQFcHJpbnQEZWRpdAdmb3J3YXJkBXJlcGx5CXJlcGx5LWFsbANleWUDdGFnBHRhZ3MNbG9jay1vcGVuLWFsdAlsb2NrLW9wZW4EbG9jawRob21lBGluZm8EaGVscAZzZWFyY2gIZmxhcHBpbmcGcmV3aW5kCmNoYXJ0LWxpbmUIYmVsbC1vZmYOYmVsbC1vZmYtZW1wdHkEcGx1ZwdleWUtb2ZmCnJlc2NoZWR1bGUCY3cEaG9zdAl0aHVtYnMtdXALdGh1bWJzLWRvd24Hc3Bpbm5lcgZhdHRhY2gIa2V5Ym9hcmQEbWVudQR3aWZpBG1vb24JY2hhcnQtcGllCmNoYXJ0LWFyZWEJY2hhcnQtYmFyBmJlYWtlcgVtYWdpYwVzcGluNgpkb3duLXNtYWxsCmxlZnQtc21hbGwLcmlnaHQtc21hbGwIdXAtc21hbGwDcGluEWFuZ2xlLWRvdWJsZS1sZWZ0EmFuZ2xlLWRvdWJsZS1yaWdodAZjaXJjbGUMaW5mby1jaXJjbGVkB3R3aXR0ZXIQZmFjZWJvb2stc3F1YXJlZA1ncGx1cy1zcXVhcmVkAAAAAAEAAf//AA8AAAAAAAAAAAAAAACwACwgsABVWEVZICBLuAAOUUuwBlNaWLA0G7AoWWBmIIpVWLACJWG5CAAIAGNjI2IbISGwAFmwAEMjRLIAAQBDYEItsAEssCBgZi2wAiwgZCCwwFCwBCZasigBCkNFY0VSW1ghIyEbilggsFBQWCGwQFkbILA4UFghsDhZWSCxAQpDRWNFYWSwKFBYIbEBCkNFY0UgsDBQWCGwMFkbILDAUFggZiCKimEgsApQWGAbILAgUFghsApgGyCwNlBYIbA2YBtgWVlZG7ABK1lZI7AAUFhlWVktsAMsIEUgsAQlYWQgsAVDUFiwBSNCsAYjQhshIVmwAWAtsAQsIyEjISBksQViQiCwBiNCsQEK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') format('truetype');
+ src: url('data:application/octet-stream;base64,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') format('woff'),
+ url('data:application/octet-stream;base64,AAEAAAAPAIAAAwBwR1NVQiCMJXkAAAD8AAAAVE9TLzI+IVLhAAABUAAAAFZjbWFwyyEWGwAAAagAAAjcY3Z0IAbX/wIAAKBEAAAAIGZwZ22KkZBZAACgZAAAC3BnYXNwAAAAEAAAoDwAAAAIZ2x5ZhltR7EAAAqEAACJjmhlYWQMfTFLAACUFAAAADZoaGVhB/cE3AAAlEwAAAAkaG10eNFM/5cAAJRwAAACIGxvY2GhxIEUAACWkAAAARJtYXhwAf8NvgAAl6QAAAAgbmFtZcQUf/oAAJfEAAACqXBvc3St3UkxAACacAAABctwcmVw5UErvAAAq9QAAACGAAEAAAAKADAAPgACbGF0bgAOREZMVAAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAEDbAGQAAUAAAJ6ArwAAACMAnoCvAAAAeAAMQECAAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAQOgA8eUDUv9qAFoDUwCXAAAAAQAAAAAAAAAAAAUAAAADAAAALAAAAAQAAAJ4AAEAAAAAAXIAAwABAAAALAADAAoAAAJ4AAQBRgAAAAoACAACAALogeiF8drx5f//AADoAOiD8drx5f//AAAAAAAAAAAAAQAKAQwBEAEQAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZABlAGYAZwBoAGkAagBrAGwAbQBuAG8AcABxAHIAcwB0AHUAdgB3AHgAeQB6AHsAfAB9AH4AfwCAAIEAggCDAIQAhQCGAIcAAAEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAABmQAAAAAAAAAhwAA6AAAAOgAAAAAAQAA6AEAAOgBAAAAAgAA6AIAAOgCAAAAAwAA6AMAAOgDAAAABAAA6AQAAOgEAAAABQAA6AUAAOgFAAAABgAA6AYAAOgGAAAABwAA6AcAAOgHAAAACAAA6AgAAOgIAAAACQAA6AkAAOgJAAAACgAA6AoAAOgKAAAACwAA6AsAAOgLAAAADAAA6AwAAOgMAAAADQAA6A0AAOgNAAAADgAA6A4AAOgOAAAADwAA6A8AAOgPAAAAEAAA6BAAAOgQAAAAEQAA6BEAAOgRAAAAEgAA6BIAAOgSAAAAEwAA6BMAAOgTAAAAFAAA6BQAAOgUAAAAFQAA6BUAAOgVAAAAFgAA6BYAAOgWAAAAFwAA6BcAAOgXAAAAGAAA6BgAAOgYAAAAGQAA6BkAAOgZAAAAGgAA6BoAAOgaAAAAGwAA6BsAAOgbAAAAHAAA6BwAAOgcAAAAHQAA6B0AAOgdAAAAHgAA6B4AAOgeAAAAHwAA6B8AAOgfAAAAIAAA6CAAAOggAAAAIQAA6CEAAOghAAAAIgAA6CIAAOgiAAAAIwAA6CMAAOgjAAAAJAAA6CQAAOgkAAAAJQAA6CUAAOglAAAAJgAA6CYAAOgmAAAAJwAA6CcAAOgnAAAAKAAA6CgAAOgoAAAAKQAA6CkAAOgpAAAAKgAA6CoAAOgqAAAAKwAA6CsAAOgrAAAALAAA6CwAAOgsAAAALQAA6C0AAOgtAAAALgAA6C4AAOguAAAALwAA6C8AAOgvAAAAMAAA6DAAAOgwAAAAMQAA6DEAAOgxAAAAMgAA6DIAAOgyAAAAMwAA6DMAAOgzAAAANAAA6DQAAOg0AAAANQAA6DUAAOg1AAAANgAA6DYAAOg2AAAANwAA6DcAAOg3AAAAOAAA6DgAAOg4AAAAOQAA6DkAAOg5AAAAOgAA6DoAAOg6AAAAOwAA6DsAAOg7AAAAPAAA6DwAAOg8AAAAPQAA6D0AAOg9AAAAPgAA6D4AAOg+AAAAPwAA6D8AAOg/AAAAQAAA6EAAAOhAAAAAQQAA6EEAAOhBAAAAQgAA6EIAAOhCAAAAQwAA6EMAAOhDAAAARAAA6EQAAOhEAAAARQAA6EUAAOhFAAAARgAA6EYAAOhGAAAARwAA6EcAAOhHAAAASAAA6EgAAOhIAAAASQAA6EkAAOhJAAAASgAA6EoAAOhKAAAASwAA6EsAAOhLAAAATAAA6EwAAOhMAAAATQAA6E0AAOhNAAAATgAA6E4AAOhOAAAATwAA6E8AAOhPAAAAUAAA6FAAAOhQAAAAUQAA6FEAAOhRAAAAUgAA6FIAAOhSAAAAUwAA6FMAAOhTAAAAVAAA6FQAAOhUAAAAVQAA6FUAAOhVAAAAVgAA6FYAAOhWAAAAVwAA6FcAAOhXAAAAWAAA6FgAAOhYAAAAWQAA6FkAAOhZAAAAWgAA6FoAAOhaAAAAWwAA6FsAAOhbAAAAXAAA6FwAAOhcAAAAXQAA6F0AAOhdAAAAXgAA6F4AAOheAAAAXwAA6F8AAOhfAAAAYAAA6GAAAOhgAAAAYQAA6GEAAOhhAAAAYgAA6GIAAOhiAAAAYwAA6GMAAOhjAAAAZAAA6GQAAOhkAAAAZQAA6GUAAOhlAAAAZgAA6GYAAOhmAAAAZwAA6GcAAOhnAAAAaAAA6GgAAOhoAAAAaQAA6GkAAOhpAAAAagAA6GoAAOhqAAAAawAA6GsAAOhrAAAAbAAA6GwAAOhsAAAAbQAA6G0AAOhtAAAAbgAA6G4AAOhuAAAAbwAA6G8AAOhvAAAAcAAA6HAAAOhwAAAAcQAA6HEAAOhxAAAAcgAA6HIAAOhyAAAAcwAA6HMAAOhzAAAAdAAA6HQAAOh0AAAAdQAA6HUAAOh1AAAAdgAA6HYAAOh2AAAAdwAA6HcAAOh3AAAAeAAA6HgAAOh4AAAAeQAA6HkAAOh5AAAAegAA6HoAAOh6AAAAewAA6HsAAOh7AAAAfAAA6HwAAOh8AAAAfQAA6H0AAOh9AAAAfgAA6H4AAOh+AAAAfwAA6H8AAOh/AAAAgAAA6IAAAOiAAAAAgQAA6IEAAOiBAAAAggAA6IMAAOiDAAAAgwAA6IQAAOiEAAAAhAAA6IUAAOiFAAAAhQAA8doAAPHaAAAAhgAA8eUAAPHlAAAAhwAJAAD/+QPo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AREBEgETARQBFQEWARcBGAEZARoBGwEcAR0BHgEfASABIQEiASMBJAElASYBJwEoASkBKgErASwBLQEuAS8BMAExATIBMwE0ATUBNgE3ATgBOQE6ATsBPAE9AT4BPwFAAUEBQgFDAUQBRQFGAUcBSAFJAUoBSwFMAU0BTgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXQFeAV8BYAFhAWIBYwFkAWUBZgFnAWgBaQFqAWsBbAFtAW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AYABgQGCAYMBhAGFAYYBhwGIAYkACWRhc2hib2FyZAR1c2VyBXVzZXJzAm9rBmNhbmNlbARwbHVzBW1pbnVzDGZvbGRlci1lbXB0eQhkb3dubG9hZAZ1cGxvYWQDZ2l0BWN1YmVzCGRhdGFiYXNlBWdhdWdlB3NpdGVtYXAMc29ydC1uYW1lLXVwDnNvcnQtbmFtZS1kb3duCW1lZ2FwaG9uZQNidWcFdGFza3MGZmlsdGVyA29mZgRib29rBXBhc3RlCHNjaXNzb3JzBWdsb2JlBWNsb3VkBWZsYXNoCGJhcmNoYXJ0CGRvd24tZGlyBnVwLWRpcghsZWZ0LWRpcglyaWdodC1kaXIJZG93bi1vcGVuCnJpZ2h0LW9wZW4HdXAtb3BlbglsZWZ0LW9wZW4GdXAtYmlnCXJpZ2h0LWJpZwhsZWZ0LWJpZwhkb3duLWJpZw9yZXNpemUtZnVsbC1hbHQLcmVzaXplLWZ1bGwMcmVzaXplLXNtYWxsBG1vdmURcmVzaXplLWhvcml6b250YWwPcmVzaXplLXZlcnRpY2FsB3pvb20taW4FYmxvY2sIem9vbS1vdXQJbGlnaHRidWxiBWNsb2NrCXZvbHVtZS11cAt2b2x1bWUtZG93bgp2b2x1bWUtb2ZmBG11dGUDbWljB2VuZHRpbWUJc3RhcnR0aW1lDmNhbGVuZGFyLWVtcHR5CGNhbGVuZGFyBndyZW5jaAdzbGlkZXJzCHNlcnZpY2VzB3NlcnZpY2UFcGhvbmUIZmlsZS1wZGYJZmlsZS13b3JkCmZpbGUtZXhjZWwIZG9jLXRleHQFdHJhc2gNY29tbWVudC1lbXB0eQdjb21tZW50BGNoYXQKY2hhdC1lbXB0eQRiZWxsCGJlbGwtYWx0DWF0dGVudGlvbi1hbHQFcHJpbnQEZWRpdAdmb3J3YXJkBXJlcGx5CXJlcGx5LWFsbANleWUDdGFnBHRhZ3MNbG9jay1vcGVuLWFsdAlsb2NrLW9wZW4EbG9jawRob21lBGluZm8EaGVscAZzZWFyY2gIZmxhcHBpbmcGcmV3aW5kCmNoYXJ0LWxpbmUIYmVsbC1vZmYOYmVsbC1vZmYtZW1wdHkEcGx1ZwdleWUtb2ZmCWFycm93cy1jdwJjdwRob3N0CXRodW1icy11cAt0aHVtYnMtZG93bgdzcGlubmVyBmF0dGFjaAhrZXlib2FyZARtZW51BHdpZmkEbW9vbgljaGFydC1waWUKY2hhcnQtYXJlYQljaGFydC1iYXIGYmVha2VyBW1hZ2ljBXNwaW42CmRvd24tc21hbGwKbGVmdC1zbWFsbAtyaWdodC1zbWFsbAh1cC1zbWFsbANwaW4RYW5nbGUtZG91YmxlLWxlZnQSYW5nbGUtZG91YmxlLXJpZ2h0BmNpcmNsZQxpbmZvLWNpcmNsZWQHdHdpdHRlchBmYWNlYm9vay1zcXVhcmVkDWdwbHVzLXNxdWFyZWQRYXR0ZW50aW9uLWNpcmNsZWQFY2hlY2sKcmVzY2hlZHVsZQ13YXJuaW5nLWVtcHR5B2hpc3RvcnkKYmlub2N1bGFycwAAAAABAAH//wAPAAAAAAAAAAAAAAAAAAAAAAAYABgAGAAYA1P/aQNT/2mwACwgsABVWEVZICBLuAAOUUuwBlNaWLA0G7AoWWBmIIpVWLACJWG5CAAIAGNjI2IbISGwAFmwAEMjRLIAAQBDYEItsAEssCBgZi2wAiwgZCCwwFCwBCZasigBCkNFY0VSW1ghIyEbilggsFBQWCGwQFkbILA4UFghsDhZWSCxAQpDRWNFYWSwKFBYIbEBCkNFY0UgsDBQWCGwMFkbILDAUFggZiCKimEgsApQWGAbILAgUFghsApgGyCwNlBYIbA2YBtgWVlZG7ABK1lZI7AAUFhlWVktsAMsIEUgsAQlYWQgsAVDUFiwBSNCsAYjQhshIVmwAWAtsAQsIyEjISBksQViQiCwBiNCsQEKQ0VjsQEKQ7ABYEVjsAMqISCwBkMgiiCKsAErsTAFJbAEJlFYYFAbYVJZWCNZISCwQFNYsAErGyGwQFkjsABQWGVZLbAFLLAH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') format('truetype');
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
@@ -17,7 +17,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'ifont';
- src: url('../font/ifont.svg?36375038#ifont') format('svg');
+ src: url('../font/ifont.svg?47279460#ifont') format('svg');
}
}
*/
@@ -152,7 +152,7 @@
.icon-bell-off-empty:before { content: '\e861'; } /* '' */
.icon-plug:before { content: '\e862'; } /* '' */
.icon-eye-off:before { content: '\e863'; } /* '' */
-.icon-reschedule:before { content: '\e864'; } /* '' */
+.icon-arrows-cw:before { content: '\e864'; } /* '' */
.icon-cw:before { content: '\e865'; } /* '' */
.icon-host:before { content: '\e866'; } /* '' */
.icon-thumbs-up:before { content: '\e867'; } /* '' */
@@ -180,4 +180,10 @@
.icon-info-circled:before { content: '\e87d'; } /* '' */
.icon-twitter:before { content: '\e87e'; } /* '' */
.icon-facebook-squared:before { content: '\e87f'; } /* '' */
-.icon-gplus-squared:before { content: '\e880'; } /* '' */
\ No newline at end of file
+.icon-gplus-squared:before { content: '\e880'; } /* '' */
+.icon-attention-circled:before { content: '\e881'; } /* '' */
+.icon-check:before { content: '\e883'; } /* '' */
+.icon-reschedule:before { content: '\e884'; } /* '' */
+.icon-warning-empty:before { content: '\e885'; } /* '' */
+.icon-history:before { content: '\f1da'; } /* '' */
+.icon-binoculars:before { content: '\f1e5'; } /* '' */
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/css/ifont-ie7-codes.css b/application/fonts/fontello-ifont/css/ifont-ie7-codes.css
old mode 100644
new mode 100755
index 660e08a3d..c50f57570
--- a/application/fonts/fontello-ifont/css/ifont-ie7-codes.css
+++ b/application/fonts/fontello-ifont/css/ifont-ie7-codes.css
@@ -99,7 +99,7 @@
.icon-bell-off-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-plug { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-eye-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
-.icon-reschedule { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-arrows-cw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-cw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-host { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-thumbs-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
@@ -127,4 +127,10 @@
.icon-info-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-facebook-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
-.icon-gplus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
\ No newline at end of file
+.icon-gplus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-attention-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-reschedule { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-warning-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-history { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-binoculars { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/css/ifont-ie7.css b/application/fonts/fontello-ifont/css/ifont-ie7.css
old mode 100644
new mode 100755
index a3c15c2d2..8c3401a9d
--- a/application/fonts/fontello-ifont/css/ifont-ie7.css
+++ b/application/fonts/fontello-ifont/css/ifont-ie7.css
@@ -110,7 +110,7 @@
.icon-bell-off-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-plug { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-eye-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
-.icon-reschedule { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-arrows-cw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-cw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-host { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-thumbs-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
@@ -138,4 +138,10 @@
.icon-info-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
.icon-facebook-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
-.icon-gplus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
\ No newline at end of file
+.icon-gplus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-attention-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-reschedule { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-warning-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-history { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
+.icon-binoculars { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/css/ifont.css b/application/fonts/fontello-ifont/css/ifont.css
old mode 100644
new mode 100755
index 9eba001ae..adbfd04ec
--- a/application/fonts/fontello-ifont/css/ifont.css
+++ b/application/fonts/fontello-ifont/css/ifont.css
@@ -1,10 +1,11 @@
@font-face {
font-family: 'ifont';
- src: url('../font/ifont.eot?65389432');
- src: url('../font/ifont.eot?65389432#iefix') format('embedded-opentype'),
- url('../font/ifont.woff?65389432') format('woff'),
- url('../font/ifont.ttf?65389432') format('truetype'),
- url('../font/ifont.svg?65389432#ifont') format('svg');
+ src: url('../font/ifont.eot?38679513');
+ src: url('../font/ifont.eot?38679513#iefix') format('embedded-opentype'),
+ url('../font/ifont.woff2?38679513') format('woff2'),
+ url('../font/ifont.woff?38679513') format('woff'),
+ url('../font/ifont.ttf?38679513') format('truetype'),
+ url('../font/ifont.svg?38679513#ifont') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -14,7 +15,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'ifont';
- src: url('../font/ifont.svg?65389432#ifont') format('svg');
+ src: url('../font/ifont.svg?38679513#ifont') format('svg');
}
}
*/
@@ -154,7 +155,7 @@
.icon-bell-off-empty:before { content: '\e861'; } /* '' */
.icon-plug:before { content: '\e862'; } /* '' */
.icon-eye-off:before { content: '\e863'; } /* '' */
-.icon-reschedule:before { content: '\e864'; } /* '' */
+.icon-arrows-cw:before { content: '\e864'; } /* '' */
.icon-cw:before { content: '\e865'; } /* '' */
.icon-host:before { content: '\e866'; } /* '' */
.icon-thumbs-up:before { content: '\e867'; } /* '' */
@@ -182,4 +183,10 @@
.icon-info-circled:before { content: '\e87d'; } /* '' */
.icon-twitter:before { content: '\e87e'; } /* '' */
.icon-facebook-squared:before { content: '\e87f'; } /* '' */
-.icon-gplus-squared:before { content: '\e880'; } /* '' */
\ No newline at end of file
+.icon-gplus-squared:before { content: '\e880'; } /* '' */
+.icon-attention-circled:before { content: '\e881'; } /* '' */
+.icon-check:before { content: '\e883'; } /* '' */
+.icon-reschedule:before { content: '\e884'; } /* '' */
+.icon-warning-empty:before { content: '\e885'; } /* '' */
+.icon-history:before { content: '\f1da'; } /* '' */
+.icon-binoculars:before { content: '\f1e5'; } /* '' */
\ No newline at end of file
diff --git a/application/fonts/fontello-ifont/demo.html b/application/fonts/fontello-ifont/demo.html
old mode 100644
new mode 100755
index 2b409f7c8..d60d62e5f
--- a/application/fonts/fontello-ifont/demo.html
+++ b/application/fonts/fontello-ifont/demo.html
@@ -229,11 +229,11 @@ body {
}
@font-face {
font-family: 'ifont';
- src: url('./font/ifont.eot?43849680');
- src: url('./font/ifont.eot?43849680#iefix') format('embedded-opentype'),
- url('./font/ifont.woff?43849680') format('woff'),
- url('./font/ifont.ttf?43849680') format('truetype'),
- url('./font/ifont.svg?43849680#ifont') format('svg');
+ src: url('./font/ifont.eot?54126565');
+ src: url('./font/ifont.eot?54126565#iefix') format('embedded-opentype'),
+ url('./font/ifont.woff?54126565') format('woff'),
+ url('./font/ifont.ttf?54126565') format('truetype'),
+ url('./font/ifont.svg?54126565#ifont') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -279,7 +279,7 @@ body {
+
diff --git a/application/layouts/scripts/pdf.phtml b/application/layouts/scripts/pdf.phtml
index 68c341e01..13e383958 100644
--- a/application/layouts/scripts/pdf.phtml
+++ b/application/layouts/scripts/pdf.phtml
@@ -31,7 +31,7 @@ if ( isset($pdf) )
}
-= $this->img('img/logo_icinga_big_dark.png', null, array('align' => 'right', 'width' => '75')) ?>
+= $this->img('img/icinga-logo-big-dark.png', null, array('align' => 'right', 'width' => '75')) ?>
');
+ if ($comment_start === false ||
+ ($comment_end !== false && $comment_end > $comment_start)) {
+ return $matches[2];
+ }
}
+ return $html;
}
}
diff --git a/library/vendor/HTMLPurifier/Printer/ConfigForm.php b/library/vendor/HTMLPurifier/Printer/ConfigForm.php
index 36100ce73..65a777904 100644
--- a/library/vendor/HTMLPurifier/Printer/ConfigForm.php
+++ b/library/vendor/HTMLPurifier/Printer/ConfigForm.php
@@ -327,6 +327,10 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer
case HTMLPurifier_VarParser::HASH:
$nvalue = '';
foreach ($value as $i => $v) {
+ if (is_array($v)) {
+ // HACK
+ $v = implode(";", $v);
+ }
$nvalue .= "$i:$v" . PHP_EOL;
}
$value = $nvalue;
diff --git a/library/vendor/HTMLPurifier/SOURCE b/library/vendor/HTMLPurifier/SOURCE
index 44e19b159..bdc316957 100644
--- a/library/vendor/HTMLPurifier/SOURCE
+++ b/library/vendor/HTMLPurifier/SOURCE
@@ -1,7 +1,10 @@
-curl https://codeload.github.com/ezyang/htmlpurifier/tar.gz/v4.7.0 -o htmlpurifier-4.7.0.tar.gz
-tar xzf htmlpurifier-4.7.0.tar.gz --strip-components 1 htmlpurifier-4.7.0/LICENSE
-tar xzf htmlpurifier-4.7.0.tar.gz --strip-components 1 htmlpurifier-4.7.0/VERSION
-tar xzf htmlpurifier-4.7.0.tar.gz -C ../ --strip-components 2 htmlpurifier-4.7.0/library/HTMLPurifier.php
-tar xzf htmlpurifier-4.7.0.tar.gz -C ../ --strip-components 2 htmlpurifier-4.7.0/library/HTMLPurifier.autoload.php
-tar xzf htmlpurifier-4.7.0.tar.gz --strip-components 3 htmlpurifier-4.7.0/library/HTMLPurifier/*
-rm htmlpurifier-4.7.0.tar.gz
+GLOBIGNORE=$0; rm -rf *
+rm ../HTMLPurifier*.php
+
+curl https://codeload.github.com/ezyang/htmlpurifier/tar.gz/v4.8.0 -o htmlpurifier-4.8.0.tar.gz
+tar xzf htmlpurifier-4.8.0.tar.gz --strip-components 1 htmlpurifier-4.8.0/LICENSE
+tar xzf htmlpurifier-4.8.0.tar.gz --strip-components 1 htmlpurifier-4.8.0/VERSION
+tar xzf htmlpurifier-4.8.0.tar.gz -C ../ --strip-components 2 htmlpurifier-4.8.0/library/HTMLPurifier.php
+tar xzf htmlpurifier-4.8.0.tar.gz -C ../ --strip-components 2 htmlpurifier-4.8.0/library/HTMLPurifier.autoload.php
+tar xzf htmlpurifier-4.8.0.tar.gz --strip-components 3 htmlpurifier-4.8.0/library/HTMLPurifier/*
+rm htmlpurifier-4.8.0.tar.gz
diff --git a/library/vendor/HTMLPurifier/URIScheme/data.php b/library/vendor/HTMLPurifier/URIScheme/data.php
index 6ebca4984..41c49d553 100644
--- a/library/vendor/HTMLPurifier/URIScheme/data.php
+++ b/library/vendor/HTMLPurifier/URIScheme/data.php
@@ -79,9 +79,18 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme
} else {
$raw_data = $data;
}
+ if ( strlen($raw_data) < 12 ) {
+ // error; exif_imagetype throws exception with small files,
+ // and this likely indicates a corrupt URI/failed parse anyway
+ return false;
+ }
// XXX probably want to refactor this into a general mechanism
// for filtering arbitrary content types
- $file = tempnam("/tmp", "");
+ if (function_exists('sys_get_temp_dir')) {
+ $file = tempnam(sys_get_temp_dir(), "");
+ } else {
+ $file = tempnam("/tmp", "");
+ }
file_put_contents($file, $raw_data);
if (function_exists('exif_imagetype')) {
$image_code = exif_imagetype($file);
diff --git a/library/vendor/HTMLPurifier/URIScheme/tel.php b/library/vendor/HTMLPurifier/URIScheme/tel.php
new file mode 100644
index 000000000..8cd193352
--- /dev/null
+++ b/library/vendor/HTMLPurifier/URIScheme/tel.php
@@ -0,0 +1,46 @@
+userinfo = null;
+ $uri->host = null;
+ $uri->port = null;
+
+ // Delete all non-numeric characters, non-x characters
+ // from phone number, EXCEPT for a leading plus sign.
+ $uri->path = preg_replace('/(?!^\+)[^\dx]/', '',
+ // Normalize e(x)tension to lower-case
+ str_replace('X', 'x', $uri->path));
+
+ return true;
+ }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/vendor/HTMLPurifier/VERSION b/library/vendor/HTMLPurifier/VERSION
index 1163055e2..6ca6df113 100644
--- a/library/vendor/HTMLPurifier/VERSION
+++ b/library/vendor/HTMLPurifier/VERSION
@@ -1 +1 @@
-4.7.0
\ No newline at end of file
+4.8.0
\ No newline at end of file
diff --git a/library/vendor/dompdf/SOURCE b/library/vendor/dompdf/SOURCE
index babe1b191..3eb54e1fd 100644
--- a/library/vendor/dompdf/SOURCE
+++ b/library/vendor/dompdf/SOURCE
@@ -1,9 +1,16 @@
-curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.6.2 -o dompdf-0.6.2.tar.gz
-tar xzf dompdf-0.6.2.tar.gz --strip-components 1 --wildcards dompdf-0.6.2/{include/\*.php,lib,dompdf\*.php,LICENSE.LGPL}
-rm dompdf-0.6.2.tar.gz
+GLOBIGNORE=$0; rm -rf *
+
+curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.7.0 -o dompdf-0.7.0.tar.gz
+tar xzf dompdf-0.7.0.tar.gz --strip-components 1 dompdf-0.7.0/{lib,src,autoload.inc.php,LICENSE.LGPL}
+rm dompdf-0.7.0.tar.gz
mv LICENSE.LGPL LICENSE
curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.4 -o php-font-lib-0.4.tar.gz
-mkdir -p lib/php-font-lib/classes
-tar xzf php-font-lib-0.4.tar.gz --strip-components 3 -C lib/php-font-lib/classes php-font-lib-0.4/src/FontLib
+mkdir -p lib/php-font-lib
+tar xzf php-font-lib-0.4.tar.gz --strip-components 1 -C lib/php-font-lib php-font-lib-0.4/{src,LICENSE}
rm php-font-lib-0.4.tar.gz
+
+curl https://codeload.github.com/PhenX/php-svg-lib/tar.gz/v0.1 -o php-svg-lib-0.1.tar.gz
+mkdir -p lib/php-svg-lib
+tar xzf php-svg-lib-0.1.tar.gz --strip-components 1 -C lib/php-svg-lib php-svg-lib-0.1/src
+rm php-svg-lib-0.1.tar.gz
diff --git a/library/vendor/dompdf/autoload.inc.php b/library/vendor/dompdf/autoload.inc.php
new file mode 100644
index 000000000..c5c32f193
--- /dev/null
+++ b/library/vendor/dompdf/autoload.inc.php
@@ -0,0 +1,28 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+/**
+ * Dompdf autoload function
+ *
+ * If you have an existing autoload function, add a call to this function
+ * from your existing __autoload() implementation.
+ *
+ * @param string $class
+ */
+
+require_once __DIR__ . '/lib/html5lib/Parser.php';
+require_once __DIR__ . '/lib/php-font-lib/src/FontLib/Autoloader.php';
+require_once __DIR__ . '/lib/php-svg-lib/src/autoload.php';
+
+/*
+ * New PHP 5.3.0 namespaced autoloader
+ */
+require_once __DIR__ . '/src/Autoloader.php';
+
+Dompdf\Autoloader::register();
diff --git a/library/vendor/dompdf/dompdf.php b/library/vendor/dompdf/dompdf.php
deleted file mode 100644
index dc3551b73..000000000
--- a/library/vendor/dompdf/dompdf.php
+++ /dev/null
@@ -1,279 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Display command line usage
- */
-function dompdf_usage() {
- $default_paper_size = DOMPDF_DEFAULT_PAPER_SIZE;
-
- echo <<set_option('enable_php', false);
-
- if ( isset($_GET["input_file"]) )
- $file = rawurldecode($_GET["input_file"]);
- else
- throw new DOMPDF_Exception("An input file is required (i.e. input_file _GET variable).");
-
- if ( isset($_GET["paper"]) )
- $paper = rawurldecode($_GET["paper"]);
- else
- $paper = DOMPDF_DEFAULT_PAPER_SIZE;
-
- if ( isset($_GET["orientation"]) )
- $orientation = rawurldecode($_GET["orientation"]);
- else
- $orientation = "portrait";
-
- if ( isset($_GET["base_path"]) ) {
- $base_path = rawurldecode($_GET["base_path"]);
- $file = $base_path . $file; # Set the input file
- }
-
- if ( isset($_GET["options"]) ) {
- $options = $_GET["options"];
- }
-
- $file_parts = explode_url($file);
-
- $outfile = "dompdf_out.pdf"; # Don't allow them to set the output file
- $save_file = false; # Don't save the file
-
- break;
-}
-
-if ( $file === "-" ) {
- $str = "";
- while ( !feof(STDIN) )
- $str .= fread(STDIN, 4096);
-
- $dompdf->load_html($str);
-
-} else
- $dompdf->load_html_file($file);
-
-if ( isset($base_path) ) {
- $dompdf->set_base_path($base_path);
-}
-
-$dompdf->set_paper($paper, $orientation);
-
-$dompdf->render();
-
-if ( $_dompdf_show_warnings ) {
- global $_dompdf_warnings;
- foreach ($_dompdf_warnings as $msg)
- echo $msg . "\n";
- echo $dompdf->get_canvas()->get_cpdf()->messages;
- flush();
-}
-
-if ( $save_file ) {
-// if ( !is_writable($outfile) )
-// throw new DOMPDF_Exception("'$outfile' is not writable.");
- if ( strtolower(DOMPDF_PDF_BACKEND) === "gd" )
- $outfile = str_replace(".pdf", ".png", $outfile);
-
- list($proto, $host, $path, $file) = explode_url($outfile);
- if ( $proto != "" ) // i.e. not file://
- $outfile = $file; // just save it locally, FIXME? could save it like wget: ./host/basepath/file
-
- $outfile = realpath(dirname($outfile)) . DIRECTORY_SEPARATOR . basename($outfile);
-
- if ( strpos($outfile, DOMPDF_CHROOT) !== 0 )
- throw new DOMPDF_Exception("Permission denied.");
-
- file_put_contents($outfile, $dompdf->output( array("compress" => 0) ));
- exit(0);
-}
-
-if ( !headers_sent() ) {
- $dompdf->stream($outfile, $options);
-}
diff --git a/library/vendor/dompdf/dompdf_config.custom.inc.php b/library/vendor/dompdf/dompdf_config.custom.inc.php
deleted file mode 100644
index e9c0899d5..000000000
--- a/library/vendor/dompdf/dompdf_config.custom.inc.php
+++ /dev/null
@@ -1,41 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @author Brian Sweeney
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-if ( class_exists( 'DOMPDF' , false ) ) { return; }
-
-PHP_VERSION >= 5.0 or die("DOMPDF requires PHP 5.0+");
-
-/**
- * The root of your DOMPDF installation
- */
-define("DOMPDF_DIR", str_replace(DIRECTORY_SEPARATOR, '/', realpath(dirname(__FILE__))));
-
-/**
- * The location of the DOMPDF include directory
- */
-define("DOMPDF_INC_DIR", DOMPDF_DIR . "/include");
-
-/**
- * The location of the DOMPDF lib directory
- */
-define("DOMPDF_LIB_DIR", DOMPDF_DIR . "/lib");
-
-/**
- * Some installations don't have $_SERVER['DOCUMENT_ROOT']
- * http://fyneworks.blogspot.com/2007/08/php-documentroot-in-iis-windows-servers.html
- */
-if( !isset($_SERVER['DOCUMENT_ROOT']) ) {
- $path = "";
-
- if ( isset($_SERVER['SCRIPT_FILENAME']) )
- $path = $_SERVER['SCRIPT_FILENAME'];
- elseif ( isset($_SERVER['PATH_TRANSLATED']) )
- $path = str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']);
-
- $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr($path, 0, 0-strlen($_SERVER['PHP_SELF'])));
-}
-
-/** Include the custom config file if it exists */
-if ( file_exists(DOMPDF_DIR . "/dompdf_config.custom.inc.php") ){
- require_once(DOMPDF_DIR . "/dompdf_config.custom.inc.php");
-}
-
-//FIXME: Some function definitions rely on the constants defined by DOMPDF. However, might this location prove problematic?
-require_once(DOMPDF_INC_DIR . "/functions.inc.php");
-
-/**
- * Username and password used by the configuration utility in www/
- */
-def("DOMPDF_ADMIN_USERNAME", "user");
-def("DOMPDF_ADMIN_PASSWORD", "password");
-
-/**
- * The location of the DOMPDF font directory
- *
- * The location of the directory where DOMPDF will store fonts and font metrics
- * Note: This directory must exist and be writable by the webserver process.
- * *Please note the trailing slash.*
- *
- * Notes regarding fonts:
- * Additional .afm font metrics can be added by executing load_font.php from command line.
- *
- * Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
- * be embedded in the pdf file or the PDF may not display correctly. This can significantly
- * increase file size unless font subsetting is enabled. Before embedding a font please
- * review your rights under the font license.
- *
- * Any font specification in the source HTML is translated to the closest font available
- * in the font directory.
- *
- * The pdf standard "Base 14 fonts" are:
- * Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
- * Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
- * Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
- * Symbol, ZapfDingbats.
- */
-def("DOMPDF_FONT_DIR", DOMPDF_DIR . "/lib/fonts/");
-
-/**
- * The location of the DOMPDF font cache directory
- *
- * This directory contains the cached font metrics for the fonts used by DOMPDF.
- * This directory can be the same as DOMPDF_FONT_DIR
- *
- * Note: This directory must exist and be writable by the webserver process.
- */
-def("DOMPDF_FONT_CACHE", DOMPDF_FONT_DIR);
-
-/**
- * The location of a temporary directory.
- *
- * The directory specified must be writeable by the webserver process.
- * The temporary directory is required to download remote images and when
- * using the PFDLib back end.
- */
-def("DOMPDF_TEMP_DIR", sys_get_temp_dir());
-
-/**
- * ==== IMPORTANT ====
- *
- * dompdf's "chroot": Prevents dompdf from accessing system files or other
- * files on the webserver. All local files opened by dompdf must be in a
- * subdirectory of this directory. DO NOT set it to '/' since this could
- * allow an attacker to use dompdf to read any files on the server. This
- * should be an absolute path.
- * This is only checked on command line call by dompdf.php, but not by
- * direct class use like:
- * $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
- */
-def("DOMPDF_CHROOT", realpath(DOMPDF_DIR));
-
-/**
- * Whether to use Unicode fonts or not.
- *
- * When set to true the PDF backend must be set to "CPDF" and fonts must be
- * loaded via load_font.php.
- *
- * When enabled, dompdf can support all Unicode glyphs. Any glyphs used in a
- * document must be present in your fonts, however.
- */
-def("DOMPDF_UNICODE_ENABLED", true);
-
-/**
- * Whether to enable font subsetting or not.
- */
-def("DOMPDF_ENABLE_FONTSUBSETTING", false);
-
-/**
- * The PDF rendering backend to use
- *
- * Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
- * 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
- * fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
- * Canvas_Factory} ultimately determines which rendering class to instantiate
- * based on this setting.
- *
- * Both PDFLib & CPDF rendering backends provide sufficient rendering
- * capabilities for dompdf, however additional features (e.g. object,
- * image and font support, etc.) differ between backends. Please see
- * {@link PDFLib_Adapter} for more information on the PDFLib backend
- * and {@link CPDF_Adapter} and lib/class.pdf.php for more information
- * on CPDF. Also see the documentation for each backend at the links
- * below.
- *
- * The GD rendering backend is a little different than PDFLib and
- * CPDF. Several features of CPDF and PDFLib are not supported or do
- * not make any sense when creating image files. For example,
- * multiple pages are not supported, nor are PDF 'objects'. Have a
- * look at {@link GD_Adapter} for more information. GD support is
- * experimental, so use it at your own risk.
- *
- * @link http://www.pdflib.com
- * @link http://www.ros.co.nz/pdf
- * @link http://www.php.net/image
- */
-def("DOMPDF_PDF_BACKEND", "CPDF");
-
-/**
- * PDFlib license key
- *
- * If you are using a licensed, commercial version of PDFlib, specify
- * your license key here. If you are using PDFlib-Lite or are evaluating
- * the commercial version of PDFlib, comment out this setting.
- *
- * @link http://www.pdflib.com
- *
- * If pdflib present in web server and auto or selected explicitely above,
- * a real license code must exist!
- */
-//def("DOMPDF_PDFLIB_LICENSE", "your license key here");
-
-/**
- * html target media view which should be rendered into pdf.
- * List of types and parsing rules for future extensions:
- * http://www.w3.org/TR/REC-html40/types.html
- * screen, tty, tv, projection, handheld, print, braille, aural, all
- * Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
- * Note, even though the generated pdf file is intended for print output,
- * the desired content might be different (e.g. screen or projection view of html file).
- * Therefore allow specification of content here.
- */
-def("DOMPDF_DEFAULT_MEDIA_TYPE", "screen");
-
-/**
- * The default paper size.
- *
- * North America standard is "letter"; other countries generally "a4"
- *
- * @see CPDF_Adapter::PAPER_SIZES for valid sizes
- */
-def("DOMPDF_DEFAULT_PAPER_SIZE", "letter");
-
-/**
- * The default font family
- *
- * Used if no suitable fonts can be found. This must exist in the font folder.
- * @var string
- */
-def("DOMPDF_DEFAULT_FONT", "serif");
-
-/**
- * Image DPI setting
- *
- * This setting determines the default DPI setting for images and fonts. The
- * DPI may be overridden for inline images by explictly setting the
- * image's width & height style attributes (i.e. if the image's native
- * width is 600 pixels and you specify the image's width as 72 points,
- * the image will have a DPI of 600 in the rendered PDF. The DPI of
- * background images can not be overridden and is controlled entirely
- * via this parameter.
- *
- * For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
- * If a size in html is given as px (or without unit as image size),
- * this tells the corresponding size in pt at 72 DPI.
- * This adjusts the relative sizes to be similar to the rendering of the
- * html page in a reference browser.
- *
- * In pdf, always 1 pt = 1/72 inch
- *
- * Rendering resolution of various browsers in px per inch:
- * Windows Firefox and Internet Explorer:
- * SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
- * Linux Firefox:
- * about:config *resolution: Default:96
- * (xorg screen dimension in mm and Desktop font dpi settings are ignored)
- *
- * Take care about extra font/image zoom factor of browser.
- *
- * In images, size in pixel attribute, img css style, are overriding
- * the real image dimension in px for rendering.
- *
- * @var int
- */
-def("DOMPDF_DPI", 96);
-
-/**
- * Enable inline PHP
- *
- * If this setting is set to true then DOMPDF will automatically evaluate
- * inline PHP contained within tags.
- *
- * Attention!
- * Enabling this for documents you do not trust (e.g. arbitrary remote html
- * pages) is a security risk. Inline scripts are run with the same level of
- * system access available to dompdf. Set this option to false (recommended)
- * if you wish to process untrusted documents.
- *
- * @var bool
- */
-def("DOMPDF_ENABLE_PHP", false);
-
-/**
- * Enable inline Javascript
- *
- * If this setting is set to true then DOMPDF will automatically insert
- * JavaScript code contained within tags.
- *
- * @var bool
- */
-def("DOMPDF_ENABLE_JAVASCRIPT", true);
-
-/**
- * Enable remote file access
- *
- * If this setting is set to true, DOMPDF will access remote sites for
- * images and CSS files as required.
- * This is required for part of test case www/test/image_variants.html through www/examples.php
- *
- * Attention!
- * This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
- * allowing remote access to dompdf.php or on allowing remote html code to be passed to
- * $dompdf = new DOMPDF(); $dompdf->load_html(...);
- * This allows anonymous users to download legally doubtful internet content which on
- * tracing back appears to being downloaded by your server, or allows malicious php code
- * in remote html pages to be executed by your server with your account privileges.
- *
- * @var bool
- */
-def("DOMPDF_ENABLE_REMOTE", false);
-
-/**
- * The debug output log
- * @var string
- */
-def("DOMPDF_LOG_OUTPUT_FILE", DOMPDF_FONT_DIR."log.htm");
-
-/**
- * A ratio applied to the fonts height to be more like browsers' line height
- */
-def("DOMPDF_FONT_HEIGHT_RATIO", 1.1);
-
-/**
- * Enable CSS float
- *
- * Allows people to disabled CSS float support
- * @var bool
- */
-def("DOMPDF_ENABLE_CSS_FLOAT", false);
-
-/**
- * Enable the built in DOMPDF autoloader
- *
- * @var bool
- */
-def("DOMPDF_ENABLE_AUTOLOAD", true);
-
-/**
- * Prepend the DOMPDF autoload function to the spl_autoload stack
- *
- * @var bool
- */
-def("DOMPDF_AUTOLOAD_PREPEND", false);
-
-/**
- * Use the more-than-experimental HTML5 Lib parser
- */
-def("DOMPDF_ENABLE_HTML5PARSER", false);
-require_once(DOMPDF_LIB_DIR . "/html5lib/Parser.php");
-
-// ### End of user-configurable options ###
-
-/**
- * Load autoloader
- */
-if (DOMPDF_ENABLE_AUTOLOAD) {
- require_once(DOMPDF_INC_DIR . "/autoload.inc.php");
- require_once(DOMPDF_LIB_DIR . "/php-font-lib/classes/Font.php");
-}
-
-/**
- * Ensure that PHP is working with text internally using UTF8 character encoding.
- */
-mb_internal_encoding('UTF-8');
-
-/**
- * Global array of warnings generated by DomDocument parser and
- * stylesheet class
- *
- * @var array
- */
-global $_dompdf_warnings;
-$_dompdf_warnings = array();
-
-/**
- * If true, $_dompdf_warnings is dumped on script termination when using
- * dompdf/dompdf.php or after rendering when using the DOMPDF class.
- * When using the class, setting this value to true will prevent you from
- * streaming the PDF.
- *
- * @var bool
- */
-global $_dompdf_show_warnings;
-$_dompdf_show_warnings = false;
-
-/**
- * If true, the entire tree is dumped to stdout in dompdf.cls.php.
- * Setting this value to true will prevent you from streaming the PDF.
- *
- * @var bool
- */
-global $_dompdf_debug;
-$_dompdf_debug = false;
-
-/**
- * Array of enabled debug message types
- *
- * @var array
- */
-global $_DOMPDF_DEBUG_TYPES;
-$_DOMPDF_DEBUG_TYPES = array(); //array("page-break" => 1);
-
-/* Optionally enable different classes of debug output before the pdf content.
- * Visible if displaying pdf as text,
- * E.g. on repeated display of same pdf in browser when pdf is not taken out of
- * the browser cache and the premature output prevents setting of the mime type.
- */
-def('DEBUGPNG', false);
-def('DEBUGKEEPTEMP', false);
-def('DEBUGCSS', false);
-
-/* Layout debugging. Will display rectangles around different block levels.
- * Visible in the PDF itself.
- */
-def('DEBUG_LAYOUT', false);
-def('DEBUG_LAYOUT_LINES', true);
-def('DEBUG_LAYOUT_BLOCKS', true);
-def('DEBUG_LAYOUT_INLINE', true);
-def('DEBUG_LAYOUT_PADDINGBOX', true);
diff --git a/library/vendor/dompdf/include/absolute_positioner.cls.php b/library/vendor/dompdf/include/absolute_positioner.cls.php
deleted file mode 100644
index 050db49f7..000000000
--- a/library/vendor/dompdf/include/absolute_positioner.cls.php
+++ /dev/null
@@ -1,125 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Positions absolutely positioned frames
- */
-class Absolute_Positioner extends Positioner {
-
- function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
-
- function position() {
-
- $frame = $this->_frame;
- $style = $frame->get_style();
-
- $p = $frame->find_positionned_parent();
-
- list($x, $y, $w, $h) = $frame->get_containing_block();
-
- $top = $style->length_in_pt($style->top, $h);
- $right = $style->length_in_pt($style->right, $w);
- $bottom = $style->length_in_pt($style->bottom, $h);
- $left = $style->length_in_pt($style->left, $w);
-
- if ( $p && !($left === "auto" && $right === "auto") ) {
- // Get the parent's padding box (see http://www.w3.org/TR/CSS21/visuren.html#propdef-top)
- list($x, $y, $w, $h) = $p->get_padding_box();
- }
-
- list($width, $height) = array($frame->get_margin_width(), $frame->get_margin_height());
-
- $orig_style = $this->_frame->get_original_style();
- $orig_width = $orig_style->width;
- $orig_height = $orig_style->height;
-
- /****************************
-
- Width auto:
- ____________| left=auto | left=fixed |
- right=auto | A | B |
- right=fixed | C | D |
-
- Width fixed:
- ____________| left=auto | left=fixed |
- right=auto | E | F |
- right=fixed | G | H |
-
- *****************************/
-
- if ( $left === "auto" ) {
- if ( $right === "auto" ) {
- // A or E - Keep the frame at the same position
- $x = $x + $frame->find_block_parent()->get_current_line_box()->w;
- }
- else {
- if ( $orig_width === "auto" ) {
- // C
- $x += $w - $width - $right;
- }
- else {
- // G
- $x += $w - $width - $right;
- }
- }
- }
- else {
- if ( $right === "auto" ) {
- // B or F
- $x += $left;
- }
- else {
- if ( $orig_width === "auto" ) {
- // D - TODO change width
- $x += $left;
- }
- else {
- // H - Everything is fixed: left + width win
- $x += $left;
- }
- }
- }
-
- // The same vertically
- if ( $top === "auto" ) {
- if ( $bottom === "auto" ) {
- // A or E - Keep the frame at the same position
- $y = $frame->find_block_parent()->get_current_line_box()->y;
- }
- else {
- if ( $orig_height === "auto" ) {
- // C
- $y += $h - $height - $bottom;
- }
- else {
- // G
- $y += $h - $height - $bottom;
- }
- }
- }
- else {
- if ( $bottom === "auto" ) {
- // B or F
- $y += $top;
- }
- else {
- if ( $orig_height === "auto" ) {
- // D - TODO change height
- $y += $top;
- }
- else {
- // H - Everything is fixed: top + height win
- $y += $top;
- }
- }
- }
-
- $frame->set_position($x, $y);
-
- }
-}
\ No newline at end of file
diff --git a/library/vendor/dompdf/include/abstract_renderer.cls.php b/library/vendor/dompdf/include/abstract_renderer.cls.php
deleted file mode 100644
index dcd801306..000000000
--- a/library/vendor/dompdf/include/abstract_renderer.cls.php
+++ /dev/null
@@ -1,759 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Base renderer class
- *
- * @access private
- * @package dompdf
- */
-abstract class Abstract_Renderer {
-
- /**
- * Rendering backend
- *
- * @var Canvas
- */
- protected $_canvas;
-
- /**
- * Current dompdf instance
- *
- * @var DOMPDF
- */
- protected $_dompdf;
-
- /**
- * Class constructor
- *
- * @param DOMPDF $dompdf The current dompdf instance
- */
- function __construct(DOMPDF $dompdf) {
- $this->_dompdf = $dompdf;
- $this->_canvas = $dompdf->get_canvas();
- }
-
- /**
- * Render a frame.
- *
- * Specialized in child classes
- *
- * @param Frame $frame The frame to render
- */
- abstract function render(Frame $frame);
-
- //........................................................................
-
- /**
- * Render a background image over a rectangular area
- *
- * @param string $url The background image to load
- * @param float $x The left edge of the rectangular area
- * @param float $y The top edge of the rectangular area
- * @param float $width The width of the rectangular area
- * @param float $height The height of the rectangular area
- * @param Style $style The associated Style object
- *
- * @throws Exception
- */
- protected function _background_image($url, $x, $y, $width, $height, $style) {
- if ( !function_exists("imagecreatetruecolor") ) {
- throw new Exception("The PHP GD extension is required, but is not installed.");
- }
-
- $sheet = $style->get_stylesheet();
-
- // Skip degenerate cases
- if ( $width == 0 || $height == 0 ) {
- return;
- }
-
- $box_width = $width;
- $box_height = $height;
-
- //debugpng
- if (DEBUGPNG) print '[_background_image '.$url.']';
-
- list($img, $type, /*$msg*/) = Image_Cache::resolve_url(
- $url,
- $sheet->get_protocol(),
- $sheet->get_host(),
- $sheet->get_base_path(),
- $this->_dompdf
- );
-
- // Bail if the image is no good
- if ( Image_Cache::is_broken($img) ) {
- return;
- }
-
- //Try to optimize away reading and composing of same background multiple times
- //Postponing read with imagecreatefrom ...()
- //final composition parameters and name not known yet
- //Therefore read dimension directly from file, instead of creating gd object first.
- //$img_w = imagesx($src); $img_h = imagesy($src);
-
- list($img_w, $img_h) = dompdf_getimagesize($img, $this->_dompdf->get_http_context());
- if (!isset($img_w) || $img_w == 0 || !isset($img_h) || $img_h == 0) {
- return;
- }
-
- $repeat = $style->background_repeat;
- $dpi = $this->_dompdf->get_option("dpi");
-
- //Increase background resolution and dependent box size according to image resolution to be placed in
- //Then image can be copied in without resize
- $bg_width = round((float)($width * $dpi) / 72);
- $bg_height = round((float)($height * $dpi) / 72);
-
- //Need %bg_x, $bg_y as background pos, where img starts, converted to pixel
-
- list($bg_x, $bg_y) = $style->background_position;
-
- if ( is_percent($bg_x) ) {
- // The point $bg_x % from the left edge of the image is placed
- // $bg_x % from the left edge of the background rectangle
- $p = ((float)$bg_x)/100.0;
- $x1 = $p * $img_w;
- $x2 = $p * $bg_width;
-
- $bg_x = $x2 - $x1;
- }
- else {
- $bg_x = (float)($style->length_in_pt($bg_x)*$dpi) / 72;
- }
-
- $bg_x = round($bg_x + $style->length_in_pt($style->border_left_width)*$dpi / 72);
-
- if ( is_percent($bg_y) ) {
- // The point $bg_y % from the left edge of the image is placed
- // $bg_y % from the left edge of the background rectangle
- $p = ((float)$bg_y)/100.0;
- $y1 = $p * $img_h;
- $y2 = $p * $bg_height;
-
- $bg_y = $y2 - $y1;
- }
- else {
- $bg_y = (float)($style->length_in_pt($bg_y)*$dpi) / 72;
- }
-
- $bg_y = round($bg_y + $style->length_in_pt($style->border_top_width)*$dpi / 72);
-
- //clip background to the image area on partial repeat. Nothing to do if img off area
- //On repeat, normalize start position to the tile at immediate left/top or 0/0 of area
- //On no repeat with positive offset: move size/start to have offset==0
- //Handle x/y Dimensions separately
-
- if ( $repeat !== "repeat" && $repeat !== "repeat-x" ) {
- //No repeat x
- if ($bg_x < 0) {
- $bg_width = $img_w + $bg_x;
- }
- else {
- $x += ($bg_x * 72)/$dpi;
- $bg_width = $bg_width - $bg_x;
- if ($bg_width > $img_w) {
- $bg_width = $img_w;
- }
- $bg_x = 0;
- }
-
- if ($bg_width <= 0) {
- return;
- }
-
- $width = (float)($bg_width * 72)/$dpi;
- }
- else {
- //repeat x
- if ($bg_x < 0) {
- $bg_x = - ((-$bg_x) % $img_w);
- }
- else {
- $bg_x = $bg_x % $img_w;
- if ($bg_x > 0) {
- $bg_x -= $img_w;
- }
- }
- }
-
- if ( $repeat !== "repeat" && $repeat !== "repeat-y" ) {
- //no repeat y
- if ($bg_y < 0) {
- $bg_height = $img_h + $bg_y;
- }
- else {
- $y += ($bg_y * 72)/$dpi;
- $bg_height = $bg_height - $bg_y;
- if ($bg_height > $img_h) {
- $bg_height = $img_h;
- }
- $bg_y = 0;
- }
- if ($bg_height <= 0) {
- return;
- }
- $height = (float)($bg_height * 72)/$dpi;
- }
- else {
- //repeat y
- if ($bg_y < 0) {
- $bg_y = - ((-$bg_y) % $img_h);
- }
- else {
- $bg_y = $bg_y % $img_h;
- if ($bg_y > 0) {
- $bg_y -= $img_h;
- }
- }
- }
-
- //Optimization, if repeat has no effect
- if ( $repeat === "repeat" && $bg_y <= 0 && $img_h+$bg_y >= $bg_height ) {
- $repeat = "repeat-x";
- }
-
- if ( $repeat === "repeat" && $bg_x <= 0 && $img_w+$bg_x >= $bg_width ) {
- $repeat = "repeat-y";
- }
-
- if ( ($repeat === "repeat-x" && $bg_x <= 0 && $img_w+$bg_x >= $bg_width) ||
- ($repeat === "repeat-y" && $bg_y <= 0 && $img_h+$bg_y >= $bg_height) ) {
- $repeat = "no-repeat";
- }
-
- //Use filename as indicator only
- //different names for different variants to have different copies in the pdf
- //This is not dependent of background color of box! .'_'.(is_array($bg_color) ? $bg_color["hex"] : $bg_color)
- //Note: Here, bg_* are the start values, not end values after going through the tile loops!
-
- $filedummy = $img;
-
- $is_png = false;
- $filedummy .= '_'.$bg_width.'_'.$bg_height.'_'.$bg_x.'_'.$bg_y.'_'.$repeat;
-
- //Optimization to avoid multiple times rendering the same image.
- //If check functions are existing and identical image already cached,
- //then skip creation of duplicate, because it is not needed by addImagePng
- if ( $this->_canvas instanceof CPDF_Adapter &&
- $this->_canvas->get_cpdf()->image_iscached($filedummy) ) {
- $bg = null;
- }
-
- else {
-
- // Create a new image to fit over the background rectangle
- $bg = imagecreatetruecolor($bg_width, $bg_height);
-
- switch (strtolower($type)) {
- case IMAGETYPE_PNG:
- $is_png = true;
- imagesavealpha($bg, true);
- imagealphablending($bg, false);
- $src = imagecreatefrompng($img);
- break;
-
- case IMAGETYPE_JPEG:
- $src = imagecreatefromjpeg($img);
- break;
-
- case IMAGETYPE_GIF:
- $src = imagecreatefromgif($img);
- break;
-
- case IMAGETYPE_BMP:
- $src = imagecreatefrombmp($img);
- break;
-
- default:
- return; // Unsupported image type
- }
-
- if ( $src == null ) {
- return;
- }
-
- //Background color if box is not relevant here
- //Non transparent image: box clipped to real size. Background non relevant.
- //Transparent image: The image controls the transparency and lets shine through whatever background.
- //However on transparent image preset the composed image with the transparency color,
- //to keep the transparency when copying over the non transparent parts of the tiles.
- $ti = imagecolortransparent($src);
-
- if ( $ti >= 0 ) {
- $tc = imagecolorsforindex($src, $ti);
- $ti = imagecolorallocate($bg, $tc['red'], $tc['green'], $tc['blue']);
- imagefill($bg, 0, 0, $ti);
- imagecolortransparent($bg, $ti);
- }
-
- //This has only an effect for the non repeatable dimension.
- //compute start of src and dest coordinates of the single copy
- if ( $bg_x < 0 ) {
- $dst_x = 0;
- $src_x = -$bg_x;
- }
- else {
- $src_x = 0;
- $dst_x = $bg_x;
- }
-
- if ( $bg_y < 0 ) {
- $dst_y = 0;
- $src_y = -$bg_y;
- }
- else {
- $src_y = 0;
- $dst_y = $bg_y;
- }
-
- //For historical reasons exchange meanings of variables:
- //start_* will be the start values, while bg_* will be the temporary start values in the loops
- $start_x = $bg_x;
- $start_y = $bg_y;
-
- // Copy regions from the source image to the background
- if ( $repeat === "no-repeat" ) {
-
- // Simply place the image on the background
- imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $img_w, $img_h);
-
- }
- else if ( $repeat === "repeat-x" ) {
-
- for ( $bg_x = $start_x; $bg_x < $bg_width; $bg_x += $img_w ) {
- if ( $bg_x < 0 ) {
- $dst_x = 0;
- $src_x = -$bg_x;
- $w = $img_w + $bg_x;
- }
- else {
- $dst_x = $bg_x;
- $src_x = 0;
- $w = $img_w;
- }
- imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $w, $img_h);
- }
-
- }
- else if ( $repeat === "repeat-y" ) {
-
- for ( $bg_y = $start_y; $bg_y < $bg_height; $bg_y += $img_h ) {
- if ( $bg_y < 0 ) {
- $dst_y = 0;
- $src_y = -$bg_y;
- $h = $img_h + $bg_y;
- }
- else {
- $dst_y = $bg_y;
- $src_y = 0;
- $h = $img_h;
- }
- imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $img_w, $h);
-
- }
-
- }
- else if ( $repeat === "repeat" ) {
-
- for ( $bg_y = $start_y; $bg_y < $bg_height; $bg_y += $img_h ) {
- for ( $bg_x = $start_x; $bg_x < $bg_width; $bg_x += $img_w ) {
-
- if ( $bg_x < 0 ) {
- $dst_x = 0;
- $src_x = -$bg_x;
- $w = $img_w + $bg_x;
- }
- else {
- $dst_x = $bg_x;
- $src_x = 0;
- $w = $img_w;
- }
-
- if ( $bg_y < 0 ) {
- $dst_y = 0;
- $src_y = -$bg_y;
- $h = $img_h + $bg_y;
- }
- else {
- $dst_y = $bg_y;
- $src_y = 0;
- $h = $img_h;
- }
- imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $w, $h);
- }
- }
- }
-
- else {
- print 'Unknown repeat!';
- }
-
- imagedestroy($src);
-
- } /* End optimize away creation of duplicates */
-
- $this->_canvas->clipping_rectangle($x, $y, $box_width, $box_height);
-
- //img: image url string
- //img_w, img_h: original image size in px
- //width, height: box size in pt
- //bg_width, bg_height: box size in px
- //x, y: left/top edge of box on page in pt
- //start_x, start_y: placement of image relative to pattern
- //$repeat: repeat mode
- //$bg: GD object of result image
- //$src: GD object of original image
- //When using cpdf and optimization to direct png creation from gd object is available,
- //don't create temp file, but place gd object directly into the pdf
- if ( !$is_png && $this->_canvas instanceof CPDF_Adapter ) {
- // Note: CPDF_Adapter image converts y position
- $this->_canvas->get_cpdf()->addImagePng($filedummy, $x, $this->_canvas->get_height() - $y - $height, $width, $height, $bg);
- }
-
- else {
- $tmp_dir = $this->_dompdf->get_option("temp_dir");
- $tmp_name = tempnam($tmp_dir, "bg_dompdf_img_");
- @unlink($tmp_name);
- $tmp_file = "$tmp_name.png";
-
- //debugpng
- if (DEBUGPNG) print '[_background_image '.$tmp_file.']';
-
- imagepng($bg, $tmp_file);
- $this->_canvas->image($tmp_file, $x, $y, $width, $height);
- imagedestroy($bg);
-
- //debugpng
- if (DEBUGPNG) print '[_background_image unlink '.$tmp_file.']';
-
- if (!DEBUGKEEPTEMP) {
- unlink($tmp_file);
- }
- }
-
- $this->_canvas->clipping_end();
- }
-
- protected function _get_dash_pattern($style, $width) {
- $pattern = array();
-
- switch ($style) {
- default:
- /*case "solid":
- case "double":
- case "groove":
- case "inset":
- case "outset":
- case "ridge":*/
- case "none": break;
-
- case "dotted":
- if ( $width <= 1 )
- $pattern = array($width, $width*2);
- else
- $pattern = array($width);
- break;
-
- case "dashed":
- $pattern = array(3 * $width);
- break;
- }
-
- return $pattern;
- }
-
- protected function _border_none($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- return;
- }
-
- protected function _border_hidden($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- return;
- }
-
- // Border rendering functions
-
- protected function _border_dotted($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- $this->_border_line($x, $y, $length, $color, $widths, $side, $corner_style, "dotted", $r1, $r2);
- }
-
-
- protected function _border_dashed($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- $this->_border_line($x, $y, $length, $color, $widths, $side, $corner_style, "dashed", $r1, $r2);
- }
-
-
- protected function _border_solid($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- // TODO: Solve rendering where one corner is beveled (radius == 0), one corner isn't.
- if ( $corner_style !== "bevel" || $r1 > 0 || $r2 > 0 ) {
- // do it the simple way
- $this->_border_line($x, $y, $length, $color, $widths, $side, $corner_style, "solid", $r1, $r2);
- return;
- }
-
- list($top, $right, $bottom, $left) = $widths;
-
- // All this polygon business is for beveled corners...
- switch ($side) {
- case "top":
- $points = array($x, $y,
- $x + $length, $y,
- $x + $length - $right, $y + $top,
- $x + $left, $y + $top);
- $this->_canvas->polygon($points, $color, null, null, true);
- break;
-
- case "bottom":
- $points = array($x, $y,
- $x + $length, $y,
- $x + $length - $right, $y - $bottom,
- $x + $left, $y - $bottom);
- $this->_canvas->polygon($points, $color, null, null, true);
- break;
-
- case "left":
- $points = array($x, $y,
- $x, $y + $length,
- $x + $left, $y + $length - $bottom,
- $x + $left, $y + $top);
- $this->_canvas->polygon($points, $color, null, null, true);
- break;
-
- case "right":
- $points = array($x, $y,
- $x, $y + $length,
- $x - $right, $y + $length - $bottom,
- $x - $right, $y + $top);
- $this->_canvas->polygon($points, $color, null, null, true);
- break;
-
- default:
- return;
- }
- }
-
- protected function _apply_ratio($side, $ratio, $top, $right, $bottom, $left, &$x, &$y, &$length, &$r1, &$r2) {
- switch ($side) {
-
- case "top":
- $r1 -= $left * $ratio;
- $r2 -= $right * $ratio;
- $x += $left * $ratio;
- $y += $top * $ratio;
- $length -= $left * $ratio + $right * $ratio;
- break;
-
- case "bottom":
- $r1 -= $right * $ratio;
- $r2 -= $left * $ratio;
- $x += $left * $ratio;
- $y -= $bottom * $ratio;
- $length -= $left * $ratio + $right * $ratio;
- break;
-
- case "left":
- $r1 -= $top * $ratio;
- $r2 -= $bottom * $ratio;
- $x += $left * $ratio;
- $y += $top * $ratio;
- $length -= $top * $ratio + $bottom * $ratio;
- break;
-
- case "right":
- $r1 -= $bottom * $ratio;
- $r2 -= $top * $ratio;
- $x -= $right * $ratio;
- $y += $top * $ratio;
- $length -= $top * $ratio + $bottom * $ratio;
- break;
-
- default:
- return;
-
- }
- }
-
- protected function _border_double($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- list($top, $right, $bottom, $left) = $widths;
-
- $third_widths = array($top / 3, $right / 3, $bottom / 3, $left / 3);
-
- // draw the outer border
- $this->_border_solid($x, $y, $length, $color, $third_widths, $side, $corner_style, $r1, $r2);
-
- $this->_apply_ratio($side, 2/3, $top, $right, $bottom, $left, $x, $y, $length, $r1, $r2);
-
- $this->_border_solid($x, $y, $length, $color, $third_widths, $side, $corner_style, $r1, $r2);
- }
-
- protected function _border_groove($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- list($top, $right, $bottom, $left) = $widths;
-
- $half_widths = array($top / 2, $right / 2, $bottom / 2, $left / 2);
-
- $this->_border_inset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
-
- $this->_apply_ratio($side, 0.5, $top, $right, $bottom, $left, $x, $y, $length, $r1, $r2);
-
- $this->_border_outset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
-
- }
-
- protected function _border_ridge($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- list($top, $right, $bottom, $left) = $widths;
-
- $half_widths = array($top / 2, $right / 2, $bottom / 2, $left / 2);
-
- $this->_border_outset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
-
- $this->_apply_ratio($side, 0.5, $top, $right, $bottom, $left, $x, $y, $length, $r1, $r2);
-
- $this->_border_inset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
-
- }
-
- protected function _tint($c) {
- if ( !is_numeric($c) )
- return $c;
-
- return min(1, $c + 0.16);
- }
-
- protected function _shade($c) {
- if ( !is_numeric($c) )
- return $c;
-
- return max(0, $c - 0.33);
- }
-
- protected function _border_inset($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- switch ($side) {
- case "top":
- case "left":
- $shade = array_map(array($this, "_shade"), $color);
- $this->_border_solid($x, $y, $length, $shade, $widths, $side, $corner_style, $r1, $r2);
- break;
-
- case "bottom":
- case "right":
- $tint = array_map(array($this, "_tint"), $color);
- $this->_border_solid($x, $y, $length, $tint, $widths, $side, $corner_style, $r1, $r2);
- break;
-
- default:
- return;
- }
- }
-
- protected function _border_outset($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0) {
- switch ($side) {
- case "top":
- case "left":
- $tint = array_map(array($this, "_tint"), $color);
- $this->_border_solid($x, $y, $length, $tint, $widths, $side, $corner_style, $r1, $r2);
- break;
-
- case "bottom":
- case "right":
- $shade = array_map(array($this, "_shade"), $color);
- $this->_border_solid($x, $y, $length, $shade, $widths, $side, $corner_style, $r1, $r2);
- break;
-
- default:
- return;
- }
- }
- // Draws a solid, dotted, or dashed line, observing the border radius
- protected function _border_line($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $pattern_name, $r1 = 0, $r2 = 0) {
- list($top, $right, $bottom, $left) = $widths;
-
- $width = $$side;
- $pattern = $this->_get_dash_pattern($pattern_name, $width);
-
- $half_width = $width/2;
- $r1 -= $half_width;
- $r2 -= $half_width;
- $adjust = $r1/80;
- $length -= $width;
-
- switch ($side) {
- case "top":
- $x += $half_width;
- $y += $half_width;
-
- if ( $r1 > 0 ) {
- $this->_canvas->arc($x + $r1, $y + $r1, $r1, $r1, 90-$adjust, 135+$adjust, $color, $width, $pattern);
- }
-
- $this->_canvas->line($x + $r1, $y, $x + $length - $r2, $y, $color, $width, $pattern);
-
- if ( $r2 > 0 ) {
- $this->_canvas->arc($x + $length - $r2, $y + $r2, $r2, $r2, 45-$adjust, 90+$adjust, $color, $width, $pattern);
- }
- break;
-
- case "bottom":
- $x += $half_width;
- $y -= $half_width;
-
- if ( $r1 > 0 ) {
- $this->_canvas->arc($x + $r1, $y - $r1, $r1, $r1, 225-$adjust, 270+$adjust, $color, $width, $pattern);
- }
-
- $this->_canvas->line($x + $r1, $y, $x + $length - $r2, $y, $color, $width, $pattern);
-
- if ( $r2 > 0 ) {
- $this->_canvas->arc($x + $length - $r2, $y - $r2, $r2, $r2, 270-$adjust, 315+$adjust, $color, $width, $pattern);
- }
- break;
-
- case "left":
- $y += $half_width;
- $x += $half_width;
-
- if ( $r1 > 0 ) {
- $this->_canvas->arc($x + $r1, $y + $r1, $r1, $r1, 135-$adjust, 180+$adjust, $color, $width, $pattern);
- }
-
- $this->_canvas->line($x, $y + $r1, $x, $y + $length - $r2, $color, $width, $pattern);
-
- if ( $r2 > 0 ) {
- $this->_canvas->arc($x + $r2, $y + $length - $r2, $r2, $r2, 180-$adjust, 225+$adjust, $color, $width, $pattern);
- }
- break;
-
- case "right":
- $y += $half_width;
- $x -= $half_width;
-
- if ( $r1 > 0 ) {
- $this->_canvas->arc($x - $r1, $y + $r1, $r1, $r1, 0-$adjust, 45+$adjust, $color, $width, $pattern);
- }
-
- $this->_canvas->line($x, $y + $r1, $x, $y + $length - $r2, $color, $width, $pattern);
-
- if ( $r2 > 0 ) {
- $this->_canvas->arc($x - $r2, $y + $length - $r2, $r2, $r2, 315-$adjust, 360+$adjust, $color, $width, $pattern);
- }
- break;
- }
- }
-
- protected function _set_opacity($opacity) {
- if ( is_numeric($opacity) && $opacity <= 1.0 && $opacity >= 0.0 ) {
- $this->_canvas->set_opacity( $opacity );
- }
- }
-
- protected function _debug_layout($box, $color = "red", $style = array()) {
- $this->_canvas->rectangle($box[0], $box[1], $box[2], $box[3], CSS_Color::parse($color), 0.1, $style);
- }
-}
diff --git a/library/vendor/dompdf/include/attribute_translator.cls.php b/library/vendor/dompdf/include/attribute_translator.cls.php
deleted file mode 100644
index 68da668c1..000000000
--- a/library/vendor/dompdf/include/attribute_translator.cls.php
+++ /dev/null
@@ -1,592 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Translates HTML 4.0 attributes into CSS rules
- *
- * @package dompdf
- */
-class Attribute_Translator {
- static $_style_attr = "_html_style_attribute";
-
- // Munged data originally from
- // http://www.w3.org/TR/REC-html40/index/attributes.html
- // http://www.cs.tut.fi/~jkorpela/html2css.html
- static private $__ATTRIBUTE_LOOKUP = array(
- //'caption' => array ( 'align' => '', ),
- 'img' => array(
- 'align' => array(
- 'bottom' => 'vertical-align: baseline;',
- 'middle' => 'vertical-align: middle;',
- 'top' => 'vertical-align: top;',
- 'left' => 'float: left;',
- 'right' => 'float: right;'
- ),
- 'border' => 'border: %0.2F px solid;',
- 'height' => 'height: %s px;',
- 'hspace' => 'padding-left: %1$0.2F px; padding-right: %1$0.2F px;',
- 'vspace' => 'padding-top: %1$0.2F px; padding-bottom: %1$0.2F px;',
- 'width' => 'width: %s px;',
- ),
- 'table' => array(
- 'align' => array(
- 'left' => 'margin-left: 0; margin-right: auto;',
- 'center' => 'margin-left: auto; margin-right: auto;',
- 'right' => 'margin-left: auto; margin-right: 0;'
- ),
- 'bgcolor' => 'background-color: %s;',
- 'border' => '!set_table_border',
- 'cellpadding' => '!set_table_cellpadding',//'border-spacing: %0.2F; border-collapse: separate;',
- 'cellspacing' => '!set_table_cellspacing',
- 'frame' => array(
- 'void' => 'border-style: none;',
- 'above' => 'border-top-style: solid;',
- 'below' => 'border-bottom-style: solid;',
- 'hsides' => 'border-left-style: solid; border-right-style: solid;',
- 'vsides' => 'border-top-style: solid; border-bottom-style: solid;',
- 'lhs' => 'border-left-style: solid;',
- 'rhs' => 'border-right-style: solid;',
- 'box' => 'border-style: solid;',
- 'border' => 'border-style: solid;'
- ),
- 'rules' => '!set_table_rules',
- 'width' => 'width: %s;',
- ),
- 'hr' => array(
- 'align' => '!set_hr_align', // Need to grab width to set 'left' & 'right' correctly
- 'noshade' => 'border-style: solid;',
- 'size' => '!set_hr_size', //'border-width: %0.2F px;',
- 'width' => 'width: %s;',
- ),
- 'div' => array(
- 'align' => 'text-align: %s;',
- ),
- 'h1' => array(
- 'align' => 'text-align: %s;',
- ),
- 'h2' => array(
- 'align' => 'text-align: %s;',
- ),
- 'h3' => array(
- 'align' => 'text-align: %s;',
- ),
- 'h4' => array(
- 'align' => 'text-align: %s;',
- ),
- 'h5' => array(
- 'align' => 'text-align: %s;',
- ),
- 'h6' => array(
- 'align' => 'text-align: %s;',
- ),
- 'p' => array(
- 'align' => 'text-align: %s;',
- ),
-// 'col' => array(
-// 'align' => '',
-// 'valign' => '',
-// ),
-// 'colgroup' => array(
-// 'align' => '',
-// 'valign' => '',
-// ),
- 'tbody' => array(
- 'align' => '!set_table_row_align',
- 'valign' => '!set_table_row_valign',
- ),
- 'td' => array(
- 'align' => 'text-align: %s;',
- 'bgcolor' => '!set_background_color',
- 'height' => 'height: %s;',
- 'nowrap' => 'white-space: nowrap;',
- 'valign' => 'vertical-align: %s;',
- 'width' => 'width: %s;',
- ),
- 'tfoot' => array(
- 'align' => '!set_table_row_align',
- 'valign' => '!set_table_row_valign',
- ),
- 'th' => array(
- 'align' => 'text-align: %s;',
- 'bgcolor' => '!set_background_color',
- 'height' => 'height: %s;',
- 'nowrap' => 'white-space: nowrap;',
- 'valign' => 'vertical-align: %s;',
- 'width' => 'width: %s;',
- ),
- 'thead' => array(
- 'align' => '!set_table_row_align',
- 'valign' => '!set_table_row_valign',
- ),
- 'tr' => array(
- 'align' => '!set_table_row_align',
- 'bgcolor' => '!set_table_row_bgcolor',
- 'valign' => '!set_table_row_valign',
- ),
- 'body' => array(
- 'background' => 'background-image: url(%s);',
- 'bgcolor' => '!set_background_color',
- 'link' => '!set_body_link',
- 'text' => '!set_color',
- ),
- 'br' => array(
- 'clear' => 'clear: %s;',
- ),
- 'basefont' => array(
- 'color' => '!set_color',
- 'face' => 'font-family: %s;',
- 'size' => '!set_basefont_size',
- ),
- 'font' => array(
- 'color' => '!set_color',
- 'face' => 'font-family: %s;',
- 'size' => '!set_font_size',
- ),
- 'dir' => array(
- 'compact' => 'margin: 0.5em 0;',
- ),
- 'dl' => array(
- 'compact' => 'margin: 0.5em 0;',
- ),
- 'menu' => array(
- 'compact' => 'margin: 0.5em 0;',
- ),
- 'ol' => array(
- 'compact' => 'margin: 0.5em 0;',
- 'start' => 'counter-reset: -dompdf-default-counter %d;',
- 'type' => 'list-style-type: %s;',
- ),
- 'ul' => array(
- 'compact' => 'margin: 0.5em 0;',
- 'type' => 'list-style-type: %s;',
- ),
- 'li' => array(
- 'type' => 'list-style-type: %s;',
- 'value' => 'counter-reset: -dompdf-default-counter %d;',
- ),
- 'pre' => array(
- 'width' => 'width: %s;',
- ),
- );
-
- static protected $_last_basefont_size = 3;
- static protected $_font_size_lookup = array(
- // For basefont support
- -3 => "4pt",
- -2 => "5pt",
- -1 => "6pt",
- 0 => "7pt",
-
- 1 => "8pt",
- 2 => "10pt",
- 3 => "12pt",
- 4 => "14pt",
- 5 => "18pt",
- 6 => "24pt",
- 7 => "34pt",
-
- // For basefont support
- 8 => "48pt",
- 9 => "44pt",
- 10 => "52pt",
- 11 => "60pt",
- );
-
- /**
- * @param Frame $frame
- */
- static function translate_attributes(Frame $frame) {
- $node = $frame->get_node();
- $tag = $node->nodeName;
-
- if ( !isset(self::$__ATTRIBUTE_LOOKUP[$tag]) ) {
- return;
- }
-
- $valid_attrs = self::$__ATTRIBUTE_LOOKUP[$tag];
- $attrs = $node->attributes;
- $style = rtrim($node->getAttribute(self::$_style_attr), "; ");
- if ( $style != "" ) {
- $style .= ";";
- }
-
- foreach ($attrs as $attr => $attr_node ) {
- if ( !isset($valid_attrs[$attr]) ) {
- continue;
- }
-
- $value = $attr_node->value;
-
- $target = $valid_attrs[$attr];
-
- // Look up $value in $target, if $target is an array:
- if ( is_array($target) ) {
- if ( isset($target[$value]) ) {
- $style .= " " . self::_resolve_target($node, $target[$value], $value);
- }
- }
- else {
- // otherwise use target directly
- $style .= " " . self::_resolve_target($node, $target, $value);
- }
- }
-
- if ( !is_null($style) ) {
- $style = ltrim($style);
- $node->setAttribute(self::$_style_attr, $style);
- }
-
- }
-
- /**
- * @param DOMNode $node
- * @param string $target
- * @param string $value
- *
- * @return string
- */
- static protected function _resolve_target(DOMNode $node, $target, $value) {
- if ( $target[0] === "!" ) {
- // Function call
- $func = "_" . mb_substr($target, 1);
- return self::$func($node, $value);
- }
-
- return $value ? sprintf($target, $value) : "";
- }
-
- /**
- * @param DOMElement $node
- * @param string $new_style
- */
- static function append_style(DOMElement $node, $new_style) {
- $style = rtrim($node->getAttribute(self::$_style_attr), ";");
- $style .= $new_style;
- $style = ltrim($style, ";");
- $node->setAttribute(self::$_style_attr, $style);
- }
-
- /**
- * @param DOMNode $node
- *
- * @return DOMNodeList|DOMElement[]
- */
- static protected function get_cell_list(DOMNode $node) {
- $xpath = new DOMXpath($node->ownerDocument);
-
- switch($node->nodeName) {
- default:
- case "table":
- $query = "tr/td | thead/tr/td | tbody/tr/td | tfoot/tr/td | tr/th | thead/tr/th | tbody/tr/th | tfoot/tr/th";
- break;
-
- case "tbody":
- case "tfoot":
- case "thead":
- $query = "tr/td | tr/th";
- break;
-
- case "tr":
- $query = "td | th";
- break;
- }
-
- return $xpath->query($query, $node);
- }
-
- /**
- * @param string $value
- *
- * @return string
- */
- static protected function _get_valid_color($value) {
- if ( preg_match('/^#?([0-9A-F]{6})$/i', $value, $matches) ) {
- $value = "#$matches[1]";
- }
-
- return $value;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return string
- */
- static protected function _set_color(DOMElement $node, $value) {
- $value = self::_get_valid_color($value);
- return "color: $value;";
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return string
- */
- static protected function _set_background_color(DOMElement $node, $value) {
- $value = self::_get_valid_color($value);
- return "background-color: $value;";
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null
- */
- static protected function _set_table_cellpadding(DOMElement $node, $value) {
- $cell_list = self::get_cell_list($node);
-
- foreach ($cell_list as $cell) {
- self::append_style($cell, "; padding: {$value}px;");
- }
-
- return null;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return string
- */
- static protected function _set_table_border(DOMElement $node, $value) {
- $cell_list = self::get_cell_list($node);
-
- foreach ($cell_list as $cell) {
- $style = rtrim($cell->getAttribute(self::$_style_attr));
- $style .= "; border-width: " . ($value > 0 ? 1 : 0) . "pt; border-style: inset;";
- $style = ltrim($style, ";");
- $cell->setAttribute(self::$_style_attr, $style);
- }
-
- $style = rtrim($node->getAttribute(self::$_style_attr), ";");
- $style .= "; border-width: $value" . "px; ";
- return ltrim($style, "; ");
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return string
- */
- static protected function _set_table_cellspacing(DOMElement $node, $value) {
- $style = rtrim($node->getAttribute(self::$_style_attr), ";");
-
- if ( $value == 0 ) {
- $style .= "; border-collapse: collapse;";
- }
- else {
- $style .= "; border-spacing: {$value}px; border-collapse: separate;";
- }
-
- return ltrim($style, ";");
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null|string
- */
- static protected function _set_table_rules(DOMElement $node, $value) {
- $new_style = "; border-collapse: collapse;";
-
- switch ($value) {
- case "none":
- $new_style .= "border-style: none;";
- break;
-
- case "groups":
- // FIXME: unsupported
- return null;
-
- case "rows":
- $new_style .= "border-style: solid none solid none; border-width: 1px; ";
- break;
-
- case "cols":
- $new_style .= "border-style: none solid none solid; border-width: 1px; ";
- break;
-
- case "all":
- $new_style .= "border-style: solid; border-width: 1px; ";
- break;
-
- default:
- // Invalid value
- return null;
- }
-
- $cell_list = self::get_cell_list($node);
-
- foreach ($cell_list as $cell) {
- $style = $cell->getAttribute(self::$_style_attr);
- $style .= $new_style;
- $cell->setAttribute(self::$_style_attr, $style);
- }
-
- $style = rtrim($node->getAttribute(self::$_style_attr), ";");
- $style .= "; border-collapse: collapse; ";
-
- return ltrim($style, "; ");
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return string
- */
- static protected function _set_hr_size(DOMElement $node, $value) {
- $style = rtrim($node->getAttribute(self::$_style_attr), ";");
- $style .= "; border-width: ".max(0, $value-2)."; ";
- return ltrim($style, "; ");
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null|string
- */
- static protected function _set_hr_align(DOMElement $node, $value) {
- $style = rtrim($node->getAttribute(self::$_style_attr),";");
- $width = $node->getAttribute("width");
-
- if ( $width == "" ) {
- $width = "100%";
- }
-
- $remainder = 100 - (double)rtrim($width, "% ");
-
- switch ($value) {
- case "left":
- $style .= "; margin-right: $remainder %;";
- break;
-
- case "right":
- $style .= "; margin-left: $remainder %;";
- break;
-
- case "center":
- $style .= "; margin-left: auto; margin-right: auto;";
- break;
-
- default:
- return null;
- }
-
- return ltrim($style, "; ");
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null
- */
- static protected function _set_table_row_align(DOMElement $node, $value) {
- $cell_list = self::get_cell_list($node);
-
- foreach ($cell_list as $cell) {
- self::append_style($cell, "; text-align: $value;");
- }
-
- return null;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null
- */
- static protected function _set_table_row_valign(DOMElement $node, $value) {
- $cell_list = self::get_cell_list($node);
-
- foreach ($cell_list as $cell) {
- self::append_style($cell, "; vertical-align: $value;");
- }
-
- return null;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null
- */
- static protected function _set_table_row_bgcolor(DOMElement $node, $value) {
- $cell_list = self::get_cell_list($node);
- $value = self::_get_valid_color($value);
-
- foreach ($cell_list as $cell) {
- self::append_style($cell, "; background-color: $value;");
- }
-
- return null;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null
- */
- static protected function _set_body_link(DOMElement $node, $value) {
- $a_list = $node->getElementsByTagName("a");
- $value = self::_get_valid_color($value);
-
- foreach ($a_list as $a) {
- self::append_style($a, "; color: $value;");
- }
-
- return null;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return null
- */
- static protected function _set_basefont_size(DOMElement $node, $value) {
- // FIXME: ? we don't actually set the font size of anything here, just
- // the base size for later modification by tags.
- self::$_last_basefont_size = $value;
- return null;
- }
-
- /**
- * @param DOMElement $node
- * @param string $value
- *
- * @return string
- */
- static protected function _set_font_size(DOMElement $node, $value) {
- $style = $node->getAttribute(self::$_style_attr);
-
- if ( $value[0] === "-" || $value[0] === "+" ) {
- $value = self::$_last_basefont_size + (int)$value;
- }
-
- if ( isset(self::$_font_size_lookup[$value]) ) {
- $style .= "; font-size: " . self::$_font_size_lookup[$value] . ";";
- }
- else {
- $style .= "; font-size: $value;";
- }
-
- return ltrim($style, "; ");
- }
-}
diff --git a/library/vendor/dompdf/include/autoload.inc.php b/library/vendor/dompdf/include/autoload.inc.php
deleted file mode 100644
index 509d3e3bc..000000000
--- a/library/vendor/dompdf/include/autoload.inc.php
+++ /dev/null
@@ -1,86 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * DOMPDF autoload function
- *
- * If you have an existing autoload function, add a call to this function
- * from your existing __autoload() implementation.
- *
- * @param string $class
- */
-function DOMPDF_autoload($class) {
- $filename = DOMPDF_INC_DIR . "/" . mb_strtolower($class) . ".cls.php";
-
- if ( is_file($filename) ) {
- include_once $filename;
- }
-}
-
-// If SPL autoload functions are available (PHP >= 5.1.2)
-if ( function_exists("spl_autoload_register") ) {
- $autoload = "DOMPDF_autoload";
- $funcs = spl_autoload_functions();
-
- // No functions currently in the stack.
- if ( !DOMPDF_AUTOLOAD_PREPEND || $funcs === false ) {
- spl_autoload_register($autoload);
- }
-
- // If PHP >= 5.3 the $prepend argument is available
- else if ( PHP_VERSION_ID >= 50300 ) {
- spl_autoload_register($autoload, true, true);
- }
-
- else {
- // Unregister existing autoloaders...
- $compat = (PHP_VERSION_ID <= 50102 && PHP_VERSION_ID >= 50100);
-
- foreach ($funcs as $func) {
- if (is_array($func)) {
- // :TRICKY: There are some compatibility issues and some
- // places where we need to error out
- $reflector = new ReflectionMethod($func[0], $func[1]);
- if (!$reflector->isStatic()) {
- throw new Exception('This function is not compatible with non-static object methods due to PHP Bug #44144.');
- }
-
- // Suprisingly, spl_autoload_register supports the
- // Class::staticMethod callback format, although call_user_func doesn't
- if ($compat) $func = implode('::', $func);
- }
-
- spl_autoload_unregister($func);
- }
-
- // Register the new one, thus putting it at the front of the stack...
- spl_autoload_register($autoload);
-
- // Now, go back and re-register all of our old ones.
- foreach ($funcs as $func) {
- spl_autoload_register($func);
- }
-
- // Be polite and ensure that userland autoload gets retained
- if ( function_exists("__autoload") ) {
- spl_autoload_register("__autoload");
- }
- }
-}
-
-else if ( !function_exists("__autoload") ) {
- /**
- * Default __autoload() function
- *
- * @param string $class
- */
- function __autoload($class) {
- DOMPDF_autoload($class);
- }
-}
diff --git a/library/vendor/dompdf/include/block_frame_decorator.cls.php b/library/vendor/dompdf/include/block_frame_decorator.cls.php
deleted file mode 100644
index 407635c0e..000000000
--- a/library/vendor/dompdf/include/block_frame_decorator.cls.php
+++ /dev/null
@@ -1,234 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Decorates frames for block layout
- *
- * @access private
- * @package dompdf
- */
-class Block_Frame_Decorator extends Frame_Decorator {
- /**
- * Current line index
- *
- * @var int
- */
- protected $_cl;
-
- /**
- * The block's line boxes
- *
- * @var Line_Box[]
- */
- protected $_line_boxes;
-
- function __construct(Frame $frame, DOMPDF $dompdf) {
- parent::__construct($frame, $dompdf);
-
- $this->_line_boxes = array(new Line_Box($this));
- $this->_cl = 0;
- }
-
- function reset() {
- parent::reset();
-
- $this->_line_boxes = array(new Line_Box($this));
- $this->_cl = 0;
- }
-
- /**
- * @return Line_Box
- */
- function get_current_line_box() {
- return $this->_line_boxes[$this->_cl];
- }
-
- /**
- * @return integer
- */
- function get_current_line_number() {
- return $this->_cl;
- }
-
- /**
- * @return Line_Box[]
- */
- function get_line_boxes() {
- return $this->_line_boxes;
- }
-
- /**
- * @param integer $i
- */
- function clear_line($i) {
- if ( isset($this->_line_boxes[$i]) ) {
- unset($this->_line_boxes[$i]);
- }
- }
-
- /**
- * @param Frame $frame
- */
- function add_frame_to_line(Frame $frame) {
- if ( !$frame->is_in_flow() ) {
- return;
- }
-
- $style = $frame->get_style();
-
- $frame->set_containing_line($this->_line_boxes[$this->_cl]);
-
- /*
- // Adds a new line after a block, only if certain conditions are met
- if ((($frame instanceof Inline_Frame_Decorator && $frame->get_node()->nodeName !== "br") ||
- $frame instanceof Text_Frame_Decorator && trim($frame->get_text())) &&
- ($frame->get_prev_sibling() && $frame->get_prev_sibling()->get_style()->display === "block" &&
- $this->_line_boxes[$this->_cl]->w > 0 )) {
-
- $this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
- $this->add_line();
-
- // Add each child of the inline frame to the line individually
- foreach ($frame->get_children() as $child)
- $this->add_frame_to_line( $child );
- }
- else*/
-
- // Handle inline frames (which are effectively wrappers)
- if ( $frame instanceof Inline_Frame_Decorator ) {
-
- // Handle line breaks
- if ( $frame->get_node()->nodeName === "br" ) {
- $this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
- $this->add_line(true);
- }
-
- return;
- }
-
- // Trim leading text if this is an empty line. Kinda a hack to put it here,
- // but what can you do...
- if ( $this->get_current_line_box()->w == 0 &&
- $frame->is_text_node() &&
- !$frame->is_pre() ) {
-
- $frame->set_text( ltrim($frame->get_text()) );
- $frame->recalculate_width();
- }
-
- $w = $frame->get_margin_width();
-
- if ( $w == 0 ) {
- return;
- }
-
- // Debugging code:
- /*
- pre_r("\nAdding frame to line: ");
-
- // pre_r("Me: " . $this->get_node()->nodeName . " (" . spl_object_hash($this->get_node()) . ")");
- // pre_r("Node: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")");
- if ( $frame->is_text_node() )
- pre_r('"'.$frame->get_node()->nodeValue.'"');
-
- pre_r("Line width: " . $this->_line_boxes[$this->_cl]->w);
- pre_r("Frame: " . get_class($frame));
- pre_r("Frame width: " . $w);
- pre_r("Frame height: " . $frame->get_margin_height());
- pre_r("Containing block width: " . $this->get_containing_block("w"));
- */
- // End debugging
-
- $line = $this->_line_boxes[$this->_cl];
- if ( $line->left + $line->w + $line->right + $w > $this->get_containing_block("w")) {
- $this->add_line();
- }
-
- $frame->position();
-
- $current_line = $this->_line_boxes[$this->_cl];
- $current_line->add_frame($frame);
-
- if ( $frame->is_text_node() ) {
- $current_line->wc += count(preg_split("/\s+/", trim($frame->get_text())));
- }
-
- $this->increase_line_width($w);
-
- $this->maximize_line_height($frame->get_margin_height(), $frame);
- }
-
- function remove_frames_from_line(Frame $frame) {
- // Search backwards through the lines for $frame
- $i = $this->_cl;
- $j = null;
-
- while ($i >= 0) {
- if ( ($j = in_array($frame, $this->_line_boxes[$i]->get_frames(), true)) !== false ) {
- break;
- }
-
- $i--;
- }
-
- if ( $j === false ) {
- return;
- }
-
- // Remove $frame and all frames that follow
- while ($j < count($this->_line_boxes[$i]->get_frames())) {
- $frames = $this->_line_boxes[$i]->get_frames();
- $f = $frames[$j];
- $frames[$j] = null;
- unset($frames[$j]);
- $j++;
- $this->_line_boxes[$i]->w -= $f->get_margin_width();
- }
-
- // Recalculate the height of the line
- $h = 0;
- foreach ($this->_line_boxes[$i]->get_frames() as $f) {
- $h = max( $h, $f->get_margin_height() );
- }
-
- $this->_line_boxes[$i]->h = $h;
-
- // Remove all lines that follow
- while ($this->_cl > $i) {
- $this->_line_boxes[ $this->_cl ] = null;
- unset($this->_line_boxes[ $this->_cl ]);
- $this->_cl--;
- }
- }
-
- function increase_line_width($w) {
- $this->_line_boxes[ $this->_cl ]->w += $w;
- }
-
- function maximize_line_height($val, Frame $frame) {
- if ( $val > $this->_line_boxes[ $this->_cl ]->h ) {
- $this->_line_boxes[ $this->_cl ]->tallest_frame = $frame;
- $this->_line_boxes[ $this->_cl ]->h = $val;
- }
- }
-
- function add_line($br = false) {
-
-// if ( $this->_line_boxes[$this->_cl]["h"] == 0 ) //count($this->_line_boxes[$i]["frames"]) == 0 ||
-// return;
-
- $this->_line_boxes[$this->_cl]->br = $br;
- $y = $this->_line_boxes[$this->_cl]->y + $this->_line_boxes[$this->_cl]->h;
-
- $new_line = new Line_Box($this, $y);
-
- $this->_line_boxes[ ++$this->_cl ] = $new_line;
- }
-
- //........................................................................
-}
diff --git a/library/vendor/dompdf/include/block_frame_reflower.cls.php b/library/vendor/dompdf/include/block_frame_reflower.cls.php
deleted file mode 100644
index bbbdba96d..000000000
--- a/library/vendor/dompdf/include/block_frame_reflower.cls.php
+++ /dev/null
@@ -1,805 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Reflows block frames
- *
- * @access private
- * @package dompdf
- */
-class Block_Frame_Reflower extends Frame_Reflower {
- // Minimum line width to justify, as fraction of available width
- const MIN_JUSTIFY_WIDTH = 0.80;
-
- /**
- * @var Block_Frame_Decorator
- */
- protected $_frame;
-
- function __construct(Block_Frame_Decorator $frame) { parent::__construct($frame); }
-
- /**
- * Calculate the ideal used value for the width property as per:
- * http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins
- *
- * @param float $width
- * @return array
- */
- protected function _calculate_width($width) {
- $frame = $this->_frame;
- $style = $frame->get_style();
- $w = $frame->get_containing_block("w");
-
- if ( $style->position === "fixed" ) {
- $w = $frame->get_parent()->get_containing_block("w");
- }
-
- $rm = $style->length_in_pt($style->margin_right, $w);
- $lm = $style->length_in_pt($style->margin_left, $w);
-
- $left = $style->length_in_pt($style->left, $w);
- $right = $style->length_in_pt($style->right, $w);
-
- // Handle 'auto' values
- $dims = array($style->border_left_width,
- $style->border_right_width,
- $style->padding_left,
- $style->padding_right,
- $width !== "auto" ? $width : 0,
- $rm !== "auto" ? $rm : 0,
- $lm !== "auto" ? $lm : 0);
-
- // absolutely positioned boxes take the 'left' and 'right' properties into account
- if ( $frame->is_absolute() ) {
- $absolute = true;
- $dims[] = $left !== "auto" ? $left : 0;
- $dims[] = $right !== "auto" ? $right : 0;
- }
- else {
- $absolute = false;
- }
-
- $sum = $style->length_in_pt($dims, $w);
-
- // Compare to the containing block
- $diff = $w - $sum;
-
- if ( $diff > 0 ) {
-
- if ( $absolute ) {
-
- // resolve auto properties: see
- // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
-
- if ( $width === "auto" && $left === "auto" && $right === "auto" ) {
-
- if ( $lm === "auto" ) $lm = 0;
- if ( $rm === "auto" ) $rm = 0;
-
- // Technically, the width should be "shrink-to-fit" i.e. based on the
- // preferred width of the content... a little too costly here as a
- // special case. Just get the width to take up the slack:
- $left = 0;
- $right = 0;
- $width = $diff;
- }
- else if ( $width === "auto" ) {
-
- if ( $lm === "auto" ) $lm = 0;
- if ( $rm === "auto" ) $rm = 0;
- if ( $left === "auto" ) $left = 0;
- if ( $right === "auto" ) $right = 0;
-
- $width = $diff;
- }
- else if ( $left === "auto" ) {
-
- if ( $lm === "auto" ) $lm = 0;
- if ( $rm === "auto" ) $rm = 0;
- if ( $right === "auto" ) $right = 0;
-
- $left = $diff;
- }
- else if ( $right === "auto" ) {
-
- if ( $lm === "auto" ) $lm = 0;
- if ( $rm === "auto" ) $rm = 0;
-
- $right = $diff;
- }
-
- }
- else {
-
- // Find auto properties and get them to take up the slack
- if ( $width === "auto" ) {
- $width = $diff;
- }
- else if ( $lm === "auto" && $rm === "auto" ) {
- $lm = $rm = round($diff / 2);
- }
- else if ( $lm === "auto" ) {
- $lm = $diff;
- }
- else if ( $rm === "auto" ) {
- $rm = $diff;
- }
- }
-
- }
- else if ($diff < 0) {
-
- // We are over constrained--set margin-right to the difference
- $rm = $diff;
-
- }
-
- return array(
- "width" => $width,
- "margin_left" => $lm,
- "margin_right" => $rm,
- "left" => $left,
- "right" => $right,
- );
- }
-
- /**
- * Call the above function, but resolve max/min widths
- *
- * @throws DOMPDF_Exception
- * @return array
- */
- protected function _calculate_restricted_width() {
- $frame = $this->_frame;
- $style = $frame->get_style();
- $cb = $frame->get_containing_block();
-
- if ( $style->position === "fixed" ) {
- $cb = $frame->get_root()->get_containing_block();
- }
-
- //if ( $style->position === "absolute" )
- // $cb = $frame->find_positionned_parent()->get_containing_block();
-
- if ( !isset($cb["w"]) ) {
- throw new DOMPDF_Exception("Box property calculation requires containing block width");
- }
-
- // Treat width 100% as auto
- if ( $style->width === "100%" ) {
- $width = "auto";
- }
- else {
- $width = $style->length_in_pt($style->width, $cb["w"]);
- }
-
- extract($this->_calculate_width($width));
-
- // Handle min/max width
- $min_width = $style->length_in_pt($style->min_width, $cb["w"]);
- $max_width = $style->length_in_pt($style->max_width, $cb["w"]);
-
- if ( $max_width !== "none" && $min_width > $max_width ) {
- list($max_width, $min_width) = array($min_width, $max_width);
- }
-
- if ( $max_width !== "none" && $width > $max_width ) {
- extract($this->_calculate_width($max_width));
- }
-
- if ( $width < $min_width ) {
- extract($this->_calculate_width($min_width));
- }
-
- return array($width, $margin_left, $margin_right, $left, $right);
- }
-
- /**
- * Determine the unrestricted height of content within the block
- * not by adding each line's height, but by getting the last line's position.
- * This because lines could have been pushed lower by a clearing element.
- *
- * @return float
- */
- protected function _calculate_content_height() {
- $lines = $this->_frame->get_line_boxes();
- $height = 0;
-
- foreach ($lines as $line) {
- $height += $line->h;
- }
-
- /*
- $first_line = reset($lines);
- $last_line = end($lines);
- $height2 = $last_line->y + $last_line->h - $first_line->y;
- */
-
- return $height;
- }
-
- /**
- * Determine the frame's restricted height
- *
- * @return array
- */
- protected function _calculate_restricted_height() {
- $frame = $this->_frame;
- $style = $frame->get_style();
- $content_height = $this->_calculate_content_height();
- $cb = $frame->get_containing_block();
-
- $height = $style->length_in_pt($style->height, $cb["h"]);
-
- $top = $style->length_in_pt($style->top, $cb["h"]);
- $bottom = $style->length_in_pt($style->bottom, $cb["h"]);
-
- $margin_top = $style->length_in_pt($style->margin_top, $cb["h"]);
- $margin_bottom = $style->length_in_pt($style->margin_bottom, $cb["h"]);
-
- if ( $frame->is_absolute() ) {
-
- // see http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height
-
- $dims = array($top !== "auto" ? $top : 0,
- $style->margin_top !== "auto" ? $style->margin_top : 0,
- $style->padding_top,
- $style->border_top_width,
- $height !== "auto" ? $height : 0,
- $style->border_bottom_width,
- $style->padding_bottom,
- $style->margin_bottom !== "auto" ? $style->margin_bottom : 0,
- $bottom !== "auto" ? $bottom : 0);
-
- $sum = $style->length_in_pt($dims, $cb["h"]);
-
- $diff = $cb["h"] - $sum;
-
- if ( $diff > 0 ) {
-
- if ( $height === "auto" && $top === "auto" && $bottom === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $height = $diff;
- }
- else if ( $height === "auto" && $top === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $height = $content_height;
- $top = $diff - $content_height;
- }
- else if ( $height === "auto" && $bottom === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $height = $content_height;
- $bottom = $diff - $content_height;
- }
- else if ( $top === "auto" && $bottom === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $bottom = $diff;
- }
- else if ( $top === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $top = $diff;
- }
- else if ( $height === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $height = $diff;
- }
- else if ( $bottom === "auto" ) {
-
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
-
- $bottom = $diff;
- }
- else {
-
- if ( $style->overflow === "visible" ) {
- // set all autos to zero
- if ( $margin_top === "auto" ) $margin_top = 0;
- if ( $margin_bottom === "auto" ) $margin_bottom = 0;
- if ( $top === "auto" ) $top = 0;
- if ( $bottom === "auto" ) $bottom = 0;
- if ( $height === "auto" ) $height = $content_height;
- }
-
- // FIXME: overflow hidden
- }
-
- }
-
- }
- else {
-
- // Expand the height if overflow is visible
- if ( $height === "auto" && $content_height > $height /* && $style->overflow === "visible" */) {
- $height = $content_height;
- }
-
- // FIXME: this should probably be moved to a seperate function as per
- // _calculate_restricted_width
-
- // Only handle min/max height if the height is independent of the frame's content
- if ( !($style->overflow === "visible" ||
- ($style->overflow === "hidden" && $height === "auto")) ) {
-
- $min_height = $style->min_height;
- $max_height = $style->max_height;
-
- if ( isset($cb["h"]) ) {
- $min_height = $style->length_in_pt($min_height, $cb["h"]);
- $max_height = $style->length_in_pt($max_height, $cb["h"]);
-
- }
- else if ( isset($cb["w"]) ) {
-
- if ( mb_strpos($min_height, "%") !== false ) {
- $min_height = 0;
- }
- else {
- $min_height = $style->length_in_pt($min_height, $cb["w"]);
- }
-
- if ( mb_strpos($max_height, "%") !== false ) {
- $max_height = "none";
- }
- else {
- $max_height = $style->length_in_pt($max_height, $cb["w"]);
- }
- }
-
- if ( $max_height !== "none" && $min_height > $max_height ) {
- // Swap 'em
- list($max_height, $min_height) = array($min_height, $max_height);
- }
-
- if ( $max_height !== "none" && $height > $max_height ) {
- $height = $max_height;
- }
-
- if ( $height < $min_height ) {
- $height = $min_height;
- }
- }
-
- }
-
- return array($height, $margin_top, $margin_bottom, $top, $bottom);
-
- }
-
- /**
- * Adjust the justification of each of our lines.
- * http://www.w3.org/TR/CSS21/text.html#propdef-text-align
- */
- protected function _text_align() {
- $style = $this->_frame->get_style();
- $w = $this->_frame->get_containing_block("w");
- $width = $style->length_in_pt($style->width, $w);
-
- switch ($style->text_align) {
- default:
- case "left":
- foreach ($this->_frame->get_line_boxes() as $line) {
- if ( !$line->left ) {
- continue;
- }
-
- foreach($line->get_frames() as $frame) {
- if ( $frame instanceof Block_Frame_Decorator) {
- continue;
- }
- $frame->set_position( $frame->get_position("x") + $line->left );
- }
- }
- return;
-
- case "right":
- foreach ($this->_frame->get_line_boxes() as $line) {
- // Move each child over by $dx
- $dx = $width - $line->w - $line->right;
-
- foreach($line->get_frames() as $frame) {
- // Block frames are not aligned by text-align
- if ($frame instanceof Block_Frame_Decorator) {
- continue;
- }
-
- $frame->set_position( $frame->get_position("x") + $dx );
- }
- }
- break;
-
-
- case "justify":
- // We justify all lines except the last one
- $lines = $this->_frame->get_line_boxes(); // needs to be a variable (strict standards)
- array_pop($lines);
-
- foreach($lines as $i => $line) {
- if ( $line->br ) {
- unset($lines[$i]);
- }
- }
-
- // One space character's width. Will be used to get a more accurate spacing
- $space_width = Font_Metrics::get_text_width(" ", $style->font_family, $style->font_size);
-
- foreach ($lines as $line) {
- if ( $line->left ) {
- foreach ( $line->get_frames() as $frame ) {
- if ( !$frame instanceof Text_Frame_Decorator ) {
- continue;
- }
-
- $frame->set_position( $frame->get_position("x") + $line->left );
- }
- }
-
- // Only set the spacing if the line is long enough. This is really
- // just an aesthetic choice ;)
- //if ( $line["left"] + $line["w"] + $line["right"] > self::MIN_JUSTIFY_WIDTH * $width ) {
-
- // Set the spacing for each child
- if ( $line->wc > 1 ) {
- $spacing = ($width - ($line->left + $line->w + $line->right) + $space_width) / ($line->wc - 1);
- }
- else {
- $spacing = 0;
- }
-
- $dx = 0;
- foreach($line->get_frames() as $frame) {
- if ( !$frame instanceof Text_Frame_Decorator ) {
- continue;
- }
-
- $text = $frame->get_text();
- $spaces = mb_substr_count($text, " ");
-
- $char_spacing = $style->length_in_pt($style->letter_spacing);
- $_spacing = $spacing + $char_spacing;
-
- $frame->set_position( $frame->get_position("x") + $dx );
- $frame->set_text_spacing($_spacing);
-
- $dx += $spaces * $_spacing;
- }
-
- // The line (should) now occupy the entire width
- $line->w = $width;
-
- //}
- }
- break;
-
- case "center":
- case "centre":
- foreach ($this->_frame->get_line_boxes() as $line) {
- // Centre each line by moving each frame in the line by:
- $dx = ($width + $line->left - $line->w - $line->right ) / 2;
-
- foreach ($line->get_frames() as $frame) {
- // Block frames are not aligned by text-align
- if ($frame instanceof Block_Frame_Decorator) {
- continue;
- }
-
- $frame->set_position( $frame->get_position("x") + $dx );
- }
- }
- break;
- }
- }
-
- /**
- * Align inline children vertically.
- * Aligns each child vertically after each line is reflowed
- */
- function vertical_align() {
-
- $canvas = null;
-
- foreach ( $this->_frame->get_line_boxes() as $line ) {
-
- $height = $line->h;
-
- foreach ( $line->get_frames() as $frame ) {
- $style = $frame->get_style();
-
- if ( $style->display !== "inline" ) {
- continue;
- }
-
- $align = $frame->get_parent()->get_style()->vertical_align;
-
- if ( !isset($canvas) ) {
- $canvas = $frame->get_root()->get_dompdf()->get_canvas();
- }
-
- $baseline = $canvas->get_font_baseline($style->font_family, $style->font_size);
- $y_offset = 0;
-
- switch ($align) {
- case "baseline":
- $y_offset = $height*0.8 - $baseline; // The 0.8 ratio is arbitrary until we find it's meaning
- break;
-
- case "middle":
- $y_offset = ($height*0.8 - $baseline) / 2;
- break;
-
- case "sub":
- $y_offset = 0.3 * $height;
- break;
-
- case "super":
- $y_offset = -0.2 * $height;
- break;
-
- case "text-top":
- case "top": // Not strictly accurate, but good enough for now
- break;
-
- case "text-bottom":
- case "bottom":
- $y_offset = $height*0.8 - $baseline;
- break;
- }
-
- if ( $y_offset ) {
- $frame->move(0, $y_offset);
- }
- }
- }
- }
-
- /**
- * @param Frame $child
- */
- function process_clear(Frame $child){
- $enable_css_float = $this->get_dompdf()->get_option("enable_css_float");
- if ( !$enable_css_float ) {
- return;
- }
-
- $child_style = $child->get_style();
- $root = $this->_frame->get_root();
-
- // Handle "clear"
- if ( $child_style->clear !== "none" ) {
- $lowest_y = $root->get_lowest_float_offset($child);
-
- // If a float is still applying, we handle it
- if ( $lowest_y ) {
- if ( $child->is_in_flow() ) {
- $line_box = $this->_frame->get_current_line_box();
- $line_box->y = $lowest_y + $child->get_margin_height();
- $line_box->left = 0;
- $line_box->right = 0;
- }
-
- $child->move(0, $lowest_y - $child->get_position("y"));
- }
- }
- }
-
- /**
- * @param Frame $child
- * @param float $cb_x
- * @param float $cb_w
- */
- function process_float(Frame $child, $cb_x, $cb_w){
- $enable_css_float = $this->_frame->get_dompdf()->get_option("enable_css_float");
- if ( !$enable_css_float ) {
- return;
- }
-
- $child_style = $child->get_style();
- $root = $this->_frame->get_root();
-
- // Handle "float"
- if ( $child_style->float !== "none" ) {
- $root->add_floating_frame($child);
-
- // Remove next frame's beginning whitespace
- $next = $child->get_next_sibling();
- if ( $next && $next instanceof Text_Frame_Decorator) {
- $next->set_text(ltrim($next->get_text()));
- }
-
- $line_box = $this->_frame->get_current_line_box();
- list($old_x, $old_y) = $child->get_position();
-
- $float_x = $cb_x;
- $float_y = $old_y;
- $float_w = $child->get_margin_width();
-
- if ( $child_style->clear === "none" ) {
- switch( $child_style->float ) {
- case "left":
- $float_x += $line_box->left;
- break;
- case "right":
- $float_x += ($cb_w - $line_box->right - $float_w);
- break;
- }
- }
- else {
- if ( $child_style->float === "right" ) {
- $float_x += ($cb_w - $float_w);
- }
- }
-
- if ( $cb_w < $float_x + $float_w - $old_x ) {
- // TODO handle when floating elements don't fit
- }
-
- $line_box->get_float_offsets();
-
- if ( $child->_float_next_line ) {
- $float_y += $line_box->h;
- }
-
- $child->set_position($float_x, $float_y);
- $child->move($float_x - $old_x, $float_y - $old_y, true);
- }
- }
-
- /**
- * @param Frame_Decorator $block
- */
- function reflow(Block_Frame_Decorator $block = null) {
-
- // Check if a page break is forced
- $page = $this->_frame->get_root();
- $page->check_forced_page_break($this->_frame);
-
- // Bail if the page is full
- if ( $page->is_full() ) {
- return;
- }
-
- // Generated content
- $this->_set_content();
-
- // Collapse margins if required
- $this->_collapse_margins();
-
- $style = $this->_frame->get_style();
- $cb = $this->_frame->get_containing_block();
-
- if ( $style->position === "fixed" ) {
- $cb = $this->_frame->get_root()->get_containing_block();
- }
-
- // Determine the constraints imposed by this frame: calculate the width
- // of the content area:
- list($w, $left_margin, $right_margin, $left, $right) = $this->_calculate_restricted_width();
-
- // Store the calculated properties
- $style->width = $w . "pt";
- $style->margin_left = $left_margin."pt";
- $style->margin_right = $right_margin."pt";
- $style->left = $left ."pt";
- $style->right = $right . "pt";
-
- // Update the position
- $this->_frame->position();
- list($x, $y) = $this->_frame->get_position();
-
- // Adjust the first line based on the text-indent property
- $indent = $style->length_in_pt($style->text_indent, $cb["w"]);
- $this->_frame->increase_line_width($indent);
-
- // Determine the content edge
- $top = $style->length_in_pt(array($style->margin_top,
- $style->padding_top,
- $style->border_top_width), $cb["h"]);
-
- $bottom = $style->length_in_pt(array($style->border_bottom_width,
- $style->margin_bottom,
- $style->padding_bottom), $cb["h"]);
-
- $cb_x = $x + $left_margin + $style->length_in_pt(array($style->border_left_width,
- $style->padding_left), $cb["w"]);
-
- $cb_y = $y + $top;
-
- $cb_h = ($cb["h"] + $cb["y"]) - $bottom - $cb_y;
-
- // Set the y position of the first line in this block
- $line_box = $this->_frame->get_current_line_box();
- $line_box->y = $cb_y;
- $line_box->get_float_offsets();
-
- // Set the containing blocks and reflow each child
- foreach ( $this->_frame->get_children() as $child ) {
-
- // Bail out if the page is full
- if ( $page->is_full() ) {
- break;
- }
-
- $child->set_containing_block($cb_x, $cb_y, $w, $cb_h);
-
- $this->process_clear($child);
-
- $child->reflow($this->_frame);
-
- // Don't add the child to the line if a page break has occurred
- if ( $page->check_page_break($child) ) {
- break;
- }
-
- $this->process_float($child, $cb_x, $w);
- }
-
- // Determine our height
- list($height, $margin_top, $margin_bottom, $top, $bottom) = $this->_calculate_restricted_height();
- $style->height = $height;
- $style->margin_top = $margin_top;
- $style->margin_bottom = $margin_bottom;
- $style->top = $top;
- $style->bottom = $bottom;
-
- $needs_reposition = ($style->position === "absolute" && ($style->right !== "auto" || $style->bottom !== "auto"));
-
- // Absolute positioning measurement
- if ( $needs_reposition ) {
- $orig_style = $this->_frame->get_original_style();
- if ( $orig_style->width === "auto" && ($orig_style->left === "auto" || $orig_style->right === "auto") ) {
- $width = 0;
- foreach ($this->_frame->get_line_boxes() as $line) {
- $width = max($line->w, $width);
- }
- $style->width = $width;
- }
-
- $style->left = $orig_style->left;
- $style->right = $orig_style->right;
- }
-
- $this->_text_align();
- $this->vertical_align();
-
- // Absolute positioning
- if ( $needs_reposition ) {
- list($x, $y) = $this->_frame->get_position();
- $this->_frame->position();
- list($new_x, $new_y) = $this->_frame->get_position();
- $this->_frame->move($new_x-$x, $new_y-$y, true);
- }
-
- if ( $block && $this->_frame->is_in_flow() ) {
- $block->add_frame_to_line($this->_frame);
-
- // May be inline-block
- if ( $style->display === "block" ) {
- $block->add_line();
- }
- }
- }
-}
diff --git a/library/vendor/dompdf/include/block_positioner.cls.php b/library/vendor/dompdf/include/block_positioner.cls.php
deleted file mode 100644
index d7e1c3fbc..000000000
--- a/library/vendor/dompdf/include/block_positioner.cls.php
+++ /dev/null
@@ -1,57 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Positions block frames
- *
- * @access private
- * @package dompdf
- */
-class Block_Positioner extends Positioner {
-
-
- function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
-
- //........................................................................
-
- function position() {
- $frame = $this->_frame;
- $style = $frame->get_style();
- $cb = $frame->get_containing_block();
- $p = $frame->find_block_parent();
-
- if ( $p ) {
- $float = $style->float;
-
- $enable_css_float = $frame->get_dompdf()->get_option("enable_css_float");
- if ( !$enable_css_float || !$float || $float === "none" ) {
- $p->add_line(true);
- }
- $y = $p->get_current_line_box()->y;
-
- }
- else {
- $y = $cb["y"];
- }
-
- $x = $cb["x"];
-
- // Relative positionning
- if ( $style->position === "relative" ) {
- $top = $style->length_in_pt($style->top, $cb["h"]);
- //$right = $style->length_in_pt($style->right, $cb["w"]);
- //$bottom = $style->length_in_pt($style->bottom, $cb["h"]);
- $left = $style->length_in_pt($style->left, $cb["w"]);
-
- $x += $left;
- $y += $top;
- }
-
- $frame->set_position($x, $y);
- }
-}
diff --git a/library/vendor/dompdf/include/block_renderer.cls.php b/library/vendor/dompdf/include/block_renderer.cls.php
deleted file mode 100644
index ef42c93d5..000000000
--- a/library/vendor/dompdf/include/block_renderer.cls.php
+++ /dev/null
@@ -1,230 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Renders block frames
- *
- * @access private
- * @package dompdf
- */
-class Block_Renderer extends Abstract_Renderer {
-
- //........................................................................
-
- function render(Frame $frame) {
- $style = $frame->get_style();
- $node = $frame->get_node();
-
- list($x, $y, $w, $h) = $frame->get_border_box();
-
- $this->_set_opacity( $frame->get_opacity( $style->opacity ) );
-
- if ( $node->nodeName === "body" ) {
- $h = $frame->get_containing_block("h") - $style->length_in_pt(array(
- $style->margin_top,
- $style->border_top_width,
- $style->border_bottom_width,
- $style->margin_bottom),
- $style->width);
- }
-
- // Handle anchors & links
- if ( $node->nodeName === "a" && $href = $node->getAttribute("href") ) {
- $this->_canvas->add_link($href, $x, $y, $w, $h);
- }
-
- // Draw our background, border and content
- list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
-
- if ( $tl + $tr + $br + $bl > 0 ) {
- $this->_canvas->clipping_roundrectangle( $x, $y, $w, $h, $tl, $tr, $br, $bl );
- }
-
- if ( ($bg = $style->background_color) !== "transparent" ) {
- $this->_canvas->filled_rectangle( $x, $y, $w, $h, $bg );
- }
-
- if ( ($url = $style->background_image) && $url !== "none" ) {
- $this->_background_image($url, $x, $y, $w, $h, $style);
- }
-
- if ( $tl + $tr + $br + $bl > 0 ) {
- $this->_canvas->clipping_end();
- }
-
- $border_box = array($x, $y, $w, $h);
- $this->_render_border($frame, $border_box);
- $this->_render_outline($frame, $border_box);
-
- if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
- $this->_debug_layout($frame->get_border_box(), "red");
- if (DEBUG_LAYOUT_PADDINGBOX) {
- $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
- }
- }
-
- if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
- foreach ($frame->get_decorator()->get_line_boxes() as $line) {
- $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
- }
- }
- }
-
- protected function _render_border(Frame_Decorator $frame, $border_box = null, $corner_style = "bevel") {
- $style = $frame->get_style();
- $bp = $style->get_border_properties();
-
- if ( empty($border_box) ) {
- $border_box = $frame->get_border_box();
- }
-
- // find the radius
- $radius = $style->get_computed_border_radius($border_box[2], $border_box[3]); // w, h
-
- // Short-cut: If all the borders are "solid" with the same color and style, and no radius, we'd better draw a rectangle
- if (
- in_array($bp["top"]["style"], array("solid", "dashed", "dotted")) &&
- $bp["top"] == $bp["right"] &&
- $bp["right"] == $bp["bottom"] &&
- $bp["bottom"] == $bp["left"] &&
- array_sum($radius) == 0
- ) {
- $props = $bp["top"];
- if ( $props["color"] === "transparent" || $props["width"] <= 0 ) return;
-
- list($x, $y, $w, $h) = $border_box;
- $width = $style->length_in_pt($props["width"]);
- $pattern = $this->_get_dash_pattern($props["style"], $width);
- $this->_canvas->rectangle($x + $width / 2, $y + $width / 2, $w - $width, $h - $width, $props["color"], $width, $pattern);
- return;
- }
-
- // Do it the long way
- $widths = array($style->length_in_pt($bp["top"]["width"]),
- $style->length_in_pt($bp["right"]["width"]),
- $style->length_in_pt($bp["bottom"]["width"]),
- $style->length_in_pt($bp["left"]["width"]));
-
- foreach ($bp as $side => $props) {
- list($x, $y, $w, $h) = $border_box;
- $length = 0;
- $r1 = 0;
- $r2 = 0;
-
- if ( !$props["style"] ||
- $props["style"] === "none" ||
- $props["width"] <= 0 ||
- $props["color"] == "transparent" )
- continue;
-
- switch($side) {
- case "top":
- $length = $w;
- $r1 = $radius["top-left"];
- $r2 = $radius["top-right"];
- break;
-
- case "bottom":
- $length = $w;
- $y += $h;
- $r1 = $radius["bottom-left"];
- $r2 = $radius["bottom-right"];
- break;
-
- case "left":
- $length = $h;
- $r1 = $radius["top-left"];
- $r2 = $radius["bottom-left"];
- break;
-
- case "right":
- $length = $h;
- $x += $w;
- $r1 = $radius["top-right"];
- $r2 = $radius["bottom-right"];
- break;
- default:
- break;
- }
- $method = "_border_" . $props["style"];
-
- // draw rounded corners
- $this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style, $r1, $r2);
- }
- }
-
- protected function _render_outline(Frame_Decorator $frame, $border_box = null, $corner_style = "bevel") {
- $style = $frame->get_style();
-
- $props = array(
- "width" => $style->outline_width,
- "style" => $style->outline_style,
- "color" => $style->outline_color,
- );
-
- if ( !$props["style"] || $props["style"] === "none" || $props["width"] <= 0 )
- return;
-
- if ( empty($border_box) ) {
- $border_box = $frame->get_border_box();
- }
-
- $offset = $style->length_in_pt($props["width"]);
- $pattern = $this->_get_dash_pattern($props["style"], $offset);
-
- // If the outline style is "solid" we'd better draw a rectangle
- if ( in_array($props["style"], array("solid", "dashed", "dotted")) ) {
- $border_box[0] -= $offset / 2;
- $border_box[1] -= $offset / 2;
- $border_box[2] += $offset;
- $border_box[3] += $offset;
-
- list($x, $y, $w, $h) = $border_box;
- $this->_canvas->rectangle($x, $y, $w, $h, $props["color"], $offset, $pattern);
- return;
- }
-
- $border_box[0] -= $offset;
- $border_box[1] -= $offset;
- $border_box[2] += $offset * 2;
- $border_box[3] += $offset * 2;
-
- $method = "_border_" . $props["style"];
- $widths = array_fill(0, 4, $props["width"]);
- $sides = array("top", "right", "left", "bottom");
- $length = 0;
-
- foreach ($sides as $side) {
- list($x, $y, $w, $h) = $border_box;
-
- switch($side) {
- case "top":
- $length = $w;
- break;
-
- case "bottom":
- $length = $w;
- $y += $h;
- break;
-
- case "left":
- $length = $h;
- break;
-
- case "right":
- $length = $h;
- $x += $w;
- break;
- default:
- break;
- }
-
- $this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style);
- }
- }
-}
diff --git a/library/vendor/dompdf/include/cached_pdf_decorator.cls.php b/library/vendor/dompdf/include/cached_pdf_decorator.cls.php
deleted file mode 100644
index 519e572e8..000000000
--- a/library/vendor/dompdf/include/cached_pdf_decorator.cls.php
+++ /dev/null
@@ -1,164 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Caching canvas implementation
- *
- * Each rendered page is serialized and stored in the {@link Page_Cache}.
- * This is useful for static forms/pages that do not need to be re-rendered
- * all the time.
- *
- * This class decorates normal CPDF_Adapters. It is currently completely
- * experimental.
- *
- * @access private
- * @package dompdf
- */
-class Cached_PDF_Decorator extends CPDF_Adapter implements Canvas {
- /**
- * @var CPDF_Adapter
- */
- protected $_pdf;
- protected $_cache_id;
- protected $_current_page_id;
- protected $_fonts; // fonts used in this document
-
- function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf) {
- $this->_fonts = array();
- }
-
- /**
- * Must be called after constructor
- *
- * @param int $cache_id
- * @param CPDF_Adapter $pdf
- */
- function init($cache_id, CPDF_Adapter $pdf) {
- $this->_cache_id = $cache_id;
- $this->_pdf = $pdf;
- $this->_current_page_id = $this->_pdf->open_object();
- }
-
- //........................................................................
-
- function get_cpdf() { return $this->_pdf->get_cpdf(); }
-
- function open_object() { $this->_pdf->open_object(); }
- function reopen_object($object) { $this->_pdf->reopen_object($object); }
-
- function close_object() { $this->_pdf->close_object(); }
-
- function add_object($object, $where = 'all') { $this->_pdf->add_object($object, $where); }
-
- function serialize_object($id) { $this->_pdf->serialize_object($id); }
-
- function reopen_serialized_object($obj) { $this->_pdf->reopen_serialized_object($obj); }
-
- //........................................................................
-
- function get_width() { return $this->_pdf->get_width(); }
- function get_height() { return $this->_pdf->get_height(); }
- function get_page_number() { return $this->_pdf->get_page_number(); }
- function get_page_count() { return $this->_pdf->get_page_count(); }
-
- function set_page_number($num) { $this->_pdf->set_page_number($num); }
- function set_page_count($count) { $this->_pdf->set_page_count($count); }
-
- function line($x1, $y1, $x2, $y2, $color, $width, $style = array()) {
- $this->_pdf->line($x1, $y1, $x2, $y2, $color, $width, $style);
- }
-
- function rectangle($x1, $y1, $w, $h, $color, $width, $style = array()) {
- $this->_pdf->rectangle($x1, $y1, $w, $h, $color, $width, $style);
- }
-
- function filled_rectangle($x1, $y1, $w, $h, $color) {
- $this->_pdf->filled_rectangle($x1, $y1, $w, $h, $color);
- }
-
- function polygon($points, $color, $width = null, $style = array(), $fill = false) {
- $this->_pdf->polygon($points, $color, $width, $style, $fill);
- }
-
- function circle($x, $y, $r1, $color, $width = null, $style = null, $fill = false) {
- $this->_pdf->circle($x, $y, $r1, $color, $width, $style, $fill);
- }
-
- function image($img_url, $x, $y, $w, $h, $resolution = "normal") {
- $this->_pdf->image($img_url, $x, $y, $w, $h, $resolution);
- }
-
- function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
- $this->_fonts[$font] = true;
- $this->_pdf->text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
- }
-
- function page_text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
-
- // We want to remove this from cached pages since it may not be correct
- $this->_pdf->close_object();
- $this->_pdf->page_text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
- $this->_pdf->reopen_object($this->_current_page_id);
- }
-
- function page_script($script, $type = 'text/php') {
-
- // We want to remove this from cached pages since it may not be correct
- $this->_pdf->close_object();
- $this->_pdf->page_script($script, $type);
- $this->_pdf->reopen_object($this->_current_page_id);
- }
-
- function new_page() {
- $this->_pdf->close_object();
-
- // Add the object to the current page
- $this->_pdf->add_object($this->_current_page_id, "add");
- $this->_pdf->new_page();
-
- Page_Cache::store_page($this->_cache_id,
- $this->_pdf->get_page_number() - 1,
- $this->_pdf->serialize_object($this->_current_page_id));
-
- $this->_current_page_id = $this->_pdf->open_object();
- return $this->_current_page_id;
- }
-
- function stream($filename, $options = null) {
- // Store the last page in the page cache
- if ( !is_null($this->_current_page_id) ) {
- $this->_pdf->close_object();
- $this->_pdf->add_object($this->_current_page_id, "add");
- Page_Cache::store_page($this->_cache_id,
- $this->_pdf->get_page_number(),
- $this->_pdf->serialize_object($this->_current_page_id));
- Page_Cache::store_fonts($this->_cache_id, $this->_fonts);
- $this->_current_page_id = null;
- }
-
- $this->_pdf->stream($filename);
-
- }
-
- function output($options = null) {
- // Store the last page in the page cache
- if ( !is_null($this->_current_page_id) ) {
- $this->_pdf->close_object();
- $this->_pdf->add_object($this->_current_page_id, "add");
- Page_Cache::store_page($this->_cache_id,
- $this->_pdf->get_page_number(),
- $this->_pdf->serialize_object($this->_current_page_id));
- $this->_current_page_id = null;
- }
-
- return $this->_pdf->output();
- }
-
- function get_messages() { return $this->_pdf->get_messages(); }
-
-}
diff --git a/library/vendor/dompdf/include/canvas.cls.php b/library/vendor/dompdf/include/canvas.cls.php
deleted file mode 100644
index 0158df6b1..000000000
--- a/library/vendor/dompdf/include/canvas.cls.php
+++ /dev/null
@@ -1,385 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Main rendering interface
- *
- * Currently {@link CPDF_Adapter}, {@link PDFLib_Adapter}, {@link TCPDF_Adapter}, and {@link GD_Adapter}
- * implement this interface.
- *
- * Implementations should measure x and y increasing to the left and down,
- * respectively, with the origin in the top left corner. Implementations
- * are free to use a unit other than points for length, but I can't
- * guarantee that the results will look any good.
- *
- * @package dompdf
- */
-interface Canvas {
- function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf);
-
- /**
- * @return DOMPDF
- */
- function get_dompdf();
-
- /**
- * Returns the current page number
- *
- * @return int
- */
- function get_page_number();
-
- /**
- * Returns the total number of pages
- *
- * @return int
- */
- function get_page_count();
-
- /**
- * Sets the total number of pages
- *
- * @param int $count
- */
- function set_page_count($count);
-
- /**
- * Draws a line from x1,y1 to x2,y2
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the format of the
- * $style parameter (aka dash).
- *
- * @param float $x1
- * @param float $y1
- * @param float $x2
- * @param float $y2
- * @param array $color
- * @param float $width
- * @param array $style
- */
- function line($x1, $y1, $x2, $y2, $color, $width, $style = null);
-
- /**
- * Draws a rectangle at x1,y1 with width w and height h
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the $style
- * parameter (aka dash)
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- * @param array $color
- * @param float $width
- * @param array $style
- */
- function rectangle($x1, $y1, $w, $h, $color, $width, $style = null);
-
- /**
- * Draws a filled rectangle at x1,y1 with width w and height h
- *
- * See {@link Style::munge_color()} for the format of the color array.
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- * @param array $color
- */
- function filled_rectangle($x1, $y1, $w, $h, $color);
-
- /**
- * Starts a clipping rectangle at x1,y1 with width w and height h
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- */
- function clipping_rectangle($x1, $y1, $w, $h);
-
- /**
- * Starts a rounded clipping rectangle at x1,y1 with width w and height h
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- * @param float $tl
- * @param float $tr
- * @param float $br
- * @param float $bl
- *
- * @return
- */
- function clipping_roundrectangle($x1, $y1, $w, $h, $tl, $tr, $br, $bl);
-
- /**
- * Ends the last clipping shape
- */
- function clipping_end();
-
- /**
- * Save current state
- */
- function save();
-
- /**
- * Restore last state
- */
- function restore();
-
- /**
- * Rotate
- */
- function rotate($angle, $x, $y);
-
- /**
- * Skew
- */
- function skew($angle_x, $angle_y, $x, $y);
-
- /**
- * Scale
- */
- function scale($s_x, $s_y, $x, $y);
-
- /**
- * Translate
- */
- function translate($t_x, $t_y);
-
- /**
- * Transform
- */
- function transform($a, $b, $c, $d, $e, $f);
-
- /**
- * Draws a polygon
- *
- * The polygon is formed by joining all the points stored in the $points
- * array. $points has the following structure:
- *
- * array(0 => x1,
- * 1 => y1,
- * 2 => x2,
- * 3 => y2,
- * ...
- * );
- *
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the $style
- * parameter (aka dash)
- *
- * @param array $points
- * @param array $color
- * @param float $width
- * @param array $style
- * @param bool $fill Fills the polygon if true
- */
- function polygon($points, $color, $width = null, $style = null, $fill = false);
-
- /**
- * Draws a circle at $x,$y with radius $r
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the $style
- * parameter (aka dash)
- *
- * @param float $x
- * @param float $y
- * @param float $r
- * @param array $color
- * @param float $width
- * @param array $style
- * @param bool $fill Fills the circle if true
- */
- function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false);
-
- /**
- * Add an image to the pdf.
- *
- * The image is placed at the specified x and y coordinates with the
- * given width and height.
- *
- * @param string $img_url the path to the image
- * @param float $x x position
- * @param float $y y position
- * @param int $w width (in pixels)
- * @param int $h height (in pixels)
- * @param string $resolution The resolution of the image
- */
- function image($img_url, $x, $y, $w, $h, $resolution = "normal");
-
- /**
- * Add an arc to the PDF
- * See {@link Style::munge_color()} for the format of the color array.
- *
- * @param float $x X coordinate of the arc
- * @param float $y Y coordinate of the arc
- * @param float $r1 Radius 1
- * @param float $r2 Radius 2
- * @param float $astart Start angle in degrees
- * @param float $aend End angle in degrees
- * @param array $color Color
- * @param float $width
- * @param array $style
- *
- * @return void
- */
- function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = array());
-
- /**
- * Writes text at the specified x and y coordinates
- * See {@link Style::munge_color()} for the format of the color array.
- *
- * @param float $x
- * @param float $y
- * @param string $text the text to write
- * @param string $font the font file to use
- * @param float $size the font size, in points
- * @param array $color
- * @param float $word_space word spacing adjustment
- * @param float $char_space char spacing adjustment
- * @param float $angle angle
- *
- * @return void
- */
- function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0);
-
- /**
- * Add a named destination (similar to ... in html)
- *
- * @param string $anchorname The name of the named destination
- */
- function add_named_dest($anchorname);
-
- /**
- * Add a link to the pdf
- *
- * @param string $url The url to link to
- * @param float $x The x position of the link
- * @param float $y The y position of the link
- * @param float $width The width of the link
- * @param float $height The height of the link
- *
- * @return void
- */
- function add_link($url, $x, $y, $width, $height);
-
- /**
- * Add meta information to the pdf
- *
- * @param string $name Label of the value (Creator, Producer, etc.)
- * @param string $value The text to set
- */
- function add_info($name, $value);
-
- /**
- * Calculates text size, in points
- *
- * @param string $text the text to be sized
- * @param string $font the desired font
- * @param float $size the desired font size
- * @param float $word_spacing word spacing, if any
- * @param float $char_spacing
- *
- * @return float
- */
- function get_text_width($text, $font, $size, $word_spacing = 0.0, $char_spacing = 0.0);
-
- /**
- * Calculates font height, in points
- *
- * @param string $font
- * @param float $size
- *
- * @return float
- */
- function get_font_height($font, $size);
-
- /**
- * Calculates font baseline, in points
- *
- * @param string $font
- * @param float $size
- *
- * @return float
- */
- function get_font_baseline($font, $size);
-
- /**
- * Returns the font x-height, in points
- *
- * @param string $font
- * @param float $size
- *
- * @return float
- */
- //function get_font_x_height($font, $size);
-
- /**
- * Sets the opacity
- *
- * @param float $opacity
- * @param string $mode
- */
- function set_opacity($opacity, $mode = "Normal");
-
- /**
- * Sets the default view
- *
- * @param string $view
- * 'XYZ' left, top, zoom
- * 'Fit'
- * 'FitH' top
- * 'FitV' left
- * 'FitR' left,bottom,right
- * 'FitB'
- * 'FitBH' top
- * 'FitBV' left
- * @param array $options
- *
- * @return void
- */
- function set_default_view($view, $options = array());
-
- /**
- * @param string $script
- *
- * @return void
- */
- function javascript($script);
-
- /**
- * Starts a new page
- *
- * Subsequent drawing operations will appear on the new page.
- */
- function new_page();
-
- /**
- * Streams the PDF directly to the browser
- *
- * @param string $filename the name of the PDF file
- * @param array $options associative array, 'Attachment' => 0 or 1, 'compress' => 1 or 0
- */
- function stream($filename, $options = null);
-
- /**
- * Returns the PDF as a string
- *
- * @param array $options associative array: 'compress' => 1 or 0
- * @return string
- */
- function output($options = null);
-}
diff --git a/library/vendor/dompdf/include/canvas_factory.cls.php b/library/vendor/dompdf/include/canvas_factory.cls.php
deleted file mode 100644
index ef634e6b0..000000000
--- a/library/vendor/dompdf/include/canvas_factory.cls.php
+++ /dev/null
@@ -1,63 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Create canvas instances
- *
- * The canvas factory creates canvas instances based on the
- * availability of rendering backends and config options.
- *
- * @package dompdf
- */
-class Canvas_Factory {
-
- /**
- * Constructor is private: this is a static class
- */
- private function __construct() { }
-
- /**
- * @param DOMPDF $dompdf
- * @param string|array $paper
- * @param string $orientation
- * @param string $class
- *
- * @return Canvas
- */
- static function get_instance(DOMPDF $dompdf, $paper = null, $orientation = null, $class = null) {
-
- $backend = strtolower(DOMPDF_PDF_BACKEND);
-
- if ( isset($class) && class_exists($class, false) ) {
- $class .= "_Adapter";
- }
-
- else if ( (DOMPDF_PDF_BACKEND === "auto" || $backend === "pdflib" ) &&
- class_exists("PDFLib", false) ) {
- $class = "PDFLib_Adapter";
- }
-
- // FIXME The TCPDF adapter is not ready yet
- //else if ( (DOMPDF_PDF_BACKEND === "auto" || $backend === "cpdf") )
- // $class = "CPDF_Adapter";
-
- else if ( $backend === "tcpdf" ) {
- $class = "TCPDF_Adapter";
- }
-
- else if ( $backend === "gd" ) {
- $class = "GD_Adapter";
- }
-
- else {
- $class = "CPDF_Adapter";
- }
-
- return new $class($paper, $orientation, $dompdf);
- }
-}
diff --git a/library/vendor/dompdf/include/cellmap.cls.php b/library/vendor/dompdf/include/cellmap.cls.php
deleted file mode 100644
index 0982849b3..000000000
--- a/library/vendor/dompdf/include/cellmap.cls.php
+++ /dev/null
@@ -1,790 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Maps table cells to the table grid.
- *
- * This class resolves borders in tables with collapsed borders and helps
- * place row & column spanned table cells.
- *
- * @access private
- * @package dompdf
- */
-class Cellmap {
-
- /**
- * Border style weight lookup for collapsed border resolution.
- *
- * @var array
- */
- static protected $_BORDER_STYLE_SCORE = array(
- "inset" => 1,
- "groove" => 2,
- "outset" => 3,
- "ridge" => 4,
- "dotted" => 5,
- "dashed" => 6,
- "solid" => 7,
- "double" => 8,
- "hidden" => 9,
- "none" => 0,
- );
-
- /**
- * The table object this cellmap is attached to.
- *
- * @var Table_Frame_Decorator
- */
- protected $_table;
-
- /**
- * The total number of rows in the table
- *
- * @var int
- */
- protected $_num_rows;
-
- /**
- * The total number of columns in the table
- *
- * @var int
- */
- protected $_num_cols;
-
- /**
- * 2D array mapping to frames
- *
- * @var Frame[][]
- */
- protected $_cells;
-
- /**
- * 1D array of column dimensions
- *
- * @var array
- */
- protected $_columns;
-
- /**
- * 1D array of row dimensions
- *
- * @var array
- */
- protected $_rows;
-
- /**
- * 2D array of border specs
- *
- * @var array
- */
- protected $_borders;
-
- /**
- * 1D Array mapping frames to (multiple) pairs, keyed on frame_id.
- *
- * @var Frame[]
- */
- protected $_frames;
-
- /**
- * Current column when adding cells, 0-based
- *
- * @var int
- */
- private $__col;
-
- /**
- * Current row when adding cells, 0-based
- *
- * @var int
- */
- private $__row;
-
- /**
- * Tells wether the columns' width can be modified
- *
- * @var bool
- */
- private $_columns_locked = false;
-
- /**
- * Tells wether the table has table-layout:fixed
- *
- * @var bool
- */
- private $_fixed_layout = false;
-
- //........................................................................
-
- function __construct(Table_Frame_Decorator $table) {
- $this->_table = $table;
- $this->reset();
- }
-
- function __destruct() {
- clear_object($this);
- }
- //........................................................................
-
- function reset() {
- $this->_num_rows = 0;
- $this->_num_cols = 0;
-
- $this->_cells = array();
- $this->_frames = array();
-
- if ( !$this->_columns_locked ) {
- $this->_columns = array();
- }
-
- $this->_rows = array();
-
- $this->_borders = array();
-
- $this->__col = $this->__row = 0;
- }
-
- //........................................................................
-
- function lock_columns() {
- $this->_columns_locked = true;
- }
-
- function is_columns_locked() {
- return $this->_columns_locked;
- }
-
- function set_layout_fixed($fixed) {
- $this->_fixed_layout = $fixed;
- }
-
- function is_layout_fixed() {
- return $this->_fixed_layout;
- }
-
- function get_num_rows() { return $this->_num_rows; }
- function get_num_cols() { return $this->_num_cols; }
-
- function &get_columns() {
- return $this->_columns;
- }
-
- function set_columns($columns) {
- $this->_columns = $columns;
- }
-
- function &get_column($i) {
- if ( !isset($this->_columns[$i]) ) {
- $this->_columns[$i] = array(
- "x" => 0,
- "min-width" => 0,
- "max-width" => 0,
- "used-width" => null,
- "absolute" => 0,
- "percent" => 0,
- "auto" => true,
- );
- }
-
- return $this->_columns[$i];
- }
-
- function &get_rows() {
- return $this->_rows;
- }
-
- function &get_row($j) {
- if ( !isset($this->_rows[$j]) ) {
- $this->_rows[$j] = array(
- "y" => 0,
- "first-column" => 0,
- "height" => null,
- );
- }
-
- return $this->_rows[$j];
- }
-
- function get_border($i, $j, $h_v, $prop = null) {
- if ( !isset($this->_borders[$i][$j][$h_v]) ) {
- $this->_borders[$i][$j][$h_v] = array(
- "width" => 0,
- "style" => "solid",
- "color" => "black",
- );
- }
-
- if ( isset($prop) ) {
- return $this->_borders[$i][$j][$h_v][$prop];
- }
-
- return $this->_borders[$i][$j][$h_v];
- }
-
- function get_border_properties($i, $j) {
- return array(
- "top" => $this->get_border($i, $j, "horizontal"),
- "right" => $this->get_border($i, $j+1, "vertical"),
- "bottom" => $this->get_border($i+1, $j, "horizontal"),
- "left" => $this->get_border($i, $j, "vertical"),
- );
- }
-
- //........................................................................
-
- function get_spanned_cells(Frame $frame) {
- $key = $frame->get_id();
-
- if ( !isset($this->_frames[$key]) ) {
- throw new DOMPDF_Exception("Frame not found in cellmap");
- }
-
- return $this->_frames[$key];
-
- }
-
- function frame_exists_in_cellmap(Frame $frame) {
- $key = $frame->get_id();
- return isset($this->_frames[$key]);
- }
-
- function get_frame_position(Frame $frame) {
- global $_dompdf_warnings;
-
- $key = $frame->get_id();
-
- if ( !isset($this->_frames[$key]) ) {
- throw new DOMPDF_Exception("Frame not found in cellmap");
- }
-
- $col = $this->_frames[$key]["columns"][0];
- $row = $this->_frames[$key]["rows"][0];
-
- if ( !isset($this->_columns[$col])) {
- $_dompdf_warnings[] = "Frame not found in columns array. Check your table layout for missing or extra TDs.";
- $x = 0;
- }
- else {
- $x = $this->_columns[$col]["x"];
- }
-
- if ( !isset($this->_rows[$row])) {
- $_dompdf_warnings[] = "Frame not found in row array. Check your table layout for missing or extra TDs.";
- $y = 0;
- }
- else {
- $y = $this->_rows[$row]["y"];
- }
-
- return array($x, $y, "x" => $x, "y" => $y);
- }
-
- function get_frame_width(Frame $frame) {
- $key = $frame->get_id();
-
- if ( !isset($this->_frames[$key]) ) {
- throw new DOMPDF_Exception("Frame not found in cellmap");
- }
-
- $cols = $this->_frames[$key]["columns"];
- $w = 0;
- foreach ($cols as $i) {
- $w += $this->_columns[$i]["used-width"];
- }
-
- return $w;
- }
-
- function get_frame_height(Frame $frame) {
- $key = $frame->get_id();
-
- if ( !isset($this->_frames[$key]) ) {
- throw new DOMPDF_Exception("Frame not found in cellmap");
- }
-
- $rows = $this->_frames[$key]["rows"];
- $h = 0;
- foreach ($rows as $i) {
- if ( !isset($this->_rows[$i]) ) {
- throw new Exception("The row #$i could not be found, please file an issue in the tracker with the HTML code");
- }
-
- $h += $this->_rows[$i]["height"];
- }
-
- return $h;
- }
-
-
- //........................................................................
-
- function set_column_width($j, $width) {
- if ( $this->_columns_locked ) {
- return;
- }
-
- $col =& $this->get_column($j);
- $col["used-width"] = $width;
- $next_col =& $this->get_column($j+1);
- $next_col["x"] = $next_col["x"] + $width;
- }
-
- function set_row_height($i, $height) {
- $row =& $this->get_row($i);
-
- if ( $row["height"] !== null && $height <= $row["height"] ) {
- return;
- }
-
- $row["height"] = $height;
- $next_row =& $this->get_row($i+1);
- $next_row["y"] = $row["y"] + $height;
-
- }
-
- //........................................................................
-
-
- protected function _resolve_border($i, $j, $h_v, $border_spec) {
- $n_width = $border_spec["width"];
- $n_style = $border_spec["style"];
-
- if ( !isset($this->_borders[$i][$j][$h_v]) ) {
- $this->_borders[$i][$j][$h_v] = $border_spec;
- return $this->_borders[$i][$j][$h_v]["width"];
- }
-
- $border = &$this->_borders[$i][$j][$h_v];
-
- $o_width = $border["width"];
- $o_style = $border["style"];
-
- if ( ($n_style === "hidden" ||
- $n_width > $o_width ||
- $o_style === "none")
-
- or
-
- ($o_width == $n_width &&
- in_array($n_style, self::$_BORDER_STYLE_SCORE) &&
- self::$_BORDER_STYLE_SCORE[ $n_style ] > self::$_BORDER_STYLE_SCORE[ $o_style ]) ) {
- $border = $border_spec;
- }
-
- return $border["width"];
- }
-
- //........................................................................
-
- function add_frame(Frame $frame) {
-
- $style = $frame->get_style();
- $display = $style->display;
-
- $collapse = $this->_table->get_style()->border_collapse == "collapse";
-
- // Recursively add the frames within tables, table-row-groups and table-rows
- if ( $display === "table-row" ||
- $display === "table" ||
- $display === "inline-table" ||
- in_array($display, Table_Frame_Decorator::$ROW_GROUPS) ) {
-
- $start_row = $this->__row;
- foreach ( $frame->get_children() as $child ) {
- $this->add_frame( $child );
- }
-
- if ( $display === "table-row" ) {
- $this->add_row();
- }
-
- $num_rows = $this->__row - $start_row - 1;
- $key = $frame->get_id();
-
- // Row groups always span across the entire table
- $this->_frames[$key]["columns"] = range(0,max(0,$this->_num_cols-1));
- $this->_frames[$key]["rows"] = range($start_row, max(0, $this->__row - 1));
- $this->_frames[$key]["frame"] = $frame;
-
- if ( $display !== "table-row" && $collapse ) {
-
- $bp = $style->get_border_properties();
-
- // Resolve the borders
- for ( $i = 0; $i < $num_rows+1; $i++) {
- $this->_resolve_border($start_row + $i, 0, "vertical", $bp["left"]);
- $this->_resolve_border($start_row + $i, $this->_num_cols, "vertical", $bp["right"]);
- }
-
- for ( $j = 0; $j < $this->_num_cols; $j++) {
- $this->_resolve_border($start_row, $j, "horizontal", $bp["top"]);
- $this->_resolve_border($this->__row, $j, "horizontal", $bp["bottom"]);
- }
- }
-
-
- return;
- }
-
- $node = $frame->get_node();
-
- // Determine where this cell is going
- $colspan = $node->getAttribute("colspan");
- $rowspan = $node->getAttribute("rowspan");
-
- if ( !$colspan ) {
- $colspan = 1;
- $node->setAttribute("colspan",1);
- }
-
- if ( !$rowspan ) {
- $rowspan = 1;
- $node->setAttribute("rowspan",1);
- }
- $key = $frame->get_id();
-
- $bp = $style->get_border_properties();
-
-
- // Add the frame to the cellmap
- $max_left = $max_right = 0;
-
- // Find the next available column (fix by Ciro Mondueri)
- $ac = $this->__col;
- while ( isset($this->_cells[$this->__row][$ac]) ) {
- $ac++;
- }
-
- $this->__col = $ac;
-
- // Rows:
- for ( $i = 0; $i < $rowspan; $i++ ) {
- $row = $this->__row + $i;
-
- $this->_frames[$key]["rows"][] = $row;
-
- for ( $j = 0; $j < $colspan; $j++) {
- $this->_cells[$row][$this->__col + $j] = $frame;
- }
-
- if ( $collapse ) {
- // Resolve vertical borders
- $max_left = max($max_left, $this->_resolve_border($row, $this->__col, "vertical", $bp["left"]));
- $max_right = max($max_right, $this->_resolve_border($row, $this->__col + $colspan, "vertical", $bp["right"]));
- }
- }
-
- $max_top = $max_bottom = 0;
-
- // Columns:
- for ( $j = 0; $j < $colspan; $j++ ) {
- $col = $this->__col + $j;
- $this->_frames[$key]["columns"][] = $col;
-
- if ( $collapse ) {
- // Resolve horizontal borders
- $max_top = max($max_top, $this->_resolve_border($this->__row, $col, "horizontal", $bp["top"]));
- $max_bottom = max($max_bottom, $this->_resolve_border($this->__row + $rowspan, $col, "horizontal", $bp["bottom"]));
- }
- }
-
- $this->_frames[$key]["frame"] = $frame;
-
- // Handle seperated border model
- if ( !$collapse ) {
- list($h, $v) = $this->_table->get_style()->border_spacing;
-
- // Border spacing is effectively a margin between cells
- $v = $style->length_in_pt($v) / 2;
- $h = $style->length_in_pt($h) / 2;
- $style->margin = "$v $h";
-
- // The additional 1/2 width gets added to the table proper
- }
- else {
- // Drop the frame's actual border
- $style->border_left_width = $max_left / 2;
- $style->border_right_width = $max_right / 2;
- $style->border_top_width = $max_top / 2;
- $style->border_bottom_width = $max_bottom / 2;
- $style->margin = "none";
- }
-
- if ( !$this->_columns_locked ) {
- // Resolve the frame's width
- if ( $this->_fixed_layout ) {
- list($frame_min, $frame_max) = array(0, 10e-10);
- }
- else {
- list($frame_min, $frame_max) = $frame->get_min_max_width();
- }
-
- $width = $style->width;
-
- $val = null;
- if ( is_percent($width) ) {
- $var = "percent";
- $val = (float)rtrim($width, "% ") / $colspan;
- }
- else if ( $width !== "auto" ) {
- $var = "absolute";
- $val = $style->length_in_pt($frame_min) / $colspan;
- }
-
- $min = 0;
- $max = 0;
- for ( $cs = 0; $cs < $colspan; $cs++ ) {
-
- // Resolve the frame's width(s) with other cells
- $col =& $this->get_column( $this->__col + $cs );
-
- // Note: $var is either 'percent' or 'absolute'. We compare the
- // requested percentage or absolute values with the existing widths
- // and adjust accordingly.
- if ( isset($var) && $val > $col[$var] ) {
- $col[$var] = $val;
- $col["auto"] = false;
- }
-
- $min += $col["min-width"];
- $max += $col["max-width"];
- }
-
- if ( $frame_min > $min ) {
- // The frame needs more space. Expand each sub-column
- // FIXME try to avoid putting this dummy value when table-layout:fixed
- $inc = ($this->is_layout_fixed() ? 10e-10 : ($frame_min - $min) / $colspan);
- for ($c = 0; $c < $colspan; $c++) {
- $col =& $this->get_column($this->__col + $c);
- $col["min-width"] += $inc;
- }
- }
-
- if ( $frame_max > $max ) {
- // FIXME try to avoid putting this dummy value when table-layout:fixed
- $inc = ($this->is_layout_fixed() ? 10e-10 : ($frame_max - $max) / $colspan);
- for ($c = 0; $c < $colspan; $c++) {
- $col =& $this->get_column($this->__col + $c);
- $col["max-width"] += $inc;
- }
- }
- }
-
- $this->__col += $colspan;
- if ( $this->__col > $this->_num_cols )
- $this->_num_cols = $this->__col;
-
- }
-
- //........................................................................
-
- function add_row() {
-
- $this->__row++;
- $this->_num_rows++;
-
- // Find the next available column
- $i = 0;
- while ( isset($this->_cells[$this->__row][$i]) ) {
- $i++;
- }
-
- $this->__col = $i;
-
- }
-
- //........................................................................
-
- /**
- * Remove a row from the cellmap.
- *
- * @param Frame
- */
- function remove_row(Frame $row) {
-
- $key = $row->get_id();
- if ( !isset($this->_frames[$key]) ) {
- return; // Presumably this row has alredy been removed
- }
-
- $this->_row = $this->_num_rows--;
-
- $rows = $this->_frames[$key]["rows"];
- $columns = $this->_frames[$key]["columns"];
-
- // Remove all frames from this row
- foreach ( $rows as $r ) {
- foreach ( $columns as $c ) {
- if ( isset($this->_cells[$r][$c]) ) {
- $id = $this->_cells[$r][$c]->get_id();
-
- $this->_frames[$id] = null;
- unset($this->_frames[$id]);
-
- $this->_cells[$r][$c] = null;
- unset($this->_cells[$r][$c]);
- }
- }
-
- $this->_rows[$r] = null;
- unset($this->_rows[$r]);
- }
-
- $this->_frames[$key] = null;
- unset($this->_frames[$key]);
-
- }
-
- /**
- * Remove a row group from the cellmap.
- *
- * @param Frame $group The group to remove
- */
- function remove_row_group(Frame $group) {
-
- $key = $group->get_id();
- if ( !isset($this->_frames[$key]) ) {
- return; // Presumably this row has alredy been removed
- }
-
- $iter = $group->get_first_child();
- while ($iter) {
- $this->remove_row($iter);
- $iter = $iter->get_next_sibling();
- }
-
- $this->_frames[$key] = null;
- unset($this->_frames[$key]);
- }
-
- /**
- * Update a row group after rows have been removed
- *
- * @param Frame $group The group to update
- * @param Frame $last_row The last row in the row group
- */
- function update_row_group(Frame $group, Frame $last_row) {
-
- $g_key = $group->get_id();
- $r_key = $last_row->get_id();
-
- $r_rows = $this->_frames[$r_key]["rows"];
- $this->_frames[$g_key]["rows"] = range( $this->_frames[$g_key]["rows"][0], end($r_rows) );
-
- }
-
- //........................................................................
-
- function assign_x_positions() {
- // Pre-condition: widths must be resolved and assigned to columns and
- // column[0]["x"] must be set.
-
- if ( $this->_columns_locked ) {
- return;
- }
-
- $x = $this->_columns[0]["x"];
- foreach ( array_keys($this->_columns) as $j ) {
- $this->_columns[$j]["x"] = $x;
- $x += $this->_columns[$j]["used-width"];
- }
-
- }
-
- function assign_frame_heights() {
- // Pre-condition: widths and heights of each column & row must be
- // calcluated
-
- foreach ( $this->_frames as $arr ) {
- $frame = $arr["frame"];
-
- $h = 0;
- foreach( $arr["rows"] as $row ) {
- if ( !isset($this->_rows[$row]) ) {
- // The row has been removed because of a page split, so skip it.
- continue;
- }
-
- $h += $this->_rows[$row]["height"];
- }
-
- if ( $frame instanceof Table_Cell_Frame_Decorator ) {
- $frame->set_cell_height($h);
- }
- else {
- $frame->get_style()->height = $h;
- }
- }
-
- }
-
- //........................................................................
-
- /**
- * Re-adjust frame height if the table height is larger than its content
- */
- function set_frame_heights($table_height, $content_height) {
-
-
- // Distribute the increased height proportionally amongst each row
- foreach ( $this->_frames as $arr ) {
- $frame = $arr["frame"];
-
- $h = 0;
- foreach ($arr["rows"] as $row ) {
- if ( !isset($this->_rows[$row]) ) {
- continue;
- }
-
- $h += $this->_rows[$row]["height"];
- }
-
- if ( $content_height > 0 ) {
- $new_height = ($h / $content_height) * $table_height;
- }
- else {
- $new_height = 0;
- }
-
- if ( $frame instanceof Table_Cell_Frame_Decorator ) {
- $frame->set_cell_height($new_height);
- }
- else {
- $frame->get_style()->height = $new_height;
- }
- }
-
- }
-
- //........................................................................
-
- // Used for debugging:
- function __toString() {
- $str = "";
- $str .= "Columns: ";
- $str .= pre_r($this->_columns, true);
- $str .= "Rows: ";
- $str .= pre_r($this->_rows, true);
-
- $str .= "Frames: ";
- $arr = array();
- foreach ( $this->_frames as $key => $val ) {
- $arr[$key] = array("columns" => $val["columns"], "rows" => $val["rows"]);
- }
-
- $str .= pre_r($arr, true);
-
- if ( php_sapi_name() == "cli" ) {
- $str = strip_tags(str_replace(array(" ",""," "),
- array("\n",chr(27)."[01;33m", chr(27)."[0m"),
- $str));
- }
-
- return $str;
- }
-}
diff --git a/library/vendor/dompdf/include/cpdf_adapter.cls.php b/library/vendor/dompdf/include/cpdf_adapter.cls.php
deleted file mode 100644
index 041e1f375..000000000
--- a/library/vendor/dompdf/include/cpdf_adapter.cls.php
+++ /dev/null
@@ -1,877 +0,0 @@
-
- * @author Orion Richardson
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-// FIXME: Need to sanity check inputs to this class
-require_once(DOMPDF_LIB_DIR . "/class.pdf.php");
-
-/**
- * PDF rendering interface
- *
- * CPDF_Adapter provides a simple stateless interface to the stateful one
- * provided by the Cpdf class.
- *
- * Unless otherwise mentioned, all dimensions are in points (1/72 in). The
- * coordinate origin is in the top left corner, and y values increase
- * downwards.
- *
- * See {@link http://www.ros.co.nz/pdf/} for more complete documentation
- * on the underlying {@link Cpdf} class.
- *
- * @package dompdf
- */
-class CPDF_Adapter implements Canvas {
-
- /**
- * Dimensions of paper sizes in points
- *
- * @var array;
- */
- static $PAPER_SIZES = array(
- "4a0" => array(0,0,4767.87,6740.79),
- "2a0" => array(0,0,3370.39,4767.87),
- "a0" => array(0,0,2383.94,3370.39),
- "a1" => array(0,0,1683.78,2383.94),
- "a2" => array(0,0,1190.55,1683.78),
- "a3" => array(0,0,841.89,1190.55),
- "a4" => array(0,0,595.28,841.89),
- "a5" => array(0,0,419.53,595.28),
- "a6" => array(0,0,297.64,419.53),
- "a7" => array(0,0,209.76,297.64),
- "a8" => array(0,0,147.40,209.76),
- "a9" => array(0,0,104.88,147.40),
- "a10" => array(0,0,73.70,104.88),
- "b0" => array(0,0,2834.65,4008.19),
- "b1" => array(0,0,2004.09,2834.65),
- "b2" => array(0,0,1417.32,2004.09),
- "b3" => array(0,0,1000.63,1417.32),
- "b4" => array(0,0,708.66,1000.63),
- "b5" => array(0,0,498.90,708.66),
- "b6" => array(0,0,354.33,498.90),
- "b7" => array(0,0,249.45,354.33),
- "b8" => array(0,0,175.75,249.45),
- "b9" => array(0,0,124.72,175.75),
- "b10" => array(0,0,87.87,124.72),
- "c0" => array(0,0,2599.37,3676.54),
- "c1" => array(0,0,1836.85,2599.37),
- "c2" => array(0,0,1298.27,1836.85),
- "c3" => array(0,0,918.43,1298.27),
- "c4" => array(0,0,649.13,918.43),
- "c5" => array(0,0,459.21,649.13),
- "c6" => array(0,0,323.15,459.21),
- "c7" => array(0,0,229.61,323.15),
- "c8" => array(0,0,161.57,229.61),
- "c9" => array(0,0,113.39,161.57),
- "c10" => array(0,0,79.37,113.39),
- "ra0" => array(0,0,2437.80,3458.27),
- "ra1" => array(0,0,1729.13,2437.80),
- "ra2" => array(0,0,1218.90,1729.13),
- "ra3" => array(0,0,864.57,1218.90),
- "ra4" => array(0,0,609.45,864.57),
- "sra0" => array(0,0,2551.18,3628.35),
- "sra1" => array(0,0,1814.17,2551.18),
- "sra2" => array(0,0,1275.59,1814.17),
- "sra3" => array(0,0,907.09,1275.59),
- "sra4" => array(0,0,637.80,907.09),
- "letter" => array(0,0,612.00,792.00),
- "legal" => array(0,0,612.00,1008.00),
- "ledger" => array(0,0,1224.00, 792.00),
- "tabloid" => array(0,0,792.00, 1224.00),
- "executive" => array(0,0,521.86,756.00),
- "folio" => array(0,0,612.00,936.00),
- "commercial #10 envelope" => array(0,0,684,297),
- "catalog #10 1/2 envelope" => array(0,0,648,864),
- "8.5x11" => array(0,0,612.00,792.00),
- "8.5x14" => array(0,0,612.00,1008.0),
- "11x17" => array(0,0,792.00, 1224.00),
- );
-
- /**
- * The DOMPDF object
- *
- * @var DOMPDF
- */
- private $_dompdf;
-
- /**
- * Instance of Cpdf class
- *
- * @var Cpdf
- */
- private $_pdf;
-
- /**
- * PDF width, in points
- *
- * @var float
- */
- private $_width;
-
- /**
- * PDF height, in points
- *
- * @var float;
- */
- private $_height;
-
- /**
- * Current page number
- *
- * @var int
- */
- private $_page_number;
-
- /**
- * Total number of pages
- *
- * @var int
- */
- private $_page_count;
-
- /**
- * Text to display on every page
- *
- * @var array
- */
- private $_page_text;
-
- /**
- * Array of pages for accesing after rendering is initially complete
- *
- * @var array
- */
- private $_pages;
-
- /**
- * Array of temporary cached images to be deleted when processing is complete
- *
- * @var array
- */
- private $_image_cache;
-
- /**
- * Class constructor
- *
- * @param mixed $paper The size of paper to use in this PDF ({@link CPDF_Adapter::$PAPER_SIZES})
- * @param string $orientation The orientation of the document (either 'landscape' or 'portrait')
- * @param DOMPDF $dompdf The DOMPDF instance
- */
- function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf) {
- if ( is_array($paper) ) {
- $size = $paper;
- }
- else if ( isset(self::$PAPER_SIZES[mb_strtolower($paper)]) ) {
- $size = self::$PAPER_SIZES[mb_strtolower($paper)];
- }
- else {
- $size = self::$PAPER_SIZES["letter"];
- }
-
- if ( mb_strtolower($orientation) === "landscape" ) {
- list($size[2], $size[3]) = array($size[3], $size[2]);
- }
-
- $this->_dompdf = $dompdf;
-
- $this->_pdf = new Cpdf(
- $size,
- $dompdf->get_option("enable_unicode"),
- $dompdf->get_option("font_cache"),
- $dompdf->get_option("temp_dir")
- );
-
- $this->_pdf->addInfo("Creator", "DOMPDF");
- $time = substr_replace(date('YmdHisO'), '\'', -2, 0).'\'';
- $this->_pdf->addInfo("CreationDate", "D:$time");
- $this->_pdf->addInfo("ModDate", "D:$time");
-
- $this->_width = $size[2] - $size[0];
- $this->_height= $size[3] - $size[1];
-
- $this->_page_number = $this->_page_count = 1;
- $this->_page_text = array();
-
- $this->_pages = array($this->_pdf->getFirstPageId());
-
- $this->_image_cache = array();
- }
-
- function get_dompdf(){
- return $this->_dompdf;
- }
-
- /**
- * Class destructor
- *
- * Deletes all temporary image files
- */
- function __destruct() {
- foreach ($this->_image_cache as $img) {
- // The file might be already deleted by 3rd party tmp cleaner,
- // the file might not have been created at all
- // (if image outputting commands failed)
- // or because the destructor was called twice accidentally.
- if (!file_exists($img)) {
- continue;
- }
-
- if (DEBUGPNG) print '[__destruct unlink '.$img.']';
- if (!DEBUGKEEPTEMP) unlink($img);
- }
- }
-
- /**
- * Returns the Cpdf instance
- *
- * @return Cpdf
- */
- function get_cpdf() {
- return $this->_pdf;
- }
-
- /**
- * Add meta information to the PDF
- *
- * @param string $label label of the value (Creator, Producer, etc.)
- * @param string $value the text to set
- */
- function add_info($label, $value) {
- $this->_pdf->addInfo($label, $value);
- }
-
- /**
- * Opens a new 'object'
- *
- * While an object is open, all drawing actions are recored in the object,
- * as opposed to being drawn on the current page. Objects can be added
- * later to a specific page or to several pages.
- *
- * The return value is an integer ID for the new object.
- *
- * @see CPDF_Adapter::close_object()
- * @see CPDF_Adapter::add_object()
- *
- * @return int
- */
- function open_object() {
- $ret = $this->_pdf->openObject();
- $this->_pdf->saveState();
- return $ret;
- }
-
- /**
- * Reopens an existing 'object'
- *
- * @see CPDF_Adapter::open_object()
- * @param int $object the ID of a previously opened object
- */
- function reopen_object($object) {
- $this->_pdf->reopenObject($object);
- $this->_pdf->saveState();
- }
-
- /**
- * Closes the current 'object'
- *
- * @see CPDF_Adapter::open_object()
- */
- function close_object() {
- $this->_pdf->restoreState();
- $this->_pdf->closeObject();
- }
-
- /**
- * Adds a specified 'object' to the document
- *
- * $object int specifying an object created with {@link
- * CPDF_Adapter::open_object()}. $where can be one of:
- * - 'add' add to current page only
- * - 'all' add to every page from the current one onwards
- * - 'odd' add to all odd numbered pages from now on
- * - 'even' add to all even numbered pages from now on
- * - 'next' add the object to the next page only
- * - 'nextodd' add to all odd numbered pages from the next one
- * - 'nexteven' add to all even numbered pages from the next one
- *
- * @see Cpdf::addObject()
- *
- * @param int $object
- * @param string $where
- */
- function add_object($object, $where = 'all') {
- $this->_pdf->addObject($object, $where);
- }
-
- /**
- * Stops the specified 'object' from appearing in the document.
- *
- * The object will stop being displayed on the page following the current
- * one.
- *
- * @param int $object
- */
- function stop_object($object) {
- $this->_pdf->stopObject($object);
- }
-
- /**
- * @access private
- */
- function serialize_object($id) {
- // Serialize the pdf object's current state for retrieval later
- return $this->_pdf->serializeObject($id);
- }
-
- /**
- * @access private
- */
- function reopen_serialized_object($obj) {
- return $this->_pdf->restoreSerializedObject($obj);
- }
-
- //........................................................................
-
- /**
- * Returns the PDF's width in points
- * @return float
- */
- function get_width() { return $this->_width; }
-
- /**
- * Returns the PDF's height in points
- * @return float
- */
- function get_height() { return $this->_height; }
-
- /**
- * Returns the current page number
- * @return int
- */
- function get_page_number() { return $this->_page_number; }
-
- /**
- * Returns the total number of pages in the document
- * @return int
- */
- function get_page_count() { return $this->_page_count; }
-
- /**
- * Sets the current page number
- *
- * @param int $num
- */
- function set_page_number($num) { $this->_page_number = $num; }
-
- /**
- * Sets the page count
- *
- * @param int $count
- */
- function set_page_count($count) { $this->_page_count = $count; }
-
- /**
- * Sets the stroke color
- *
- * See {@link Style::set_color()} for the format of the color array.
- * @param array $color
- */
- protected function _set_stroke_color($color) {
- $this->_pdf->setStrokeColor($color);
- }
-
- /**
- * Sets the fill colour
- *
- * See {@link Style::set_color()} for the format of the colour array.
- * @param array $color
- */
- protected function _set_fill_color($color) {
- $this->_pdf->setColor($color);
- }
-
- /**
- * Sets line transparency
- * @see Cpdf::setLineTransparency()
- *
- * Valid blend modes are (case-sensitive):
- *
- * Normal, Multiply, Screen, Overlay, Darken, Lighten,
- * ColorDodge, ColorBurn, HardLight, SoftLight, Difference,
- * Exclusion
- *
- * @param string $mode the blending mode to use
- * @param float $opacity 0.0 fully transparent, 1.0 fully opaque
- */
- protected function _set_line_transparency($mode, $opacity) {
- $this->_pdf->setLineTransparency($mode, $opacity);
- }
-
- /**
- * Sets fill transparency
- * @see Cpdf::setFillTransparency()
- *
- * Valid blend modes are (case-sensitive):
- *
- * Normal, Multiply, Screen, Overlay, Darken, Lighten,
- * ColorDogde, ColorBurn, HardLight, SoftLight, Difference,
- * Exclusion
- *
- * @param string $mode the blending mode to use
- * @param float $opacity 0.0 fully transparent, 1.0 fully opaque
- */
- protected function _set_fill_transparency($mode, $opacity) {
- $this->_pdf->setFillTransparency($mode, $opacity);
- }
-
- /**
- * Sets the line style
- *
- * @see Cpdf::setLineStyle()
- *
- * @param float $width
- * @param string $cap
- * @param string $join
- * @param array $dash
- */
- protected function _set_line_style($width, $cap, $join, $dash) {
- $this->_pdf->setLineStyle($width, $cap, $join, $dash);
- }
-
- /**
- * Sets the opacity
- *
- * @param $opacity
- * @param $mode
- */
- function set_opacity($opacity, $mode = "Normal") {
- $this->_set_line_transparency($mode, $opacity);
- $this->_set_fill_transparency($mode, $opacity);
- }
-
- function set_default_view($view, $options = array()) {
- array_unshift($options, $view);
- call_user_func_array(array($this->_pdf, "openHere"), $options);
- }
-
- /**
- * Remaps y coords from 4th to 1st quadrant
- *
- * @param float $y
- * @return float
- */
- protected function y($y) {
- return $this->_height - $y;
- }
-
- // Canvas implementation
- function line($x1, $y1, $x2, $y2, $color, $width, $style = array()) {
- $this->_set_stroke_color($color);
- $this->_set_line_style($width, "butt", "", $style);
-
- $this->_pdf->line($x1, $this->y($y1),
- $x2, $this->y($y2));
- }
-
- function arc($x, $y, $r1, $r2, $astart, $aend, $color, $width, $style = array()) {
- $this->_set_stroke_color($color);
- $this->_set_line_style($width, "butt", "", $style);
-
- $this->_pdf->ellipse($x, $this->y($y), $r1, $r2, 0, 8, $astart, $aend, false, false, true, false);
- }
-
- //........................................................................
-
- /**
- * Convert a GIF or BMP image to a PNG image
- *
- * @param string $image_url
- * @param integer $type
- *
- * @throws DOMPDF_Exception
- * @return string The url of the newly converted image
- */
- protected function _convert_gif_bmp_to_png($image_url, $type) {
- $image_type = Image_Cache::type_to_ext($type);
- $func_name = "imagecreatefrom$image_type";
-
- if ( !function_exists($func_name) ) {
- throw new DOMPDF_Exception("Function $func_name() not found. Cannot convert $image_type image: $image_url. Please install the image PHP extension.");
- }
-
- set_error_handler("record_warnings");
- $im = $func_name($image_url);
-
- if ( $im ) {
- imageinterlace($im, false);
-
- $tmp_dir = $this->_dompdf->get_option("temp_dir");
- $tmp_name = tempnam($tmp_dir, "{$image_type}dompdf_img_");
- @unlink($tmp_name);
- $filename = "$tmp_name.png";
- $this->_image_cache[] = $filename;
-
- imagepng($im, $filename);
- imagedestroy($im);
- }
- else {
- $filename = Image_Cache::$broken_image;
- }
-
- restore_error_handler();
-
- return $filename;
- }
-
- function rectangle($x1, $y1, $w, $h, $color, $width, $style = array()) {
- $this->_set_stroke_color($color);
- $this->_set_line_style($width, "butt", "", $style);
- $this->_pdf->rectangle($x1, $this->y($y1) - $h, $w, $h);
- }
-
- function filled_rectangle($x1, $y1, $w, $h, $color) {
- $this->_set_fill_color($color);
- $this->_pdf->filledRectangle($x1, $this->y($y1) - $h, $w, $h);
- }
-
- function clipping_rectangle($x1, $y1, $w, $h) {
- $this->_pdf->clippingRectangle($x1, $this->y($y1) - $h, $w, $h);
- }
-
- function clipping_roundrectangle($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) {
- $this->_pdf->clippingRectangleRounded($x1, $this->y($y1) - $h, $w, $h, $rTL, $rTR, $rBR, $rBL);
- }
-
- function clipping_end() {
- $this->_pdf->clippingEnd();
- }
-
- function save() {
- $this->_pdf->saveState();
- }
-
- function restore() {
- $this->_pdf->restoreState();
- }
-
- function rotate($angle, $x, $y) {
- $this->_pdf->rotate($angle, $x, $y);
- }
-
- function skew($angle_x, $angle_y, $x, $y) {
- $this->_pdf->skew($angle_x, $angle_y, $x, $y);
- }
-
- function scale($s_x, $s_y, $x, $y) {
- $this->_pdf->scale($s_x, $s_y, $x, $y);
- }
-
- function translate($t_x, $t_y) {
- $this->_pdf->translate($t_x, $t_y);
- }
-
- function transform($a, $b, $c, $d, $e, $f) {
- $this->_pdf->transform(array($a, $b, $c, $d, $e, $f));
- }
-
- function polygon($points, $color, $width = null, $style = array(), $fill = false) {
- $this->_set_fill_color($color);
- $this->_set_stroke_color($color);
-
- // Adjust y values
- for ( $i = 1; $i < count($points); $i += 2) {
- $points[$i] = $this->y($points[$i]);
- }
-
- $this->_pdf->polygon($points, count($points) / 2, $fill);
- }
-
- function circle($x, $y, $r1, $color, $width = null, $style = null, $fill = false) {
- $this->_set_fill_color($color);
- $this->_set_stroke_color($color);
-
- if ( !$fill && isset($width) ) {
- $this->_set_line_style($width, "round", "round", $style);
- }
-
- $this->_pdf->ellipse($x, $this->y($y), $r1, 0, 0, 8, 0, 360, 1, $fill);
- }
-
- function image($img, $x, $y, $w, $h, $resolution = "normal") {
- list($width, $height, $type) = dompdf_getimagesize($img, $this->_dompdf->get_http_context());
-
- $debug_png = $this->_dompdf->get_option("debug_png");
-
- if ($debug_png) print "[image:$img|$width|$height|$type]";
-
- switch ($type) {
- case IMAGETYPE_JPEG:
- if ($debug_png) print '!!!jpg!!!';
- $this->_pdf->addJpegFromFile($img, $x, $this->y($y) - $h, $w, $h);
- break;
-
- case IMAGETYPE_GIF:
- case IMAGETYPE_BMP:
- if ($debug_png) print '!!!bmp or gif!!!';
- // @todo use cache for BMP and GIF
- $img = $this->_convert_gif_bmp_to_png($img, $type);
-
- case IMAGETYPE_PNG:
- if ($debug_png) print '!!!png!!!';
-
- $this->_pdf->addPngFromFile($img, $x, $this->y($y) - $h, $w, $h);
- break;
-
- default:
- if ($debug_png) print '!!!unknown!!!';
- }
- }
-
- function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
- $pdf = $this->_pdf;
-
- $pdf->setColor($color);
-
- $font .= ".afm";
- $pdf->selectFont($font);
-
- //Font_Metrics::get_font_height($font, $size) ==
- //$this->get_font_height($font, $size) ==
- //$this->_pdf->selectFont($font),$this->_pdf->getFontHeight($size)
- //- FontBBoxheight+FontHeightOffset, scaled to $size, in pt
- //$this->_pdf->getFontDescender($size)
- //- Descender scaled to size
- //
- //$this->_pdf->fonts[$this->_pdf->currentFont] sizes:
- //['FontBBox'][0] left, ['FontBBox'][1] bottom, ['FontBBox'][2] right, ['FontBBox'][3] top
- //Maximum extent of all glyphs of the font from the baseline point
- //['Ascender'] maximum height above baseline except accents
- //['Descender'] maximum depth below baseline, negative number means below baseline
- //['FontHeightOffset'] manual enhancement of .afm files to trim windows fonts. currently not used.
- //Values are in 1/1000 pt for a font size of 1 pt
- //
- //['FontBBox'][1] should be close to ['Descender']
- //['FontBBox'][3] should be close to ['Ascender']+Accents
- //in practice, FontBBox values are a little bigger
- //
- //The text position is referenced to the baseline, not to the lower corner of the FontBBox,
- //for what the left,top corner is given.
- //FontBBox spans also the background box for the text.
- //If the lower corner would be used as reference point, the Descents of the glyphs would
- //hang over the background box border.
- //Therefore compensate only the extent above the Baseline.
- //
- //print '['.$font.','.$size.','.$pdf->getFontHeight($size).','.$pdf->getFontDescender($size).','.$pdf->fonts[$pdf->currentFont]['FontBBox'][3].','.$pdf->fonts[$pdf->currentFont]['FontBBox'][1].','.$pdf->fonts[$pdf->currentFont]['FontHeightOffset'].','.$pdf->fonts[$pdf->currentFont]['Ascender'].','.$pdf->fonts[$pdf->currentFont]['Descender'].'] ';
- //
- //$pdf->addText($x, $this->y($y) - ($pdf->fonts[$pdf->currentFont]['FontBBox'][3]*$size)/1000, $size, $text, $angle, $word_space, $char_space);
- $pdf->addText($x, $this->y($y) - $pdf->getFontHeight($size), $size, $text, $angle, $word_space, $char_space);
- }
-
- //........................................................................
-
- function javascript($code) {
- $this->_pdf->addJavascript($code);
- }
-
- //........................................................................
-
- /**
- * Add a named destination (similar to ... in html)
- *
- * @param string $anchorname The name of the named destination
- */
- function add_named_dest($anchorname) {
- $this->_pdf->addDestination($anchorname, "Fit");
- }
-
- //........................................................................
-
- /**
- * Add a link to the pdf
- *
- * @param string $url The url to link to
- * @param float $x The x position of the link
- * @param float $y The y position of the link
- * @param float $width The width of the link
- * @param float $height The height of the link
- */
- function add_link($url, $x, $y, $width, $height) {
-
- $y = $this->y($y) - $height;
-
- if ( strpos($url, '#') === 0 ) {
- // Local link
- $name = substr($url,1);
- if ( $name ) {
- $this->_pdf->addInternalLink($name, $x, $y, $x + $width, $y + $height);
- }
-
- }
- else {
- $this->_pdf->addLink(rawurldecode($url), $x, $y, $x + $width, $y + $height);
- }
- }
-
- function get_text_width($text, $font, $size, $word_spacing = 0, $char_spacing = 0) {
- $this->_pdf->selectFont($font);
-
- $unicode = $this->_dompdf->get_option("enable_unicode");
- if (!$unicode) {
- $text = mb_convert_encoding($text, 'Windows-1252', 'UTF-8');
- }
-
- return $this->_pdf->getTextWidth($size, $text, $word_spacing, $char_spacing);
- }
-
- function register_string_subset($font, $string) {
- $this->_pdf->registerText($font, $string);
- }
-
- function get_font_height($font, $size) {
- $this->_pdf->selectFont($font);
-
- $ratio = $this->_dompdf->get_option("font_height_ratio");
- return $this->_pdf->getFontHeight($size) * $ratio;
- }
-
- /*function get_font_x_height($font, $size) {
- $this->_pdf->selectFont($font);
- $ratio = $this->_dompdf->get_option("font_height_ratio");
- return $this->_pdf->getFontXHeight($size) * $ratio;
- }*/
-
- function get_font_baseline($font, $size) {
- $ratio = $this->_dompdf->get_option("font_height_ratio");
- return $this->get_font_height($font, $size) / $ratio;
- }
-
- /**
- * Writes text at the specified x and y coordinates on every page
- *
- * The strings '{PAGE_NUM}' and '{PAGE_COUNT}' are automatically replaced
- * with their current values.
- *
- * See {@link Style::munge_color()} for the format of the colour array.
- *
- * @param float $x
- * @param float $y
- * @param string $text the text to write
- * @param string $font the font file to use
- * @param float $size the font size, in points
- * @param array $color
- * @param float $word_space word spacing adjustment
- * @param float $char_space char spacing adjustment
- * @param float $angle angle to write the text at, measured CW starting from the x-axis
- */
- function page_text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
- $_t = "text";
- $this->_page_text[] = compact("_t", "x", "y", "text", "font", "size", "color", "word_space", "char_space", "angle");
- }
-
- /**
- * Processes a script on every page
- *
- * The variables $pdf, $PAGE_NUM, and $PAGE_COUNT are available.
- *
- * This function can be used to add page numbers to all pages
- * after the first one, for example.
- *
- * @param string $code the script code
- * @param string $type the language type for script
- */
- function page_script($code, $type = "text/php") {
- $_t = "script";
- $this->_page_text[] = compact("_t", "code", "type");
- }
-
- function new_page() {
- $this->_page_number++;
- $this->_page_count++;
-
- $ret = $this->_pdf->newPage();
- $this->_pages[] = $ret;
- return $ret;
- }
-
- /**
- * Add text to each page after rendering is complete
- */
- protected function _add_page_text() {
-
- if ( !count($this->_page_text) ) {
- return;
- }
-
- $page_number = 1;
- $eval = null;
-
- foreach ($this->_pages as $pid) {
- $this->reopen_object($pid);
-
- foreach ($this->_page_text as $pt) {
- extract($pt);
-
- switch ($_t) {
- case "text":
- $text = str_replace(array("{PAGE_NUM}","{PAGE_COUNT}"),
- array($page_number, $this->_page_count), $text);
- $this->text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
- break;
-
- case "script":
- if ( !$eval ) {
- $eval = new PHP_Evaluator($this);
- }
- $eval->evaluate($code, array('PAGE_NUM' => $page_number, 'PAGE_COUNT' => $this->_page_count));
- break;
- }
- }
-
- $this->close_object();
- $page_number++;
- }
- }
-
- /**
- * Streams the PDF directly to the browser
- *
- * @param string $filename the name of the PDF file
- * @param array $options associative array, 'Attachment' => 0 or 1, 'compress' => 1 or 0
- */
- function stream($filename, $options = null) {
- // Add page text
- $this->_add_page_text();
-
- $options["Content-Disposition"] = $filename;
- $this->_pdf->stream($options);
- }
-
- /**
- * Returns the PDF as a string
- *
- * @param array $options Output options
- * @return string
- */
- function output($options = null) {
- $this->_add_page_text();
-
- $debug = isset($options["compress"]) && $options["compress"] != 1;
-
- return $this->_pdf->output($debug);
- }
-
- /**
- * Returns logging messages generated by the Cpdf class
- *
- * @return string
- */
- function get_messages() {
- return $this->_pdf->messages;
- }
-}
diff --git a/library/vendor/dompdf/include/css_color.cls.php b/library/vendor/dompdf/include/css_color.cls.php
deleted file mode 100644
index 481751db5..000000000
--- a/library/vendor/dompdf/include/css_color.cls.php
+++ /dev/null
@@ -1,287 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-class CSS_Color {
- static $cssColorNames = array(
- "aliceblue" => "F0F8FF",
- "antiquewhite" => "FAEBD7",
- "aqua" => "00FFFF",
- "aquamarine" => "7FFFD4",
- "azure" => "F0FFFF",
- "beige" => "F5F5DC",
- "bisque" => "FFE4C4",
- "black" => "000000",
- "blanchedalmond" => "FFEBCD",
- "blue" => "0000FF",
- "blueviolet" => "8A2BE2",
- "brown" => "A52A2A",
- "burlywood" => "DEB887",
- "cadetblue" => "5F9EA0",
- "chartreuse" => "7FFF00",
- "chocolate" => "D2691E",
- "coral" => "FF7F50",
- "cornflowerblue" => "6495ED",
- "cornsilk" => "FFF8DC",
- "crimson" => "DC143C",
- "cyan" => "00FFFF",
- "darkblue" => "00008B",
- "darkcyan" => "008B8B",
- "darkgoldenrod" => "B8860B",
- "darkgray" => "A9A9A9",
- "darkgreen" => "006400",
- "darkgrey" => "A9A9A9",
- "darkkhaki" => "BDB76B",
- "darkmagenta" => "8B008B",
- "darkolivegreen" => "556B2F",
- "darkorange" => "FF8C00",
- "darkorchid" => "9932CC",
- "darkred" => "8B0000",
- "darksalmon" => "E9967A",
- "darkseagreen" => "8FBC8F",
- "darkslateblue" => "483D8B",
- "darkslategray" => "2F4F4F",
- "darkslategrey" => "2F4F4F",
- "darkturquoise" => "00CED1",
- "darkviolet" => "9400D3",
- "deeppink" => "FF1493",
- "deepskyblue" => "00BFFF",
- "dimgray" => "696969",
- "dimgrey" => "696969",
- "dodgerblue" => "1E90FF",
- "firebrick" => "B22222",
- "floralwhite" => "FFFAF0",
- "forestgreen" => "228B22",
- "fuchsia" => "FF00FF",
- "gainsboro" => "DCDCDC",
- "ghostwhite" => "F8F8FF",
- "gold" => "FFD700",
- "goldenrod" => "DAA520",
- "gray" => "808080",
- "green" => "008000",
- "greenyellow" => "ADFF2F",
- "grey" => "808080",
- "honeydew" => "F0FFF0",
- "hotpink" => "FF69B4",
- "indianred" => "CD5C5C",
- "indigo" => "4B0082",
- "ivory" => "FFFFF0",
- "khaki" => "F0E68C",
- "lavender" => "E6E6FA",
- "lavenderblush" => "FFF0F5",
- "lawngreen" => "7CFC00",
- "lemonchiffon" => "FFFACD",
- "lightblue" => "ADD8E6",
- "lightcoral" => "F08080",
- "lightcyan" => "E0FFFF",
- "lightgoldenrodyellow" => "FAFAD2",
- "lightgray" => "D3D3D3",
- "lightgreen" => "90EE90",
- "lightgrey" => "D3D3D3",
- "lightpink" => "FFB6C1",
- "lightsalmon" => "FFA07A",
- "lightseagreen" => "20B2AA",
- "lightskyblue" => "87CEFA",
- "lightslategray" => "778899",
- "lightslategrey" => "778899",
- "lightsteelblue" => "B0C4DE",
- "lightyellow" => "FFFFE0",
- "lime" => "00FF00",
- "limegreen" => "32CD32",
- "linen" => "FAF0E6",
- "magenta" => "FF00FF",
- "maroon" => "800000",
- "mediumaquamarine" => "66CDAA",
- "mediumblue" => "0000CD",
- "mediumorchid" => "BA55D3",
- "mediumpurple" => "9370DB",
- "mediumseagreen" => "3CB371",
- "mediumslateblue" => "7B68EE",
- "mediumspringgreen" => "00FA9A",
- "mediumturquoise" => "48D1CC",
- "mediumvioletred" => "C71585",
- "midnightblue" => "191970",
- "mintcream" => "F5FFFA",
- "mistyrose" => "FFE4E1",
- "moccasin" => "FFE4B5",
- "navajowhite" => "FFDEAD",
- "navy" => "000080",
- "oldlace" => "FDF5E6",
- "olive" => "808000",
- "olivedrab" => "6B8E23",
- "orange" => "FFA500",
- "orangered" => "FF4500",
- "orchid" => "DA70D6",
- "palegoldenrod" => "EEE8AA",
- "palegreen" => "98FB98",
- "paleturquoise" => "AFEEEE",
- "palevioletred" => "DB7093",
- "papayawhip" => "FFEFD5",
- "peachpuff" => "FFDAB9",
- "peru" => "CD853F",
- "pink" => "FFC0CB",
- "plum" => "DDA0DD",
- "powderblue" => "B0E0E6",
- "purple" => "800080",
- "red" => "FF0000",
- "rosybrown" => "BC8F8F",
- "royalblue" => "4169E1",
- "saddlebrown" => "8B4513",
- "salmon" => "FA8072",
- "sandybrown" => "F4A460",
- "seagreen" => "2E8B57",
- "seashell" => "FFF5EE",
- "sienna" => "A0522D",
- "silver" => "C0C0C0",
- "skyblue" => "87CEEB",
- "slateblue" => "6A5ACD",
- "slategray" => "708090",
- "slategrey" => "708090",
- "snow" => "FFFAFA",
- "springgreen" => "00FF7F",
- "steelblue" => "4682B4",
- "tan" => "D2B48C",
- "teal" => "008080",
- "thistle" => "D8BFD8",
- "tomato" => "FF6347",
- "turquoise" => "40E0D0",
- "violet" => "EE82EE",
- "wheat" => "F5DEB3",
- "white" => "FFFFFF",
- "whitesmoke" => "F5F5F5",
- "yellow" => "FFFF00",
- "yellowgreen" => "9ACD32",
- );
-
- static function parse($color) {
- if ( is_array($color) ) {
- // Assume the array has the right format...
- // FIXME: should/could verify this.
- return $color;
- }
-
- static $cache = array();
-
- $color = strtolower($color);
-
- if ( isset($cache[$color]) ) {
- return $cache[$color];
- }
-
- if ( in_array($color, array("transparent", "inherit")) ) {
- return $cache[$color] = $color;
- }
-
- if ( isset(self::$cssColorNames[$color]) ) {
- return $cache[$color] = self::getArray(self::$cssColorNames[$color]);
- }
-
- $length = mb_strlen($color);
-
- // #rgb format
- if ( $length == 4 && $color[0] === "#" ) {
- return $cache[$color] = self::getArray($color[1].$color[1].$color[2].$color[2].$color[3].$color[3]);
- }
-
- // #rrggbb format
- else if ( $length == 7 && $color[0] === "#" ) {
- return $cache[$color] = self::getArray(mb_substr($color, 1, 6));
- }
-
- // rgb( r,g,b ) / rgbaa( r,g,b,α ) format
- else if ( mb_strpos($color, "rgb") !== false ) {
- $i = mb_strpos($color, "(");
- $j = mb_strpos($color, ")");
-
- // Bad color value
- if ( $i === false || $j === false ) {
- return null;
- }
-
- $triplet = explode(",", mb_substr($color, $i+1, $j-$i-1));
-
- // alpha transparency
- // FIXME: not currently using transparency
- $alpha = 1;
- if ( count( $triplet ) == 4 ) {
- $alpha = (float) ( trim( array_pop( $triplet ) ) );
- // bad value, set to fully opaque
- if ( $alpha > 1 || $alpha < 0 ) {
- $alpha = 1;
- }
- }
-
- if ( count($triplet) != 3 ) {
- return null;
- }
-
- foreach (array_keys($triplet) as $c) {
- $triplet[$c] = trim($triplet[$c]);
-
- if ( $triplet[$c][mb_strlen($triplet[$c]) - 1] === "%" ) {
- $triplet[$c] = round($triplet[$c] * 2.55);
- }
- }
-
- return $cache[$color] = self::getArray(vsprintf("%02X%02X%02X", $triplet));
-
- }
-
- // cmyk( c,m,y,k ) format
- // http://www.w3.org/TR/css3-gcpm/#cmyk-colors
- else if ( mb_strpos($color, "cmyk") !== false ) {
- $i = mb_strpos($color, "(");
- $j = mb_strpos($color, ")");
-
- // Bad color value
- if ( $i === false || $j === false ) {
- return null;
- }
-
- $values = explode(",", mb_substr($color, $i+1, $j-$i-1));
-
- if ( count($values) != 4 ) {
- return null;
- }
-
- foreach ($values as &$c) {
- $c = floatval(trim($c));
- if ($c > 1.0) $c = 1.0;
- if ($c < 0.0) $c = 0.0;
- }
-
- return $cache[$color] = self::getArray($values);
- }
-
- return null;
- }
-
- static function getArray($color) {
- $c = array(null, null, null, null, "hex" => null);
-
- if (is_array($color)) {
- $c = $color;
- $c["c"] = $c[0];
- $c["m"] = $c[1];
- $c["y"] = $c[2];
- $c["k"] = $c[3];
- $c["hex"] = "cmyk($c[0],$c[1],$c[2],$c[3])";
- }
- else {
- $c[0] = hexdec(mb_substr($color, 0, 2)) / 0xff;
- $c[1] = hexdec(mb_substr($color, 2, 2)) / 0xff;
- $c[2] = hexdec(mb_substr($color, 4, 2)) / 0xff;
- $c["r"] = $c[0];
- $c["g"] = $c[1];
- $c["b"] = $c[2];
- $c["hex"] = "#$color";
- }
-
- return $c;
- }
-}
diff --git a/library/vendor/dompdf/include/dompdf.cls.php b/library/vendor/dompdf/include/dompdf.cls.php
deleted file mode 100644
index b798d486e..000000000
--- a/library/vendor/dompdf/include/dompdf.cls.php
+++ /dev/null
@@ -1,1101 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * DOMPDF - PHP5 HTML to PDF renderer
- *
- * DOMPDF loads HTML and does its best to render it as a PDF. It gets its
- * name from the new DomDocument PHP5 extension. Source HTML is first
- * parsed by a DomDocument object. DOMPDF takes the resulting DOM tree and
- * attaches a {@link Frame} object to each node. {@link Frame} objects store
- * positioning and layout information and each has a reference to a {@link
- * Style} object.
- *
- * Style information is loaded and parsed (see {@link Stylesheet}) and is
- * applied to the frames in the tree by using XPath. CSS selectors are
- * converted into XPath queries, and the computed {@link Style} objects are
- * applied to the {@link Frame}s.
- *
- * {@link Frame}s are then decorated (in the design pattern sense of the
- * word) based on their CSS display property ({@link
- * http://www.w3.org/TR/CSS21/visuren.html#propdef-display}).
- * Frame_Decorators augment the basic {@link Frame} class by adding
- * additional properties and methods specific to the particular type of
- * {@link Frame}. For example, in the CSS layout model, block frames
- * (display: block;) contain line boxes that are usually filled with text or
- * other inline frames. The Block_Frame_Decorator therefore adds a $lines
- * property as well as methods to add {@link Frame}s to lines and to add
- * additional lines. {@link Frame}s also are attached to specific
- * Positioner and {@link Frame_Reflower} objects that contain the
- * positioining and layout algorithm for a specific type of frame,
- * respectively. This is an application of the Strategy pattern.
- *
- * Layout, or reflow, proceeds recursively (post-order) starting at the root
- * of the document. Space constraints (containing block width & height) are
- * pushed down, and resolved positions and sizes bubble up. Thus, every
- * {@link Frame} in the document tree is traversed once (except for tables
- * which use a two-pass layout algorithm). If you are interested in the
- * details, see the reflow() method of the Reflower classes.
- *
- * Rendering is relatively straightforward once layout is complete. {@link
- * Frame}s are rendered using an adapted {@link Cpdf} class, originally
- * written by Wayne Munro, http://www.ros.co.nz/pdf/. (Some performance
- * related changes have been made to the original {@link Cpdf} class, and
- * the {@link CPDF_Adapter} class provides a simple, stateless interface to
- * PDF generation.) PDFLib support has now also been added, via the {@link
- * PDFLib_Adapter}.
- *
- *
- * @package dompdf
- */
-class DOMPDF {
-
- /**
- * DomDocument representing the HTML document
- *
- * @var DOMDocument
- */
- protected $_xml;
-
- /**
- * Frame_Tree derived from the DOM tree
- *
- * @var Frame_Tree
- */
- protected $_tree;
-
- /**
- * Stylesheet for the document
- *
- * @var Stylesheet
- */
- protected $_css;
-
- /**
- * Actual PDF renderer
- *
- * @var Canvas
- */
- protected $_pdf;
-
- /**
- * Desired paper size ('letter', 'legal', 'A4', etc.)
- *
- * @var string
- */
- protected $_paper_size;
-
- /**
- * Paper orientation ('portrait' or 'landscape')
- *
- * @var string
- */
- protected $_paper_orientation;
-
- /**
- * Callbacks on new page and new element
- *
- * @var array
- */
- protected $_callbacks;
-
- /**
- * Experimental caching capability
- *
- * @var string
- */
- private $_cache_id;
-
- /**
- * Base hostname
- *
- * Used for relative paths/urls
- * @var string
- */
- protected $_base_host;
-
- /**
- * Absolute base path
- *
- * Used for relative paths/urls
- * @var string
- */
- protected $_base_path;
-
- /**
- * Protcol used to request file (file://, http://, etc)
- *
- * @var string
- */
- protected $_protocol;
-
- /**
- * HTTP context created with stream_context_create()
- * Will be used for file_get_contents
- *
- * @var resource
- */
- protected $_http_context;
-
- /**
- * Timestamp of the script start time
- *
- * @var int
- */
- private $_start_time = null;
-
- /**
- * The system's locale
- *
- * @var string
- */
- private $_system_locale = null;
-
- /**
- * Tells if the system's locale is the C standard one
- *
- * @var bool
- */
- private $_locale_standard = false;
-
- /**
- * The default view of the PDF in the viewer
- *
- * @var string
- */
- private $_default_view = "Fit";
-
- /**
- * The default view options of the PDF in the viewer
- *
- * @var array
- */
- private $_default_view_options = array();
-
- /**
- * Tells wether the DOM document is in quirksmode (experimental)
- *
- * @var bool
- */
- private $_quirksmode = false;
-
- /**
- * Protocol whitelist
- *
- * Protocols and PHP wrappers allowed in URLs. Full support is not
- * guarantee for the protocols/wrappers contained in this array.
- *
- * @var array
- */
- private $_allowed_protocols = array(null, "", "file://", "http://", "https://");
-
- /**
- * Local file extension whitelist
- *
- * File extensions supported by dompdf for local files.
- *
- * @var array
- */
- private $_allowed_local_file_extensions = array("htm", "html");
-
- /**
- * The list of built-in fonts
- *
- * @var array
- */
- public static $native_fonts = array(
- "courier", "courier-bold", "courier-oblique", "courier-boldoblique",
- "helvetica", "helvetica-bold", "helvetica-oblique", "helvetica-boldoblique",
- "times-roman", "times-bold", "times-italic", "times-bolditalic",
- "symbol", "zapfdinbats"
- );
-
- private $_options = array(
- // Directories
- "temp_dir" => DOMPDF_TEMP_DIR,
- "font_dir" => DOMPDF_FONT_DIR,
- "font_cache" => DOMPDF_FONT_CACHE,
- "chroot" => DOMPDF_CHROOT,
- "log_output_file" => DOMPDF_LOG_OUTPUT_FILE,
-
- // Rendering
- "default_media_type" => DOMPDF_DEFAULT_MEDIA_TYPE,
- "default_paper_size" => DOMPDF_DEFAULT_PAPER_SIZE,
- "default_font" => DOMPDF_DEFAULT_FONT,
- "dpi" => DOMPDF_DPI,
- "font_height_ratio" => DOMPDF_FONT_HEIGHT_RATIO,
-
- // Features
- "enable_unicode" => DOMPDF_UNICODE_ENABLED,
- "enable_php" => DOMPDF_ENABLE_PHP,
- "enable_remote" => DOMPDF_ENABLE_REMOTE,
- "enable_css_float" => DOMPDF_ENABLE_CSS_FLOAT,
- "enable_javascript" => DOMPDF_ENABLE_JAVASCRIPT,
- "enable_html5_parser" => DOMPDF_ENABLE_HTML5PARSER,
- "enable_font_subsetting" => DOMPDF_ENABLE_FONTSUBSETTING,
-
- // Debug
- "debug_png" => DEBUGPNG,
- "debug_keep_temp" => DEBUGKEEPTEMP,
- "debug_css" => DEBUGCSS,
- "debug_layout" => DEBUG_LAYOUT,
- "debug_layout_lines" => DEBUG_LAYOUT_LINES,
- "debug_layout_blocks" => DEBUG_LAYOUT_BLOCKS,
- "debug_layout_inline" => DEBUG_LAYOUT_INLINE,
- "debug_layout_padding_box" => DEBUG_LAYOUT_PADDINGBOX,
-
- // Admin
- "admin_username" => DOMPDF_ADMIN_USERNAME,
- "admin_password" => DOMPDF_ADMIN_PASSWORD,
- );
-
- /**
- * Class constructor
- */
- function __construct() {
- $this->_locale_standard = sprintf('%.1f', 1.0) == '1.0';
-
- $this->save_locale();
-
- $this->_messages = array();
- $this->_css = new Stylesheet($this);
- $this->_pdf = null;
- $this->_paper_size = DOMPDF_DEFAULT_PAPER_SIZE;
- $this->_paper_orientation = "portrait";
- $this->_base_protocol = "";
- $this->_base_host = "";
- $this->_base_path = "";
- $this->_http_context = null;
- $this->_callbacks = array();
- $this->_cache_id = null;
-
- $this->restore_locale();
- }
-
- /**
- * Class destructor
- */
- function __destruct() {
- clear_object($this);
- }
-
- /**
- * Get the dompdf option value
- *
- * @param string $key
- *
- * @return mixed
- * @throws DOMPDF_Exception
- */
- function get_option($key) {
- if ( !array_key_exists($key, $this->_options) ) {
- throw new DOMPDF_Exception("Option '$key' doesn't exist");
- }
-
- return $this->_options[$key];
- }
-
- /**
- * @param string $key
- * @param mixed $value
- *
- * @throws DOMPDF_Exception
- */
- function set_option($key, $value) {
- if ( !array_key_exists($key, $this->_options) ) {
- throw new DOMPDF_Exception("Option '$key' doesn't exist");
- }
-
- $this->_options[$key] = $value;
- }
-
- /**
- * @param array $options
- */
- function set_options(array $options) {
- foreach ($options as $key => $value) {
- $this->set_option($key, $value);
- }
- }
-
- /**
- * Save the system's locale configuration and
- * set the right value for numeric formatting
- */
- private function save_locale() {
- if ( $this->_locale_standard ) {
- return;
- }
-
- $this->_system_locale = setlocale(LC_NUMERIC, "0");
- setlocale(LC_NUMERIC, "C");
- }
-
- /**
- * Restore the system's locale configuration
- */
- private function restore_locale() {
- if ( $this->_locale_standard ) {
- return;
- }
-
- setlocale(LC_NUMERIC, $this->_system_locale);
- }
-
- /**
- * Returns the underlying {@link Frame_Tree} object
- *
- * @return Frame_Tree
- */
- function get_tree() {
- return $this->_tree;
- }
-
- /**
- * Sets the protocol to use
- * FIXME validate these
- *
- * @param string $proto
- */
- function set_protocol($proto) {
- $this->_protocol = $proto;
- }
-
- /**
- * Sets the base hostname
- *
- * @param string $host
- */
- function set_host($host) {
- $this->_base_host = $host;
- }
-
- /**
- * Sets the base path
- *
- * @param string $path
- */
- function set_base_path($path) {
- $this->_base_path = $path;
- }
-
- /**
- * Sets the HTTP context
- *
- * @param resource $http_context
- */
- function set_http_context($http_context) {
- $this->_http_context = $http_context;
- }
-
- /**
- * Sets the default view
- *
- * @param string $default_view The default document view
- * @param array $options The view's options
- */
- function set_default_view($default_view, $options) {
- $this->_default_view = $default_view;
- $this->_default_view_options = $options;
- }
-
- /**
- * Returns the protocol in use
- *
- * @return string
- */
- function get_protocol() {
- return $this->_protocol;
- }
-
- /**
- * Returns the base hostname
- *
- * @return string
- */
- function get_host() {
- return $this->_base_host;
- }
-
- /**
- * Returns the base path
- *
- * @return string
- */
- function get_base_path() {
- return $this->_base_path;
- }
-
- /**
- * Returns the HTTP context
- *
- * @return resource
- */
- function get_http_context() {
- return $this->_http_context;
- }
-
- /**
- * Return the underlying Canvas instance (e.g. CPDF_Adapter, GD_Adapter)
- *
- * @return Canvas
- */
- function get_canvas() {
- return $this->_pdf;
- }
-
- /**
- * Returns the callbacks array
- *
- * @return array
- */
- function get_callbacks() {
- return $this->_callbacks;
- }
-
- /**
- * Returns the stylesheet
- *
- * @return Stylesheet
- */
- function get_css() {
- return $this->_css;
- }
-
- /**
- * @return DOMDocument
- */
- function get_dom() {
- return $this->_xml;
- }
-
- /**
- * Loads an HTML file
- * Parse errors are stored in the global array _dompdf_warnings.
- *
- * @param string $file a filename or url to load
- *
- * @throws DOMPDF_Exception
- */
- function load_html_file($file) {
- $this->save_locale();
-
- // Store parsing warnings as messages (this is to prevent output to the
- // browser if the html is ugly and the dom extension complains,
- // preventing the pdf from being streamed.)
- if ( !$this->_protocol && !$this->_base_host && !$this->_base_path ) {
- list($this->_protocol, $this->_base_host, $this->_base_path) = explode_url($file);
- }
-
- if ( !in_array($this->_protocol, $this->_allowed_protocols) ) {
- throw new DOMPDF_Exception("Permission denied on $file. The communication protocol is not supported.");
- }
-
- if ( !$this->get_option("enable_remote") && ($this->_protocol != "" && $this->_protocol !== "file://" ) ) {
- throw new DOMPDF_Exception("Remote file requested, but DOMPDF_ENABLE_REMOTE is false.");
- }
-
- if ($this->_protocol == "" || $this->_protocol === "file://") {
-
- // Get the full path to $file, returns false if the file doesn't exist
- $realfile = realpath($file);
-
- $chroot = $this->get_option("chroot");
- if ( strpos($realfile, $chroot) !== 0 ) {
- throw new DOMPDF_Exception("Permission denied on $file. The file could not be found under the directory specified by DOMPDF_CHROOT.");
- }
-
- $ext = pathinfo($realfile, PATHINFO_EXTENSION);
- if (!in_array($ext, $this->_allowed_local_file_extensions)) {
- throw new DOMPDF_Exception("Permission denied on $file.");
- }
-
- if ( !$realfile ) {
- throw new DOMPDF_Exception("File '$file' not found.");
- }
-
- $file = $realfile;
- }
-
- $contents = file_get_contents($file, null, $this->_http_context);
- $encoding = null;
-
- // See http://the-stickman.com/web-development/php/getting-http-response-headers-when-using-file_get_contents/
- if ( isset($http_response_header) ) {
- foreach($http_response_header as $_header) {
- if ( preg_match("@Content-Type:\s*[\w/]+;\s*?charset=([^\s]+)@i", $_header, $matches) ) {
- $encoding = strtoupper($matches[1]);
- break;
- }
- }
- }
-
- $this->restore_locale();
-
- $this->load_html($contents, $encoding);
- }
-
- /**
- * Loads an HTML string
- * Parse errors are stored in the global array _dompdf_warnings.
- * @todo use the $encoding variable
- *
- * @param string $str HTML text to load
- * @param string $encoding Not used yet
- */
- function load_html($str, $encoding = null) {
- $this->save_locale();
-
- // FIXME: Determine character encoding, switch to UTF8, update meta tag. Need better http/file stream encoding detection, currently relies on text or meta tag.
- mb_detect_order('auto');
-
- if (mb_detect_encoding($str) !== 'UTF-8') {
- $metatags = array(
- '@ ]*charset\s*=\s*["\']?\s*([^"\' ]+)@i',
- );
-
- foreach($metatags as $metatag) {
- if (preg_match($metatag, $str, $matches)) break;
- }
-
- if (mb_detect_encoding($str) == '') {
- if (isset($matches[1])) {
- $encoding = strtoupper($matches[1]);
- }
- else {
- $encoding = 'UTF-8';
- }
- }
- else {
- if ( isset($matches[1]) ) {
- $encoding = strtoupper($matches[1]);
- }
- else {
- $encoding = 'auto';
- }
- }
-
- if ( $encoding !== 'UTF-8' ) {
- $str = mb_convert_encoding($str, 'UTF-8', $encoding);
- }
-
- if ( isset($matches[1]) ) {
- $str = preg_replace('/charset=([^\s"]+)/i', 'charset=UTF-8', $str);
- }
- else {
- $str = str_replace('', ' ', $str);
- }
- }
- else {
- $encoding = 'UTF-8';
- }
-
- // remove BOM mark from UTF-8, it's treated as document text by DOMDocument
- // FIXME: roll this into the encoding detection using UTF-8/16/32 BOM (http://us2.php.net/manual/en/function.mb-detect-encoding.php#91051)?
- if ( substr($str, 0, 3) == chr(0xEF).chr(0xBB).chr(0xBF) ) {
- $str = substr($str, 3);
- }
-
- // if the document contains non utf-8 with a utf-8 meta tag chars and was
- // detected as utf-8 by mbstring, problems could happen.
- // http://devzone.zend.com/article/8855
- if ( $encoding !== 'UTF-8' ) {
- $re = '/ ]*)((?:charset=[^"\' ]+)([^>]*)|(?:charset=["\'][^"\' ]+["\']))([^>]*)>/i';
- $str = preg_replace($re, ' ', $str);
- }
-
- // Store parsing warnings as messages
- set_error_handler("record_warnings");
-
- // @todo Take the quirksmode into account
- // http://hsivonen.iki.fi/doctype/
- // https://developer.mozilla.org/en/mozilla's_quirks_mode
- $quirksmode = false;
-
- if ( $this->get_option("enable_html5_parser") ) {
- $tokenizer = new HTML5_Tokenizer($str);
- $tokenizer->parse();
- $doc = $tokenizer->save();
-
- // Remove #text children nodes in nodes that shouldn't have
- $tag_names = array("html", "table", "tbody", "thead", "tfoot", "tr");
- foreach($tag_names as $tag_name) {
- $nodes = $doc->getElementsByTagName($tag_name);
-
- foreach($nodes as $node) {
- self::remove_text_nodes($node);
- }
- }
-
- $quirksmode = ($tokenizer->getTree()->getQuirksMode() > HTML5_TreeBuilder::NO_QUIRKS);
- }
- else {
- // loadHTML assumes ISO-8859-1 unless otherwise specified, but there are
- // bugs in how DOMDocument determines the actual encoding. Converting to
- // HTML-ENTITIES prior to import appears to resolve the issue.
- // http://devzone.zend.com/1538/php-dom-xml-extension-encoding-processing/ (see #4)
- // http://stackoverflow.com/a/11310258/264628
- $doc = new DOMDocument();
- $doc->preserveWhiteSpace = true;
- $doc->loadHTML( mb_convert_encoding( $str , 'HTML-ENTITIES' , 'UTF-8' ) );
-
- // If some text is before the doctype, we are in quirksmode
- if ( preg_match("/^(.+)
- if ( !$doc->doctype->publicId && !$doc->doctype->systemId ) {
- $quirksmode = false;
- }
-
- // not XHTML
- if ( !preg_match("/xhtml/i", $doc->doctype->publicId) ) {
- $quirksmode = true;
- }
- }
- }
-
- $this->_xml = $doc;
- $this->_quirksmode = $quirksmode;
-
- $this->_tree = new Frame_Tree($this->_xml);
-
- restore_error_handler();
-
- $this->restore_locale();
- }
-
- static function remove_text_nodes(DOMNode $node) {
- $children = array();
- for ($i = 0; $i < $node->childNodes->length; $i++) {
- $child = $node->childNodes->item($i);
- if ( $child->nodeName === "#text" ) {
- $children[] = $child;
- }
- }
-
- foreach($children as $child) {
- $node->removeChild($child);
- }
- }
-
- /**
- * Builds the {@link Frame_Tree}, loads any CSS and applies the styles to
- * the {@link Frame_Tree}
- */
- protected function _process_html() {
- $this->_tree->build_tree();
-
- $this->_css->load_css_file(Stylesheet::DEFAULT_STYLESHEET, Stylesheet::ORIG_UA);
-
- $acceptedmedia = Stylesheet::$ACCEPTED_GENERIC_MEDIA_TYPES;
- $acceptedmedia[] = $this->get_option("default_media_type");
-
- //
- $base_nodes = $this->_xml->getElementsByTagName("base");
- if ( $base_nodes->length && ($href = $base_nodes->item(0)->getAttribute("href")) ) {
- list($this->_protocol, $this->_base_host, $this->_base_path) = explode_url($href);
- }
-
- // Set the base path of the Stylesheet to that of the file being processed
- $this->_css->set_protocol($this->_protocol);
- $this->_css->set_host($this->_base_host);
- $this->_css->set_base_path($this->_base_path);
-
- // Get all the stylesheets so that they are processed in document order
- $xpath = new DOMXPath($this->_xml);
- $stylesheets = $xpath->query("//*[name() = 'link' or name() = 'style']");
-
- foreach($stylesheets as $tag) {
- switch (strtolower($tag->nodeName)) {
- // load tags
- case "link":
- if ( mb_strtolower(stripos($tag->getAttribute("rel"), "stylesheet") !== false) || // may be "appendix stylesheet"
- mb_strtolower($tag->getAttribute("type")) === "text/css" ) {
- //Check if the css file is for an accepted media type
- //media not given then always valid
- $formedialist = preg_split("/[\s\n,]/", $tag->getAttribute("media"),-1, PREG_SPLIT_NO_EMPTY);
- if ( count($formedialist) > 0 ) {
- $accept = false;
- foreach ( $formedialist as $type ) {
- if ( in_array(mb_strtolower(trim($type)), $acceptedmedia) ) {
- $accept = true;
- break;
- }
- }
-
- if (!$accept) {
- //found at least one mediatype, but none of the accepted ones
- //Skip this css file.
- continue;
- }
- }
-
- $url = $tag->getAttribute("href");
- $url = build_url($this->_protocol, $this->_base_host, $this->_base_path, $url);
-
- $this->_css->load_css_file($url, Stylesheet::ORIG_AUTHOR);
- }
- break;
-
- // load
- $child = $child->nextSibling;
- }
- }
- else {
- $css = $tag->nodeValue;
- }
-
- $this->_css->load_css($css);
- break;
- }
- }
- }
-
- /**
- * Sets the paper size & orientation
- *
- * @param string $size 'letter', 'legal', 'A4', etc. {@link CPDF_Adapter::$PAPER_SIZES}
- * @param string $orientation 'portrait' or 'landscape'
- */
- function set_paper($size, $orientation = "portrait") {
- $this->_paper_size = $size;
- $this->_paper_orientation = $orientation;
- }
-
- /**
- * Enable experimental caching capability
- * @access private
- */
- function enable_caching($cache_id) {
- $this->_cache_id = $cache_id;
- }
-
- /**
- * Sets callbacks for events like rendering of pages and elements.
- * The callbacks array contains arrays with 'event' set to 'begin_page',
- * 'end_page', 'begin_frame', or 'end_frame' and 'f' set to a function or
- * object plus method to be called.
- *
- * The function 'f' must take an array as argument, which contains info
- * about the event.
- *
- * @param array $callbacks the set of callbacks to set
- */
- function set_callbacks($callbacks) {
- if (is_array($callbacks)) {
- $this->_callbacks = array();
- foreach ($callbacks as $c) {
- if (is_array($c) && isset($c['event']) && isset($c['f'])) {
- $event = $c['event'];
- $f = $c['f'];
- if (is_callable($f) && is_string($event)) {
- $this->_callbacks[$event][] = $f;
- }
- }
- }
- }
- }
-
- /**
- * Get the quirks mode
- *
- * @return boolean true if quirks mode is active
- */
- function get_quirksmode(){
- return $this->_quirksmode;
- }
-
- function parse_default_view($value) {
- $valid = array("XYZ", "Fit", "FitH", "FitV", "FitR", "FitB", "FitBH", "FitBV");
-
- $options = preg_split("/\s*,\s*/", trim($value));
- $default_view = array_shift($options);
-
- if ( !in_array($default_view, $valid) ) {
- return false;
- }
-
- $this->set_default_view($default_view, $options);
- return true;
- }
-
- /**
- * Renders the HTML to PDF
- */
- function render() {
- $this->save_locale();
-
- $log_output_file = $this->get_option("log_output_file");
- if ( $log_output_file ) {
- if ( !file_exists($log_output_file) && is_writable(dirname($log_output_file)) ) {
- touch($log_output_file);
- }
-
- $this->_start_time = microtime(true);
- ob_start();
- }
-
- //enable_mem_profile();
-
- $this->_process_html();
-
- $this->_css->apply_styles($this->_tree);
-
- // @page style rules : size, margins
- $page_styles = $this->_css->get_page_styles();
-
- $base_page_style = $page_styles["base"];
- unset($page_styles["base"]);
-
- foreach($page_styles as $_page_style) {
- $_page_style->inherit($base_page_style);
- }
-
- if ( is_array($base_page_style->size) ) {
- $this->set_paper(array(0, 0, $base_page_style->size[0], $base_page_style->size[1]));
- }
-
- $this->_pdf = Canvas_Factory::get_instance($this, $this->_paper_size, $this->_paper_orientation);
- Font_Metrics::init($this->_pdf);
-
- if ( $this->get_option("enable_font_subsetting") && $this->_pdf instanceof CPDF_Adapter ) {
- foreach ($this->_tree->get_frames() as $frame) {
- $style = $frame->get_style();
- $node = $frame->get_node();
-
- // Handle text nodes
- if ( $node->nodeName === "#text" ) {
- $this->_pdf->register_string_subset($style->font_family, $node->nodeValue);
- continue;
- }
-
- // Handle generated content (list items)
- if ( $style->display === "list-item" ) {
- $chars = List_Bullet_Renderer::get_counter_chars($style->list_style_type);
- $this->_pdf->register_string_subset($style->font_family, $chars);
- continue;
- }
-
- // Handle other generated content (pseudo elements)
- // FIXME: This only captures the text of the stylesheet declaration,
- // not the actual generated content, and forces all possible counter
- // values. See notes in issue #750.
- if ( $frame->get_node()->nodeName == "dompdf_generated" ) {
- // all possible counter values
- $chars = List_Bullet_Renderer::get_counter_chars('decimal');
- $this->_pdf->register_string_subset($style->font_family, $chars);
- $chars = List_Bullet_Renderer::get_counter_chars('upper-alpha');
- $this->_pdf->register_string_subset($style->font_family, $chars);
- $chars = List_Bullet_Renderer::get_counter_chars('lower-alpha');
- $this->_pdf->register_string_subset($style->font_family, $chars);
- $chars = List_Bullet_Renderer::get_counter_chars('lower-greek');
- $this->_pdf->register_string_subset($style->font_family, $chars);
- // the text of the stylesheet declaration
- $this->_pdf->register_string_subset($style->font_family, $style->content);
- continue;
- }
- }
- }
-
- $root = null;
-
- foreach ($this->_tree->get_frames() as $frame) {
- // Set up the root frame
- if ( is_null($root) ) {
- $root = Frame_Factory::decorate_root( $this->_tree->get_root(), $this );
- continue;
- }
-
- // Create the appropriate decorators, reflowers & positioners.
- Frame_Factory::decorate_frame($frame, $this, $root);
- }
-
- // Add meta information
- $title = $this->_xml->getElementsByTagName("title");
- if ( $title->length ) {
- $this->_pdf->add_info("Title", trim($title->item(0)->nodeValue));
- }
-
- $metas = $this->_xml->getElementsByTagName("meta");
- $labels = array(
- "author" => "Author",
- "keywords" => "Keywords",
- "description" => "Subject",
- );
- foreach($metas as $meta) {
- $name = mb_strtolower($meta->getAttribute("name"));
- $value = trim($meta->getAttribute("content"));
-
- if ( isset($labels[$name]) ) {
- $this->_pdf->add_info($labels[$name], $value);
- continue;
- }
-
- if ( $name === "dompdf.view" && $this->parse_default_view($value) ) {
- $this->_pdf->set_default_view($this->_default_view, $this->_default_view_options);
- }
- }
-
- $root->set_containing_block(0, 0, $this->_pdf->get_width(), $this->_pdf->get_height());
- $root->set_renderer(new Renderer($this));
-
- // This is where the magic happens:
- $root->reflow();
-
- // Clean up cached images
- Image_Cache::clear();
-
- global $_dompdf_warnings, $_dompdf_show_warnings;
- if ( $_dompdf_show_warnings ) {
- echo 'DOMPDF Warnings ';
- foreach ($_dompdf_warnings as $msg) {
- echo $msg . "\n";
- }
- echo $this->get_canvas()->get_cpdf()->messages;
- echo ' ';
- flush();
- }
-
- $this->restore_locale();
- }
-
- /**
- * Add meta information to the PDF after rendering
- */
- function add_info($label, $value) {
- if ( !is_null($this->_pdf) ) {
- $this->_pdf->add_info($label, $value);
- }
- }
-
- /**
- * Writes the output buffer in the log file
- *
- * @return void
- */
- private function write_log() {
- $log_output_file = $this->get_option("log_output_file");
- if ( !$log_output_file || !is_writable($log_output_file) ) {
- return;
- }
-
- $frames = Frame::$ID_COUNTER;
- $memory = DOMPDF_memory_usage() / 1024;
- $time = (microtime(true) - $this->_start_time) * 1000;
-
- $out = sprintf(
- "%6d ".
- "%10.2f KB ".
- "%10.2f ms ".
- " ".
- ($this->_quirksmode ? " ON " : "OFF ").
- " ", $frames, $memory, $time);
-
- $out .= ob_get_clean();
-
- $log_output_file = $this->get_option("log_output_file");
- file_put_contents($log_output_file, $out);
- }
-
- /**
- * Streams the PDF to the client
- *
- * The file will open a download dialog by default. The options
- * parameter controls the output. Accepted options are:
- *
- * 'Accept-Ranges' => 1 or 0 - if this is not set to 1, then this
- * header is not included, off by default this header seems to
- * have caused some problems despite the fact that it is supposed
- * to solve them, so I am leaving it off by default.
- *
- * 'compress' = > 1 or 0 - apply content stream compression, this is
- * on (1) by default
- *
- * 'Attachment' => 1 or 0 - if 1, force the browser to open a
- * download dialog, on (1) by default
- *
- * @param string $filename the name of the streamed file
- * @param array $options header options (see above)
- */
- function stream($filename, $options = null) {
- $this->save_locale();
-
- $this->write_log();
-
- if ( !is_null($this->_pdf) ) {
- $this->_pdf->stream($filename, $options);
- }
-
- $this->restore_locale();
- }
-
- /**
- * Returns the PDF as a string
- *
- * The file will open a download dialog by default. The options
- * parameter controls the output. Accepted options are:
- *
- *
- * 'compress' = > 1 or 0 - apply content stream compression, this is
- * on (1) by default
- *
- *
- * @param array $options options (see above)
- *
- * @return string
- */
- function output($options = null) {
- $this->save_locale();
-
- $this->write_log();
-
- if ( is_null($this->_pdf) ) {
- return null;
- }
-
- $output = $this->_pdf->output( $options );
-
- $this->restore_locale();
-
- return $output;
- }
-
- /**
- * Returns the underlying HTML document as a string
- *
- * @return string
- */
- function output_html() {
- return $this->_xml->saveHTML();
- }
-}
diff --git a/library/vendor/dompdf/include/dompdf_exception.cls.php b/library/vendor/dompdf/include/dompdf_exception.cls.php
deleted file mode 100644
index ca47fa036..000000000
--- a/library/vendor/dompdf/include/dompdf_exception.cls.php
+++ /dev/null
@@ -1,26 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Standard exception thrown by DOMPDF classes
- *
- * @package dompdf
- */
-class DOMPDF_Exception extends Exception {
-
- /**
- * Class constructor
- *
- * @param string $message Error message
- * @param int $code Error code
- */
- function __construct($message = null, $code = 0) {
- parent::__construct($message, $code);
- }
-
-}
diff --git a/library/vendor/dompdf/include/dompdf_image_exception.cls.php b/library/vendor/dompdf/include/dompdf_image_exception.cls.php
deleted file mode 100644
index 8fdecec52..000000000
--- a/library/vendor/dompdf/include/dompdf_image_exception.cls.php
+++ /dev/null
@@ -1,26 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Image exception thrown by DOMPDF
- *
- * @package dompdf
- */
-class DOMPDF_Image_Exception extends DOMPDF_Exception {
-
- /**
- * Class constructor
- *
- * @param string $message Error message
- * @param int $code Error code
- */
- function __construct($message = null, $code = 0) {
- parent::__construct($message, $code);
- }
-
-}
diff --git a/library/vendor/dompdf/include/fixed_positioner.cls.php b/library/vendor/dompdf/include/fixed_positioner.cls.php
deleted file mode 100644
index 31a2a079c..000000000
--- a/library/vendor/dompdf/include/fixed_positioner.cls.php
+++ /dev/null
@@ -1,88 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Positions fixely positioned frames
- */
-class Fixed_Positioner extends Positioner {
-
- function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
-
- function position() {
-
- $frame = $this->_frame;
- $style = $frame->get_original_style();
- $root = $frame->get_root();
- $initialcb = $root->get_containing_block();
- $initialcb_style = $root->get_style();
-
- $p = $frame->find_block_parent();
- if ( $p ) {
- $p->add_line();
- }
-
- // Compute the margins of the @page style
- $margin_top = $initialcb_style->length_in_pt($initialcb_style->margin_top, $initialcb["h"]);
- $margin_right = $initialcb_style->length_in_pt($initialcb_style->margin_right, $initialcb["w"]);
- $margin_bottom = $initialcb_style->length_in_pt($initialcb_style->margin_bottom, $initialcb["h"]);
- $margin_left = $initialcb_style->length_in_pt($initialcb_style->margin_left, $initialcb["w"]);
-
- // The needed computed style of the element
- $height = $style->length_in_pt($style->height, $initialcb["h"]);
- $width = $style->length_in_pt($style->width, $initialcb["w"]);
-
- $top = $style->length_in_pt($style->top, $initialcb["h"]);
- $right = $style->length_in_pt($style->right, $initialcb["w"]);
- $bottom = $style->length_in_pt($style->bottom, $initialcb["h"]);
- $left = $style->length_in_pt($style->left, $initialcb["w"]);
-
- $y = $margin_top;
- if ( isset($top) ) {
- $y = $top + $margin_top;
- if ( $top === "auto" ) {
- $y = $margin_top;
- if ( isset($bottom) && $bottom !== "auto" ) {
- $y = $initialcb["h"] - $bottom - $margin_bottom;
- $margin_height = $this->_frame->get_margin_height();
- if ( $margin_height !== "auto" ) {
- $y -= $margin_height;
- }
- else {
- $y -= $height;
- }
- }
- }
- }
-
- $x = $margin_left;
- if ( isset($left) ) {
- $x = $left + $margin_left;
- if ( $left === "auto" ) {
- $x = $margin_left;
- if ( isset($right) && $right !== "auto" ) {
- $x = $initialcb["w"] - $right - $margin_right;
- $margin_width = $this->_frame->get_margin_width();
- if ( $margin_width !== "auto" ) {
- $x -= $margin_width;
- }
- else {
- $x -= $width;
- }
- }
- }
- }
-
- $frame->set_position($x, $y);
-
- $children = $frame->get_children();
- foreach($children as $child) {
- $child->set_position($x, $y);
- }
- }
-}
\ No newline at end of file
diff --git a/library/vendor/dompdf/include/font_metrics.cls.php b/library/vendor/dompdf/include/font_metrics.cls.php
deleted file mode 100644
index 2d15d6714..000000000
--- a/library/vendor/dompdf/include/font_metrics.cls.php
+++ /dev/null
@@ -1,382 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-require_once DOMPDF_LIB_DIR . "/class.pdf.php";
-
-/**
- * Name of the font cache file
- *
- * This file must be writable by the webserver process only to update it
- * with save_font_families() after adding the .afm file references of a new font family
- * with Font_Metrics::save_font_families().
- * This is typically done only from command line with load_font.php on converting
- * ttf fonts to ufm with php-font-lib.
- *
- * Declared here because PHP5 prevents constants from being declared with expressions
- */
-define('__DOMPDF_FONT_CACHE_FILE', DOMPDF_FONT_DIR . "dompdf_font_family_cache.php");
-
-/**
- * The font metrics class
- *
- * This class provides information about fonts and text. It can resolve
- * font names into actual installed font files, as well as determine the
- * size of text in a particular font and size.
- *
- * @static
- * @package dompdf
- */
-class Font_Metrics {
-
- /**
- * @see __DOMPDF_FONT_CACHE_FILE
- */
- const CACHE_FILE = __DOMPDF_FONT_CACHE_FILE;
-
- /**
- * Underlying {@link Canvas} object to perform text size calculations
- *
- * @var Canvas
- */
- static protected $_pdf = null;
-
- /**
- * Array of font family names to font files
- *
- * Usually cached by the {@link load_font.php} script
- *
- * @var array
- */
- static protected $_font_lookup = array();
-
-
- /**
- * Class initialization
- *
- */
- static function init(Canvas $canvas = null) {
- if (!self::$_pdf) {
- if (!$canvas) {
- $canvas = Canvas_Factory::get_instance(new DOMPDF());
- }
-
- self::$_pdf = $canvas;
- }
- }
-
- /**
- * Calculates text size, in points
- *
- * @param string $text the text to be sized
- * @param string $font the desired font
- * @param float $size the desired font size
- * @param float $word_spacing
- * @param float $char_spacing
- *
- * @internal param float $spacing word spacing, if any
- * @return float
- */
- static function get_text_width($text, $font, $size, $word_spacing = 0.0, $char_spacing = 0.0) {
- //return self::$_pdf->get_text_width($text, $font, $size, $word_spacing, $char_spacing);
-
- // @todo Make sure this cache is efficient before enabling it
- static $cache = array();
-
- if ( $text === "" ) {
- return 0;
- }
-
- // Don't cache long strings
- $use_cache = !isset($text[50]); // Faster than strlen
-
- $key = "$font/$size/$word_spacing/$char_spacing";
-
- if ( $use_cache && isset($cache[$key][$text]) ) {
- return $cache[$key]["$text"];
- }
-
- $width = self::$_pdf->get_text_width($text, $font, $size, $word_spacing, $char_spacing);
-
- if ( $use_cache ) {
- $cache[$key][$text] = $width;
- }
-
- return $width;
- }
-
- /**
- * Calculates font height
- *
- * @param string $font
- * @param float $size
- * @return float
- */
- static function get_font_height($font, $size) {
- return self::$_pdf->get_font_height($font, $size);
- }
-
- /**
- * Resolves a font family & subtype into an actual font file
- * Subtype can be one of 'normal', 'bold', 'italic' or 'bold_italic'. If
- * the particular font family has no suitable font file, the default font
- * ({@link DOMPDF_DEFAULT_FONT}) is used. The font file returned
- * is the absolute pathname to the font file on the system.
- *
- * @param string $family_raw
- * @param string $subtype_raw
- *
- * @return string
- */
- static function get_font($family_raw, $subtype_raw = "normal") {
- static $cache = array();
-
- if ( isset($cache[$family_raw][$subtype_raw]) ) {
- return $cache[$family_raw][$subtype_raw];
- }
-
- /* Allow calling for various fonts in search path. Therefore not immediately
- * return replacement on non match.
- * Only when called with NULL try replacement.
- * When this is also missing there is really trouble.
- * If only the subtype fails, nevertheless return failure.
- * Only on checking the fallback font, check various subtypes on same font.
- */
-
- $subtype = strtolower($subtype_raw);
-
- if ( $family_raw ) {
- $family = str_replace( array("'", '"'), "", strtolower($family_raw));
-
- if ( isset(self::$_font_lookup[$family][$subtype]) ) {
- return $cache[$family_raw][$subtype_raw] = self::$_font_lookup[$family][$subtype];
- }
-
- return null;
- }
-
- $family = "serif";
-
- if ( isset(self::$_font_lookup[$family][$subtype]) ) {
- return $cache[$family_raw][$subtype_raw] = self::$_font_lookup[$family][$subtype];
- }
-
- if ( !isset(self::$_font_lookup[$family]) ) {
- return null;
- }
-
- $family = self::$_font_lookup[$family];
-
- foreach ( $family as $sub => $font ) {
- if (strpos($subtype, $sub) !== false) {
- return $cache[$family_raw][$subtype_raw] = $font;
- }
- }
-
- if ($subtype !== "normal") {
- foreach ( $family as $sub => $font ) {
- if ($sub !== "normal") {
- return $cache[$family_raw][$subtype_raw] = $font;
- }
- }
- }
-
- $subtype = "normal";
-
- if ( isset($family[$subtype]) ) {
- return $cache[$family_raw][$subtype_raw] = $family[$subtype];
- }
-
- return null;
- }
-
- static function get_family($family) {
- $family = str_replace( array("'", '"'), "", mb_strtolower($family));
-
- if ( isset(self::$_font_lookup[$family]) ) {
- return self::$_font_lookup[$family];
- }
-
- return null;
- }
-
- /**
- * Saves the stored font family cache
- *
- * The name and location of the cache file are determined by {@link
- * Font_Metrics::CACHE_FILE}. This file should be writable by the
- * webserver process.
- *
- * @see Font_Metrics::load_font_families()
- */
- static function save_font_families() {
- // replace the path to the DOMPDF font directories with the corresponding constants (allows for more portability)
- $cache_data = sprintf(" $variants) {
- $cache_data .= sprintf(" '%s' => array(%s", addslashes($family), PHP_EOL);
- foreach ($variants as $variant => $path) {
- $path = sprintf("'%s'", $path);
- $path = str_replace('\'' . DOMPDF_FONT_DIR , 'DOMPDF_FONT_DIR . \'' , $path);
- $path = str_replace('\'' . DOMPDF_DIR , 'DOMPDF_DIR . \'' , $path);
- $cache_data .= sprintf(" '%s' => %s,%s", $variant, $path, PHP_EOL);
- }
- $cache_data .= sprintf(" ),%s", PHP_EOL);
- }
- $cache_data .= ") ?>";
- file_put_contents(self::CACHE_FILE, $cache_data);
- }
-
- /**
- * Loads the stored font family cache
- *
- * @see save_font_families()
- */
- static function load_font_families() {
- $dist_fonts = require_once DOMPDF_DIR . "/lib/fonts/dompdf_font_family_cache.dist.php";
-
- // FIXME: temporary step for font cache created before the font cache fix
- if ( is_readable( DOMPDF_FONT_DIR . "dompdf_font_family_cache" ) ) {
- $old_fonts = require_once DOMPDF_FONT_DIR . "dompdf_font_family_cache";
- // If the font family cache is still in the old format
- if ( $old_fonts === 1 ) {
- $cache_data = file_get_contents(DOMPDF_FONT_DIR . "dompdf_font_family_cache");
- file_put_contents(DOMPDF_FONT_DIR . "dompdf_font_family_cache", "<"."?php return $cache_data ?".">");
- $old_fonts = require_once DOMPDF_FONT_DIR . "dompdf_font_family_cache";
- }
- $dist_fonts += $old_fonts;
- }
-
- if ( !is_readable(self::CACHE_FILE) ) {
- self::$_font_lookup = $dist_fonts;
- return;
- }
-
- $cache_data = require_once self::CACHE_FILE;
-
- // If the font family cache is still in the old format
- if ( self::$_font_lookup === 1 ) {
- $cache_data = file_get_contents(self::CACHE_FILE);
- file_put_contents(self::CACHE_FILE, "<"."?php return $cache_data ?".">");
- $cache_data = require_once self::CACHE_FILE;
- }
-
- self::$_font_lookup = array();
- foreach ($cache_data as $key => $value) {
- self::$_font_lookup[stripslashes($key)] = $value;
- }
-
- // Merge provided fonts
- self::$_font_lookup += $dist_fonts;
- }
-
- static function get_type($type) {
- if (preg_match("/bold/i", $type)) {
- if (preg_match("/italic|oblique/i", $type)) {
- $type = "bold_italic";
- }
- else {
- $type = "bold";
- }
- }
- elseif (preg_match("/italic|oblique/i", $type)) {
- $type = "italic";
- }
- else {
- $type = "normal";
- }
-
- return $type;
- }
-
- static function install_fonts($files) {
- $names = array();
-
- foreach($files as $file) {
- $font = Font::load($file);
- $records = $font->getData("name", "records");
- $type = self::get_type($records[2]);
- $names[mb_strtolower($records[1])][$type] = $file;
- }
-
- return $names;
- }
-
- static function get_system_fonts() {
- $files = glob("/usr/share/fonts/truetype/*.ttf") +
- glob("/usr/share/fonts/truetype/*/*.ttf") +
- glob("/usr/share/fonts/truetype/*/*/*.ttf") +
- glob("C:\\Windows\\fonts\\*.ttf") +
- glob("C:\\WinNT\\fonts\\*.ttf") +
- glob("/mnt/c_drive/WINDOWS/Fonts/");
-
- return self::install_fonts($files);
- }
-
- /**
- * Returns the current font lookup table
- *
- * @return array
- */
- static function get_font_families() {
- return self::$_font_lookup;
- }
-
- static function set_font_family($fontname, $entry) {
- self::$_font_lookup[mb_strtolower($fontname)] = $entry;
- }
-
- static function register_font($style, $remote_file, $context = null) {
- $fontname = mb_strtolower($style["family"]);
- $families = Font_Metrics::get_font_families();
-
- $entry = array();
- if ( isset($families[$fontname]) ) {
- $entry = $families[$fontname];
- }
-
- $local_file = DOMPDF_FONT_DIR . md5($remote_file);
- $local_temp_file = DOMPDF_TEMP_DIR . "/" . md5($remote_file);
- $cache_entry = $local_file;
- $local_file .= ".ttf";
-
- $style_string = Font_Metrics::get_type("{$style['weight']} {$style['style']}");
-
- if ( !isset($entry[$style_string]) ) {
- $entry[$style_string] = $cache_entry;
-
- // Download the remote file
- file_put_contents($local_temp_file, file_get_contents($remote_file, null, $context));
-
- $font = Font::load($local_temp_file);
-
- if (!$font) {
- unlink($local_temp_file);
- return false;
- }
-
- $font->parse();
- $font->saveAdobeFontMetrics("$cache_entry.ufm");
-
- unlink($local_temp_file);
-
- if ( !file_exists("$cache_entry.ufm") ) {
- return false;
- }
-
- // Save the changes
- file_put_contents($local_file, file_get_contents($remote_file, null, $context));
- Font_Metrics::set_font_family($fontname, $entry);
- Font_Metrics::save_font_families();
- }
-
- return true;
- }
-}
-
-Font_Metrics::load_font_families();
diff --git a/library/vendor/dompdf/include/frame.cls.php b/library/vendor/dompdf/include/frame.cls.php
deleted file mode 100644
index bc2f26d40..000000000
--- a/library/vendor/dompdf/include/frame.cls.php
+++ /dev/null
@@ -1,1191 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * The main Frame class
- *
- * This class represents a single HTML element. This class stores
- * positioning information as well as containing block location and
- * dimensions. Style information for the element is stored in a {@link
- * Style} object. Tree structure is maintained via the parent & children
- * links.
- *
- * @access protected
- * @package dompdf
- */
-class Frame {
-
- /**
- * The DOMElement or DOMText object this frame represents
- *
- * @var DOMElement|DOMText
- */
- protected $_node;
-
- /**
- * Unique identifier for this frame. Used to reference this frame
- * via the node.
- *
- * @var string
- */
- protected $_id;
-
- /**
- * Unique id counter
- */
- static /*protected*/ $ID_COUNTER = 0;
-
- /**
- * This frame's calculated style
- *
- * @var Style
- */
- protected $_style;
-
- /**
- * This frame's original style. Needed for cases where frames are
- * split across pages.
- *
- * @var Style
- */
- protected $_original_style;
-
- /**
- * This frame's parent in the document tree.
- *
- * @var Frame
- */
- protected $_parent;
-
- /**
- * This frame's children
- *
- * @var Frame[]
- */
- protected $_frame_list;
-
- /**
- * This frame's first child. All children are handled as a
- * doubly-linked list.
- *
- * @var Frame
- */
- protected $_first_child;
-
- /**
- * This frame's last child.
- *
- * @var Frame
- */
- protected $_last_child;
-
- /**
- * This frame's previous sibling in the document tree.
- *
- * @var Frame
- */
- protected $_prev_sibling;
-
- /**
- * This frame's next sibling in the document tree.
- *
- * @var Frame
- */
- protected $_next_sibling;
-
- /**
- * This frame's containing block (used in layout): array(x, y, w, h)
- *
- * @var float[]
- */
- protected $_containing_block;
-
- /**
- * Position on the page of the top-left corner of the margin box of
- * this frame: array(x,y)
- *
- * @var float[]
- */
- protected $_position;
-
- /**
- * Absolute opacity of this frame
- *
- * @var float
- */
- protected $_opacity;
-
- /**
- * This frame's decorator
- *
- * @var Frame_Decorator
- */
- protected $_decorator;
-
- /**
- * This frame's containing line box
- *
- * @var Line_Box
- */
- protected $_containing_line;
-
- protected $_is_cache = array();
-
- /**
- * Tells wether the frame was already pushed to the next page
- *
- * @var bool
- */
- public $_already_pushed = false;
-
- public $_float_next_line = false;
-
- /**
- * Tells wether the frame was split
- *
- * @var bool
- */
- public $_splitted;
-
- static $_ws_state = self::WS_SPACE;
-
- const WS_TEXT = 1;
- const WS_SPACE = 2;
-
- /**
- * Class destructor
- */
- function __destruct() {
- clear_object($this);
- }
-
- /**
- * Class constructor
- *
- * @param DOMNode $node the DOMNode this frame represents
- */
- function __construct(DOMNode $node) {
- $this->_node = $node;
-
- $this->_parent = null;
- $this->_first_child = null;
- $this->_last_child = null;
- $this->_prev_sibling = $this->_next_sibling = null;
-
- $this->_style = null;
- $this->_original_style = null;
-
- $this->_containing_block = array(
- "x" => null,
- "y" => null,
- "w" => null,
- "h" => null,
- );
-
- $this->_containing_block[0] =& $this->_containing_block["x"];
- $this->_containing_block[1] =& $this->_containing_block["y"];
- $this->_containing_block[2] =& $this->_containing_block["w"];
- $this->_containing_block[3] =& $this->_containing_block["h"];
-
- $this->_position = array(
- "x" => null,
- "y" => null,
- );
-
- $this->_position[0] =& $this->_position["x"];
- $this->_position[1] =& $this->_position["y"];
-
- $this->_opacity = 1.0;
- $this->_decorator = null;
-
- $this->set_id( self::$ID_COUNTER++ );
- }
-
- // WIP : preprocessing to remove all the unused whitespace
- protected function ws_trim(){
- if ( $this->ws_keep() ) {
- return;
- }
-
- switch(self::$_ws_state) {
- case self::WS_SPACE:
- $node = $this->_node;
-
- if ( $node->nodeName === "#text" ) {
- $node->nodeValue = preg_replace("/[ \t\r\n\f]+/u", " ", $node->nodeValue);
-
- // starts with a whitespace
- if ( isset($node->nodeValue[0]) && $node->nodeValue[0] === " " ) {
- $node->nodeValue = ltrim($node->nodeValue);
- }
-
- // if not empty
- if ( $node->nodeValue !== "" ) {
- // change the current state (text)
- self::$_ws_state = self::WS_TEXT;
-
- // ends with a whitespace
- if ( preg_match("/[ \t\r\n\f]+$/u", $node->nodeValue) ) {
- $node->nodeValue = ltrim($node->nodeValue);
- }
- }
- }
- break;
-
- case self::WS_TEXT:
- }
- }
-
- protected function ws_keep(){
- $whitespace = $this->get_style()->white_space;
- return in_array($whitespace, array("pre", "pre-wrap", "pre-line"));
- }
-
- protected function ws_is_text(){
- $node = $this->get_node();
-
- if ($node->nodeName === "img") {
- return true;
- }
-
- if ( !$this->is_in_flow() ) {
- return false;
- }
-
- if ($this->is_text_node()) {
- return trim($node->nodeValue) !== "";
- }
-
- return true;
- }
-
- /**
- * "Destructor": forcibly free all references held by this frame
- *
- * @param bool $recursive if true, call dispose on all children
- */
- function dispose($recursive = false) {
-
- if ( $recursive ) {
- while ( $child = $this->_first_child ) {
- $child->dispose(true);
- }
- }
-
- // Remove this frame from the tree
- if ( $this->_prev_sibling ) {
- $this->_prev_sibling->_next_sibling = $this->_next_sibling;
- }
-
- if ( $this->_next_sibling ) {
- $this->_next_sibling->_prev_sibling = $this->_prev_sibling;
- }
-
- if ( $this->_parent && $this->_parent->_first_child === $this ) {
- $this->_parent->_first_child = $this->_next_sibling;
- }
-
- if ( $this->_parent && $this->_parent->_last_child === $this ) {
- $this->_parent->_last_child = $this->_prev_sibling;
- }
-
- if ( $this->_parent ) {
- $this->_parent->get_node()->removeChild($this->_node);
- }
-
- $this->_style->dispose();
- $this->_style = null;
- unset($this->_style);
-
- $this->_original_style->dispose();
- $this->_original_style = null;
- unset($this->_original_style);
-
- }
-
- // Re-initialize the frame
- function reset() {
- $this->_position["x"] = null;
- $this->_position["y"] = null;
-
- $this->_containing_block["x"] = null;
- $this->_containing_block["y"] = null;
- $this->_containing_block["w"] = null;
- $this->_containing_block["h"] = null;
-
- $this->_style = null;
- unset($this->_style);
- $this->_style = clone $this->_original_style;
- }
-
- //........................................................................
-
- /**
- * @return DOMElement|DOMText
- */
- function get_node() {
- return $this->_node;
- }
-
- /**
- * @return string
- */
- function get_id() {
- return $this->_id;
- }
-
- /**
- * @return Style
- */
- function get_style() {
- return $this->_style;
- }
-
- /**
- * @return Style
- */
- function get_original_style() {
- return $this->_original_style;
- }
-
- /**
- * @return Frame
- */
- function get_parent() {
- return $this->_parent;
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_decorator() {
- return $this->_decorator;
- }
-
- /**
- * @return Frame
- */
- function get_first_child() {
- return $this->_first_child;
- }
-
- /**
- * @return Frame
- */
- function get_last_child() {
- return $this->_last_child;
- }
-
- /**
- * @return Frame
- */
- function get_prev_sibling() {
- return $this->_prev_sibling;
- }
-
- /**
- * @return Frame
- */
- function get_next_sibling() {
- return $this->_next_sibling;
- }
-
- /**
- * @return FrameList|Frame[]
- */
- function get_children() {
- if ( isset($this->_frame_list) ) {
- return $this->_frame_list;
- }
-
- $this->_frame_list = new FrameList($this);
- return $this->_frame_list;
- }
-
- // Layout property accessors
-
- /**
- * Containing block dimensions
- *
- * @param $i string The key of the wanted containing block's dimension (x, y, x, h)
- *
- * @return float[]|float
- */
- function get_containing_block($i = null) {
- if ( isset($i) ) {
- return $this->_containing_block[$i];
- }
- return $this->_containing_block;
- }
-
- /**
- * Block position
- *
- * @param $i string The key of the wanted position value (x, y)
- *
- * @return array|float
- */
- function get_position($i = null) {
- if ( isset($i) ) {
- return $this->_position[$i];
- }
- return $this->_position;
- }
-
- //........................................................................
-
- /**
- * Return the height of the margin box of the frame, in pt. Meaningless
- * unless the height has been calculated properly.
- *
- * @return float
- */
- function get_margin_height() {
- $style = $this->_style;
-
- return $style->length_in_pt(array(
- $style->height,
- $style->margin_top,
- $style->margin_bottom,
- $style->border_top_width,
- $style->border_bottom_width,
- $style->padding_top,
- $style->padding_bottom
- ), $this->_containing_block["h"]);
- }
-
- /**
- * Return the width of the margin box of the frame, in pt. Meaningless
- * unless the width has been calculated properly.
- *
- * @return float
- */
- function get_margin_width() {
- $style = $this->_style;
-
- return $style->length_in_pt(array(
- $style->width,
- $style->margin_left,
- $style->margin_right,
- $style->border_left_width,
- $style->border_right_width,
- $style->padding_left,
- $style->padding_right
- ), $this->_containing_block["w"]);
- }
-
- function get_break_margins(){
- $style = $this->_style;
-
- return $style->length_in_pt(array(
- //$style->height,
- $style->margin_top,
- $style->margin_bottom,
- $style->border_top_width,
- $style->border_bottom_width,
- $style->padding_top,
- $style->padding_bottom
- ), $this->_containing_block["h"]);
- }
-
- /**
- * Return the padding box (x,y,w,h) of the frame
- *
- * @return array
- */
- function get_padding_box() {
- $style = $this->_style;
- $cb = $this->_containing_block;
-
- $x = $this->_position["x"] +
- $style->length_in_pt(array($style->margin_left,
- $style->border_left_width),
- $cb["w"]);
-
- $y = $this->_position["y"] +
- $style->length_in_pt(array($style->margin_top,
- $style->border_top_width),
- $cb["h"]);
-
- $w = $style->length_in_pt(array($style->padding_left,
- $style->width,
- $style->padding_right),
- $cb["w"]);
-
- $h = $style->length_in_pt(array($style->padding_top,
- $style->height,
- $style->padding_bottom),
- $cb["h"]);
-
- return array(0 => $x, "x" => $x,
- 1 => $y, "y" => $y,
- 2 => $w, "w" => $w,
- 3 => $h, "h" => $h);
- }
-
- /**
- * Return the border box of the frame
- *
- * @return array
- */
- function get_border_box() {
- $style = $this->_style;
- $cb = $this->_containing_block;
-
- $x = $this->_position["x"] + $style->length_in_pt($style->margin_left, $cb["w"]);
-
- $y = $this->_position["y"] + $style->length_in_pt($style->margin_top, $cb["h"]);
-
- $w = $style->length_in_pt(array($style->border_left_width,
- $style->padding_left,
- $style->width,
- $style->padding_right,
- $style->border_right_width),
- $cb["w"]);
-
- $h = $style->length_in_pt(array($style->border_top_width,
- $style->padding_top,
- $style->height,
- $style->padding_bottom,
- $style->border_bottom_width),
- $cb["h"]);
-
- return array(0 => $x, "x" => $x,
- 1 => $y, "y" => $y,
- 2 => $w, "w" => $w,
- 3 => $h, "h" => $h);
- }
-
- function get_opacity($opacity = null) {
- if ( $opacity !== null ) {
- $this->set_opacity($opacity);
- }
- return $this->_opacity;
- }
-
- /**
- * @return Line_Box
- */
- function &get_containing_line() {
- return $this->_containing_line;
- }
-
- //........................................................................
-
- // Set methods
- function set_id($id) {
- $this->_id = $id;
-
- // We can only set attributes of DOMElement objects (nodeType == 1).
- // Since these are the only objects that we can assign CSS rules to,
- // this shortcoming is okay.
- if ( $this->_node->nodeType == XML_ELEMENT_NODE ) {
- $this->_node->setAttribute("frame_id", $id);
- }
- }
-
- function set_style(Style $style) {
- if ( is_null($this->_style) ) {
- $this->_original_style = clone $style;
- }
-
- //$style->set_frame($this);
- $this->_style = $style;
- }
-
- function set_decorator(Frame_Decorator $decorator) {
- $this->_decorator = $decorator;
- }
-
- function set_containing_block($x = null, $y = null, $w = null, $h = null) {
- if ( is_array($x) ){
- foreach($x as $key => $val){
- $$key = $val;
- }
- }
-
- if (is_numeric($x)) {
- $this->_containing_block["x"] = $x;
- }
-
- if (is_numeric($y)) {
- $this->_containing_block["y"] = $y;
- }
-
- if (is_numeric($w)) {
- $this->_containing_block["w"] = $w;
- }
-
- if (is_numeric($h)) {
- $this->_containing_block["h"] = $h;
- }
- }
-
- function set_position($x = null, $y = null) {
- if ( is_array($x) ) {
- list($x, $y) = array($x["x"], $x["y"]);
- }
-
- if ( is_numeric($x) ) {
- $this->_position["x"] = $x;
- }
-
- if ( is_numeric($y) ) {
- $this->_position["y"] = $y;
- }
- }
-
- function set_opacity($opacity) {
- $parent = $this->get_parent();
- $base_opacity = (($parent && $parent->_opacity !== null) ? $parent->_opacity : 1.0);
- $this->_opacity = $base_opacity * $opacity;
- }
-
- function set_containing_line(Line_Box $line) {
- $this->_containing_line = $line;
- }
-
- //........................................................................
-
- /**
- * Tells if the frame is a text node
- * @return bool
- */
- function is_text_node() {
- if ( isset($this->_is_cache["text_node"]) ) {
- return $this->_is_cache["text_node"];
- }
-
- return $this->_is_cache["text_node"] = ($this->get_node()->nodeName === "#text");
- }
-
- function is_positionned() {
- if ( isset($this->_is_cache["positionned"]) ) {
- return $this->_is_cache["positionned"];
- }
-
- $position = $this->get_style()->position;
-
- return $this->_is_cache["positionned"] = in_array($position, Style::$POSITIONNED_TYPES);
- }
-
- function is_absolute() {
- if ( isset($this->_is_cache["absolute"]) ) {
- return $this->_is_cache["absolute"];
- }
-
- $position = $this->get_style()->position;
-
- return $this->_is_cache["absolute"] = ($position === "absolute" || $position === "fixed");
- }
-
- function is_block() {
- if ( isset($this->_is_cache["block"]) ) {
- return $this->_is_cache["block"];
- }
-
- return $this->_is_cache["block"] = in_array($this->get_style()->display, Style::$BLOCK_TYPES);
- }
-
- function is_in_flow() {
- if ( isset($this->_is_cache["in_flow"]) ) {
- return $this->_is_cache["in_flow"];
- }
-
- $enable_css_float = $this->get_style()->get_stylesheet()->get_dompdf()->get_option("enable_css_float");
- return $this->_is_cache["in_flow"] = !($enable_css_float && $this->get_style()->float !== "none" || $this->is_absolute());
- }
-
- function is_pre(){
- if ( isset($this->_is_cache["pre"]) ) {
- return $this->_is_cache["pre"];
- }
-
- $white_space = $this->get_style()->white_space;
-
- return $this->_is_cache["pre"] = in_array($white_space, array("pre", "pre-wrap"));
- }
-
- function is_table(){
- if ( isset($this->_is_cache["table"]) ) {
- return $this->_is_cache["table"];
- }
-
- $display = $this->get_style()->display;
-
- return $this->_is_cache["table"] = in_array($display, Style::$TABLE_TYPES);
- }
-
-
- /**
- * Inserts a new child at the beginning of the Frame
- *
- * @param $child Frame The new Frame to insert
- * @param $update_node boolean Whether or not to update the DOM
- */
- function prepend_child(Frame $child, $update_node = true) {
- if ( $update_node ) {
- $this->_node->insertBefore($child->_node, $this->_first_child ? $this->_first_child->_node : null);
- }
-
- // Remove the child from its parent
- if ( $child->_parent ) {
- $child->_parent->remove_child($child, false);
- }
-
- $child->_parent = $this;
- $child->_prev_sibling = null;
-
- // Handle the first child
- if ( !$this->_first_child ) {
- $this->_first_child = $child;
- $this->_last_child = $child;
- $child->_next_sibling = null;
- }
- else {
- $this->_first_child->_prev_sibling = $child;
- $child->_next_sibling = $this->_first_child;
- $this->_first_child = $child;
- }
- }
-
- /**
- * Inserts a new child at the end of the Frame
- *
- * @param $child Frame The new Frame to insert
- * @param $update_node boolean Whether or not to update the DOM
- */
- function append_child(Frame $child, $update_node = true) {
- if ( $update_node ) {
- $this->_node->appendChild($child->_node);
- }
-
- // Remove the child from its parent
- if ( $child->_parent ) {
- $child->_parent->remove_child($child, false);
- }
-
- $child->_parent = $this;
- $child->_next_sibling = null;
-
- // Handle the first child
- if ( !$this->_last_child ) {
- $this->_first_child = $child;
- $this->_last_child = $child;
- $child->_prev_sibling = null;
- }
- else {
- $this->_last_child->_next_sibling = $child;
- $child->_prev_sibling = $this->_last_child;
- $this->_last_child = $child;
- }
- }
-
- /**
- * Inserts a new child immediately before the specified frame
- *
- * @param $new_child Frame The new Frame to insert
- * @param $ref Frame The Frame after the new Frame
- * @param $update_node boolean Whether or not to update the DOM
- *
- * @throws DOMPDF_Exception
- */
- function insert_child_before(Frame $new_child, Frame $ref, $update_node = true) {
- if ( $ref === $this->_first_child ) {
- $this->prepend_child($new_child, $update_node);
- return;
- }
-
- if ( is_null($ref) ) {
- $this->append_child($new_child, $update_node);
- return;
- }
-
- if ( $ref->_parent !== $this ) {
- throw new DOMPDF_Exception("Reference child is not a child of this node.");
- }
-
- // Update the node
- if ( $update_node ) {
- $this->_node->insertBefore($new_child->_node, $ref->_node);
- }
-
- // Remove the child from its parent
- if ( $new_child->_parent ) {
- $new_child->_parent->remove_child($new_child, false);
- }
-
- $new_child->_parent = $this;
- $new_child->_next_sibling = $ref;
- $new_child->_prev_sibling = $ref->_prev_sibling;
-
- if ( $ref->_prev_sibling ) {
- $ref->_prev_sibling->_next_sibling = $new_child;
- }
-
- $ref->_prev_sibling = $new_child;
- }
-
- /**
- * Inserts a new child immediately after the specified frame
- *
- * @param $new_child Frame The new Frame to insert
- * @param $ref Frame The Frame before the new Frame
- * @param $update_node boolean Whether or not to update the DOM
- *
- * @throws DOMPDF_Exception
- */
- function insert_child_after(Frame $new_child, Frame $ref, $update_node = true) {
- if ( $ref === $this->_last_child ) {
- $this->append_child($new_child, $update_node);
- return;
- }
-
- if ( is_null($ref) ) {
- $this->prepend_child($new_child, $update_node);
- return;
- }
-
- if ( $ref->_parent !== $this ) {
- throw new DOMPDF_Exception("Reference child is not a child of this node.");
- }
-
- // Update the node
- if ( $update_node ) {
- if ( $ref->_next_sibling ) {
- $next_node = $ref->_next_sibling->_node;
- $this->_node->insertBefore($new_child->_node, $next_node);
- }
- else {
- $new_child->_node = $this->_node->appendChild($new_child->_node);
- }
- }
-
- // Remove the child from its parent
- if ( $new_child->_parent ) {
- $new_child->_parent->remove_child($new_child, false);
- }
-
- $new_child->_parent = $this;
- $new_child->_prev_sibling = $ref;
- $new_child->_next_sibling = $ref->_next_sibling;
-
- if ( $ref->_next_sibling ) {
- $ref->_next_sibling->_prev_sibling = $new_child;
- }
-
- $ref->_next_sibling = $new_child;
- }
-
-
- /**
- * Remove a child frame
- *
- * @param Frame $child
- * @param boolean $update_node Whether or not to remove the DOM node
- *
- * @throws DOMPDF_Exception
- * @return Frame The removed child frame
- */
- function remove_child(Frame $child, $update_node = true) {
- if ( $child->_parent !== $this ) {
- throw new DOMPDF_Exception("Child not found in this frame");
- }
-
- if ( $update_node ) {
- $this->_node->removeChild($child->_node);
- }
-
- if ( $child === $this->_first_child ) {
- $this->_first_child = $child->_next_sibling;
- }
-
- if ( $child === $this->_last_child ) {
- $this->_last_child = $child->_prev_sibling;
- }
-
- if ( $child->_prev_sibling ) {
- $child->_prev_sibling->_next_sibling = $child->_next_sibling;
- }
-
- if ( $child->_next_sibling ) {
- $child->_next_sibling->_prev_sibling = $child->_prev_sibling;
- }
-
- $child->_next_sibling = null;
- $child->_prev_sibling = null;
- $child->_parent = null;
- return $child;
- }
-
- //........................................................................
-
- // Debugging function:
- function __toString() {
- // Skip empty text frames
-// if ( $this->is_text_node() &&
-// preg_replace("/\s/", "", $this->_node->data) === "" )
-// return "";
-
-
- $str = "" . $this->_node->nodeName . ": ";
- //$str .= spl_object_hash($this->_node) . " ";
- $str .= "Id: " .$this->get_id() . " ";
- $str .= "Class: " .get_class($this) . " ";
-
- if ( $this->is_text_node() ) {
- $tmp = htmlspecialchars($this->_node->nodeValue);
- $str .= "'" . mb_substr($tmp,0,70) .
- (mb_strlen($tmp) > 70 ? "..." : "") . "' ";
- }
- elseif ( $css_class = $this->_node->getAttribute("class") ) {
- $str .= "CSS class: '$css_class' ";
- }
-
- if ( $this->_parent ) {
- $str .= "\nParent:" . $this->_parent->_node->nodeName .
- " (" . spl_object_hash($this->_parent->_node) . ") " .
- " ";
- }
-
- if ( $this->_prev_sibling ) {
- $str .= "Prev: " . $this->_prev_sibling->_node->nodeName .
- " (" . spl_object_hash($this->_prev_sibling->_node) . ") " .
- " ";
- }
-
- if ( $this->_next_sibling ) {
- $str .= "Next: " . $this->_next_sibling->_node->nodeName .
- " (" . spl_object_hash($this->_next_sibling->_node) . ") " .
- " ";
- }
-
- $d = $this->get_decorator();
- while ($d && $d != $d->get_decorator()) {
- $str .= "Decorator: " . get_class($d) . " ";
- $d = $d->get_decorator();
- }
-
- $str .= "Position: " . pre_r($this->_position, true);
- $str .= "\nContaining block: " . pre_r($this->_containing_block, true);
- $str .= "\nMargin width: " . pre_r($this->get_margin_width(), true);
- $str .= "\nMargin height: " . pre_r($this->get_margin_height(), true);
-
- $str .= "\nStyle: ". $this->_style->__toString() . " ";
-
- if ( $this->_decorator instanceof Block_Frame_Decorator ) {
- $str .= "Lines:";
- foreach ($this->_decorator->get_line_boxes() as $line) {
- foreach ($line->get_frames() as $frame) {
- if ($frame instanceof Text_Frame_Decorator) {
- $str .= "\ntext: ";
- $str .= "'". htmlspecialchars($frame->get_text()) ."'";
- }
- else {
- $str .= "\nBlock: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")";
- }
- }
-
- $str .=
- "\ny => " . $line->y . "\n" .
- "w => " . $line->w . "\n" .
- "h => " . $line->h . "\n" .
- "left => " . $line->left . "\n" .
- "right => " . $line->right . "\n";
- }
- $str .= " ";
- }
-
- $str .= "\n";
- if ( php_sapi_name() === "cli" ) {
- $str = strip_tags(str_replace(array(" ",""," "),
- array("\n","",""),
- $str));
- }
-
- return $str;
- }
-}
-
-//------------------------------------------------------------------------
-
-/**
- * Linked-list IteratorAggregate
- *
- * @access private
- * @package dompdf
- */
-class FrameList implements IteratorAggregate {
- protected $_frame;
-
- function __construct($frame) { $this->_frame = $frame; }
- function getIterator() { return new FrameListIterator($this->_frame); }
-}
-
-/**
- * Linked-list Iterator
- *
- * Returns children in order and allows for list to change during iteration,
- * provided the changes occur to or after the current element
- *
- * @access private
- * @package dompdf
- */
-class FrameListIterator implements Iterator {
-
- /**
- * @var Frame
- */
- protected $_parent;
-
- /**
- * @var Frame
- */
- protected $_cur;
-
- /**
- * @var int
- */
- protected $_num;
-
- function __construct(Frame $frame) {
- $this->_parent = $frame;
- $this->_cur = $frame->get_first_child();
- $this->_num = 0;
- }
-
- function rewind() {
- $this->_cur = $this->_parent->get_first_child();
- $this->_num = 0;
- }
-
- /**
- * @return bool
- */
- function valid() {
- return isset($this->_cur);// && ($this->_cur->get_prev_sibling() === $this->_prev);
- }
-
- function key() { return $this->_num; }
-
- /**
- * @return Frame
- */
- function current() { return $this->_cur; }
-
- /**
- * @return Frame
- */
- function next() {
-
- $ret = $this->_cur;
- if ( !$ret ) {
- return null;
- }
-
- $this->_cur = $this->_cur->get_next_sibling();
- $this->_num++;
- return $ret;
- }
-}
-
-//------------------------------------------------------------------------
-
-/**
- * Pre-order IteratorAggregate
- *
- * @access private
- * @package dompdf
- */
-class FrameTreeList implements IteratorAggregate {
- /**
- * @var Frame
- */
- protected $_root;
-
- function __construct(Frame $root) { $this->_root = $root; }
-
- /**
- * @return FrameTreeIterator
- */
- function getIterator() { return new FrameTreeIterator($this->_root); }
-}
-
-/**
- * Pre-order Iterator
- *
- * Returns frames in preorder traversal order (parent then children)
- *
- * @access private
- * @package dompdf
- */
-class FrameTreeIterator implements Iterator {
- /**
- * @var Frame
- */
- protected $_root;
- protected $_stack = array();
-
- /**
- * @var int
- */
- protected $_num;
-
- function __construct(Frame $root) {
- $this->_stack[] = $this->_root = $root;
- $this->_num = 0;
- }
-
- function rewind() {
- $this->_stack = array($this->_root);
- $this->_num = 0;
- }
-
- /**
- * @return bool
- */
- function valid() {
- return count($this->_stack) > 0;
- }
-
- /**
- * @return int
- */
- function key() {
- return $this->_num;
- }
-
- /**
- * @return Frame
- */
- function current() {
- return end($this->_stack);
- }
-
- /**
- * @return Frame
- */
- function next() {
- $b = end($this->_stack);
-
- // Pop last element
- unset($this->_stack[ key($this->_stack) ]);
- $this->_num++;
-
- // Push all children onto the stack in reverse order
- if ( $c = $b->get_last_child() ) {
- $this->_stack[] = $c;
- while ( $c = $c->get_prev_sibling() ) {
- $this->_stack[] = $c;
- }
- }
-
- return $b;
- }
-}
-
diff --git a/library/vendor/dompdf/include/frame_decorator.cls.php b/library/vendor/dompdf/include/frame_decorator.cls.php
deleted file mode 100644
index 987e32ee1..000000000
--- a/library/vendor/dompdf/include/frame_decorator.cls.php
+++ /dev/null
@@ -1,717 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Base Frame_Decorator class
- *
- * @access private
- * @package dompdf
- */
-abstract class Frame_Decorator extends Frame {
- const DEFAULT_COUNTER = "-dompdf-default-counter";
-
- public $_counters = array(); // array([id] => counter_value) (for generated content)
-
- /**
- * The root node of the DOM tree
- *
- * @var Frame
- */
- protected $_root;
-
- /**
- * The decorated frame
- *
- * @var Frame
- */
- protected $_frame;
-
- /**
- * Positioner object used to position this frame (Strategy pattern)
- *
- * @var Positioner
- */
- protected $_positioner;
-
- /**
- * Reflower object used to calculate frame dimensions (Strategy pattern)
- *
- * @var Frame_Reflower
- */
- protected $_reflower;
-
- /**
- * Reference to the current dompdf instance
- *
- * @var DOMPDF
- */
- protected $_dompdf;
-
- /**
- * First block parent
- *
- * @var Block_Frame_Decorator
- */
- private $_block_parent;
-
- /**
- * First positionned parent (position: relative | absolute | fixed)
- *
- * @var Frame_Decorator
- */
- private $_positionned_parent;
-
- /**
- * Class constructor
- *
- * @param Frame $frame The decoration target
- * @param DOMPDF $dompdf The DOMPDF object
- */
- function __construct(Frame $frame, DOMPDF $dompdf) {
- $this->_frame = $frame;
- $this->_root = null;
- $this->_dompdf = $dompdf;
- $frame->set_decorator($this);
- }
-
- /**
- * "Destructor": foribly free all references held by this object
- *
- * @param bool $recursive if true, call dispose on all children
- */
- function dispose($recursive = false) {
- if ( $recursive ) {
- while ( $child = $this->get_first_child() ) {
- $child->dispose(true);
- }
- }
-
- $this->_root = null;
- unset($this->_root);
-
- $this->_frame->dispose(true);
- $this->_frame = null;
- unset($this->_frame);
-
- $this->_positioner = null;
- unset($this->_positioner);
-
- $this->_reflower = null;
- unset($this->_reflower);
- }
-
- /**
- * Return a copy of this frame with $node as its node
- *
- * @param DOMNode $node
- *
- * @return Frame
- */
- function copy(DOMNode $node) {
- $frame = new Frame($node);
- $frame->set_style(clone $this->_frame->get_original_style());
-
- return Frame_Factory::decorate_frame($frame, $this->_dompdf, $this->_root);
- }
-
- /**
- * Create a deep copy: copy this node and all children
- *
- * @return Frame
- */
- function deep_copy() {
- $frame = new Frame($this->get_node()->cloneNode());
- $frame->set_style(clone $this->_frame->get_original_style());
-
- $deco = Frame_Factory::decorate_frame($frame, $this->_dompdf, $this->_root);
-
- foreach ($this->get_children() as $child) {
- $deco->append_child($child->deep_copy());
- }
-
- return $deco;
- }
-
- /**
- * Delegate calls to decorated frame object
- */
- function reset() {
- $this->_frame->reset();
-
- $this->_counters = array();
-
- // Reset all children
- foreach ($this->get_children() as $child) {
- $child->reset();
- }
- }
-
- // Getters -----------
- function get_id() {
- return $this->_frame->get_id();
- }
-
- /**
- * @return Frame
- */
- function get_frame() {
- return $this->_frame;
- }
-
- /**
- * @return DOMElement|DOMText
- */
- function get_node() {
- return $this->_frame->get_node();
- }
-
- /**
- * @return Style
- */
- function get_style() {
- return $this->_frame->get_style();
- }
-
- /**
- * @return Style
- */
- function get_original_style() {
- return $this->_frame->get_original_style();
- }
-
- /**
- * @param integer $i
- *
- * @return array|float
- */
- function get_containing_block($i = null) {
- return $this->_frame->get_containing_block($i);
- }
-
- /**
- * @param integer $i
- *
- * @return array|float
- */
- function get_position($i = null) {
- return $this->_frame->get_position($i);
- }
-
- /**
- * @return DOMPDF
- */
- function get_dompdf() {
- return $this->_dompdf;
- }
-
- /**
- * @return float
- */
- function get_margin_height() {
- return $this->_frame->get_margin_height();
- }
-
- /**
- * @return float
- */
- function get_margin_width() {
- return $this->_frame->get_margin_width();
- }
-
- /**
- * @return array
- */
- function get_padding_box() {
- return $this->_frame->get_padding_box();
- }
-
- /**
- * @return array
- */
- function get_border_box() {
- return $this->_frame->get_border_box();
- }
-
- /**
- * @param integer $id
- */
- function set_id($id) {
- $this->_frame->set_id($id);
- }
-
- /**
- * @param Style $style
- */
- function set_style(Style $style) {
- $this->_frame->set_style($style);
- }
-
- /**
- * @param float $x
- * @param float $y
- * @param float $w
- * @param float $h
- */
- function set_containing_block($x = null, $y = null, $w = null, $h = null) {
- $this->_frame->set_containing_block($x, $y, $w, $h);
- }
-
- /**
- * @param float $x
- * @param float $y
- */
- function set_position($x = null, $y = null) {
- $this->_frame->set_position($x, $y);
- }
-
- /**
- * @return string
- */
- function __toString() {
- return $this->_frame->__toString();
- }
-
- /**
- * @param Frame $child
- * @param bool $update_node
- */
- function prepend_child(Frame $child, $update_node = true) {
- while ( $child instanceof Frame_Decorator ) {
- $child = $child->_frame;
- }
-
- $this->_frame->prepend_child($child, $update_node);
- }
-
- /**
- * @param Frame $child
- * @param bool $update_node
- */
- function append_child(Frame $child, $update_node = true) {
- while ( $child instanceof Frame_Decorator ) {
- $child = $child->_frame;
- }
-
- $this->_frame->append_child($child, $update_node);
- }
-
- /**
- * @param Frame $new_child
- * @param Frame $ref
- * @param bool $update_node
- */
- function insert_child_before(Frame $new_child, Frame $ref, $update_node = true) {
- while ( $new_child instanceof Frame_Decorator ) {
- $new_child = $new_child->_frame;
- }
-
- if ( $ref instanceof Frame_Decorator ) {
- $ref = $ref->_frame;
- }
-
- $this->_frame->insert_child_before($new_child, $ref, $update_node);
- }
-
- /**
- * @param Frame $new_child
- * @param Frame $ref
- * @param bool $update_node
- */
- function insert_child_after(Frame $new_child, Frame $ref, $update_node = true) {
- while ( $new_child instanceof Frame_Decorator ) {
- $new_child = $new_child->_frame;
- }
-
- while ( $ref instanceof Frame_Decorator ) {
- $ref = $ref->_frame;
- }
-
- $this->_frame->insert_child_after($new_child, $ref, $update_node);
- }
-
- /**
- * @param Frame $child
- * @param bool $update_node
- *
- * @return Frame
- */
- function remove_child(Frame $child, $update_node = true) {
- while ( $child instanceof Frame_Decorator ) {
- $child = $child->_frame;
- }
-
- return $this->_frame->remove_child($child, $update_node);
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_parent() {
- $p = $this->_frame->get_parent();
- if ( $p && $deco = $p->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() ) {
- $deco = $tmp;
- }
-
- return $deco;
- }
- else if ( $p ) {
- return $p;
- }
-
- return null;
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_first_child() {
- $c = $this->_frame->get_first_child();
- if ( $c && $deco = $c->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() ) {
- $deco = $tmp;
- }
-
- return $deco;
- }
- else if ( $c ) {
- return $c;
- }
-
- return null;
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_last_child() {
- $c = $this->_frame->get_last_child();
- if ( $c && $deco = $c->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() ) {
- $deco = $tmp;
- }
-
- return $deco;
- }
- else if ( $c ) {
- return $c;
- }
-
- return null;
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_prev_sibling() {
- $s = $this->_frame->get_prev_sibling();
- if ( $s && $deco = $s->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() ) {
- $deco = $tmp;
- }
- return $deco;
- }
- else if ( $s ) {
- return $s;
- }
-
- return null;
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_next_sibling() {
- $s = $this->_frame->get_next_sibling();
- if ( $s && $deco = $s->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() ) {
- $deco = $tmp;
- }
-
- return $deco;
- }
- else if ( $s ) {
- return $s;
- }
-
- return null;
- }
-
- /**
- * @return FrameTreeList
- */
- function get_subtree() {
- return new FrameTreeList($this);
- }
-
- function set_positioner(Positioner $posn) {
- $this->_positioner = $posn;
- if ( $this->_frame instanceof Frame_Decorator ) {
- $this->_frame->set_positioner($posn);
- }
- }
-
- function set_reflower(Frame_Reflower $reflower) {
- $this->_reflower = $reflower;
- if ( $this->_frame instanceof Frame_Decorator ) {
- $this->_frame->set_reflower( $reflower );
- }
- }
-
- /**
- * @return Frame_Reflower
- */
- function get_reflower() {
- return $this->_reflower;
- }
-
- /**
- * @param Frame $root
- */
- function set_root(Frame $root) {
- $this->_root = $root;
-
- if ( $this->_frame instanceof Frame_Decorator ) {
- $this->_frame->set_root($root);
- }
- }
-
- /**
- * @return Page_Frame_Decorator
- */
- function get_root() {
- return $this->_root;
- }
-
- /**
- * @return Block_Frame_Decorator
- */
- function find_block_parent() {
- // Find our nearest block level parent
- $p = $this->get_parent();
-
- while ( $p ) {
- if ( $p->is_block() ) {
- break;
- }
-
- $p = $p->get_parent();
- }
-
- return $this->_block_parent = $p;
- }
-
- /**
- * @return Frame_Decorator
- */
- function find_positionned_parent() {
- // Find our nearest relative positionned parent
- $p = $this->get_parent();
- while ( $p ) {
- if ( $p->is_positionned() ) {
- break;
- }
-
- $p = $p->get_parent();
- }
-
- if ( !$p ) {
- $p = $this->_root->get_first_child(); //
- }
-
- return $this->_positionned_parent = $p;
- }
-
- /**
- * split this frame at $child.
- * The current frame is cloned and $child and all children following
- * $child are added to the clone. The clone is then passed to the
- * current frame's parent->split() method.
- *
- * @param Frame $child
- * @param boolean $force_pagebreak
- *
- * @throws DOMPDF_Exception
- * @return void
- */
- function split(Frame $child = null, $force_pagebreak = false) {
- // decrement any counters that were incremented on the current node, unless that node is the body
- $style = $this->_frame->get_style();
- if ( $this->_frame->get_node()->nodeName !== "body" && $style->counter_increment && ($decrement = $style->counter_increment) !== "none" ) {
- $this->decrement_counters($decrement);
- }
-
- if ( is_null( $child ) ) {
- // check for counter increment on :before content (always a child of the selected element @link Frame_Reflower::_set_content)
- // this can push the current node to the next page before counter rules have bubbled up (but only if
- // it's been rendered, thus the position check)
- if ( !$this->is_text_node() && $this->get_node()->hasAttribute("dompdf_before_frame_id") ) {
- foreach($this->_frame->get_children() as $child) {
- if ( $this->get_node()->getAttribute("dompdf_before_frame_id") == $child->get_id() && $child->get_position('x') !== NULL ) {
- $style = $child->get_style();
- if ( $style->counter_increment && ($decrement = $style->counter_increment) !== "none" ) {
- $this->decrement_counters($decrement);
- }
- }
- }
- }
- $this->get_parent()->split($this, $force_pagebreak);
- return;
- }
-
- if ( $child->get_parent() !== $this ) {
- throw new DOMPDF_Exception("Unable to split: frame is not a child of this one.");
- }
-
- $node = $this->_frame->get_node();
-
- $split = $this->copy( $node->cloneNode() );
- $split->reset();
- $split->get_original_style()->text_indent = 0;
- $split->_splitted = true;
-
- // The body's properties must be kept
- if ( $node->nodeName !== "body" ) {
- // Style reset on the first and second parts
- $style = $this->_frame->get_style();
- $style->margin_bottom = 0;
- $style->padding_bottom = 0;
- $style->border_bottom = 0;
-
- // second
- $orig_style = $split->get_original_style();
- $orig_style->text_indent = 0;
- $orig_style->margin_top = 0;
- $orig_style->padding_top = 0;
- $orig_style->border_top = 0;
- }
-
- $this->get_parent()->insert_child_after($split, $this);
-
- // Add $frame and all following siblings to the new split node
- $iter = $child;
- while ($iter) {
- $frame = $iter;
- $iter = $iter->get_next_sibling();
- $frame->reset();
- $split->append_child($frame);
- }
-
- $this->get_parent()->split($split, $force_pagebreak);
-
- // If this node resets a counter save the current value to use when rendering on the next page
- if ( $style->counter_reset && ( $reset = $style->counter_reset ) !== "none" ) {
- $vars = preg_split( '/\s+/' , trim( $reset ) , 2 );
- $split->_counters[ '__' . $vars[0] ] = $this->lookup_counter_frame( $vars[0] )->_counters[$vars[0]];
- }
- }
-
- function reset_counter($id = self::DEFAULT_COUNTER, $value = 0) {
- $this->get_parent()->_counters[$id] = intval($value);
- }
-
- function decrement_counters($counters) {
- foreach($counters as $id => $increment) {
- $this->increment_counter($id, intval($increment) * -1);
- }
- }
-
- function increment_counters($counters) {
- foreach($counters as $id => $increment) {
- $this->increment_counter($id, intval($increment));
- }
- }
-
- function increment_counter($id = self::DEFAULT_COUNTER, $increment = 1) {
- $counter_frame = $this->lookup_counter_frame($id);
-
- if ( $counter_frame ) {
- if ( !isset($counter_frame->_counters[$id]) ) {
- $counter_frame->_counters[$id] = 0;
- }
-
- $counter_frame->_counters[$id] += $increment;
- }
- }
-
- function lookup_counter_frame($id = self::DEFAULT_COUNTER) {
- $f = $this->get_parent();
-
- while( $f ) {
- if( isset($f->_counters[$id]) ) {
- return $f;
- }
- $fp = $f->get_parent();
-
- if ( !$fp ) {
- return $f;
- }
-
- $f = $fp;
- }
- }
-
- // TODO: What version is the best : this one or the one in List_Bullet_Renderer ?
- function counter_value($id = self::DEFAULT_COUNTER, $type = "decimal") {
- $type = mb_strtolower($type);
-
- if ( !isset($this->_counters[$id]) ) {
- $this->_counters[$id] = 0;
- }
-
- $value = $this->_counters[$id];
-
- switch ($type) {
- default:
- case "decimal":
- return $value;
-
- case "decimal-leading-zero":
- return str_pad($value, 2, "0");
-
- case "lower-roman":
- return dec2roman($value);
-
- case "upper-roman":
- return mb_strtoupper(dec2roman($value));
-
- case "lower-latin":
- case "lower-alpha":
- return chr( ($value % 26) + ord('a') - 1);
-
- case "upper-latin":
- case "upper-alpha":
- return chr( ($value % 26) + ord('A') - 1);
-
- case "lower-greek":
- return unichr($value + 944);
-
- case "upper-greek":
- return unichr($value + 912);
- }
- }
-
- final function position() {
- $this->_positioner->position();
- }
-
- final function move($offset_x, $offset_y, $ignore_self = false) {
- $this->_positioner->move($offset_x, $offset_y, $ignore_self);
- }
-
- final function reflow(Block_Frame_Decorator $block = null) {
- // Uncomment this to see the frames before they're laid out, instead of
- // during rendering.
- //echo $this->_frame; flush();
- $this->_reflower->reflow($block);
- }
-
- final function get_min_max_width() {
- return $this->_reflower->get_min_max_width();
- }
-}
diff --git a/library/vendor/dompdf/include/frame_factory.cls.php b/library/vendor/dompdf/include/frame_factory.cls.php
deleted file mode 100644
index 70813d2e3..000000000
--- a/library/vendor/dompdf/include/frame_factory.cls.php
+++ /dev/null
@@ -1,252 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Contains frame decorating logic
- *
- * This class is responsible for assigning the correct {@link Frame_Decorator},
- * {@link Positioner}, and {@link Frame_Reflower} objects to {@link Frame}
- * objects. This is determined primarily by the Frame's display type, but
- * also by the Frame's node's type (e.g. DomElement vs. #text)
- *
- * @access private
- * @package dompdf
- */
-class Frame_Factory {
-
- /**
- * Decorate the root Frame
- *
- * @param $root Frame The frame to decorate
- * @param $dompdf DOMPDF The dompdf instance
- * @return Page_Frame_Decorator
- */
- static function decorate_root(Frame $root, DOMPDF $dompdf) {
- $frame = new Page_Frame_Decorator($root, $dompdf);
- $frame->set_reflower( new Page_Frame_Reflower($frame) );
- $root->set_decorator($frame);
- return $frame;
- }
-
- /**
- * Decorate a Frame
- *
- * @param Frame $frame The frame to decorate
- * @param DOMPDF $dompdf The dompdf instance
- * @param Frame $root The frame to decorate
- *
- * @throws DOMPDF_Exception
- * @return Frame_Decorator
- * FIXME: this is admittedly a little smelly...
- */
- static function decorate_frame(Frame $frame, DOMPDF $dompdf, Frame $root = null) {
- if ( is_null($dompdf) ) {
- throw new DOMPDF_Exception("The DOMPDF argument is required");
- }
-
- $style = $frame->get_style();
-
- // Floating (and more generally out-of-flow) elements are blocks
- // http://coding.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
- if ( !$frame->is_in_flow() && in_array($style->display, Style::$INLINE_TYPES)) {
- $style->display = "block";
- }
-
- $display = $style->display;
-
- switch ($display) {
-
- case "block":
- $positioner = "Block";
- $decorator = "Block";
- $reflower = "Block";
- break;
-
- case "inline-block":
- $positioner = "Inline";
- $decorator = "Block";
- $reflower = "Block";
- break;
-
- case "inline":
- $positioner = "Inline";
- if ( $frame->is_text_node() ) {
- $decorator = "Text";
- $reflower = "Text";
- }
- else {
- $enable_css_float = $dompdf->get_option("enable_css_float");
- if ( $enable_css_float && $style->float !== "none" ) {
- $decorator = "Block";
- $reflower = "Block";
- }
- else {
- $decorator = "Inline";
- $reflower = "Inline";
- }
- }
- break;
-
- case "table":
- $positioner = "Block";
- $decorator = "Table";
- $reflower = "Table";
- break;
-
- case "inline-table":
- $positioner = "Inline";
- $decorator = "Table";
- $reflower = "Table";
- break;
-
- case "table-row-group":
- case "table-header-group":
- case "table-footer-group":
- $positioner = "Null";
- $decorator = "Table_Row_Group";
- $reflower = "Table_Row_Group";
- break;
-
- case "table-row":
- $positioner = "Null";
- $decorator = "Table_Row";
- $reflower = "Table_Row";
- break;
-
- case "table-cell":
- $positioner = "Table_Cell";
- $decorator = "Table_Cell";
- $reflower = "Table_Cell";
- break;
-
- case "list-item":
- $positioner = "Block";
- $decorator = "Block";
- $reflower = "Block";
- break;
-
- case "-dompdf-list-bullet":
- if ( $style->list_style_position === "inside" ) {
- $positioner = "Inline";
- }
- else {
- $positioner = "List_Bullet";
- }
-
- if ( $style->list_style_image !== "none" ) {
- $decorator = "List_Bullet_Image";
- }
- else {
- $decorator = "List_Bullet";
- }
-
- $reflower = "List_Bullet";
- break;
-
- case "-dompdf-image":
- $positioner = "Inline";
- $decorator = "Image";
- $reflower = "Image";
- break;
-
- case "-dompdf-br":
- $positioner = "Inline";
- $decorator = "Inline";
- $reflower = "Inline";
- break;
-
- default:
- // FIXME: should throw some sort of warning or something?
- case "none":
- if ( $style->_dompdf_keep !== "yes" ) {
- // Remove the node and the frame
- $frame->get_parent()->remove_child($frame);
- return;
- }
-
- $positioner = "Null";
- $decorator = "Null";
- $reflower = "Null";
- break;
- }
-
- // Handle CSS position
- $position = $style->position;
-
- if ( $position === "absolute" ) {
- $positioner = "Absolute";
- }
- else if ( $position === "fixed" ) {
- $positioner = "Fixed";
- }
-
- $node = $frame->get_node();
-
- // Handle nodeName
- if ( $node->nodeName === "img" ) {
- $style->display = "-dompdf-image";
- $decorator = "Image";
- $reflower = "Image";
- }
-
- $positioner .= "_Positioner";
- $decorator .= "_Frame_Decorator";
- $reflower .= "_Frame_Reflower";
-
- $deco = new $decorator($frame, $dompdf);
-
- $deco->set_positioner( new $positioner($deco) );
- $deco->set_reflower( new $reflower($deco) );
-
- if ( $root ) {
- $deco->set_root($root);
- }
-
- if ( $display === "list-item" ) {
- // Insert a list-bullet frame
- $xml = $dompdf->get_dom();
- $bullet_node = $xml->createElement("bullet"); // arbitrary choice
- $b_f = new Frame($bullet_node);
-
- $node = $frame->get_node();
- $parent_node = $node->parentNode;
-
- if ( $parent_node ) {
- if ( !$parent_node->hasAttribute("dompdf-children-count") ) {
- $xpath = new DOMXPath($xml);
- $count = $xpath->query("li", $parent_node)->length;
- $parent_node->setAttribute("dompdf-children-count", $count);
- }
-
- if ( is_numeric($node->getAttribute("value")) ) {
- $index = intval($node->getAttribute("value"));
- }
- else {
- if ( !$parent_node->hasAttribute("dompdf-counter") ) {
- $index = ($parent_node->hasAttribute("start") ? $parent_node->getAttribute("start") : 1);
- }
- else {
- $index = $parent_node->getAttribute("dompdf-counter")+1;
- }
- }
-
- $parent_node->setAttribute("dompdf-counter", $index);
- $bullet_node->setAttribute("dompdf-counter", $index);
- }
-
- $new_style = $dompdf->get_css()->create_style();
- $new_style->display = "-dompdf-list-bullet";
- $new_style->inherit($style);
- $b_f->set_style($new_style);
-
- $deco->prepend_child( Frame_Factory::decorate_frame($b_f, $dompdf, $root) );
- }
-
- return $deco;
- }
-}
diff --git a/library/vendor/dompdf/include/frame_reflower.cls.php b/library/vendor/dompdf/include/frame_reflower.cls.php
deleted file mode 100644
index 576039e1f..000000000
--- a/library/vendor/dompdf/include/frame_reflower.cls.php
+++ /dev/null
@@ -1,458 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Base reflower class
- *
- * Reflower objects are responsible for determining the width and height of
- * individual frames. They also create line and page breaks as necessary.
- *
- * @access private
- * @package dompdf
- */
-abstract class Frame_Reflower {
-
- /**
- * Frame for this reflower
- *
- * @var Frame
- */
- protected $_frame;
-
- /**
- * Cached min/max size
- *
- * @var array
- */
- protected $_min_max_cache;
-
- function __construct(Frame $frame) {
- $this->_frame = $frame;
- $this->_min_max_cache = null;
- }
-
- function dispose() {
- clear_object($this);
- }
-
- /**
- * @return DOMPDF
- */
- function get_dompdf() {
- return $this->_frame->get_dompdf();
- }
-
- /**
- * Collapse frames margins
- * http://www.w3.org/TR/CSS2/box.html#collapsing-margins
- */
- protected function _collapse_margins() {
- $frame = $this->_frame;
- $cb = $frame->get_containing_block();
- $style = $frame->get_style();
-
- if ( !$frame->is_in_flow() ) {
- return;
- }
-
- $t = $style->length_in_pt($style->margin_top, $cb["h"]);
- $b = $style->length_in_pt($style->margin_bottom, $cb["h"]);
-
- // Handle 'auto' values
- if ( $t === "auto" ) {
- $style->margin_top = "0pt";
- $t = 0;
- }
-
- if ( $b === "auto" ) {
- $style->margin_bottom = "0pt";
- $b = 0;
- }
-
- // Collapse vertical margins:
- $n = $frame->get_next_sibling();
- if ( $n && !$n->is_block() ) {
- while ( $n = $n->get_next_sibling() ) {
- if ( $n->is_block() ) {
- break;
- }
-
- if ( !$n->get_first_child() ) {
- $n = null;
- break;
- }
- }
- }
-
- if ( $n ) {
- $n_style = $n->get_style();
- $b = max($b, $n_style->length_in_pt($n_style->margin_top, $cb["h"]));
- $n_style->margin_top = "0pt";
- $style->margin_bottom = $b."pt";
- }
-
- // Collapse our first child's margin
- /*$f = $this->_frame->get_first_child();
- if ( $f && !$f->is_block() ) {
- while ( $f = $f->get_next_sibling() ) {
- if ( $f->is_block() ) {
- break;
- }
-
- if ( !$f->get_first_child() ) {
- $f = null;
- break;
- }
- }
- }
-
- // Margin are collapsed only between block elements
- if ( $f ) {
- $f_style = $f->get_style();
- $t = max($t, $f_style->length_in_pt($f_style->margin_top, $cb["h"]));
- $style->margin_top = $t."pt";
- $f_style->margin_bottom = "0pt";
- }*/
- }
-
- //........................................................................
-
- abstract function reflow(Block_Frame_Decorator $block = null);
-
- //........................................................................
-
- // Required for table layout: Returns an array(0 => min, 1 => max, "min"
- // => min, "max" => max) of the minimum and maximum widths of this frame.
- // This provides a basic implementation. Child classes should override
- // this if necessary.
- function get_min_max_width() {
- if ( !is_null($this->_min_max_cache) ) {
- return $this->_min_max_cache;
- }
-
- $style = $this->_frame->get_style();
-
- // Account for margins & padding
- $dims = array($style->padding_left,
- $style->padding_right,
- $style->border_left_width,
- $style->border_right_width,
- $style->margin_left,
- $style->margin_right);
-
- $cb_w = $this->_frame->get_containing_block("w");
- $delta = $style->length_in_pt($dims, $cb_w);
-
- // Handle degenerate case
- if ( !$this->_frame->get_first_child() ) {
- return $this->_min_max_cache = array(
- $delta, $delta,
- "min" => $delta,
- "max" => $delta,
- );
- }
-
- $low = array();
- $high = array();
-
- for ( $iter = $this->_frame->get_children()->getIterator();
- $iter->valid();
- $iter->next() ) {
-
- $inline_min = 0;
- $inline_max = 0;
-
- // Add all adjacent inline widths together to calculate max width
- while ( $iter->valid() && in_array( $iter->current()->get_style()->display, Style::$INLINE_TYPES ) ) {
-
- $child = $iter->current();
-
- $minmax = $child->get_min_max_width();
-
- if ( in_array( $iter->current()->get_style()->white_space, array("pre", "nowrap") ) ) {
- $inline_min += $minmax["min"];
- }
- else {
- $low[] = $minmax["min"];
- }
-
- $inline_max += $minmax["max"];
- $iter->next();
-
- }
-
- if ( $inline_max > 0 ) $high[] = $inline_max;
- if ( $inline_min > 0 ) $low[] = $inline_min;
-
- if ( $iter->valid() ) {
- list($low[], $high[]) = $iter->current()->get_min_max_width();
- continue;
- }
-
- }
- $min = count($low) ? max($low) : 0;
- $max = count($high) ? max($high) : 0;
-
- // Use specified width if it is greater than the minimum defined by the
- // content. If the width is a percentage ignore it for now.
- $width = $style->width;
- if ( $width !== "auto" && !is_percent($width) ) {
- $width = $style->length_in_pt($width, $cb_w);
- if ( $min < $width ) $min = $width;
- if ( $max < $width ) $max = $width;
- }
-
- $min += $delta;
- $max += $delta;
- return $this->_min_max_cache = array($min, $max, "min"=>$min, "max"=>$max);
- }
-
- /**
- * Parses a CSS string containing quotes and escaped hex characters
- *
- * @param $string string The CSS string to parse
- * @param $single_trim
- * @return string
- */
- protected function _parse_string($string, $single_trim = false) {
- if ( $single_trim ) {
- $string = preg_replace('/^[\"\']/', "", $string);
- $string = preg_replace('/[\"\']$/', "", $string);
- }
- else {
- $string = trim($string, "'\"");
- }
-
- $string = str_replace(array("\\\n",'\\"',"\\'"),
- array("",'"',"'"), $string);
-
- // Convert escaped hex characters into ascii characters (e.g. \A => newline)
- $string = preg_replace_callback("/\\\\([0-9a-fA-F]{0,6})/",
- create_function('$matches',
- 'return unichr(hexdec($matches[1]));'),
- $string);
- return $string;
- }
-
- /**
- * Parses a CSS "quotes" property
- *
- * @return array|null An array of pairs of quotes
- */
- protected function _parse_quotes() {
-
- // Matches quote types
- $re = '/(\'[^\']*\')|(\"[^\"]*\")/';
-
- $quotes = $this->_frame->get_style()->quotes;
-
- // split on spaces, except within quotes
- if ( !preg_match_all($re, "$quotes", $matches, PREG_SET_ORDER) ) {
- return null;
- }
-
- $quotes_array = array();
- foreach($matches as &$_quote){
- $quotes_array[] = $this->_parse_string($_quote[0], true);
- }
-
- if ( empty($quotes_array) ) {
- $quotes_array = array('"', '"');
- }
-
- return array_chunk($quotes_array, 2);
- }
-
- /**
- * Parses the CSS "content" property
- *
- * @return string|null The resulting string
- */
- protected function _parse_content() {
-
- // Matches generated content
- $re = "/\n".
- "\s(counters?\\([^)]*\\))|\n".
- "\A(counters?\\([^)]*\\))|\n".
- "\s([\"']) ( (?:[^\"']|\\\\[\"'])+ )(?_frame->get_style()->content;
-
- $quotes = $this->_parse_quotes();
-
- // split on spaces, except within quotes
- if ( !preg_match_all($re, $content, $matches, PREG_SET_ORDER) ) {
- return null;
- }
-
- $text = "";
-
- foreach ($matches as $match) {
-
- if ( isset($match[2]) && $match[2] !== "" ) {
- $match[1] = $match[2];
- }
-
- if ( isset($match[6]) && $match[6] !== "" ) {
- $match[4] = $match[6];
- }
-
- if ( isset($match[8]) && $match[8] !== "" ) {
- $match[7] = $match[8];
- }
-
- if ( isset($match[1]) && $match[1] !== "" ) {
-
- // counters?(...)
- $match[1] = mb_strtolower(trim($match[1]));
-
- // Handle counter() references:
- // http://www.w3.org/TR/CSS21/generate.html#content
-
- $i = mb_strpos($match[1], ")");
- if ( $i === false ) {
- continue;
- }
-
- preg_match( '/(counters?)(^\()*?\(\s*([^\s,]+)\s*(,\s*["\']?([^"\'\)]+)["\']?\s*(,\s*([^\s)]+)\s*)?)?\)/i' , $match[1] , $args );
- $counter_id = $args[3];
- if ( strtolower( $args[1] ) == 'counter' ) {
- // counter(name [,style])
- if ( isset( $args[5] ) ) {
- $type = trim( $args[5] );
- }
- else {
- $type = null;
- }
- $p = $this->_frame->lookup_counter_frame( $counter_id );
-
- $text .= $p->counter_value($counter_id, $type);
-
- }
- else if ( strtolower( $args[1] ) == 'counters' ) {
- // counters(name, string [,style])
- if ( isset($args[5]) ) {
- $string = $this->_parse_string( $args[5] );
- }
- else {
- $string = "";
- }
-
- if ( isset( $args[7] ) ) {
- $type = trim( $args[7] );
- }
- else {
- $type = null;
- }
-
- $p = $this->_frame->lookup_counter_frame($counter_id);
- $tmp = array();
- while ($p) {
- // We only want to use the counter values when they actually increment the counter
- if ( array_key_exists( $counter_id , $p->_counters ) ) {
- array_unshift( $tmp , $p->counter_value($counter_id, $type) );
- }
- $p = $p->lookup_counter_frame($counter_id);
-
- }
- $text .= implode( $string , $tmp );
-
- }
- else {
- // countertops?
- continue;
- }
-
- }
- else if ( isset($match[4]) && $match[4] !== "" ) {
- // String match
- $text .= $this->_parse_string($match[4]);
- }
- else if ( isset($match[7]) && $match[7] !== "" ) {
- // Directive match
-
- if ( $match[7] === "open-quote" ) {
- // FIXME: do something here
- $text .= $quotes[0][0];
- }
- else if ( $match[7] === "close-quote" ) {
- // FIXME: do something else here
- $text .= $quotes[0][1];
- }
- else if ( $match[7] === "no-open-quote" ) {
- // FIXME:
- }
- else if ( $match[7] === "no-close-quote" ) {
- // FIXME:
- }
- else if ( mb_strpos($match[7],"attr(") === 0 ) {
-
- $i = mb_strpos($match[7],")");
- if ( $i === false ) {
- continue;
- }
-
- $attr = mb_substr($match[7], 5, $i - 5);
- if ( $attr == "" ) {
- continue;
- }
-
- $text .= $this->_frame->get_parent()->get_node()->getAttribute($attr);
- }
- else {
- continue;
- }
- }
- }
-
- return $text;
- }
-
- /**
- * Sets the generated content of a generated frame
- */
- protected function _set_content(){
- $frame = $this->_frame;
- $style = $frame->get_style();
-
- // if the element was pushed to a new page use the saved counter value, otherwise use the CSS reset value
- if ( $style->counter_reset && ($reset = $style->counter_reset) !== "none" ) {
- $vars = preg_split('/\s+/', trim($reset), 2);
- $frame->reset_counter( $vars[0] , ( isset($frame->_counters['__'.$vars[0]]) ? $frame->_counters['__'.$vars[0]] : ( isset($vars[1]) ? $vars[1] : 0 ) ) );
- }
-
- if ( $style->counter_increment && ($increment = $style->counter_increment) !== "none" ) {
- $frame->increment_counters($increment);
- }
-
- if ( $style->content && !$frame->get_first_child() && $frame->get_node()->nodeName === "dompdf_generated" ) {
- $content = $this->_parse_content();
- // add generated content to the font subset
- // FIXME: This is currently too late because the font subset has already been generated.
- // See notes in issue #750.
- if ( $frame->get_dompdf()->get_option("enable_font_subsetting") && $frame->get_dompdf()->get_canvas() instanceof CPDF_Adapter ) {
- $frame->get_dompdf()->get_canvas()->register_string_subset($style->font_family, $content);
- }
-
- $node = $frame->get_node()->ownerDocument->createTextNode($content);
-
- $new_style = $style->get_stylesheet()->create_style();
- $new_style->inherit($style);
-
- $new_frame = new Frame($node);
- $new_frame->set_style($new_style);
-
- Frame_Factory::decorate_frame($new_frame, $frame->get_dompdf(), $frame->get_root());
- $frame->append_child($new_frame);
- }
- }
-}
diff --git a/library/vendor/dompdf/include/frame_tree.cls.php b/library/vendor/dompdf/include/frame_tree.cls.php
deleted file mode 100644
index 257ca097e..000000000
--- a/library/vendor/dompdf/include/frame_tree.cls.php
+++ /dev/null
@@ -1,241 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Represents an entire document as a tree of frames
- *
- * The Frame_Tree consists of {@link Frame} objects each tied to specific
- * DOMNode objects in a specific DomDocument. The Frame_Tree has the same
- * structure as the DomDocument, but adds additional capabalities for
- * styling and layout.
- *
- * @package dompdf
- * @access protected
- */
-class Frame_Tree {
-
- /**
- * Tags to ignore while parsing the tree
- *
- * @var array
- */
- static protected $_HIDDEN_TAGS = array("area", "base", "basefont", "head", "style",
- "meta", "title", "colgroup",
- "noembed", "noscript", "param", "#comment");
- /**
- * The main DomDocument
- *
- * @see http://ca2.php.net/manual/en/ref.dom.php
- * @var DomDocument
- */
- protected $_dom;
-
- /**
- * The root node of the FrameTree.
- *
- * @var Frame
- */
- protected $_root;
-
- /**
- * Subtrees of absolutely positioned elements
- *
- * @var array of Frames
- */
- protected $_absolute_frames;
-
- /**
- * A mapping of {@link Frame} objects to DOMNode objects
- *
- * @var array
- */
- protected $_registry;
-
-
- /**
- * Class constructor
- *
- * @param DomDocument $dom the main DomDocument object representing the current html document
- */
- function __construct(DomDocument $dom) {
- $this->_dom = $dom;
- $this->_root = null;
- $this->_registry = array();
- }
-
- function __destruct() {
- clear_object($this);
- }
-
- /**
- * Returns the DomDocument object representing the curent html document
- *
- * @return DOMDocument
- */
- function get_dom() {
- return $this->_dom;
- }
-
- /**
- * Returns the root frame of the tree
- *
- * @return Page_Frame_Decorator
- */
- function get_root() {
- return $this->_root;
- }
-
- /**
- * Returns a specific frame given its id
- *
- * @param string $id
- * @return Frame
- */
- function get_frame($id) {
- return isset($this->_registry[$id]) ? $this->_registry[$id] : null;
- }
-
- /**
- * Returns a post-order iterator for all frames in the tree
- *
- * @return FrameTreeList|Frame[]
- */
- function get_frames() {
- return new FrameTreeList($this->_root);
- }
-
- /**
- * Builds the tree
- */
- function build_tree() {
- $html = $this->_dom->getElementsByTagName("html")->item(0);
- if ( is_null($html) ) {
- $html = $this->_dom->firstChild;
- }
-
- if ( is_null($html) ) {
- throw new DOMPDF_Exception("Requested HTML document contains no data.");
- }
-
- $this->fix_tables();
-
- $this->_root = $this->_build_tree_r($html);
- }
-
- /**
- * Adds missing TBODYs around TR
- */
- protected function fix_tables(){
- $xp = new DOMXPath($this->_dom);
-
- // Move table caption before the table
- // FIXME find a better way to deal with it...
- $captions = $xp->query("//table/caption");
- foreach($captions as $caption) {
- $table = $caption->parentNode;
- $table->parentNode->insertBefore($caption, $table);
- }
-
- $rows = $xp->query("//table/tr");
- foreach($rows as $row) {
- $tbody = $this->_dom->createElement("tbody");
- $tbody = $row->parentNode->insertBefore($tbody, $row);
- $tbody->appendChild($row);
- }
- }
-
- /**
- * Recursively adds {@link Frame} objects to the tree
- *
- * Recursively build a tree of Frame objects based on a dom tree.
- * No layout information is calculated at this time, although the
- * tree may be adjusted (i.e. nodes and frames for generated content
- * and images may be created).
- *
- * @param DOMNode $node the current DOMNode being considered
- * @return Frame
- */
- protected function _build_tree_r(DOMNode $node) {
-
- $frame = new Frame($node);
- $id = $frame->get_id();
- $this->_registry[ $id ] = $frame;
-
- if ( !$node->hasChildNodes() ) {
- return $frame;
- }
-
- // Fixes 'cannot access undefined property for object with
- // overloaded access', fix by Stefan radulian
- //
- //foreach ($node->childNodes as $child) {
-
- // Store the children in an array so that the tree can be modified
- $children = array();
- for ($i = 0; $i < $node->childNodes->length; $i++) {
- $children[] = $node->childNodes->item($i);
- }
-
- foreach ($children as $child) {
- $node_name = mb_strtolower($child->nodeName);
-
- // Skip non-displaying nodes
- if ( in_array($node_name, self::$_HIDDEN_TAGS) ) {
- if ( $node_name !== "head" && $node_name !== "style" ) {
- $child->parentNode->removeChild($child);
- }
-
- continue;
- }
-
- // Skip empty text nodes
- if ( $node_name === "#text" && $child->nodeValue == "" ) {
- $child->parentNode->removeChild($child);
- continue;
- }
-
- // Skip empty image nodes
- if ( $node_name === "img" && $child->getAttribute("src") == "" ) {
- $child->parentNode->removeChild($child);
- continue;
- }
-
- $frame->append_child($this->_build_tree_r($child), false);
- }
-
- return $frame;
- }
-
- public function insert_node(DOMNode $node, DOMNode $new_node, $pos) {
- if ( $pos === "after" || !$node->firstChild ) {
- $node->appendChild($new_node);
- }
- else {
- $node->insertBefore($new_node, $node->firstChild);
- }
-
- $this->_build_tree_r($new_node);
-
- $frame_id = $new_node->getAttribute("frame_id");
- $frame = $this->get_frame($frame_id);
-
- $parent_id = $node->getAttribute("frame_id");
- $parent = $this->get_frame($parent_id);
-
- if ( $parent ) {
- if ( $pos === "before" ) {
- $parent->prepend_child($frame, false);
- }
- else {
- $parent->append_child($frame, false);
- }
- }
-
- return $frame_id;
- }
-}
diff --git a/library/vendor/dompdf/include/functions.inc.php b/library/vendor/dompdf/include/functions.inc.php
deleted file mode 100644
index 265244aaf..000000000
--- a/library/vendor/dompdf/include/functions.inc.php
+++ /dev/null
@@ -1,1036 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-if ( !defined('PHP_VERSION_ID') ) {
- $version = explode('.', PHP_VERSION);
- define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
-}
-
-/**
- * Defined a constant if not already defined
- *
- * @param string $name The constant name
- * @param mixed $value The value
- */
-function def($name, $value = true) {
- if ( !defined($name) ) {
- define($name, $value);
- }
-}
-
-if ( !function_exists("pre_r") ) {
-/**
- * print_r wrapper for html/cli output
- *
- * Wraps print_r() output in < pre > tags if the current sapi is not 'cli'.
- * Returns the output string instead of displaying it if $return is true.
- *
- * @param mixed $mixed variable or expression to display
- * @param bool $return
- *
- * @return string
- */
-function pre_r($mixed, $return = false) {
- if ( $return ) {
- return "" . print_r($mixed, true) . " ";
- }
-
- if ( php_sapi_name() !== "cli" ) {
- echo "";
- }
-
- print_r($mixed);
-
- if ( php_sapi_name() !== "cli" ) {
- echo " ";
- }
- else {
- echo "\n";
- }
-
- flush();
-
-}
-}
-
-if ( !function_exists("pre_var_dump") ) {
-/**
- * var_dump wrapper for html/cli output
- *
- * Wraps var_dump() output in < pre > tags if the current sapi is not 'cli'.
- *
- * @param mixed $mixed variable or expression to display.
- */
-function pre_var_dump($mixed) {
- if ( php_sapi_name() !== "cli" ) {
- echo "";
- }
-
- var_dump($mixed);
-
- if ( php_sapi_name() !== "cli" ) {
- echo " ";
- }
-}
-}
-
-if ( !function_exists("d") ) {
-/**
- * generic debug function
- *
- * Takes everything and does its best to give a good debug output
- *
- * @param mixed $mixed variable or expression to display.
- */
-function d($mixed) {
- if ( php_sapi_name() !== "cli" ) {
- echo "";
- }
-
- // line
- if ( $mixed instanceof Line_Box ) {
- echo $mixed;
- }
-
- // other
- else {
- var_export($mixed);
- }
-
- if ( php_sapi_name() !== "cli" ) {
- echo " ";
- }
-}
-}
-
-/**
- * builds a full url given a protocol, hostname, base path and url
- *
- * @param string $protocol
- * @param string $host
- * @param string $base_path
- * @param string $url
- * @return string
- *
- * Initially the trailing slash of $base_path was optional, and conditionally appended.
- * However on dynamically created sites, where the page is given as url parameter,
- * the base path might not end with an url.
- * Therefore do not append a slash, and **require** the $base_url to ending in a slash
- * when needed.
- * Vice versa, on using the local file system path of a file, make sure that the slash
- * is appended (o.k. also for Windows)
- */
-function build_url($protocol, $host, $base_path, $url) {
- $protocol = mb_strtolower($protocol);
- if (strlen($url) == 0) {
- //return $protocol . $host . rtrim($base_path, "/\\") . "/";
- return $protocol . $host . $base_path;
- }
- // Is the url already fully qualified or a Data URI?
- if (mb_strpos($url, "://") !== false || mb_strpos($url, "data:") === 0) {
- return $url;
- }
- $ret = $protocol;
- if (!in_array(mb_strtolower($protocol), array("http://", "https://", "ftp://", "ftps://"))) {
- //On Windows local file, an abs path can begin also with a '\' or a drive letter and colon
- //drive: followed by a relative path would be a drive specific default folder.
- //not known in php app code, treat as abs path
- //($url[1] !== ':' || ($url[2]!=='\\' && $url[2]!=='/'))
- if ($url[0] !== '/' && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' || ($url[0] !== '\\' && $url[1] !== ':'))) {
- // For rel path and local acess we ignore the host, and run the path through realpath()
- $ret .= realpath($base_path) . '/';
- }
- $ret .= $url;
- $ret = preg_replace('/\?(.*)$/', "", $ret);
- return $ret;
- }
- // Protocol relative urls (e.g. "//example.org/style.css")
- if (strpos($url, '//') === 0) {
- $ret .= substr($url, 2);
- //remote urls with backslash in html/css are not really correct, but lets be genereous
- } elseif ($url[0] === '/' || $url[0] === '\\') {
- // Absolute path
- $ret .= $host . $url;
- } else {
- // Relative path
- //$base_path = $base_path !== "" ? rtrim($base_path, "/\\") . "/" : "";
- $ret .= $host . $base_path . $url;
- }
- return $ret;
-}
-
-
-/**
- * parse a full url or pathname and return an array(protocol, host, path,
- * file + query + fragment)
- *
- * @param string $url
- * @return array
- */
-function explode_url($url) {
- $protocol = "";
- $host = "";
- $path = "";
- $file = "";
-
- $arr = parse_url($url);
- if ( isset($arr["scheme"])) {
- $arr["scheme"] == mb_strtolower($arr["scheme"]);
- }
-
- // Exclude windows drive letters...
- if ( isset($arr["scheme"]) && $arr["scheme"] !== "file" && strlen($arr["scheme"]) > 1 ) {
- $protocol = $arr["scheme"] . "://";
-
- if ( isset($arr["user"]) ) {
- $host .= $arr["user"];
-
- if ( isset($arr["pass"]) ) {
- $host .= ":" . $arr["pass"];
- }
-
- $host .= "@";
- }
-
- if ( isset($arr["host"]) ) {
- $host .= $arr["host"];
- }
-
- if ( isset($arr["port"]) ) {
- $host .= ":" . $arr["port"];
- }
-
- if ( isset($arr["path"]) && $arr["path"] !== "" ) {
- // Do we have a trailing slash?
- if ( $arr["path"][ mb_strlen($arr["path"]) - 1 ] === "/" ) {
- $path = $arr["path"];
- $file = "";
- }
- else {
- $path = rtrim(dirname($arr["path"]), '/\\') . "/";
- $file = basename($arr["path"]);
- }
- }
-
- if ( isset($arr["query"]) ) {
- $file .= "?" . $arr["query"];
- }
-
- if ( isset($arr["fragment"]) ) {
- $file .= "#" . $arr["fragment"];
- }
-
- }
- else {
-
- $i = mb_stripos($url, "file://");
- if ( $i !== false ) {
- $url = mb_substr($url, $i + 7);
- }
-
- $protocol = ""; // "file://"; ? why doesn't this work... It's because of
- // network filenames like //COMPU/SHARENAME
-
- $host = ""; // localhost, really
- $file = basename($url);
-
- $path = dirname($url);
-
- // Check that the path exists
- if ( $path !== false ) {
- $path .= '/';
-
- }
- else {
- // generate a url to access the file if no real path found.
- $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
-
- $host = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : php_uname("n");
-
- if ( substr($arr["path"], 0, 1) === '/' ) {
- $path = dirname($arr["path"]);
- }
- else {
- $path = '/' . rtrim(dirname($_SERVER["SCRIPT_NAME"]), '/') . '/' . $arr["path"];
- }
- }
- }
-
- $ret = array($protocol, $host, $path, $file,
- "protocol" => $protocol,
- "host" => $host,
- "path" => $path,
- "file" => $file);
- return $ret;
-}
-
-/**
- * Converts decimal numbers to roman numerals
- *
- * @param int $num
- *
- * @throws DOMPDF_Exception
- * @return string
- */
-function dec2roman($num) {
-
- static $ones = array("", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix");
- static $tens = array("", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc");
- static $hund = array("", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm");
- static $thou = array("", "m", "mm", "mmm");
-
- if ( !is_numeric($num) ) {
- throw new DOMPDF_Exception("dec2roman() requires a numeric argument.");
- }
-
- if ( $num > 4000 || $num < 0 ) {
- return "(out of range)";
- }
-
- $num = strrev((string)$num);
-
- $ret = "";
- switch (mb_strlen($num)) {
- case 4: $ret .= $thou[$num[3]];
- case 3: $ret .= $hund[$num[2]];
- case 2: $ret .= $tens[$num[1]];
- case 1: $ret .= $ones[$num[0]];
- default: break;
- }
-
- return $ret;
-}
-
-/**
- * Determines whether $value is a percentage or not
- *
- * @param float $value
- *
- * @return bool
- */
-function is_percent($value) {
- return false !== mb_strpos($value, "%");
-}
-
-/**
- * Parses a data URI scheme
- * http://en.wikipedia.org/wiki/Data_URI_scheme
- *
- * @param string $data_uri The data URI to parse
- *
- * @return array The result with charset, mime type and decoded data
- */
-function parse_data_uri($data_uri) {
- if (!preg_match('/^data:(?P[a-z0-9\/+-.]+)(;charset=(?P[a-z0-9-])+)?(?P;base64)?\,(?P.*)?/i', $data_uri, $match)) {
- return false;
- }
-
- $match['data'] = rawurldecode($match['data']);
- $result = array(
- 'charset' => $match['charset'] ? $match['charset'] : 'US-ASCII',
- 'mime' => $match['mime'] ? $match['mime'] : 'text/plain',
- 'data' => $match['base64'] ? base64_decode($match['data']) : $match['data'],
- );
-
- return $result;
-}
-
-/**
- * mb_string compatibility
- */
-if (!extension_loaded('mbstring')) {
- def('MB_OVERLOAD_MAIL', 1);
- def('MB_OVERLOAD_STRING', 2);
- def('MB_OVERLOAD_REGEX', 4);
- def('MB_CASE_UPPER', 0);
- def('MB_CASE_LOWER', 1);
- def('MB_CASE_TITLE', 2);
-
- if (!function_exists('mb_convert_encoding')) {
- function mb_convert_encoding($data, $to_encoding, $from_encoding = 'UTF-8') {
- if (str_replace('-', '', strtolower($to_encoding)) === 'utf8') {
- return utf8_encode($data);
- }
-
- return utf8_decode($data);
- }
- }
-
- if (!function_exists('mb_detect_encoding')) {
- function mb_detect_encoding($data, $encoding_list = array('iso-8859-1'), $strict = false) {
- return 'iso-8859-1';
- }
- }
-
- if (!function_exists('mb_detect_order')) {
- function mb_detect_order($encoding_list = array('iso-8859-1')) {
- return 'iso-8859-1';
- }
- }
-
- if (!function_exists('mb_internal_encoding')) {
- function mb_internal_encoding($encoding = null) {
- if (isset($encoding)) {
- return true;
- }
-
- return 'iso-8859-1';
- }
- }
-
- if (!function_exists('mb_strlen')) {
- function mb_strlen($str, $encoding = 'iso-8859-1') {
- switch (str_replace('-', '', strtolower($encoding))) {
- case "utf8": return strlen(utf8_encode($str));
- case "8bit": return strlen($str);
- default: return strlen(utf8_decode($str));
- }
- }
- }
-
- if (!function_exists('mb_strpos')) {
- function mb_strpos($haystack, $needle, $offset = 0) {
- return strpos($haystack, $needle, $offset);
- }
- }
-
- if (!function_exists('mb_stripos')) {
- function mb_stripos($haystack, $needle, $offset = 0) {
- return stripos($haystack, $needle, $offset);
- }
- }
-
- if (!function_exists('mb_strrpos')) {
- function mb_strrpos($haystack, $needle, $offset = 0) {
- return strrpos($haystack, $needle, $offset);
- }
- }
-
- if (!function_exists('mb_strtolower')) {
- function mb_strtolower( $str ) {
- return strtolower($str);
- }
- }
-
- if (!function_exists('mb_strtoupper')) {
- function mb_strtoupper( $str ) {
- return strtoupper($str);
- }
- }
-
- if (!function_exists('mb_substr')) {
- function mb_substr($string, $start, $length = null, $encoding = 'iso-8859-1') {
- if ( is_null($length) ) {
- return substr($string, $start);
- }
-
- return substr($string, $start, $length);
- }
- }
-
- if (!function_exists('mb_substr_count')) {
- function mb_substr_count($haystack, $needle, $encoding = 'iso-8859-1') {
- return substr_count($haystack, $needle);
- }
- }
-
- if (!function_exists('mb_encode_numericentity')) {
- function mb_encode_numericentity($str, $convmap, $encoding) {
- return htmlspecialchars($str);
- }
- }
-
- if (!function_exists('mb_convert_case')) {
- function mb_convert_case($str, $mode = MB_CASE_UPPER, $encoding = array()) {
- switch($mode) {
- case MB_CASE_UPPER: return mb_strtoupper($str);
- case MB_CASE_LOWER: return mb_strtolower($str);
- case MB_CASE_TITLE: return ucwords(mb_strtolower($str));
- default: return $str;
- }
- }
- }
-
- if (!function_exists('mb_list_encodings')) {
- function mb_list_encodings() {
- return array(
- "ISO-8859-1",
- "UTF-8",
- "8bit",
- );
- }
- }
-}
-
-/**
- * Decoder for RLE8 compression in windows bitmaps
- * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
- *
- * @param string $str Data to decode
- * @param integer $width Image width
- *
- * @return string
- */
-function rle8_decode ($str, $width){
- $lineWidth = $width + (3 - ($width-1) % 4);
- $out = '';
- $cnt = strlen($str);
-
- for ($i = 0; $i <$cnt; $i++) {
- $o = ord($str[$i]);
- switch ($o){
- case 0: # ESCAPE
- $i++;
- switch (ord($str[$i])){
- case 0: # NEW LINE
- $padCnt = $lineWidth - strlen($out)%$lineWidth;
- if ($padCnt<$lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
- break;
- case 1: # END OF FILE
- $padCnt = $lineWidth - strlen($out)%$lineWidth;
- if ($padCnt<$lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
- break 3;
- case 2: # DELTA
- $i += 2;
- break;
- default: # ABSOLUTE MODE
- $num = ord($str[$i]);
- for ($j = 0; $j < $num; $j++)
- $out .= $str[++$i];
- if ($num % 2) $i++;
- }
- break;
- default:
- $out .= str_repeat($str[++$i], $o);
- }
- }
- return $out;
-}
-
-/**
- * Decoder for RLE4 compression in windows bitmaps
- * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
- *
- * @param string $str Data to decode
- * @param integer $width Image width
- *
- * @return string
- */
-function rle4_decode ($str, $width) {
- $w = floor($width/2) + ($width % 2);
- $lineWidth = $w + (3 - ( ($width-1) / 2) % 4);
- $pixels = array();
- $cnt = strlen($str);
- $c = 0;
-
- for ($i = 0; $i < $cnt; $i++) {
- $o = ord($str[$i]);
- switch ($o) {
- case 0: # ESCAPE
- $i++;
- switch (ord($str[$i])){
- case 0: # NEW LINE
- while (count($pixels)%$lineWidth != 0) {
- $pixels[] = 0;
- }
- break;
- case 1: # END OF FILE
- while (count($pixels)%$lineWidth != 0) {
- $pixels[] = 0;
- }
- break 3;
- case 2: # DELTA
- $i += 2;
- break;
- default: # ABSOLUTE MODE
- $num = ord($str[$i]);
- for ($j = 0; $j < $num; $j++) {
- if ($j%2 == 0) {
- $c = ord($str[++$i]);
- $pixels[] = ($c & 240)>>4;
- }
- else {
- $pixels[] = $c & 15;
- }
- }
-
- if ($num % 2 == 0) {
- $i++;
- }
- }
- break;
- default:
- $c = ord($str[++$i]);
- for ($j = 0; $j < $o; $j++) {
- $pixels[] = ($j%2==0 ? ($c & 240)>>4 : $c & 15);
- }
- }
- }
-
- $out = '';
- if (count($pixels)%2) {
- $pixels[] = 0;
- }
-
- $cnt = count($pixels)/2;
-
- for ($i = 0; $i < $cnt; $i++) {
- $out .= chr(16*$pixels[2*$i] + $pixels[2*$i+1]);
- }
-
- return $out;
-}
-
-if ( !function_exists("imagecreatefrombmp") ) {
-
-/**
- * Credit goes to mgutt
- * http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm
- * Modified by Fabien Menager to support RGB555 BMP format
- */
-function imagecreatefrombmp($filename) {
- if (!function_exists("imagecreatetruecolor")) {
- trigger_error("The PHP GD extension is required, but is not installed.", E_ERROR);
- return false;
- }
-
- // version 1.00
- if (!($fh = fopen($filename, 'rb'))) {
- trigger_error('imagecreatefrombmp: Can not open ' . $filename, E_USER_WARNING);
- return false;
- }
-
- $bytes_read = 0;
-
- // read file header
- $meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14));
-
- // check for bitmap
- if ($meta['type'] != 19778) {
- trigger_error('imagecreatefrombmp: ' . $filename . ' is not a bitmap!', E_USER_WARNING);
- return false;
- }
-
- // read image header
- $meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread($fh, 40));
- $bytes_read += 40;
-
- // read additional bitfield header
- if ($meta['compression'] == 3) {
- $meta += unpack('VrMask/VgMask/VbMask', fread($fh, 12));
- $bytes_read += 12;
- }
-
- // set bytes and padding
- $meta['bytes'] = $meta['bits'] / 8;
- $meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4)- floor($meta['width'] * $meta['bytes'] / 4)));
- if ($meta['decal'] == 4) {
- $meta['decal'] = 0;
- }
-
- // obtain imagesize
- if ($meta['imagesize'] < 1) {
- $meta['imagesize'] = $meta['filesize'] - $meta['offset'];
- // in rare cases filesize is equal to offset so we need to read physical size
- if ($meta['imagesize'] < 1) {
- $meta['imagesize'] = @filesize($filename) - $meta['offset'];
- if ($meta['imagesize'] < 1) {
- trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING);
- return false;
- }
- }
- }
-
- // calculate colors
- $meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors'];
-
- // read color palette
- $palette = array();
- if ($meta['bits'] < 16) {
- $palette = unpack('l' . $meta['colors'], fread($fh, $meta['colors'] * 4));
- // in rare cases the color value is signed
- if ($palette[1] < 0) {
- foreach ($palette as $i => $color) {
- $palette[$i] = $color + 16777216;
- }
- }
- }
-
- // ignore extra bitmap headers
- if ($meta['headersize'] > $bytes_read) {
- fread($fh, $meta['headersize'] - $bytes_read);
- }
-
- // create gd image
- $im = imagecreatetruecolor($meta['width'], $meta['height']);
- $data = fread($fh, $meta['imagesize']);
-
- // uncompress data
- switch ($meta['compression']) {
- case 1: $data = rle8_decode($data, $meta['width']); break;
- case 2: $data = rle4_decode($data, $meta['width']); break;
- }
-
- $p = 0;
- $vide = chr(0);
- $y = $meta['height'] - 1;
- $error = 'imagecreatefrombmp: ' . $filename . ' has not enough data!';
-
- // loop through the image data beginning with the lower left corner
- while ($y >= 0) {
- $x = 0;
- while ($x < $meta['width']) {
- switch ($meta['bits']) {
- case 32:
- case 24:
- if (!($part = substr($data, $p, 3 /*$meta['bytes']*/))) {
- trigger_error($error, E_USER_WARNING);
- return $im;
- }
- $color = unpack('V', $part . $vide);
- break;
- case 16:
- if (!($part = substr($data, $p, 2 /*$meta['bytes']*/))) {
- trigger_error($error, E_USER_WARNING);
- return $im;
- }
- $color = unpack('v', $part);
-
- if (empty($meta['rMask']) || $meta['rMask'] != 0xf800) {
- $color[1] = (($color[1] & 0x7c00) >> 7) * 65536 + (($color[1] & 0x03e0) >> 2) * 256 + (($color[1] & 0x001f) << 3); // 555
- }
- else {
- $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3); // 565
- }
- break;
- case 8:
- $color = unpack('n', $vide . substr($data, $p, 1));
- $color[1] = $palette[ $color[1] + 1 ];
- break;
- case 4:
- $color = unpack('n', $vide . substr($data, floor($p), 1));
- $color[1] = ($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F;
- $color[1] = $palette[ $color[1] + 1 ];
- break;
- case 1:
- $color = unpack('n', $vide . substr($data, floor($p), 1));
- switch (($p * 8) % 8) {
- case 0: $color[1] = $color[1] >> 7; break;
- case 1: $color[1] = ($color[1] & 0x40) >> 6; break;
- case 2: $color[1] = ($color[1] & 0x20) >> 5; break;
- case 3: $color[1] = ($color[1] & 0x10) >> 4; break;
- case 4: $color[1] = ($color[1] & 0x8 ) >> 3; break;
- case 5: $color[1] = ($color[1] & 0x4 ) >> 2; break;
- case 6: $color[1] = ($color[1] & 0x2 ) >> 1; break;
- case 7: $color[1] = ($color[1] & 0x1 ); break;
- }
- $color[1] = $palette[ $color[1] + 1 ];
- break;
- default:
- trigger_error('imagecreatefrombmp: ' . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', E_USER_WARNING);
- return false;
- }
- imagesetpixel($im, $x, $y, $color[1]);
- $x++;
- $p += $meta['bytes'];
- }
- $y--;
- $p += $meta['decal'];
- }
- fclose($fh);
- return $im;
-}
-}
-
-/**
- * getimagesize doesn't give a good size for 32bit BMP image v5
- *
- * @param string $filename
- * @return array The same format as getimagesize($filename)
- */
-function dompdf_getimagesize($filename, $context = null) {
- static $cache = array();
-
- if ( isset($cache[$filename]) ) {
- return $cache[$filename];
- }
-
- list($width, $height, $type) = getimagesize($filename);
-
- if ( $width == null || $height == null ) {
- $data = file_get_contents($filename, null, $context, 0, 26);
-
- if ( substr($data, 0, 2) === "BM" ) {
- $meta = unpack('vtype/Vfilesize/Vreserved/Voffset/Vheadersize/Vwidth/Vheight', $data);
- $width = (int)$meta['width'];
- $height = (int)$meta['height'];
- $type = IMAGETYPE_BMP;
- }
- }
-
- return $cache[$filename] = array($width, $height, $type);
-}
-
-/**
- * Converts a CMYK color to RGB
- *
- * @param float|float[] $c
- * @param float $m
- * @param float $y
- * @param float $k
- *
- * @return float[]
- */
-function cmyk_to_rgb($c, $m = null, $y = null, $k = null) {
- if (is_array($c)) {
- list($c, $m, $y, $k) = $c;
- }
-
- $c *= 255;
- $m *= 255;
- $y *= 255;
- $k *= 255;
-
- $r = (1 - round(2.55 * ($c+$k))) ;
- $g = (1 - round(2.55 * ($m+$k))) ;
- $b = (1 - round(2.55 * ($y+$k))) ;
-
- if ($r < 0) $r = 0;
- if ($g < 0) $g = 0;
- if ($b < 0) $b = 0;
-
- return array(
- $r, $g, $b,
- "r" => $r, "g" => $g, "b" => $b
- );
-}
-
-function unichr($c) {
- if ($c <= 0x7F) {
- return chr($c);
- }
- else if ($c <= 0x7FF) {
- return chr(0xC0 | $c >> 6) . chr(0x80 | $c & 0x3F);
- }
- else if ($c <= 0xFFFF) {
- return chr(0xE0 | $c >> 12) . chr(0x80 | $c >> 6 & 0x3F)
- . chr(0x80 | $c & 0x3F);
- }
- else if ($c <= 0x10FFFF) {
- return chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F)
- . chr(0x80 | $c >> 6 & 0x3F)
- . chr(0x80 | $c & 0x3F);
- }
- return false;
-}
-
-if ( !function_exists("date_default_timezone_get") ) {
- function date_default_timezone_get() {
- return "";
- }
-
- function date_default_timezone_set($timezone_identifier) {
- return true;
- }
-}
-
-/**
- * Stores warnings in an array for display later
- * This function allows warnings generated by the DomDocument parser
- * and CSS loader ({@link Stylesheet}) to be captured and displayed
- * later. Without this function, errors are displayed immediately and
- * PDF streaming is impossible.
- * @see http://www.php.net/manual/en/function.set-error_handler.php
- *
- * @param int $errno
- * @param string $errstr
- * @param string $errfile
- * @param string $errline
- *
- * @throws DOMPDF_Exception
- */
-function record_warnings($errno, $errstr, $errfile, $errline) {
-
- // Not a warning or notice
- if ( !($errno & (E_WARNING | E_NOTICE | E_USER_NOTICE | E_USER_WARNING )) ) {
- throw new DOMPDF_Exception($errstr . " $errno");
- }
-
- global $_dompdf_warnings;
- global $_dompdf_show_warnings;
-
- if ( $_dompdf_show_warnings ) {
- echo $errstr . "\n";
- }
-
- $_dompdf_warnings[] = $errstr;
-}
-
-/**
- * Print a useful backtrace
- */
-function bt() {
- if ( php_sapi_name() !== "cli") {
- echo "";
- }
-
- $bt = debug_backtrace();
-
- array_shift($bt); // remove actual bt() call
- echo "\n";
-
- $i = 0;
- foreach ($bt as $call) {
- $file = basename($call["file"]) . " (" . $call["line"] . ")";
- if ( isset($call["class"]) ) {
- $func = $call["class"] . "->" . $call["function"] . "()";
- }
- else {
- $func = $call["function"] . "()";
- }
-
- echo "#" . str_pad($i, 2, " ", STR_PAD_RIGHT) . ": " . str_pad($file.":", 42) . " $func\n";
- $i++;
- }
- echo "\n";
-
- if ( php_sapi_name() !== "cli") {
- echo " ";
- }
-}
-
-/**
- * Print debug messages
- *
- * @param string $type The type of debug messages to print
- * @param string $msg The message to show
- */
-function dompdf_debug($type, $msg) {
- global $_DOMPDF_DEBUG_TYPES, $_dompdf_show_warnings, $_dompdf_debug;
- if ( isset($_DOMPDF_DEBUG_TYPES[$type]) && ($_dompdf_show_warnings || $_dompdf_debug) ) {
- $arr = debug_backtrace();
-
- echo basename($arr[0]["file"]) . " (" . $arr[0]["line"] ."): " . $arr[1]["function"] . ": ";
- pre_r($msg);
- }
-}
-
-if ( !function_exists("print_memusage") ) {
-/**
- * Dump memory usage
- */
-function print_memusage() {
- global $memusage;
- echo "Memory Usage\n";
- $prev = 0;
- $initial = reset($memusage);
- echo str_pad("Initial:", 40) . $initial . "\n\n";
-
- foreach ($memusage as $key=>$mem) {
- $mem -= $initial;
- echo str_pad("$key:" , 40);
- echo str_pad("$mem", 12) . "(diff: " . ($mem - $prev) . ")\n";
- $prev = $mem;
- }
-
- echo "\n" . str_pad("Total:", 40) . memory_get_usage() . "\n";
-}
-}
-
-if ( !function_exists("enable_mem_profile") ) {
-/**
- * Initialize memory profiling code
- */
-function enable_mem_profile() {
- global $memusage;
- $memusage = array("Startup" => memory_get_usage());
- register_shutdown_function("print_memusage");
-}
-}
-
-if ( !function_exists("mark_memusage") ) {
-/**
- * Record the current memory usage
- *
- * @param string $location a meaningful location
- */
-function mark_memusage($location) {
- global $memusage;
- if ( isset($memusage) ) {
- $memusage[$location] = memory_get_usage();
- }
-}
-}
-
-if ( !function_exists('sys_get_temp_dir')) {
-/**
- * Find the current system temporary directory
- *
- * @link http://us.php.net/manual/en/function.sys-get-temp-dir.php#85261
- */
-function sys_get_temp_dir() {
- if (!empty($_ENV['TMP'])) {
- return realpath($_ENV['TMP']);
- }
-
- if (!empty($_ENV['TMPDIR'])) {
- return realpath( $_ENV['TMPDIR']);
- }
-
- if (!empty($_ENV['TEMP'])) {
- return realpath( $_ENV['TEMP']);
- }
-
- $tempfile=tempnam(uniqid(rand(), true), '');
- if (file_exists($tempfile)) {
- unlink($tempfile);
- return realpath(dirname($tempfile));
- }
-}
-}
-
-if ( function_exists("memory_get_peak_usage") ) {
- function DOMPDF_memory_usage(){
- return memory_get_peak_usage(true);
- }
-}
-else if ( function_exists("memory_get_usage") ) {
- function DOMPDF_memory_usage(){
- return memory_get_usage(true);
- }
-}
-else {
- function DOMPDF_memory_usage(){
- return "N/A";
- }
-}
-
-
-/**
- * Affect null to the unused objects
- * @param mixed $object
- */
-if ( PHP_VERSION_ID < 50300 ) {
- function clear_object(&$object) {
- if ( is_object($object) ) {
- foreach ($object as &$value) {
- clear_object($value);
- }
- }
-
- $object = null;
- unset($object);
- }
-}
-else {
- function clear_object(&$object) {
- // void
- }
-}
diff --git a/library/vendor/dompdf/include/gd_adapter.cls.php b/library/vendor/dompdf/include/gd_adapter.cls.php
deleted file mode 100644
index 1eab04cc4..000000000
--- a/library/vendor/dompdf/include/gd_adapter.cls.php
+++ /dev/null
@@ -1,840 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Image rendering interface
- *
- * Renders to an image format supported by GD (jpeg, gif, png, xpm).
- * Not super-useful day-to-day but handy nonetheless
- *
- * @package dompdf
- */
-class GD_Adapter implements Canvas {
- /**
- * @var DOMPDF
- */
- private $_dompdf;
-
- /**
- * Resource handle for the image
- *
- * @var resource
- */
- private $_img;
-
- /**
- * Image width in pixels
- *
- * @var int
- */
- private $_width;
-
- /**
- * Image height in pixels
- *
- * @var int
- */
- private $_height;
-
- /**
- * Current page number
- *
- * @var int
- */
- private $_page_number;
-
- /**
- * Total number of pages
- *
- * @var int
- */
- private $_page_count;
-
- /**
- * Image antialias factor
- *
- * @var float
- */
- private $_aa_factor;
-
- /**
- * Allocated colors
- *
- * @var array
- */
- private $_colors;
-
- /**
- * Background color
- *
- * @var int
- */
- private $_bg_color;
-
- /**
- * Class constructor
- *
- * @param mixed $size The size of image to create: array(x1,y1,x2,y2) or "letter", "legal", etc.
- * @param string $orientation The orientation of the document (either 'landscape' or 'portrait')
- * @param DOMPDF $dompdf
- * @param float $aa_factor Anti-aliasing factor, 1 for no AA
- * @param array $bg_color Image background color: array(r,g,b,a), 0 <= r,g,b,a <= 1
- */
- function __construct($size, $orientation = "portrait", DOMPDF $dompdf, $aa_factor = 1.0, $bg_color = array(1,1,1,0) ) {
-
- if ( !is_array($size) ) {
- $size = strtolower($size);
-
- if ( isset(CPDF_Adapter::$PAPER_SIZES[$size]) ) {
- $size = CPDF_Adapter::$PAPER_SIZES[$size];
- }
- else {
- $size = CPDF_Adapter::$PAPER_SIZES["letter"];
- }
- }
-
- if ( strtolower($orientation) === "landscape" ) {
- list($size[2],$size[3]) = array($size[3],$size[2]);
- }
-
- $this->_dompdf = $dompdf;
-
- if ( $aa_factor < 1 ) {
- $aa_factor = 1;
- }
-
- $this->_aa_factor = $aa_factor;
-
- $size[2] *= $aa_factor;
- $size[3] *= $aa_factor;
-
- $this->_width = $size[2] - $size[0];
- $this->_height = $size[3] - $size[1];
-
- $this->_img = imagecreatetruecolor($this->_width, $this->_height);
-
- if ( is_null($bg_color) || !is_array($bg_color) ) {
- // Pure white bg
- $bg_color = array(1,1,1,0);
- }
-
- $this->_bg_color = $this->_allocate_color($bg_color);
- imagealphablending($this->_img, true);
- imagesavealpha($this->_img, true);
- imagefill($this->_img, 0, 0, $this->_bg_color);
-
- }
-
- function get_dompdf(){
- return $this->_dompdf;
- }
-
- /**
- * Return the GF image resource
- *
- * @return resource
- */
- function get_image() { return $this->_img; }
-
- /**
- * Return the image's width in pixels
- *
- * @return float
- */
- function get_width() { return $this->_width / $this->_aa_factor; }
-
- /**
- * Return the image's height in pixels
- *
- * @return float
- */
- function get_height() { return $this->_height / $this->_aa_factor; }
-
- /**
- * Returns the current page number
- * @return int
- */
- function get_page_number() { return $this->_page_number; }
-
- /**
- * Returns the total number of pages in the document
- * @return int
- */
- function get_page_count() { return $this->_page_count; }
-
- /**
- * Sets the current page number
- *
- * @param int $num
- */
- function set_page_number($num) { $this->_page_number = $num; }
-
- /**
- * Sets the page count
- *
- * @param int $count
- */
- function set_page_count($count) { $this->_page_count = $count; }
-
- /**
- * Sets the opacity
- *
- * @param $opacity
- * @param $mode
- */
- function set_opacity($opacity, $mode = "Normal") {
- // FIXME
- }
-
- /**
- * Allocate a new color. Allocate with GD as needed and store
- * previously allocated colors in $this->_colors.
- *
- * @param array $color The new current color
- * @return int The allocated color
- */
- private function _allocate_color($color) {
-
- if ( isset($color["c"]) ) {
- $color = cmyk_to_rgb($color);
- }
-
- // Full opacity if no alpha set
- if ( !isset($color[3]) )
- $color[3] = 0;
-
- list($r,$g,$b,$a) = $color;
-
- $r *= 255;
- $g *= 255;
- $b *= 255;
- $a *= 127;
-
- // Clip values
- $r = $r > 255 ? 255 : $r;
- $g = $g > 255 ? 255 : $g;
- $b = $b > 255 ? 255 : $b;
- $a = $a > 127 ? 127 : $a;
-
- $r = $r < 0 ? 0 : $r;
- $g = $g < 0 ? 0 : $g;
- $b = $b < 0 ? 0 : $b;
- $a = $a < 0 ? 0 : $a;
-
- $key = sprintf("#%02X%02X%02X%02X", $r, $g, $b, $a);
-
- if ( isset($this->_colors[$key]) )
- return $this->_colors[$key];
-
- if ( $a != 0 )
- $this->_colors[$key] = imagecolorallocatealpha($this->_img, $r, $g, $b, $a);
- else
- $this->_colors[$key] = imagecolorallocate($this->_img, $r, $g, $b);
-
- return $this->_colors[$key];
-
- }
-
- /**
- * Draws a line from x1,y1 to x2,y2
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the format of the
- * $style parameter (aka dash).
- *
- * @param float $x1
- * @param float $y1
- * @param float $x2
- * @param float $y2
- * @param array $color
- * @param float $width
- * @param array $style
- */
- function line($x1, $y1, $x2, $y2, $color, $width, $style = null) {
-
- // Scale by the AA factor
- $x1 *= $this->_aa_factor;
- $y1 *= $this->_aa_factor;
- $x2 *= $this->_aa_factor;
- $y2 *= $this->_aa_factor;
- $width *= $this->_aa_factor;
-
- $c = $this->_allocate_color($color);
-
- // Convert the style array if required
- if ( !is_null($style) ) {
- $gd_style = array();
-
- if ( count($style) == 1 ) {
- for ($i = 0; $i < $style[0] * $this->_aa_factor; $i++) {
- $gd_style[] = $c;
- }
-
- for ($i = 0; $i < $style[0] * $this->_aa_factor; $i++) {
- $gd_style[] = $this->_bg_color;
- }
-
- } else {
-
- $i = 0;
- foreach ($style as $length) {
-
- if ( $i % 2 == 0 ) {
- // 'On' pattern
- for ($i = 0; $i < $style[0] * $this->_aa_factor; $i++)
- $gd_style[] = $c;
-
- } else {
- // Off pattern
- for ($i = 0; $i < $style[0] * $this->_aa_factor; $i++)
- $gd_style[] = $this->_bg_color;
-
- }
- $i++;
- }
- }
-
- imagesetstyle($this->_img, $gd_style);
- $c = IMG_COLOR_STYLED;
- }
-
- imagesetthickness($this->_img, $width);
-
- imageline($this->_img, $x1, $y1, $x2, $y2, $c);
-
- }
-
- function arc($x1, $y1, $r1, $r2, $astart, $aend, $color, $width, $style = array()) {
- // @todo
- }
-
- /**
- * Draws a rectangle at x1,y1 with width w and height h
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the $style
- * parameter (aka dash)
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- * @param array $color
- * @param float $width
- * @param array $style
- */
- function rectangle($x1, $y1, $w, $h, $color, $width, $style = null) {
-
- // Scale by the AA factor
- $x1 *= $this->_aa_factor;
- $y1 *= $this->_aa_factor;
- $w *= $this->_aa_factor;
- $h *= $this->_aa_factor;
-
- $c = $this->_allocate_color($color);
-
- // Convert the style array if required
- if ( !is_null($style) ) {
- $gd_style = array();
-
- foreach ($style as $length) {
- for ($i = 0; $i < $length; $i++) {
- $gd_style[] = $c;
- }
- }
-
- imagesetstyle($this->_img, $gd_style);
- $c = IMG_COLOR_STYLED;
- }
-
- imagesetthickness($this->_img, $width);
-
- imagerectangle($this->_img, $x1, $y1, $x1 + $w, $y1 + $h, $c);
-
- }
-
- /**
- * Draws a filled rectangle at x1,y1 with width w and height h
- *
- * See {@link Style::munge_color()} for the format of the color array.
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- * @param array $color
- */
- function filled_rectangle($x1, $y1, $w, $h, $color) {
-
- // Scale by the AA factor
- $x1 *= $this->_aa_factor;
- $y1 *= $this->_aa_factor;
- $w *= $this->_aa_factor;
- $h *= $this->_aa_factor;
-
- $c = $this->_allocate_color($color);
-
- imagefilledrectangle($this->_img, $x1, $y1, $x1 + $w, $y1 + $h, $c);
-
- }
-
- /**
- * Starts a clipping rectangle at x1,y1 with width w and height h
- *
- * @param float $x1
- * @param float $y1
- * @param float $w
- * @param float $h
- */
- function clipping_rectangle($x1, $y1, $w, $h) {
- // @todo
- }
-
- function clipping_roundrectangle($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) {
- // @todo
- }
-
- /**
- * Ends the last clipping shape
- */
- function clipping_end() {
- // @todo
- }
-
- function save() {
- // @todo
- }
-
- function restore() {
- // @todo
- }
-
- function rotate($angle, $x, $y) {
- // @todo
- }
-
- function skew($angle_x, $angle_y, $x, $y) {
- // @todo
- }
-
- function scale($s_x, $s_y, $x, $y) {
- // @todo
- }
-
- function translate($t_x, $t_y) {
- // @todo
- }
-
- function transform($a, $b, $c, $d, $e, $f) {
- // @todo
- }
-
- /**
- * Draws a polygon
- *
- * The polygon is formed by joining all the points stored in the $points
- * array. $points has the following structure:
- *
- * array(0 => x1,
- * 1 => y1,
- * 2 => x2,
- * 3 => y2,
- * ...
- * );
- *
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the $style
- * parameter (aka dash)
- *
- * @param array $points
- * @param array $color
- * @param float $width
- * @param array $style
- * @param bool $fill Fills the polygon if true
- */
- function polygon($points, $color, $width = null, $style = null, $fill = false) {
-
- // Scale each point by the AA factor
- foreach (array_keys($points) as $i)
- $points[$i] *= $this->_aa_factor;
-
- $c = $this->_allocate_color($color);
-
- // Convert the style array if required
- if ( !is_null($style) && !$fill ) {
- $gd_style = array();
-
- foreach ($style as $length) {
- for ($i = 0; $i < $length; $i++) {
- $gd_style[] = $c;
- }
- }
-
- imagesetstyle($this->_img, $gd_style);
- $c = IMG_COLOR_STYLED;
- }
-
- imagesetthickness($this->_img, $width);
-
- if ( $fill )
- imagefilledpolygon($this->_img, $points, count($points) / 2, $c);
- else
- imagepolygon($this->_img, $points, count($points) / 2, $c);
-
- }
-
- /**
- * Draws a circle at $x,$y with radius $r
- *
- * See {@link Style::munge_color()} for the format of the color array.
- * See {@link Cpdf::setLineStyle()} for a description of the $style
- * parameter (aka dash)
- *
- * @param float $x
- * @param float $y
- * @param float $r
- * @param array $color
- * @param float $width
- * @param array $style
- * @param bool $fill Fills the circle if true
- */
- function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false) {
-
- // Scale by the AA factor
- $x *= $this->_aa_factor;
- $y *= $this->_aa_factor;
- $r *= $this->_aa_factor;
-
- $c = $this->_allocate_color($color);
-
- // Convert the style array if required
- if ( !is_null($style) && !$fill ) {
- $gd_style = array();
-
- foreach ($style as $length) {
- for ($i = 0; $i < $length; $i++) {
- $gd_style[] = $c;
- }
- }
-
- imagesetstyle($this->_img, $gd_style);
- $c = IMG_COLOR_STYLED;
- }
-
- imagesetthickness($this->_img, $width);
-
- if ( $fill )
- imagefilledellipse($this->_img, $x, $y, $r, $r, $c);
- else
- imageellipse($this->_img, $x, $y, $r, $r, $c);
-
- }
-
- /**
- * Add an image to the pdf.
- * The image is placed at the specified x and y coordinates with the
- * given width and height.
- *
- * @param string $img_url the path to the image
- * @param float $x x position
- * @param float $y y position
- * @param int $w width (in pixels)
- * @param int $h height (in pixels)
- * @param string $resolution
- *
- * @return void
- * @internal param string $img_type the type (e.g. extension) of the image
- */
- function image($img_url, $x, $y, $w, $h, $resolution = "normal") {
- $img_type = Image_Cache::detect_type($img_url, $this->_dompdf->get_http_context());
- $img_ext = Image_Cache::type_to_ext($img_type);
-
- if ( !$img_ext ) {
- return;
- }
-
- $func = "imagecreatefrom$img_ext";
- $src = @$func($img_url);
-
- if ( !$src ) {
- return; // Probably should add to $_dompdf_errors or whatever here
- }
-
- // Scale by the AA factor
- $x *= $this->_aa_factor;
- $y *= $this->_aa_factor;
-
- $w *= $this->_aa_factor;
- $h *= $this->_aa_factor;
-
- $img_w = imagesx($src);
- $img_h = imagesy($src);
-
- imagecopyresampled($this->_img, $src, $x, $y, 0, 0, $w, $h, $img_w, $img_h);
-
- }
-
- /**
- * Writes text at the specified x and y coordinates
- * See {@link Style::munge_color()} for the format of the color array.
- *
- * @param float $x
- * @param float $y
- * @param string $text the text to write
- * @param string $font the font file to use
- * @param float $size the font size, in points
- * @param array $color
- * @param float $word_spacing word spacing adjustment
- * @param float $char_spacing
- * @param float $angle Text angle
- *
- * @return void
- */
- function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_spacing = 0.0, $char_spacing = 0.0, $angle = 0.0) {
-
- // Scale by the AA factor
- $x *= $this->_aa_factor;
- $y *= $this->_aa_factor;
- $size *= $this->_aa_factor;
-
- $h = $this->get_font_height($font, $size);
- $c = $this->_allocate_color($color);
-
- $text = mb_encode_numericentity($text, array(0x0080, 0xff, 0, 0xff), 'UTF-8');
-
- $font = $this->get_ttf_file($font);
-
- // FIXME: word spacing
- @imagettftext($this->_img, $size, $angle, $x, $y + $h, $c, $font, $text);
-
- }
-
- function javascript($code) {
- // Not implemented
- }
-
- /**
- * Add a named destination (similar to ... in html)
- *
- * @param string $anchorname The name of the named destination
- */
- function add_named_dest($anchorname) {
- // Not implemented
- }
-
- /**
- * Add a link to the pdf
- *
- * @param string $url The url to link to
- * @param float $x The x position of the link
- * @param float $y The y position of the link
- * @param float $width The width of the link
- * @param float $height The height of the link
- */
- function add_link($url, $x, $y, $width, $height) {
- // Not implemented
- }
-
- /**
- * Add meta information to the PDF
- *
- * @param string $label label of the value (Creator, Producer, etc.)
- * @param string $value the text to set
- */
- function add_info($label, $value) {
- // N/A
- }
-
- function set_default_view($view, $options = array()) {
- // N/A
- }
-
- /**
- * Calculates text size, in points
- *
- * @param string $text the text to be sized
- * @param string $font the desired font
- * @param float $size the desired font size
- * @param float $word_spacing word spacing, if any
- * @param float $char_spacing char spacing, if any
- *
- * @return float
- */
- function get_text_width($text, $font, $size, $word_spacing = 0.0, $char_spacing = 0.0) {
- $font = $this->get_ttf_file($font);
-
- $text = mb_encode_numericentity($text, array(0x0080, 0xffff, 0, 0xffff), 'UTF-8');
-
- // FIXME: word spacing
- list($x1,,$x2) = @imagettfbbox($size, 0, $font, $text);
- return $x2 - $x1;
- }
-
- function get_ttf_file($font) {
- if ( strpos($font, '.ttf') === false )
- $font .= ".ttf";
-
- /*$filename = substr(strtolower(basename($font)), 0, -4);
-
- if ( in_array($filename, DOMPDF::$native_fonts) ) {
- return "arial.ttf";
- }*/
-
- return $font;
- }
-
- /**
- * Calculates font height, in points
- *
- * @param string $font
- * @param float $size
- * @return float
- */
- function get_font_height($font, $size) {
- $font = $this->get_ttf_file($font);
- $ratio = $this->_dompdf->get_option("font_height_ratio");
-
- // FIXME: word spacing
- list(,$y2,,,,$y1) = imagettfbbox($size, 0, $font, "MXjpqytfhl"); // Test string with ascenders, descenders and caps
- return ($y2 - $y1) * $ratio;
- }
-
- function get_font_baseline($font, $size) {
- $ratio = $this->_dompdf->get_option("font_height_ratio");
- return $this->get_font_height($font, $size) / $ratio;
- }
-
- /**
- * Starts a new page
- *
- * Subsequent drawing operations will appear on the new page.
- */
- function new_page() {
- $this->_page_number++;
- $this->_page_count++;
- }
-
- function open_object(){
- // N/A
- }
-
- function close_object(){
- // N/A
- }
-
- function add_object(){
- // N/A
- }
-
- function page_text(){
- // N/A
- }
-
- /**
- * Streams the image directly to the browser
- *
- * @param string $filename the name of the image file (ignored)
- * @param array $options associative array, 'type' => jpeg|jpg|png, 'quality' => 0 - 100 (jpeg only)
- */
- function stream($filename, $options = null) {
-
- // Perform any antialiasing
- if ( $this->_aa_factor != 1 ) {
- $dst_w = $this->_width / $this->_aa_factor;
- $dst_h = $this->_height / $this->_aa_factor;
- $dst = imagecreatetruecolor($dst_w, $dst_h);
- imagecopyresampled($dst, $this->_img, 0, 0, 0, 0,
- $dst_w, $dst_h,
- $this->_width, $this->_height);
- } else {
- $dst = $this->_img;
- }
-
- if ( !isset($options["type"]) )
- $options["type"] = "png";
-
- $type = strtolower($options["type"]);
-
- header("Cache-Control: private");
-
- switch ($type) {
-
- case "jpg":
- case "jpeg":
- if ( !isset($options["quality"]) )
- $options["quality"] = 75;
-
- header("Content-type: image/jpeg");
- imagejpeg($dst, '', $options["quality"]);
- break;
-
- case "png":
- default:
- header("Content-type: image/png");
- imagepng($dst);
- break;
- }
-
- if ( $this->_aa_factor != 1 )
- imagedestroy($dst);
- }
-
- /**
- * Returns the PNG as a string
- *
- * @param array $options associative array, 'type' => jpeg|jpg|png, 'quality' => 0 - 100 (jpeg only)
- * @return string
- */
- function output($options = null) {
-
- if ( $this->_aa_factor != 1 ) {
- $dst_w = $this->_width / $this->_aa_factor;
- $dst_h = $this->_height / $this->_aa_factor;
- $dst = imagecreatetruecolor($dst_w, $dst_h);
- imagecopyresampled($dst, $this->_img, 0, 0, 0, 0,
- $dst_w, $dst_h,
- $this->_width, $this->_height);
- } else {
- $dst = $this->_img;
- }
-
- if ( !isset($options["type"]) )
- $options["type"] = "png";
-
- $type = $options["type"];
-
- ob_start();
-
- switch ($type) {
-
- case "jpg":
- case "jpeg":
- if ( !isset($options["quality"]) )
- $options["quality"] = 75;
-
- imagejpeg($dst, '', $options["quality"]);
- break;
-
- case "png":
- default:
- imagepng($dst);
- break;
- }
-
- $image = ob_get_clean();
-
- if ( $this->_aa_factor != 1 )
- imagedestroy($dst);
-
- return $image;
- }
-
-
-}
diff --git a/library/vendor/dompdf/include/image_cache.cls.php b/library/vendor/dompdf/include/image_cache.cls.php
deleted file mode 100644
index e7175c4dc..000000000
--- a/library/vendor/dompdf/include/image_cache.cls.php
+++ /dev/null
@@ -1,185 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Static class that resolves image urls and downloads and caches
- * remote images if required.
- *
- * @access private
- * @package dompdf
- */
-class Image_Cache {
-
- /**
- * Array of downloaded images. Cached so that identical images are
- * not needlessly downloaded.
- *
- * @var array
- */
- static protected $_cache = array();
-
- /**
- * The url to the "broken image" used when images can't be loade
- *
- * @var string
- */
- public static $broken_image;
-
- /**
- * Resolve and fetch an image for use.
- *
- * @param string $url The url of the image
- * @param string $protocol Default protocol if none specified in $url
- * @param string $host Default host if none specified in $url
- * @param string $base_path Default path if none specified in $url
- * @param DOMPDF $dompdf The DOMPDF instance
- *
- * @throws DOMPDF_Image_Exception
- * @return array An array with two elements: The local path to the image and the image extension
- */
- static function resolve_url($url, $protocol, $host, $base_path, DOMPDF $dompdf) {
- $protocol = mb_strtolower($protocol);
- $parsed_url = explode_url($url);
- $message = null;
-
- $remote = ($protocol && $protocol !== "file://") || ($parsed_url['protocol'] != "");
-
- $data_uri = strpos($parsed_url['protocol'], "data:") === 0;
- $full_url = null;
- $enable_remote = $dompdf->get_option("enable_remote");
-
- try {
-
- // Remote not allowed and is not DataURI
- if ( !$enable_remote && $remote && !$data_uri ) {
- throw new DOMPDF_Image_Exception("DOMPDF_ENABLE_REMOTE is set to FALSE");
- }
-
- // Remote allowed or DataURI
- else if ( $enable_remote && $remote || $data_uri ) {
- // Download remote files to a temporary directory
- $full_url = build_url($protocol, $host, $base_path, $url);
-
- // From cache
- if ( isset(self::$_cache[$full_url]) ) {
- $resolved_url = self::$_cache[$full_url];
- }
-
- // From remote
- else {
- $tmp_dir = $dompdf->get_option("temp_dir");
- $resolved_url = tempnam($tmp_dir, "ca_dompdf_img_");
- $image = "";
-
- if ($data_uri) {
- if ($parsed_data_uri = parse_data_uri($url)) {
- $image = $parsed_data_uri['data'];
- }
- }
- else {
- set_error_handler("record_warnings");
- $image = file_get_contents($full_url, null, $dompdf->get_http_context());
- restore_error_handler();
- }
-
- // Image not found or invalid
- if ( strlen($image) == 0 ) {
- $msg = ($data_uri ? "Data-URI could not be parsed" : "Image not found");
- throw new DOMPDF_Image_Exception($msg);
- }
-
- // Image found, put in cache and process
- else {
- //e.g. fetch.php?media=url.jpg&cache=1
- //- Image file name might be one of the dynamic parts of the url, don't strip off!
- //- a remote url does not need to have a file extension at all
- //- local cached file does not have a matching file extension
- //Therefore get image type from the content
- file_put_contents($resolved_url, $image);
- }
- }
- }
-
- // Not remote, local image
- else {
- $resolved_url = build_url($protocol, $host, $base_path, $url);
- }
-
- // Check if the local file is readable
- if ( !is_readable($resolved_url) || !filesize($resolved_url) ) {
- throw new DOMPDF_Image_Exception("Image not readable or empty");
- }
-
- // Check is the file is an image
- else {
- list($width, $height, $type) = dompdf_getimagesize($resolved_url, $dompdf->get_http_context());
-
- // Known image type
- if ( $width && $height && in_array($type, array(IMAGETYPE_GIF, IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_BMP)) ) {
- //Don't put replacement image into cache - otherwise it will be deleted on cache cleanup.
- //Only execute on successful caching of remote image.
- if ( $enable_remote && $remote || $data_uri ) {
- self::$_cache[$full_url] = $resolved_url;
- }
- }
-
- // Unknown image type
- else {
- throw new DOMPDF_Image_Exception("Image type unknown");
- }
- }
- }
- catch(DOMPDF_Image_Exception $e) {
- $resolved_url = self::$broken_image;
- $type = IMAGETYPE_PNG;
- $message = "Image not found or type unknown";
- $_dompdf_warnings[] = $e->getMessage()." :: $url";
- }
-
- return array($resolved_url, $type, $message);
- }
-
- /**
- * Unlink all cached images (i.e. temporary images either downloaded
- * or converted)
- */
- static function clear() {
- if ( empty(self::$_cache) || DEBUGKEEPTEMP ) return;
-
- foreach ( self::$_cache as $file ) {
- if (DEBUGPNG) print "[clear unlink $file]";
- unlink($file);
- }
-
- self::$_cache = array();
- }
-
- static function detect_type($file, $context = null) {
- list(, , $type) = dompdf_getimagesize($file, $context);
- return $type;
- }
-
- static function type_to_ext($type) {
- $image_types = array(
- IMAGETYPE_GIF => "gif",
- IMAGETYPE_PNG => "png",
- IMAGETYPE_JPEG => "jpeg",
- IMAGETYPE_BMP => "bmp",
- );
-
- return (isset($image_types[$type]) ? $image_types[$type] : null);
- }
-
- static function is_broken($url) {
- return $url === self::$broken_image;
- }
-}
-
-Image_Cache::$broken_image = DOMPDF_LIB_DIR . "/res/broken_image.png";
diff --git a/library/vendor/dompdf/include/image_frame_decorator.cls.php b/library/vendor/dompdf/include/image_frame_decorator.cls.php
deleted file mode 100644
index b5a7983aa..000000000
--- a/library/vendor/dompdf/include/image_frame_decorator.cls.php
+++ /dev/null
@@ -1,80 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Decorates frames for image layout and rendering
- *
- * @access private
- * @package dompdf
- */
-class Image_Frame_Decorator extends Frame_Decorator {
-
- /**
- * The path to the image file (note that remote images are
- * downloaded locally to DOMPDF_TEMP_DIR).
- *
- * @var string
- */
- protected $_image_url;
-
- /**
- * The image's file error message
- *
- * @var string
- */
- protected $_image_msg;
-
- /**
- * Class constructor
- *
- * @param Frame $frame the frame to decorate
- * @param DOMPDF $dompdf the document's dompdf object (required to resolve relative & remote urls)
- */
- function __construct(Frame $frame, DOMPDF $dompdf) {
- parent::__construct($frame, $dompdf);
- $url = $frame->get_node()->getAttribute("src");
-
- $debug_png = $dompdf->get_option("debug_png");
- if ($debug_png) print '[__construct '.$url.']';
-
- list($this->_image_url, /*$type*/, $this->_image_msg) = Image_Cache::resolve_url(
- $url,
- $dompdf->get_protocol(),
- $dompdf->get_host(),
- $dompdf->get_base_path(),
- $dompdf
- );
-
- if ( Image_Cache::is_broken($this->_image_url) &&
- $alt = $frame->get_node()->getAttribute("alt") ) {
- $style = $frame->get_style();
- $style->width = (4/3)*Font_Metrics::get_text_width($alt, $style->font_family, $style->font_size, $style->word_spacing);
- $style->height = Font_Metrics::get_font_height($style->font_family, $style->font_size);
- }
- }
-
- /**
- * Return the image's url
- *
- * @return string The url of this image
- */
- function get_image_url() {
- return $this->_image_url;
- }
-
- /**
- * Return the image's error message
- *
- * @return string The image's error message
- */
- function get_image_msg() {
- return $this->_image_msg;
- }
-
-}
diff --git a/library/vendor/dompdf/include/image_frame_reflower.cls.php b/library/vendor/dompdf/include/image_frame_reflower.cls.php
deleted file mode 100644
index c938bd075..000000000
--- a/library/vendor/dompdf/include/image_frame_reflower.cls.php
+++ /dev/null
@@ -1,186 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Image reflower class
- *
- * @access private
- * @package dompdf
- */
-class Image_Frame_Reflower extends Frame_Reflower {
-
- function __construct(Image_Frame_Decorator $frame) {
- parent::__construct($frame);
- }
-
- function reflow(Block_Frame_Decorator $block = null) {
- $this->_frame->position();
-
- //FLOAT
- //$frame = $this->_frame;
- //$page = $frame->get_root();
-
- //$enable_css_float = $this->get_dompdf()->get_option("enable_css_float");
- //if ($enable_css_float && $frame->get_style()->float !== "none" ) {
- // $page->add_floating_frame($this);
- //}
- // Set the frame's width
- $this->get_min_max_width();
-
- if ( $block ) {
- $block->add_frame_to_line($this->_frame);
- }
- }
-
- function get_min_max_width() {
- if (DEBUGPNG) {
- // Determine the image's size. Time consuming. Only when really needed?
- list($img_width, $img_height) = dompdf_getimagesize($this->_frame->get_image_url(), $this->get_dompdf()->get_http_context());
- print "get_min_max_width() ".
- $this->_frame->get_style()->width.' '.
- $this->_frame->get_style()->height.';'.
- $this->_frame->get_parent()->get_style()->width." ".
- $this->_frame->get_parent()->get_style()->height.";".
- $this->_frame->get_parent()->get_parent()->get_style()->width.' '.
- $this->_frame->get_parent()->get_parent()->get_style()->height.';'.
- $img_width. ' '.
- $img_height.'|' ;
- }
-
- $style = $this->_frame->get_style();
-
- $width_forced = true;
- $height_forced = true;
-
- //own style auto or invalid value: use natural size in px
- //own style value: ignore suffix text including unit, use given number as px
- //own style %: walk up parent chain until found available space in pt; fill available space
- //
- //special ignored unit: e.g. 10ex: e treated as exponent; x ignored; 10e completely invalid ->like auto
-
- $width = ($style->width > 0 ? $style->width : 0);
- if ( is_percent($width) ) {
- $t = 0.0;
- for ($f = $this->_frame->get_parent(); $f; $f = $f->get_parent()) {
- $f_style = $f->get_style();
- $t = $f_style->length_in_pt($f_style->width);
- if ($t != 0) {
- break;
- }
- }
- $width = ((float)rtrim($width,"%") * $t)/100; //maybe 0
- } elseif ( !mb_strpos($width, 'pt') ) {
- // Don't set image original size if "%" branch was 0 or size not given.
- // Otherwise aspect changed on %/auto combination for width/height
- // Resample according to px per inch
- // See also List_Bullet_Image_Frame_Decorator::__construct
- $width = $style->length_in_pt($width);
- }
-
- $height = ($style->height > 0 ? $style->height : 0);
- if ( is_percent($height) ) {
- $t = 0.0;
- for ($f = $this->_frame->get_parent(); $f; $f = $f->get_parent()) {
- $f_style = $f->get_style();
- $t = $f_style->length_in_pt($f_style->height);
- if ($t != 0) {
- break;
- }
- }
- $height = ((float)rtrim($height,"%") * $t)/100; //maybe 0
- } elseif ( !mb_strpos($height, 'pt') ) {
- // Don't set image original size if "%" branch was 0 or size not given.
- // Otherwise aspect changed on %/auto combination for width/height
- // Resample according to px per inch
- // See also List_Bullet_Image_Frame_Decorator::__construct
- $height = $style->length_in_pt($height);
- }
-
- if ($width == 0 || $height == 0) {
- // Determine the image's size. Time consuming. Only when really needed!
- list($img_width, $img_height) = dompdf_getimagesize($this->_frame->get_image_url(), $this->get_dompdf()->get_http_context());
-
- // don't treat 0 as error. Can be downscaled or can be catched elsewhere if image not readable.
- // Resample according to px per inch
- // See also List_Bullet_Image_Frame_Decorator::__construct
- if ($width == 0 && $height == 0) {
- $dpi = $this->_frame->get_dompdf()->get_option("dpi");
- $width = (float)($img_width * 72) / $dpi;
- $height = (float)($img_height * 72) / $dpi;
- $width_forced = false;
- $height_forced = false;
- } elseif ($height == 0 && $width != 0) {
- $height_forced = false;
- $height = ($width / $img_width) * $img_height; //keep aspect ratio
- } elseif ($width == 0 && $height != 0) {
- $width_forced = false;
- $width = ($height / $img_height) * $img_width; //keep aspect ratio
- }
- }
-
- // Handle min/max width/height
- if ( $style->min_width !== "none" ||
- $style->max_width !== "none" ||
- $style->min_height !== "none" ||
- $style->max_height !== "none" ) {
-
- list(/*$x*/, /*$y*/, $w, $h) = $this->_frame->get_containing_block();
-
- $min_width = $style->length_in_pt($style->min_width, $w);
- $max_width = $style->length_in_pt($style->max_width, $w);
- $min_height = $style->length_in_pt($style->min_height, $h);
- $max_height = $style->length_in_pt($style->max_height, $h);
-
- if ( $max_width !== "none" && $width > $max_width ) {
- if ( !$height_forced ) {
- $height *= $max_width / $width;
- }
-
- $width = $max_width;
- }
-
- if ( $min_width !== "none" && $width < $min_width ) {
- if ( !$height_forced ) {
- $height *= $min_width / $width;
- }
-
- $width = $min_width;
- }
-
- if ( $max_height !== "none" && $height > $max_height ) {
- if ( !$width_forced ) {
- $width *= $max_height / $height;
- }
-
- $height = $max_height;
- }
-
- if ( $min_height !== "none" && $height < $min_height ) {
- if ( !$width_forced ) {
- $width *= $min_height / $height;
- }
-
- $height = $min_height;
- }
- }
-
- if (DEBUGPNG) print $width.' '.$height.';';
-
- $style->width = $width . "pt";
- $style->height = $height . "pt";
-
- $style->min_width = "none";
- $style->max_width = "none";
- $style->min_height = "none";
- $style->max_height = "none";
-
- return array( $width, $width, "min" => $width, "max" => $width);
-
- }
-}
diff --git a/library/vendor/dompdf/include/image_renderer.cls.php b/library/vendor/dompdf/include/image_renderer.cls.php
deleted file mode 100644
index 561b70153..000000000
--- a/library/vendor/dompdf/include/image_renderer.cls.php
+++ /dev/null
@@ -1,119 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Image renderer
- *
- * @access private
- * @package dompdf
- */
-class Image_Renderer extends Block_Renderer {
-
- function render(Frame $frame) {
- // Render background & borders
- $style = $frame->get_style();
- $cb = $frame->get_containing_block();
- list($x, $y, $w, $h) = $frame->get_border_box();
-
- $this->_set_opacity( $frame->get_opacity( $style->opacity ) );
-
- list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
-
- $has_border_radius = $tl + $tr + $br + $bl > 0;
-
- if ( $has_border_radius ) {
- $this->_canvas->clipping_roundrectangle( $x, $y, $w, $h, $tl, $tr, $br, $bl );
- }
-
- if ( ($bg = $style->background_color) !== "transparent" ) {
- $this->_canvas->filled_rectangle($x, $y, $w, $h, $bg);
- }
-
- if ( ($url = $style->background_image) && $url !== "none" ) {
- $this->_background_image($url, $x, $y, $w, $h, $style);
- }
-
- if ( $has_border_radius ) {
- $this->_canvas->clipping_end();
- }
-
- $this->_render_border($frame);
- $this->_render_outline($frame);
-
- list($x, $y) = $frame->get_padding_box();
-
- $x += $style->length_in_pt($style->padding_left, $cb["w"]);
- $y += $style->length_in_pt($style->padding_top, $cb["h"]);
-
- $w = $style->length_in_pt($style->width, $cb["w"]);
- $h = $style->length_in_pt($style->height, $cb["h"]);
-
- if ( $has_border_radius ) {
- list($wt, $wr, $wb, $wl) = array(
- $style->border_top_width,
- $style->border_right_width,
- $style->border_bottom_width,
- $style->border_left_width,
- );
-
- // we have to get the "inner" radius
- if ( $tl > 0 ) {
- $tl -= ($wt + $wl) / 2;
- }
- if ( $tr > 0 ) {
- $tr -= ($wt + $wr) / 2;
- }
- if ( $br > 0 ) {
- $br -= ($wb + $wr) / 2;
- }
- if ( $bl > 0 ) {
- $bl -= ($wb + $wl) / 2;
- }
-
- $this->_canvas->clipping_roundrectangle( $x, $y, $w, $h, $tl, $tr, $br, $bl );
- }
-
- $src = $frame->get_image_url();
- $alt = null;
-
- if ( Image_Cache::is_broken($src) &&
- $alt = $frame->get_node()->getAttribute("alt") ) {
- $font = $style->font_family;
- $size = $style->font_size;
- $spacing = $style->word_spacing;
- $this->_canvas->text($x, $y, $alt,
- $font, $size,
- $style->color, $spacing);
- }
- else {
- $this->_canvas->image( $src, $x, $y, $w, $h, $style->image_resolution);
- }
-
- if ( $has_border_radius ) {
- $this->_canvas->clipping_end();
- }
-
- if ( $msg = $frame->get_image_msg() ) {
- $parts = preg_split("/\s*\n\s*/", $msg);
- $height = 10;
- $_y = $alt ? $y+$h-count($parts)*$height : $y;
-
- foreach($parts as $i => $_part) {
- $this->_canvas->text($x, $_y + $i*$height, $_part, "times", $height*0.8, array(0.5, 0.5, 0.5));
- }
- }
-
- if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
- $this->_debug_layout($frame->get_border_box(), "blue");
- if (DEBUG_LAYOUT_PADDINGBOX) {
- $this->_debug_layout($frame->get_padding_box(), "blue", array(0.5, 0.5));
- }
- }
- }
-}
diff --git a/library/vendor/dompdf/include/inline_frame_decorator.cls.php b/library/vendor/dompdf/include/inline_frame_decorator.cls.php
deleted file mode 100644
index ce79bab08..000000000
--- a/library/vendor/dompdf/include/inline_frame_decorator.cls.php
+++ /dev/null
@@ -1,74 +0,0 @@
-
- * @author Helmut Tischer
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Decorates frames for inline layout
- *
- * @access private
- * @package dompdf
- */
-class Inline_Frame_Decorator extends Frame_Decorator {
-
- function __construct(Frame $frame, DOMPDF $dompdf) { parent::__construct($frame, $dompdf); }
-
- function split(Frame $frame = null, $force_pagebreak = false) {
-
- if ( is_null($frame) ) {
- $this->get_parent()->split($this, $force_pagebreak);
- return;
- }
-
- if ( $frame->get_parent() !== $this )
- throw new DOMPDF_Exception("Unable to split: frame is not a child of this one.");
-
- $split = $this->copy( $this->_frame->get_node()->cloneNode() );
- $this->get_parent()->insert_child_after($split, $this);
-
- // Unset the current node's right style properties
- $style = $this->_frame->get_style();
- $style->margin_right = 0;
- $style->padding_right = 0;
- $style->border_right_width = 0;
-
- // Unset the split node's left style properties since we don't want them
- // to propagate
- $style = $split->get_style();
- $style->margin_left = 0;
- $style->padding_left = 0;
- $style->border_left_width = 0;
-
- //On continuation of inline element on next line,
- //don't repeat non-vertically repeatble background images
- //See e.g. in testcase image_variants, long desriptions
- if ( ($url = $style->background_image) && $url !== "none"
- && ($repeat = $style->background_repeat) && $repeat !== "repeat" && $repeat !== "repeat-y"
- ) {
- $style->background_image = "none";
- }
-
- // Add $frame and all following siblings to the new split node
- $iter = $frame;
- while ($iter) {
- $frame = $iter;
- $iter = $iter->get_next_sibling();
- $frame->reset();
- $split->append_child($frame);
- }
-
- $page_breaks = array("always", "left", "right");
- $frame_style = $frame->get_style();
- if( $force_pagebreak ||
- in_array($frame_style->page_break_before, $page_breaks) ||
- in_array($frame_style->page_break_after, $page_breaks) ) {
-
- $this->get_parent()->split($split, true);
- }
- }
-
-}
diff --git a/library/vendor/dompdf/include/inline_frame_reflower.cls.php b/library/vendor/dompdf/include/inline_frame_reflower.cls.php
deleted file mode 100644
index 049b8e586..000000000
--- a/library/vendor/dompdf/include/inline_frame_reflower.cls.php
+++ /dev/null
@@ -1,66 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Reflows inline frames
- *
- * @access private
- * @package dompdf
- */
-class Inline_Frame_Reflower extends Frame_Reflower {
-
- function __construct(Frame $frame) { parent::__construct($frame); }
-
- //........................................................................
-
- function reflow(Block_Frame_Decorator $block = null) {
- $frame = $this->_frame;
-
- // Check if a page break is forced
- $page = $frame->get_root();
- $page->check_forced_page_break($frame);
-
- if ( $page->is_full() )
- return;
-
- $style = $frame->get_style();
-
- // Generated content
- $this->_set_content();
-
- $frame->position();
-
- $cb = $frame->get_containing_block();
-
- // Add our margin, padding & border to the first and last children
- if ( ($f = $frame->get_first_child()) && $f instanceof Text_Frame_Decorator ) {
- $f_style = $f->get_style();
- $f_style->margin_left = $style->margin_left;
- $f_style->padding_left = $style->padding_left;
- $f_style->border_left = $style->border_left;
- }
-
- if ( ($l = $frame->get_last_child()) && $l instanceof Text_Frame_Decorator ) {
- $l_style = $l->get_style();
- $l_style->margin_right = $style->margin_right;
- $l_style->padding_right = $style->padding_right;
- $l_style->border_right = $style->border_right;
- }
-
- if ( $block ) {
- $block->add_frame_to_line($this->_frame);
- }
-
- // Set the containing blocks and reflow each child. The containing
- // block is not changed by line boxes.
- foreach ( $frame->get_children() as $child ) {
- $child->set_containing_block($cb);
- $child->reflow($block);
- }
- }
-}
diff --git a/library/vendor/dompdf/include/inline_positioner.cls.php b/library/vendor/dompdf/include/inline_positioner.cls.php
deleted file mode 100644
index 1694ce8e2..000000000
--- a/library/vendor/dompdf/include/inline_positioner.cls.php
+++ /dev/null
@@ -1,70 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Positions inline frames
- *
- * @access private
- * @package dompdf
- */
-class Inline_Positioner extends Positioner {
-
- function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
-
- //........................................................................
-
- function position() {
- /**
- * Find our nearest block level parent and access its lines property.
- * @var Block_Frame_Decorator
- */
- $p = $this->_frame->find_block_parent();
-
- // Debugging code:
-
-// pre_r("\nPositioning:");
-// pre_r("Me: " . $this->_frame->get_node()->nodeName . " (" . spl_object_hash($this->_frame->get_node()) . ")");
-// pre_r("Parent: " . $p->get_node()->nodeName . " (" . spl_object_hash($p->get_node()) . ")");
-
- // End debugging
-
- if ( !$p )
- throw new DOMPDF_Exception("No block-level parent found. Not good.");
-
- $f = $this->_frame;
-
- $cb = $f->get_containing_block();
- $line = $p->get_current_line_box();
-
- // Skip the page break if in a fixed position element
- $is_fixed = false;
- while($f = $f->get_parent()) {
- if($f->get_style()->position === "fixed") {
- $is_fixed = true;
- break;
- }
- }
-
- $f = $this->_frame;
-
- if ( !$is_fixed && $f->get_parent() &&
- $f->get_parent() instanceof Inline_Frame_Decorator &&
- $f->is_text_node() ) {
-
- $min_max = $f->get_reflower()->get_min_max_width();
-
- // If the frame doesn't fit in the current line, a line break occurs
- if ( $min_max["min"] > ($cb["w"] - $line->left - $line->w - $line->right) ) {
- $p->add_line();
- }
- }
-
- $f->set_position($cb["x"] + $line->w, $line->y);
-
- }
-}
diff --git a/library/vendor/dompdf/include/inline_renderer.cls.php b/library/vendor/dompdf/include/inline_renderer.cls.php
deleted file mode 100644
index 7a8ff51c3..000000000
--- a/library/vendor/dompdf/include/inline_renderer.cls.php
+++ /dev/null
@@ -1,190 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Renders inline frames
- *
- * @access private
- * @package dompdf
- */
-class Inline_Renderer extends Abstract_Renderer {
-
- //........................................................................
-
- function render(Frame $frame) {
- $style = $frame->get_style();
-
- if ( !$frame->get_first_child() )
- return; // No children, no service
-
- // Draw the left border if applicable
- $bp = $style->get_border_properties();
- $widths = array($style->length_in_pt($bp["top"]["width"]),
- $style->length_in_pt($bp["right"]["width"]),
- $style->length_in_pt($bp["bottom"]["width"]),
- $style->length_in_pt($bp["left"]["width"]));
-
- // Draw the background & border behind each child. To do this we need
- // to figure out just how much space each child takes:
- list($x, $y) = $frame->get_first_child()->get_position();
- $w = null;
- $h = 0;
-// $x += $widths[3];
-// $y += $widths[0];
-
- $this->_set_opacity( $frame->get_opacity( $style->opacity ) );
-
- $first_row = true;
-
- foreach ($frame->get_children() as $child) {
- list($child_x, $child_y, $child_w, $child_h) = $child->get_padding_box();
-
- if ( !is_null($w) && $child_x < $x + $w ) {
- //This branch seems to be supposed to being called on the first part
- //of an inline html element, and the part after the if clause for the
- //parts after a line break.
- //But because $w initially mostly is 0, and gets updated only on the next
- //round, this seem to be never executed and the common close always.
-
- // The next child is on another line. Draw the background &
- // borders on this line.
-
- // Background:
- if ( ($bg = $style->background_color) !== "transparent" )
- $this->_canvas->filled_rectangle( $x, $y, $w, $h, $bg);
-
- if ( ($url = $style->background_image) && $url !== "none" ) {
- $this->_background_image($url, $x, $y, $w, $h, $style);
- }
-
- // If this is the first row, draw the left border
- if ( $first_row ) {
-
- if ( $bp["left"]["style"] !== "none" && $bp["left"]["color"] !== "transparent" && $bp["left"]["width"] > 0 ) {
- $method = "_border_" . $bp["left"]["style"];
- $this->$method($x, $y, $h + $widths[0] + $widths[2], $bp["left"]["color"], $widths, "left");
- }
- $first_row = false;
- }
-
- // Draw the top & bottom borders
- if ( $bp["top"]["style"] !== "none" && $bp["top"]["color"] !== "transparent" && $bp["top"]["width"] > 0 ) {
- $method = "_border_" . $bp["top"]["style"];
- $this->$method($x, $y, $w + $widths[1] + $widths[3], $bp["top"]["color"], $widths, "top");
- }
-
- if ( $bp["bottom"]["style"] !== "none" && $bp["bottom"]["color"] !== "transparent" && $bp["bottom"]["width"] > 0 ) {
- $method = "_border_" . $bp["bottom"]["style"];
- $this->$method($x, $y + $h + $widths[0] + $widths[2], $w + $widths[1] + $widths[3], $bp["bottom"]["color"], $widths, "bottom");
- }
-
- // Handle anchors & links
- $link_node = null;
- if ( $frame->get_node()->nodeName === "a" ) {
- $link_node = $frame->get_node();
- }
- else if ( $frame->get_parent()->get_node()->nodeName === "a" ){
- $link_node = $frame->get_parent()->get_node();
- }
-
- if ( $link_node && $href = $link_node->getAttribute("href") ) {
- $this->_canvas->add_link($href, $x, $y, $w, $h);
- }
-
- $x = $child_x;
- $y = $child_y;
- $w = $child_w;
- $h = $child_h;
- continue;
- }
-
- if ( is_null($w) )
- $w = $child_w;
- else
- $w += $child_w;
-
- $h = max($h, $child_h);
-
- if (DEBUG_LAYOUT && DEBUG_LAYOUT_INLINE) {
- $this->_debug_layout($child->get_border_box(), "blue");
- if (DEBUG_LAYOUT_PADDINGBOX) {
- $this->_debug_layout($child->get_padding_box(), "blue", array(0.5, 0.5));
- }
- }
- }
-
-
- // Handle the last child
- if ( ($bg = $style->background_color) !== "transparent" )
- $this->_canvas->filled_rectangle( $x + $widths[3], $y + $widths[0], $w, $h, $bg);
-
- //On continuation lines (after line break) of inline elements, the style got copied.
- //But a non repeatable background image should not be repeated on the next line.
- //But removing the background image above has never an effect, and removing it below
- //removes it always, even on the initial line.
- //Need to handle it elsewhere, e.g. on certain ...clone()... usages.
- // Repeat not given: default is Style::__construct
- // ... && (!($repeat = $style->background_repeat) || $repeat === "repeat" ...
- //different position? $this->_background_image($url, $x, $y, $w, $h, $style);
- if ( ($url = $style->background_image) && $url !== "none" )
- $this->_background_image($url, $x + $widths[3], $y + $widths[0], $w, $h, $style);
-
- // Add the border widths
- $w += $widths[1] + $widths[3];
- $h += $widths[0] + $widths[2];
-
- // make sure the border and background start inside the left margin
- $left_margin = $style->length_in_pt($style->margin_left);
- $x += $left_margin;
-
- // If this is the first row, draw the left border too
- if ( $first_row && $bp["left"]["style"] !== "none" && $bp["left"]["color"] !== "transparent" && $widths[3] > 0 ) {
- $method = "_border_" . $bp["left"]["style"];
- $this->$method($x, $y, $h, $bp["left"]["color"], $widths, "left");
- }
-
- // Draw the top & bottom borders
- if ( $bp["top"]["style"] !== "none" && $bp["top"]["color"] !== "transparent" && $widths[0] > 0 ) {
- $method = "_border_" . $bp["top"]["style"];
- $this->$method($x, $y, $w, $bp["top"]["color"], $widths, "top");
- }
-
- if ( $bp["bottom"]["style"] !== "none" && $bp["bottom"]["color"] !== "transparent" && $widths[2] > 0 ) {
- $method = "_border_" . $bp["bottom"]["style"];
- $this->$method($x, $y + $h, $w, $bp["bottom"]["color"], $widths, "bottom");
- }
-
- // pre_var_dump(get_class($frame->get_next_sibling()));
- // $last_row = get_class($frame->get_next_sibling()) !== 'Inline_Frame_Decorator';
- // Draw the right border if this is the last row
- if ( $bp["right"]["style"] !== "none" && $bp["right"]["color"] !== "transparent" && $widths[1] > 0 ) {
- $method = "_border_" . $bp["right"]["style"];
- $this->$method($x + $w, $y, $h, $bp["right"]["color"], $widths, "right");
- }
-
- // Only two levels of links frames
- $link_node = null;
- if ( $frame->get_node()->nodeName === "a" ) {
- $link_node = $frame->get_node();
-
- if ( ($name = $link_node->getAttribute("name")) || ($name = $link_node->getAttribute("id")) ) {
- $this->_canvas->add_named_dest($name);
- }
- }
-
- if ( $frame->get_parent() && $frame->get_parent()->get_node()->nodeName === "a" ){
- $link_node = $frame->get_parent()->get_node();
- }
-
- // Handle anchors & links
- if ( $link_node ) {
- if ( $href = $link_node->getAttribute("href") )
- $this->_canvas->add_link($href, $x, $y, $w, $h);
- }
- }
-}
diff --git a/library/vendor/dompdf/include/javascript_embedder.cls.php b/library/vendor/dompdf/include/javascript_embedder.cls.php
deleted file mode 100644
index 92c244b2d..000000000
--- a/library/vendor/dompdf/include/javascript_embedder.cls.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Embeds Javascript into the PDF document
- *
- * @access private
- * @package dompdf
- */
-class Javascript_Embedder {
-
- /**
- * @var DOMPDF
- */
- protected $_dompdf;
-
- function __construct(DOMPDF $dompdf) {
- $this->_dompdf = $dompdf;
- }
-
- function insert($script) {
- $this->_dompdf->get_canvas()->javascript($script);
- }
-
- function render(Frame $frame) {
- if ( !$this->_dompdf->get_option("enable_javascript") ) {
- return;
- }
-
- $this->insert($frame->get_node()->nodeValue);
- }
-}
diff --git a/library/vendor/dompdf/include/line_box.cls.php b/library/vendor/dompdf/include/line_box.cls.php
deleted file mode 100644
index 352359729..000000000
--- a/library/vendor/dompdf/include/line_box.cls.php
+++ /dev/null
@@ -1,252 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * The line box class
- *
- * This class represents a line box
- * http://www.w3.org/TR/CSS2/visuren.html#line-box
- *
- * @access protected
- * @package dompdf
- */
-class Line_Box {
-
- /**
- * @var Block_Frame_Decorator
- */
- protected $_block_frame;
-
- /**
- * @var Frame[]
- */
- protected $_frames = array();
-
- /**
- * @var integer
- */
- public $wc = 0;
-
- /**
- * @var float
- */
- public $y = null;
-
- /**
- * @var float
- */
- public $w = 0.0;
-
- /**
- * @var float
- */
- public $h = 0.0;
-
- /**
- * @var float
- */
- public $left = 0.0;
-
- /**
- * @var float
- */
- public $right = 0.0;
-
- /**
- * @var Frame
- */
- public $tallest_frame = null;
-
- /**
- * @var bool[]
- */
- public $floating_blocks = array();
-
- /**
- * @var bool
- */
- public $br = false;
-
- /**
- * Class constructor
- *
- * @param Block_Frame_Decorator $frame the Block_Frame_Decorator containing this line
- */
- function __construct(Block_Frame_Decorator $frame, $y = 0) {
- $this->_block_frame = $frame;
- $this->_frames = array();
- $this->y = $y;
-
- $this->get_float_offsets();
- }
-
- /**
- * Returns the floating elements inside the first floating parent
- *
- * @param Page_Frame_Decorator $root
- *
- * @return Frame[]
- */
- function get_floats_inside(Page_Frame_Decorator $root) {
- $floating_frames = $root->get_floating_frames();
-
- if ( count($floating_frames) == 0 ) {
- return $floating_frames;
- }
-
- // Find nearest floating element
- $p = $this->_block_frame;
- while( $p->get_style()->float === "none" ) {
- $parent = $p->get_parent();
-
- if ( !$parent ) {
- break;
- }
-
- $p = $parent;
- }
-
- if ( $p == $root ) {
- return $floating_frames;
- }
-
- $parent = $p;
-
- $childs = array();
-
- foreach ($floating_frames as $_floating) {
- $p = $_floating->get_parent();
-
- while (($p = $p->get_parent()) && $p !== $parent);
-
- if ( $p ) {
- $childs[] = $p;
- }
- }
-
- return $childs;
- }
-
- function get_float_offsets() {
- $enable_css_float = $this->_block_frame->get_dompdf()->get_option("enable_css_float");
- if ( !$enable_css_float ) {
- return;
- }
-
- static $anti_infinite_loop = 500; // FIXME smelly hack
-
- $reflower = $this->_block_frame->get_reflower();
-
- if ( !$reflower ) {
- return;
- }
-
- $cb_w = null;
-
- $block = $this->_block_frame;
- $root = $block->get_root();
-
- if ( !$root ) {
- return;
- }
-
- $floating_frames = $this->get_floats_inside($root);
-
- foreach ( $floating_frames as $child_key => $floating_frame ) {
- $id = $floating_frame->get_id();
-
- if ( isset($this->floating_blocks[$id]) ) {
- continue;
- }
-
- $floating_style = $floating_frame->get_style();
- $float = $floating_style->float;
-
- $floating_width = $floating_frame->get_margin_width();
-
- if (!$cb_w) {
- $cb_w = $floating_frame->get_containing_block("w");
- }
-
- $line_w = $this->get_width();
-
- if ( !$floating_frame->_float_next_line && ($cb_w <= $line_w + $floating_width) && ($cb_w > $line_w) ) {
- $floating_frame->_float_next_line = true;
- continue;
- }
-
- // If the child is still shifted by the floating element
- if ( $anti_infinite_loop-- > 0 &&
- $floating_frame->get_position("y") + $floating_frame->get_margin_height() > $this->y &&
- $block->get_position("x") + $block->get_margin_width() > $floating_frame->get_position("x")
- ) {
- if ( $float === "left" )
- $this->left += $floating_width;
- else
- $this->right += $floating_width;
-
- $this->floating_blocks[$id] = true;
- }
-
- // else, the floating element won't shift anymore
- else {
- $root->remove_floating_frame($child_key);
- }
- }
- }
-
- /**
- * @return float
- */
- function get_width(){
- return $this->left + $this->w + $this->right;
- }
-
- /**
- * @return Block_Frame_Decorator
- */
- function get_block_frame() {
- return $this->_block_frame;
- }
-
- /**
- * @return Frame[]
- */
- function &get_frames() {
- return $this->_frames;
- }
-
- /**
- * @param Frame $frame
- */
- function add_frame(Frame $frame) {
- $this->_frames[] = $frame;
- }
-
- function __toString(){
- $props = array("wc", "y", "w", "h", "left", "right", "br");
- $s = "";
- foreach($props as $prop) {
- $s .= "$prop: ".$this->$prop."\n";
- }
- $s .= count($this->_frames)." frames\n";
- return $s;
- }
- /*function __get($prop) {
- if (!isset($this->{"_$prop"})) return;
- return $this->{"_$prop"};
- }*/
-}
-
-/*
-class LineBoxList implements Iterator {
- private $_p = 0;
- private $_lines = array();
-
-}
-*/
diff --git a/library/vendor/dompdf/include/list_bullet_frame_decorator.cls.php b/library/vendor/dompdf/include/list_bullet_frame_decorator.cls.php
deleted file mode 100644
index a661dc050..000000000
--- a/library/vendor/dompdf/include/list_bullet_frame_decorator.cls.php
+++ /dev/null
@@ -1,65 +0,0 @@
-
- * @author Helmut Tischer
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Decorates frames for list bullet rendering
- *
- * @access private
- * @package dompdf
- */
-class List_Bullet_Frame_Decorator extends Frame_Decorator {
-
- const BULLET_PADDING = 1; // Distance from bullet to text in pt
- // As fraction of font size (including descent). See also DECO_THICKNESS.
- const BULLET_THICKNESS = 0.04; // Thickness of bullet outline. Screen: 0.08, print: better less, e.g. 0.04
- const BULLET_DESCENT = 0.3; //descent of font below baseline. Todo: Guessed for now.
- const BULLET_SIZE = 0.35; // bullet diameter. For now 0.5 of font_size without descent.
-
- static $BULLET_TYPES = array("disc", "circle", "square");
-
- //........................................................................
-
- function __construct(Frame $frame, DOMPDF $dompdf) {
- parent::__construct($frame, $dompdf);
- }
-
- function get_margin_width() {
- $style = $this->_frame->get_style();
-
- // Small hack to prevent extra indenting of list text on list_style_position === "inside"
- // and on suppressed bullet
- if ( $style->list_style_position === "outside" ||
- $style->list_style_type === "none" ) {
- return 0;
- }
-
- return $style->get_font_size() * self::BULLET_SIZE + 2 * self::BULLET_PADDING;
- }
-
- //hits only on "inset" lists items, to increase height of box
- function get_margin_height() {
- $style = $this->_frame->get_style();
-
- if ( $style->list_style_type === "none" ) {
- return 0;
- }
-
- return $style->get_font_size() * self::BULLET_SIZE + 2 * self::BULLET_PADDING;
- }
-
- function get_width() {
- return $this->get_margin_height();
- }
-
- function get_height() {
- return $this->get_margin_height();
- }
-
- //........................................................................
-}
diff --git a/library/vendor/dompdf/include/list_bullet_frame_reflower.cls.php b/library/vendor/dompdf/include/list_bullet_frame_reflower.cls.php
deleted file mode 100644
index 283056f00..000000000
--- a/library/vendor/dompdf/include/list_bullet_frame_reflower.cls.php
+++ /dev/null
@@ -1,33 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Reflows list bullets
- *
- * @access private
- * @package dompdf
- */
-class List_Bullet_Frame_Reflower extends Frame_Reflower {
-
- function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
-
- //........................................................................
-
- function reflow(Block_Frame_Decorator $block = null) {
- $style = $this->_frame->get_style();
-
- $style->width = $this->_frame->get_width();
- $this->_frame->position();
-
- if ( $style->list_style_position === "inside" ) {
- $p = $this->_frame->find_block_parent();
- $p->add_frame_to_line($this->_frame);
- }
-
- }
-}
diff --git a/library/vendor/dompdf/include/list_bullet_image_frame_decorator.cls.php b/library/vendor/dompdf/include/list_bullet_image_frame_decorator.cls.php
deleted file mode 100644
index 6cfb546cb..000000000
--- a/library/vendor/dompdf/include/list_bullet_image_frame_decorator.cls.php
+++ /dev/null
@@ -1,143 +0,0 @@
-
- * @author Helmut Tischer
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Decorates frames for list bullets with custom images
- *
- * @access private
- * @package dompdf
- */
-class List_Bullet_Image_Frame_Decorator extends Frame_Decorator {
-
- /**
- * The underlying image frame
- *
- * @var Image_Frame_Decorator
- */
- protected $_img;
-
- /**
- * The image's width in pixels
- *
- * @var int
- */
- protected $_width;
-
- /**
- * The image's height in pixels
- *
- * @var int
- */
- protected $_height;
-
- /**
- * Class constructor
- *
- * @param Frame $frame the bullet frame to decorate
- * @param DOMPDF $dompdf the document's dompdf object
- */
- function __construct(Frame $frame, DOMPDF $dompdf) {
- $style = $frame->get_style();
- $url = $style->list_style_image;
- $frame->get_node()->setAttribute("src", $url);
- $this->_img = new Image_Frame_Decorator($frame, $dompdf);
- parent::__construct($this->_img, $dompdf);
- list($width, $height) = dompdf_getimagesize($this->_img->get_image_url(), $dompdf->get_http_context());
-
- // Resample the bullet image to be consistent with 'auto' sized images
- // See also Image_Frame_Reflower::get_min_max_width
- // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary.
- $dpi = $this->_dompdf->get_option("dpi");
- $this->_width = ((float)rtrim($width, "px") * 72) / $dpi;
- $this->_height = ((float)rtrim($height, "px") * 72) / $dpi;
-
- //If an image is taller as the containing block/box, the box should be extended.
- //Neighbour elements are overwriting the overlapping image areas.
- //Todo: Where can the box size be extended?
- //Code below has no effect.
- //See block_frame_reflower _calculate_restricted_height
- //See generated_frame_reflower, Dompdf:render() "list-item", "-dompdf-list-bullet"S.
- //Leave for now
- //if ($style->min_height < $this->_height ) {
- // $style->min_height = $this->_height;
- //}
- //$style->height = "auto";
- }
-
- /**
- * Return the bullet's width
- *
- * @return int
- */
- function get_width() {
- //ignore image width, use same width as on predefined bullet List_Bullet_Frame_Decorator
- //for proper alignment of bullet image and text. Allow image to not fitting on left border.
- //This controls the distance between bullet image and text
- //return $this->_width;
- return $this->_frame->get_style()->get_font_size()*List_Bullet_Frame_Decorator::BULLET_SIZE +
- 2 * List_Bullet_Frame_Decorator::BULLET_PADDING;
- }
-
- /**
- * Return the bullet's height
- *
- * @return int
- */
- function get_height() {
- //based on image height
- return $this->_height;
- }
-
- /**
- * Override get_margin_width
- *
- * @return int
- */
- function get_margin_width() {
- //ignore image width, use same width as on predefined bullet List_Bullet_Frame_Decorator
- //for proper alignment of bullet image and text. Allow image to not fitting on left border.
- //This controls the extra indentation of text to make room for the bullet image.
- //Here use actual image size, not predefined bullet size
- //return $this->_frame->get_style()->get_font_size()*List_Bullet_Frame_Decorator::BULLET_SIZE +
- // 2 * List_Bullet_Frame_Decorator::BULLET_PADDING;
-
- // Small hack to prevent indenting of list text
- // Image Might not exist, then position like on list_bullet_frame_decorator fallback to none.
- if ( $this->_frame->get_style()->list_style_position === "outside" ||
- $this->_width == 0)
- return 0;
- //This aligns the "inside" image position with the text.
- //The text starts to the right of the image.
- //Between the image and the text there is an added margin of image width.
- //Where this comes from is unknown.
- //The corresponding List_Bullet_Frame_Decorator sets a smaller margin. bullet size?
- return $this->_width + 2 * List_Bullet_Frame_Decorator::BULLET_PADDING;
- }
-
- /**
- * Override get_margin_height()
- *
- * @return int
- */
- function get_margin_height() {
- //Hits only on "inset" lists items, to increase height of box
- //based on image height
- return $this->_height + 2 * List_Bullet_Frame_Decorator::BULLET_PADDING;
- }
-
- /**
- * Return image url
- *
- * @return string
- */
- function get_image_url() {
- return $this->_img->get_image_url();
- }
-
-}
diff --git a/library/vendor/dompdf/include/list_bullet_positioner.cls.php b/library/vendor/dompdf/include/list_bullet_positioner.cls.php
deleted file mode 100644
index 7e89ae471..000000000
--- a/library/vendor/dompdf/include/list_bullet_positioner.cls.php
+++ /dev/null
@@ -1,73 +0,0 @@
-
- * @author Helmut Tischer
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Positions list bullets
- *
- * @access private
- * @package dompdf
- */
-class List_Bullet_Positioner extends Positioner {
-
- function __construct(Frame_Decorator $frame) { parent::__construct($frame); }
-
- //........................................................................
-
- function position() {
-
- // Bullets & friends are positioned an absolute distance to the left of
- // the content edge of their parent element
- $cb = $this->_frame->get_containing_block();
-
- // Note: this differs from most frames in that we must position
- // ourselves after determining our width
- $x = $cb["x"] - $this->_frame->get_width();
-
- $p = $this->_frame->find_block_parent();
-
- $y = $p->get_current_line_box()->y;
-
- // This is a bit of a hack...
- $n = $this->_frame->get_next_sibling();
- if ( $n ) {
- $style = $n->get_style();
- $line_height = $style->length_in_pt($style->line_height, $style->get_font_size());
- $offset = $style->length_in_pt($line_height, $n->get_containing_block("h")) - $this->_frame->get_height();
- $y += $offset / 2;
- }
-
- // Now the position is the left top of the block which should be marked with the bullet.
- // We tried to find out the y of the start of the first text character within the block.
- // But the top margin/padding does not fit, neither from this nor from the next sibling
- // The "bit of a hack" above does not work also.
-
- // Instead let's position the bullet vertically centered to the block which should be marked.
- // But for get_next_sibling() the get_containing_block is all zero, and for find_block_parent()
- // the get_containing_block is paper width and the entire list as height.
-
- // if ($p) {
- // //$cb = $n->get_containing_block();
- // $cb = $p->get_containing_block();
- // $y += $cb["h"]/2;
- // print 'cb:'.$cb["x"].':'.$cb["y"].':'.$cb["w"].':'.$cb["h"].':';
- // }
-
- // Todo:
- // For now give up on the above. Use Guesswork with font y-pos in the middle of the line spacing
-
- /*$style = $p->get_style();
- $font_size = $style->get_font_size();
- $line_height = $style->length_in_pt($style->line_height, $font_size);
- $y += ($line_height - $font_size) / 2; */
-
- //Position is x-end y-top of character position of the bullet.
- $this->_frame->set_position($x, $y);
-
- }
-}
diff --git a/library/vendor/dompdf/include/list_bullet_renderer.cls.php b/library/vendor/dompdf/include/list_bullet_renderer.cls.php
deleted file mode 100644
index be4cde2bd..000000000
--- a/library/vendor/dompdf/include/list_bullet_renderer.cls.php
+++ /dev/null
@@ -1,236 +0,0 @@
-
- * @author Helmut Tischer
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Renders list bullets
- *
- * @access private
- * @package dompdf
- */
-class List_Bullet_Renderer extends Abstract_Renderer {
- static function get_counter_chars($type) {
- static $cache = array();
-
- if ( isset($cache[$type]) ) {
- return $cache[$type];
- }
-
- $uppercase = false;
- $text = "";
-
- switch ($type) {
- case "decimal-leading-zero":
- case "decimal":
- case "1":
- return "0123456789";
-
- case "upper-alpha":
- case "upper-latin":
- case "A":
- $uppercase = true;
- case "lower-alpha":
- case "lower-latin":
- case "a":
- $text = "abcdefghijklmnopqrstuvwxyz";
- break;
-
- case "upper-roman":
- case "I":
- $uppercase = true;
- case "lower-roman":
- case "i":
- $text = "ivxlcdm";
- break;
-
- case "lower-greek":
- for($i = 0; $i < 24; $i++) {
- $text .= unichr($i+944);
- }
- break;
- }
-
- if ( $uppercase ) {
- $text = strtoupper($text);
- }
-
- return $cache[$type] = "$text.";
- }
-
- /**
- * @param integer $n
- * @param string $type
- * @param integer $pad
- *
- * @return string
- */
- private function make_counter($n, $type, $pad = null){
- $n = intval($n);
- $text = "";
- $uppercase = false;
-
- switch ($type) {
- case "decimal-leading-zero":
- case "decimal":
- case "1":
- if ($pad)
- $text = str_pad($n, $pad, "0", STR_PAD_LEFT);
- else
- $text = $n;
- break;
-
- case "upper-alpha":
- case "upper-latin":
- case "A":
- $uppercase = true;
- case "lower-alpha":
- case "lower-latin":
- case "a":
- $text = chr( ($n % 26) + ord('a') - 1);
- break;
-
- case "upper-roman":
- case "I":
- $uppercase = true;
- case "lower-roman":
- case "i":
- $text = dec2roman($n);
- break;
-
- case "lower-greek":
- $text = unichr($n + 944);
- break;
- }
-
- if ( $uppercase ) {
- $text = strtoupper($text);
- }
-
- return "$text.";
- }
-
- function render(Frame $frame) {
- $style = $frame->get_style();
- $font_size = $style->get_font_size();
- $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w"));
-
- $this->_set_opacity( $frame->get_opacity( $style->opacity ) );
-
- $li = $frame->get_parent();
-
- // Don't render bullets twice if if was split
- if ($li->_splitted) {
- return;
- }
-
- // Handle list-style-image
- // If list style image is requested but missing, fall back to predefined types
- if ( $style->list_style_image !== "none" &&
- !Image_Cache::is_broken($img = $frame->get_image_url())) {
-
- list($x,$y) = $frame->get_position();
-
- //For expected size and aspect, instead of box size, use image natural size scaled to DPI.
- // Resample the bullet image to be consistent with 'auto' sized images
- // See also Image_Frame_Reflower::get_min_max_width
- // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary.
- //$w = $frame->get_width();
- //$h = $frame->get_height();
- list($width, $height) = dompdf_getimagesize($img, $this->_dompdf->get_http_context());
- $dpi = $this->_dompdf->get_option("dpi");
- $w = ((float)rtrim($width, "px") * 72) / $dpi;
- $h = ((float)rtrim($height, "px") * 72) / $dpi;
-
- $x -= $w;
- $y -= ($line_height - $font_size)/2; //Reverse hinting of list_bullet_positioner
-
- $this->_canvas->image( $img, $x, $y, $w, $h);
-
- } else {
-
- $bullet_style = $style->list_style_type;
-
- $fill = false;
-
- switch ($bullet_style) {
-
- default:
- case "disc":
- $fill = true;
-
- case "circle":
- list($x,$y) = $frame->get_position();
- $r = ($font_size*(List_Bullet_Frame_Decorator::BULLET_SIZE /*-List_Bullet_Frame_Decorator::BULLET_THICKNESS*/ ))/2;
- $x -= $font_size*(List_Bullet_Frame_Decorator::BULLET_SIZE/2);
- $y += ($font_size*(1-List_Bullet_Frame_Decorator::BULLET_DESCENT))/2;
- $o = $font_size*List_Bullet_Frame_Decorator::BULLET_THICKNESS;
- $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill);
- break;
-
- case "square":
- list($x, $y) = $frame->get_position();
- $w = $font_size*List_Bullet_Frame_Decorator::BULLET_SIZE;
- $x -= $w;
- $y += ($font_size*(1-List_Bullet_Frame_Decorator::BULLET_DESCENT-List_Bullet_Frame_Decorator::BULLET_SIZE))/2;
- $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color);
- break;
-
- case "decimal-leading-zero":
- case "decimal":
- case "lower-alpha":
- case "lower-latin":
- case "lower-roman":
- case "lower-greek":
- case "upper-alpha":
- case "upper-latin":
- case "upper-roman":
- case "1": // HTML 4.0 compatibility
- case "a":
- case "i":
- case "A":
- case "I":
- $pad = null;
- if ( $bullet_style === "decimal-leading-zero" ) {
- $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count"));
- }
-
- $node = $frame->get_node();
-
- if ( !$node->hasAttribute("dompdf-counter") ) {
- return;
- }
-
- $index = $node->getAttribute("dompdf-counter");
- $text = $this->make_counter($index, $bullet_style, $pad);
-
- if ( trim($text) == "" ) {
- return;
- }
-
- $spacing = 0;
- $font_family = $style->font_family;
-
- $line = $li->get_containing_line();
- list($x, $y) = array($frame->get_position("x"), $line->y);
-
- $x -= Font_Metrics::get_text_width($text, $font_family, $font_size, $spacing);
-
- // Take line-height into account
- $line_height = $style->line_height;
- $y += ($line_height - $font_size) / 4; // FIXME I thought it should be 2, but 4 gives better results
-
- $this->_canvas->text($x, $y, $text,
- $font_family, $font_size,
- $style->color, $spacing);
-
- case "none":
- break;
- }
- }
- }
-}
diff --git a/library/vendor/dompdf/include/null_frame_decorator.cls.php b/library/vendor/dompdf/include/null_frame_decorator.cls.php
deleted file mode 100644
index 15f806d0d..000000000
--- a/library/vendor/dompdf/include/null_frame_decorator.cls.php
+++ /dev/null
@@ -1,26 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Dummy decorator
- *
- * @access private
- * @package dompdf
- */
-class Null_Frame_Decorator extends Frame_Decorator {
-
- function __construct(Frame $frame, DOMPDF $dompdf) {
- parent::__construct($frame, $dompdf);
- $style = $this->_frame->get_style();
- $style->width = 0;
- $style->height = 0;
- $style->margin = 0;
- $style->padding = 0;
- }
-
-}
diff --git a/library/vendor/dompdf/include/null_frame_reflower.cls.php b/library/vendor/dompdf/include/null_frame_reflower.cls.php
deleted file mode 100644
index 389f1479d..000000000
--- a/library/vendor/dompdf/include/null_frame_reflower.cls.php
+++ /dev/null
@@ -1,21 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Dummy reflower
- *
- * @access private
- * @package dompdf
- */
-class Null_Frame_Reflower extends Frame_Reflower {
-
- function __construct(Frame $frame) { parent::__construct($frame); }
-
- function reflow(Block_Frame_Decorator $block = null) { return; }
-
-}
diff --git a/library/vendor/dompdf/include/null_positioner.cls.php b/library/vendor/dompdf/include/null_positioner.cls.php
deleted file mode 100644
index 97d4986dc..000000000
--- a/library/vendor/dompdf/include/null_positioner.cls.php
+++ /dev/null
@@ -1,23 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Dummy positioner
- *
- * @access private
- * @package dompdf
- */
-class Null_Positioner extends Positioner {
-
- function __construct(Frame_Decorator $frame) {
- parent::__construct($frame);
- }
-
- function position() { return; }
-
-}
diff --git a/library/vendor/dompdf/include/page_cache.cls.php b/library/vendor/dompdf/include/page_cache.cls.php
deleted file mode 100644
index 652da160a..000000000
--- a/library/vendor/dompdf/include/page_cache.cls.php
+++ /dev/null
@@ -1,126 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Caches individual rendered PDF pages
- *
- * Not totally implemented yet. Use at your own risk ;)
- *
- * @access private
- * @package dompdf
- * @static
- */
-class Page_Cache {
-
- const DB_USER = "dompdf_page_cache";
- const DB_PASS = "some meaningful password";
- const DB_NAME = "dompdf_page_cache";
-
- static private $__connection = null;
-
- static function init() {
- if ( is_null(self::$__connection) ) {
- $con_str = "host=" . DB_HOST .
- " dbname=" . self::DB_NAME .
- " user=" . self::DB_USER .
- " password=" . self::DB_PASS;
-
- if ( !self::$__connection = pg_connect($con_str) )
- throw new Exception("Database connection failed.");
- }
- }
-
- function __construct() { throw new Exception("Can not create instance of Page_Class. Class is static."); }
-
- private static function __query($sql) {
- if ( !($res = pg_query(self::$__connection, $sql)) )
- throw new Exception(pg_last_error(self::$__connection));
- return $res;
- }
-
- static function store_page($id, $page_num, $data) {
- $where = "WHERE id='" . pg_escape_string($id) . "' AND ".
- "page_num=". pg_escape_string($page_num);
-
- $res = self::__query("SELECT timestamp FROM page_cache ". $where);
-
- $row = pg_fetch_assoc($res);
-
- if ( $row )
- self::__query("UPDATE page_cache SET data='" . pg_escape_string($data) . "' " . $where);
- else
- self::__query("INSERT INTO page_cache (id, page_num, data) VALUES ('" . pg_escape_string($id) . "', ".
- pg_escape_string($page_num) . ", ".
- "'". pg_escape_string($data) . "')");
-
- }
-
- static function store_fonts($id, $fonts) {
- self::__query("BEGIN");
- // Update the font information
- self::__query("DELETE FROM page_fonts WHERE id='" . pg_escape_string($id) . "'");
-
- foreach (array_keys($fonts) as $font)
- self::__query("INSERT INTO page_fonts (id, font_name) VALUES ('" .
- pg_escape_string($id) . "', '" . pg_escape_string($font) . "')");
- self::__query("COMMIT");
- }
-
-// static function retrieve_page($id, $page_num) {
-
-// $res = self::__query("SELECT data FROM page_cache WHERE id='" . pg_escape_string($id) . "' AND ".
-// "page_num=". pg_escape_string($page_num));
-
-// $row = pg_fetch_assoc($res);
-
-// return pg_unescape_bytea($row["data"]);
-
-// }
-
- static function get_page_timestamp($id, $page_num) {
- $res = self::__query("SELECT timestamp FROM page_cache WHERE id='" . pg_escape_string($id) . "' AND ".
- "page_num=". pg_escape_string($page_num));
-
- $row = pg_fetch_assoc($res);
-
- return $row["timestamp"];
-
- }
-
- // Adds the cached document referenced by $id to the provided pdf
- static function insert_cached_document(CPDF_Adapter $pdf, $id, $new_page = true) {
- $res = self::__query("SELECT font_name FROM page_fonts WHERE id='" . pg_escape_string($id) . "'");
-
- // Ensure that the fonts needed by the cached document are loaded into
- // the pdf
- while ($row = pg_fetch_assoc($res))
- $pdf->get_cpdf()->selectFont($row["font_name"]);
-
- $res = self::__query("SELECT data FROM page_cache WHERE id='" . pg_escape_string($id) . "'");
-
- if ( $new_page )
- $pdf->new_page();
-
- $first = true;
- while ($row = pg_fetch_assoc($res)) {
-
- if ( !$first )
- $pdf->new_page();
- else
- $first = false;
-
- $page = $pdf->reopen_serialized_object($row["data"]);
- //$pdf->close_object();
- $pdf->add_object($page, "add");
-
- }
-
- }
-}
-
-Page_Cache::init();
diff --git a/library/vendor/dompdf/include/page_frame_decorator.cls.php b/library/vendor/dompdf/include/page_frame_decorator.cls.php
deleted file mode 100644
index f089d0075..000000000
--- a/library/vendor/dompdf/include/page_frame_decorator.cls.php
+++ /dev/null
@@ -1,592 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Decorates frames for page layout
- *
- * @access private
- * @package dompdf
- */
-class Page_Frame_Decorator extends Frame_Decorator {
-
- /**
- * y value of bottom page margin
- *
- * @var float
- */
- protected $_bottom_page_margin;
-
- /**
- * Flag indicating page is full.
- *
- * @var bool
- */
- protected $_page_full;
-
- /**
- * Number of tables currently being reflowed
- *
- * @var int
- */
- protected $_in_table;
-
- /**
- * The pdf renderer
- *
- * @var Renderer
- */
- protected $_renderer;
-
- /**
- * This page's floating frames
- *
- * @var array
- */
- protected $_floating_frames = array();
-
- //........................................................................
-
- /**
- * Class constructor
- *
- * @param Frame $frame the frame to decorate
- * @param DOMPDF $dompdf
- */
- function __construct(Frame $frame, DOMPDF $dompdf) {
- parent::__construct($frame, $dompdf);
- $this->_page_full = false;
- $this->_in_table = 0;
- $this->_bottom_page_margin = null;
- }
-
- /**
- * Set the renderer used for this pdf
- *
- * @param Renderer $renderer the renderer to use
- */
- function set_renderer($renderer) {
- $this->_renderer = $renderer;
- }
-
- /**
- * Return the renderer used for this pdf
- *
- * @return Renderer
- */
- function get_renderer() {
- return $this->_renderer;
- }
-
- /**
- * Set the frame's containing block. Overridden to set $this->_bottom_page_margin.
- *
- * @param float $x
- * @param float $y
- * @param float $w
- * @param float $h
- */
- function set_containing_block($x = null, $y = null, $w = null, $h = null) {
- parent::set_containing_block($x,$y,$w,$h);
- //$w = $this->get_containing_block("w");
- if ( isset($h) )
- $this->_bottom_page_margin = $h; // - $this->_frame->get_style()->length_in_pt($this->_frame->get_style()->margin_bottom, $w);
- }
-
- /**
- * Returns true if the page is full and is no longer accepting frames.
- *
- * @return bool
- */
- function is_full() {
- return $this->_page_full;
- }
-
- /**
- * Start a new page by resetting the full flag.
- */
- function next_page() {
- $this->_floating_frames = array();
- $this->_renderer->new_page();
- $this->_page_full = false;
- }
-
- /**
- * Indicate to the page that a table is currently being reflowed.
- */
- function table_reflow_start() {
- $this->_in_table++;
- }
-
- /**
- * Indicate to the page that table reflow is finished.
- */
- function table_reflow_end() {
- $this->_in_table--;
- }
-
- /**
- * Return whether we are currently in a nested table or not
- *
- * @return bool
- */
- function in_nested_table() {
- return $this->_in_table > 1;
- }
-
- /**
- * Check if a forced page break is required before $frame. This uses the
- * frame's page_break_before property as well as the preceeding frame's
- * page_break_after property.
- *
- * @link http://www.w3.org/TR/CSS21/page.html#forced
- *
- * @param Frame $frame the frame to check
- * @return bool true if a page break occured
- */
- function check_forced_page_break(Frame $frame) {
-
- // Skip check if page is already split
- if ( $this->_page_full )
- return null;
-
- $block_types = array("block", "list-item", "table", "inline");
- $page_breaks = array("always", "left", "right");
-
- $style = $frame->get_style();
-
- if ( !in_array($style->display, $block_types) )
- return false;
-
- // Find the previous block-level sibling
- $prev = $frame->get_prev_sibling();
-
- while ( $prev && !in_array($prev->get_style()->display, $block_types) )
- $prev = $prev->get_prev_sibling();
-
-
- if ( in_array($style->page_break_before, $page_breaks) ) {
-
- // Prevent cascading splits
- $frame->split(null, true);
- // We have to grab the style again here because split() resets
- // $frame->style to the frame's orignal style.
- $frame->get_style()->page_break_before = "auto";
- $this->_page_full = true;
-
- return true;
- }
-
- if ( $prev && in_array($prev->get_style()->page_break_after, $page_breaks) ) {
- // Prevent cascading splits
- $frame->split(null, true);
- $prev->get_style()->page_break_after = "auto";
- $this->_page_full = true;
- return true;
- }
-
- if( $prev && $prev->get_last_child() && $frame->get_node()->nodeName != "body" ) {
- $prev_last_child = $prev->get_last_child();
- if ( in_array($prev_last_child->get_style()->page_break_after, $page_breaks) ) {
- $frame->split(null, true);
- $prev_last_child->get_style()->page_break_after = "auto";
- $this->_page_full = true;
- return true;
- }
- }
-
-
- return false;
- }
-
- /**
- * Determine if a page break is allowed before $frame
- * http://www.w3.org/TR/CSS21/page.html#allowed-page-breaks
- *
- * In the normal flow, page breaks can occur at the following places:
- *
- * 1. In the vertical margin between block boxes. When a page
- * break occurs here, the used values of the relevant
- * 'margin-top' and 'margin-bottom' properties are set to '0'.
- * 2. Between line boxes inside a block box.
- *
- * These breaks are subject to the following rules:
- *
- * * Rule A: Breaking at (1) is allowed only if the
- * 'page-break-after' and 'page-break-before' properties of
- * all the elements generating boxes that meet at this margin
- * allow it, which is when at least one of them has the value
- * 'always', 'left', or 'right', or when all of them are
- * 'auto'.
- *
- * * Rule B: However, if all of them are 'auto' and the
- * nearest common ancestor of all the elements has a
- * 'page-break-inside' value of 'avoid', then breaking here is
- * not allowed.
- *
- * * Rule C: Breaking at (2) is allowed only if the number of
- * line boxes between the break and the start of the enclosing
- * block box is the value of 'orphans' or more, and the number
- * of line boxes between the break and the end of the box is
- * the value of 'widows' or more.
- *
- * * Rule D: In addition, breaking at (2) is allowed only if
- * the 'page-break-inside' property is 'auto'.
- *
- * If the above doesn't provide enough break points to keep
- * content from overflowing the page boxes, then rules B and D are
- * dropped in order to find additional breakpoints.
- *
- * If that still does not lead to sufficient break points, rules A
- * and C are dropped as well, to find still more break points.
- *
- * We will also allow breaks between table rows. However, when
- * splitting a table, the table headers should carry over to the
- * next page (but they don't yet).
- *
- * @param Frame $frame the frame to check
- * @return bool true if a break is allowed, false otherwise
- */
- protected function _page_break_allowed(Frame $frame) {
-
- $block_types = array("block", "list-item", "table", "-dompdf-image");
- dompdf_debug("page-break", "_page_break_allowed(" . $frame->get_node()->nodeName. ")");
- $display = $frame->get_style()->display;
-
- // Block Frames (1):
- if ( in_array($display, $block_types) ) {
-
- // Avoid breaks within table-cells
- if ( $this->_in_table ) {
- dompdf_debug("page-break", "In table: " . $this->_in_table);
- return false;
- }
-
- // Rules A & B
-
- if ( $frame->get_style()->page_break_before === "avoid" ) {
- dompdf_debug("page-break", "before: avoid");
- return false;
- }
-
- // Find the preceeding block-level sibling
- $prev = $frame->get_prev_sibling();
- while ( $prev && !in_array($prev->get_style()->display, $block_types) )
- $prev = $prev->get_prev_sibling();
-
- // Does the previous element allow a page break after?
- if ( $prev && $prev->get_style()->page_break_after === "avoid" ) {
- dompdf_debug("page-break", "after: avoid");
- return false;
- }
-
- // If both $prev & $frame have the same parent, check the parent's
- // page_break_inside property.
- $parent = $frame->get_parent();
- if ( $prev && $parent && $parent->get_style()->page_break_inside === "avoid" ) {
- dompdf_debug("page-break", "parent inside: avoid");
- return false;
- }
-
- // To prevent cascading page breaks when a top-level element has
- // page-break-inside: avoid, ensure that at least one frame is
- // on the page before splitting.
- if ( $parent->get_node()->nodeName === "body" && !$prev ) {
- // We are the body's first child
- dompdf_debug("page-break", "Body's first child.");
- return false;
- }
-
- // If the frame is the first block-level frame, use the value from
- // $frame's parent instead.
- if ( !$prev && $parent )
- return $this->_page_break_allowed( $parent );
-
- dompdf_debug("page-break", "block: break allowed");
- return true;
-
- }
-
- // Inline frames (2):
- else if ( in_array($display, Style::$INLINE_TYPES) ) {
-
- // Avoid breaks within table-cells
- if ( $this->_in_table ) {
- dompdf_debug("page-break", "In table: " . $this->_in_table);
- return false;
- }
-
- // Rule C
- $block_parent = $frame->find_block_parent();
- if ( count($block_parent->get_line_boxes() ) < $frame->get_style()->orphans ) {
- dompdf_debug("page-break", "orphans");
- return false;
- }
-
- // FIXME: Checking widows is tricky without having laid out the
- // remaining line boxes. Just ignore it for now...
-
- // Rule D
- $p = $block_parent;
- while ($p) {
- if ( $p->get_style()->page_break_inside === "avoid" ) {
- dompdf_debug("page-break", "parent->inside: avoid");
- return false;
- }
- $p = $p->find_block_parent();
- }
-
- // To prevent cascading page breaks when a top-level element has
- // page-break-inside: avoid, ensure that at least one frame with
- // some content is on the page before splitting.
- $prev = $frame->get_prev_sibling();
- while ( $prev && ($prev->is_text_node() && trim($prev->get_node()->nodeValue) == "") )
- $prev = $prev->get_prev_sibling();
-
- if ( $block_parent->get_node()->nodeName === "body" && !$prev ) {
- // We are the body's first child
- dompdf_debug("page-break", "Body's first child.");
- return false;
- }
-
- // Skip breaks on empty text nodes
- if ( $frame->is_text_node() &&
- $frame->get_node()->nodeValue == "" )
- return false;
-
- dompdf_debug("page-break", "inline: break allowed");
- return true;
-
- // Table-rows
- } else if ( $display === "table-row" ) {
-
- // Simply check if the parent table's page_break_inside property is
- // not 'avoid'
- $p = Table_Frame_Decorator::find_parent_table($frame);
-
- while ($p) {
- if ( $p->get_style()->page_break_inside === "avoid" ) {
- dompdf_debug("page-break", "parent->inside: avoid");
- return false;
- }
- $p = $p->find_block_parent();
- }
-
- // Avoid breaking after the first row of a table
- if ( $p && $p->get_first_child() === $frame) {
- dompdf_debug("page-break", "table: first-row");
- return false;
- }
-
- // If this is a nested table, prevent the page from breaking
- if ( $this->_in_table > 1 ) {
- dompdf_debug("page-break", "table: nested table");
- return false;
- }
-
- dompdf_debug("page-break","table-row/row-groups: break allowed");
- return true;
-
- } else if ( in_array($display, Table_Frame_Decorator::$ROW_GROUPS) ) {
-
- // Disallow breaks at row-groups: only split at row boundaries
- return false;
-
- } else {
-
- dompdf_debug("page-break", "? " . $frame->get_style()->display . "");
- return false;
- }
-
- }
-
- /**
- * Check if $frame will fit on the page. If the frame does not fit,
- * the frame tree is modified so that a page break occurs in the
- * correct location.
- *
- * @param Frame $frame the frame to check
- * @return Frame the frame following the page break
- */
- function check_page_break(Frame $frame) {
- // Do not split if we have already or if the frame was already
- // pushed to the next page (prevents infinite loops)
- if ( $this->_page_full || $frame->_already_pushed ) {
- return false;
- }
-
- // If the frame is absolute of fixed it shouldn't break
- $p = $frame;
- do {
- if ( $p->is_absolute() )
- return false;
- } while ( $p = $p->get_parent() );
-
- $margin_height = $frame->get_margin_height();
-
- // FIXME If the row is taller than the page and
- // if it the first of the page, we don't break
- if ( $frame->get_style()->display === "table-row" &&
- !$frame->get_prev_sibling() &&
- $margin_height > $this->get_margin_height() )
- return false;
-
- // Determine the frame's maximum y value
- $max_y = $frame->get_position("y") + $margin_height;
-
- // If a split is to occur here, then the bottom margins & paddings of all
- // parents of $frame must fit on the page as well:
- $p = $frame->get_parent();
- while ( $p ) {
- $style = $p->get_style();
- $max_y += $style->length_in_pt(array($style->margin_bottom,
- $style->padding_bottom,
- $style->border_bottom_width));
- $p = $p->get_parent();
- }
-
-
- // Check if $frame flows off the page
- if ( $max_y <= $this->_bottom_page_margin )
- // no: do nothing
- return false;
-
- dompdf_debug("page-break", "check_page_break");
- dompdf_debug("page-break", "in_table: " . $this->_in_table);
-
- // yes: determine page break location
- $iter = $frame;
- $flg = false;
-
- $in_table = $this->_in_table;
-
- dompdf_debug("page-break","Starting search");
- while ( $iter ) {
- // echo "\nbacktrack: " .$iter->get_node()->nodeName ." ".spl_object_hash($iter->get_node()). "";
- if ( $iter === $this ) {
- dompdf_debug("page-break", "reached root.");
- // We've reached the root in our search. Just split at $frame.
- break;
- }
-
- if ( $this->_page_break_allowed($iter) ) {
- dompdf_debug("page-break","break allowed, splitting.");
- $iter->split(null, true);
- $this->_page_full = true;
- $this->_in_table = $in_table;
- $frame->_already_pushed = true;
- return true;
- }
-
- if ( !$flg && $next = $iter->get_last_child() ) {
- dompdf_debug("page-break", "following last child.");
-
- if ( $next->is_table() )
- $this->_in_table++;
-
- $iter = $next;
- continue;
- }
-
- if ( $next = $iter->get_prev_sibling() ) {
- dompdf_debug("page-break", "following prev sibling.");
-
- if ( $next->is_table() && !$iter->is_table() )
- $this->_in_table++;
-
- else if ( !$next->is_table() && $iter->is_table() )
- $this->_in_table--;
-
- $iter = $next;
- $flg = false;
- continue;
- }
-
- if ( $next = $iter->get_parent() ) {
- dompdf_debug("page-break", "following parent.");
-
- if ( $iter->is_table() )
- $this->_in_table--;
-
- $iter = $next;
- $flg = true;
- continue;
- }
-
- break;
- }
-
- $this->_in_table = $in_table;
-
- // No valid page break found. Just break at $frame.
- dompdf_debug("page-break", "no valid break found, just splitting.");
-
- // If we are in a table, backtrack to the nearest top-level table row
- if ( $this->_in_table ) {
- $iter = $frame;
- while ($iter && $iter->get_style()->display !== "table-row")
- $iter = $iter->get_parent();
-
- $iter->split(null, true);
- } else {
- $frame->split(null, true);
- }
-
- $this->_page_full = true;
- $frame->_already_pushed = true;
- return true;
- }
-
- //........................................................................
-
- function split(Frame $frame = null, $force_pagebreak = false) {
- // Do nothing
- }
-
- /**
- * Add a floating frame
- *
- * @param Frame $frame
- *
- * @return void
- */
- function add_floating_frame(Frame $frame) {
- array_unshift($this->_floating_frames, $frame);
- }
-
- /**
- * @return Frame[]
- */
- function get_floating_frames() {
- return $this->_floating_frames;
- }
-
- public function remove_floating_frame($key) {
- unset($this->_floating_frames[$key]);
- }
-
- public function get_lowest_float_offset(Frame $child) {
- $style = $child->get_style();
- $side = $style->clear;
- $float = $style->float;
-
- $y = 0;
-
- foreach($this->_floating_frames as $key => $frame) {
- if ( $side === "both" || $frame->get_style()->float === $side ) {
- $y = max($y, $frame->get_position("y") + $frame->get_margin_height());
-
- if ( $float !== "none" ) {
- $this->remove_floating_frame($key);
- }
- }
- }
-
- return $y;
- }
-
-}
diff --git a/library/vendor/dompdf/include/page_frame_reflower.cls.php b/library/vendor/dompdf/include/page_frame_reflower.cls.php
deleted file mode 100644
index 4223f4e85..000000000
--- a/library/vendor/dompdf/include/page_frame_reflower.cls.php
+++ /dev/null
@@ -1,186 +0,0 @@
-
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Reflows pages
- *
- * @access private
- * @package dompdf
- */
-class Page_Frame_Reflower extends Frame_Reflower {
-
- /**
- * Cache of the callbacks array
- *
- * @var array
- */
- private $_callbacks;
-
- /**
- * Cache of the canvas
- *
- * @var Canvas
- */
- private $_canvas;
-
- function __construct(Page_Frame_Decorator $frame) { parent::__construct($frame); }
-
- function apply_page_style(Frame $frame, $page_number){
- $style = $frame->get_style();
- $page_styles = $style->get_stylesheet()->get_page_styles();
-
- // http://www.w3.org/TR/CSS21/page.html#page-selectors
- if ( count($page_styles) > 1 ) {
- $odd = $page_number % 2 == 1;
- $first = $page_number == 1;
-
- $style = clone $page_styles["base"];
-
- // FIXME RTL
- if ( $odd && isset($page_styles[":right"]) ) {
- $style->merge($page_styles[":right"]);
- }
-
- if ( $odd && isset($page_styles[":odd"]) ) {
- $style->merge($page_styles[":odd"]);
- }
-
- // FIXME RTL
- if ( !$odd && isset($page_styles[":left"]) ) {
- $style->merge($page_styles[":left"]);
- }
-
- if ( !$odd && isset($page_styles[":even"]) ) {
- $style->merge($page_styles[":even"]);
- }
-
- if ( $first && isset($page_styles[":first"]) ) {
- $style->merge($page_styles[":first"]);
- }
-
- $frame->set_style($style);
- }
- }
-
- //........................................................................
-
- /**
- * Paged layout:
- * http://www.w3.org/TR/CSS21/page.html
- */
- function reflow(Block_Frame_Decorator $block = null) {
- $fixed_children = array();
- $prev_child = null;
- $child = $this->_frame->get_first_child();
- $current_page = 0;
-
- while ($child) {
- $this->apply_page_style($this->_frame, $current_page + 1);
-
- $style = $this->_frame->get_style();
-
- // Pages are only concerned with margins
- $cb = $this->_frame->get_containing_block();
- $left = $style->length_in_pt($style->margin_left, $cb["w"]);
- $right = $style->length_in_pt($style->margin_right, $cb["w"]);
- $top = $style->length_in_pt($style->margin_top, $cb["h"]);
- $bottom = $style->length_in_pt($style->margin_bottom, $cb["h"]);
-
- $content_x = $cb["x"] + $left;
- $content_y = $cb["y"] + $top;
- $content_width = $cb["w"] - $left - $right;
- $content_height = $cb["h"] - $top - $bottom;
-
- // Only if it's the first page, we save the nodes with a fixed position
- if ($current_page == 0) {
- $children = $child->get_children();
- foreach ($children as $onechild) {
- if ($onechild->get_style()->position === "fixed") {
- $fixed_children[] = $onechild->deep_copy();
- }
- }
- $fixed_children = array_reverse($fixed_children);
- }
-
- $child->set_containing_block($content_x, $content_y, $content_width, $content_height);
-
- // Check for begin reflow callback
- $this->_check_callbacks("begin_page_reflow", $child);
-
- //Insert a copy of each node which have a fixed position
- if ($current_page >= 1) {
- foreach ($fixed_children as $fixed_child) {
- $child->insert_child_before($fixed_child->deep_copy(), $child->get_first_child());
- }
- }
-
- $child->reflow();
- $next_child = $child->get_next_sibling();
-
- // Check for begin render callback
- $this->_check_callbacks("begin_page_render", $child);
-
- // Render the page
- $this->_frame->get_renderer()->render($child);
-
- // Check for end render callback
- $this->_check_callbacks("end_page_render", $child);
-
- if ( $next_child ) {
- $this->_frame->next_page();
- }
-
- // Wait to dispose of all frames on the previous page
- // so callback will have access to them
- if ( $prev_child ) {
- $prev_child->dispose(true);
- }
- $prev_child = $child;
- $child = $next_child;
- $current_page++;
- }
-
- // Dispose of previous page if it still exists
- if ( $prev_child ) {
- $prev_child->dispose(true);
- }
- }
-
- //........................................................................
-
- /**
- * Check for callbacks that need to be performed when a given event
- * gets triggered on a page
- *
- * @param string $event the type of event
- * @param Frame $frame the frame that event is triggered on
- */
- protected function _check_callbacks($event, $frame) {
- if (!isset($this->_callbacks)) {
- $dompdf = $this->_frame->get_dompdf();
- $this->_callbacks = $dompdf->get_callbacks();
- $this->_canvas = $dompdf->get_canvas();
- }
-
- if (is_array($this->_callbacks) && isset($this->_callbacks[$event])) {
- $info = array(0 => $this->_canvas, "canvas" => $this->_canvas,
- 1 => $frame, "frame" => $frame);
- $fs = $this->_callbacks[$event];
- foreach ($fs as $f) {
- if (is_callable($f)) {
- if (is_array($f)) {
- $f[0]->$f[1]($info);
- } else {
- $f($info);
- }
- }
- }
- }
- }
-}
diff --git a/library/vendor/dompdf/include/pdflib_adapter.cls.php b/library/vendor/dompdf/include/pdflib_adapter.cls.php
deleted file mode 100644
index 2417d5f52..000000000
--- a/library/vendor/dompdf/include/pdflib_adapter.cls.php
+++ /dev/null
@@ -1,1085 +0,0 @@
-
- * @author Helmut Tischer
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * PDF rendering interface
- *
- * PDFLib_Adapter provides a simple, stateless interface to the one
- * provided by PDFLib.
- *
- * Unless otherwise mentioned, all dimensions are in points (1/72 in).
- * The coordinate origin is in the top left corner and y values
- * increase downwards.
- *
- * See {@link http://www.pdflib.com/} for more complete documentation
- * on the underlying PDFlib functions.
- *
- * @package dompdf
- */
-class PDFLib_Adapter implements Canvas {
-
- /**
- * Dimensions of paper sizes in points
- *
- * @var array;
- */
- static public $PAPER_SIZES = array(); // Set to CPDF_Adapter::$PAPER_SIZES below.
-
- /**
- * Whether to create PDFs in memory or on disk
- *
- * @var bool
- */
- static $IN_MEMORY = true;
-
- /**
- * @var DOMPDF
- */
- private $_dompdf;
-
- /**
- * Instance of PDFLib class
- *
- * @var PDFlib
- */
- private $_pdf;
-
- /**
- * Name of temporary file used for PDFs created on disk
- *
- * @var string
- */
- private $_file;
-
- /**
- * PDF width, in points
- *
- * @var float
- */
- private $_width;
-
- /**
- * PDF height, in points
- *
- * @var float
- */
- private $_height;
-
- /**
- * Last fill color used
- *
- * @var array
- */
- private $_last_fill_color;
-
- /**
- * Last stroke color used
- *
- * @var array
- */
- private $_last_stroke_color;
-
- /**
- * Cache of image handles
- *
- * @var array
- */
- private $_imgs;
-
- /**
- * Cache of font handles
- *
- * @var array
- */
- private $_fonts;
-
- /**
- * List of objects (templates) to add to multiple pages
- *
- * @var array
- */
- private $_objs;
-
- /**
- * Current page number
- *
- * @var int
- */
- private $_page_number;
-
- /**
- * Total number of pages
- *
- * @var int
- */
- private $_page_count;
-
- /**
- * Text to display on every page
- *
- * @var array
- */
- private $_page_text;
-
- /**
- * Array of pages for accesing after rendering is initially complete
- *
- * @var array
- */
- private $_pages;
-
- /**
- * Class constructor
- *
- * @param mixed $paper The size of paper to use either a string (see {@link CPDF_Adapter::$PAPER_SIZES}) or
- * an array(xmin,ymin,xmax,ymax)
- * @param string $orientation The orientation of the document (either 'landscape' or 'portrait')
- * @param DOMPDF $dompdf
- */
- function __construct($paper = "letter", $orientation = "portrait", DOMPDF $dompdf) {
- if ( is_array($paper) ) {
- $size = $paper;
- }
- else if ( isset(self::$PAPER_SIZES[mb_strtolower($paper)]) ) {
- $size = self::$PAPER_SIZES[mb_strtolower($paper)];
- }
- else {
- $size = self::$PAPER_SIZES["letter"];
- }
-
- if ( mb_strtolower($orientation) === "landscape" ) {
- list($size[2], $size[3]) = array($size[3], $size[2]);
- }
-
- $this->_width = $size[2] - $size[0];
- $this->_height= $size[3] - $size[1];
-
- $this->_dompdf = $dompdf;
-
- $this->_pdf = new PDFLib();
-
- if ( defined("DOMPDF_PDFLIB_LICENSE") )
- $this->_pdf->set_parameter( "license", DOMPDF_PDFLIB_LICENSE);
-
- $this->_pdf->set_parameter("textformat", "utf8");
- $this->_pdf->set_parameter("fontwarning", "false");
-
- $this->_pdf->set_info("Creator", "DOMPDF");
-
- // Silence pedantic warnings about missing TZ settings
- $tz = @date_default_timezone_get();
- date_default_timezone_set("UTC");
- $this->_pdf->set_info("Date", date("Y-m-d"));
- date_default_timezone_set($tz);
-
- if ( self::$IN_MEMORY )
- $this->_pdf->begin_document("","");
- else {
- $tmp_dir = $this->_dompdf->get_options("temp_dir");
- $tmp_name = tempnam($tmp_dir, "libdompdf_pdf_");
- @unlink($tmp_name);
- $this->_file = "$tmp_name.pdf";
- $this->_pdf->begin_document($this->_file,"");
- }
-
- $this->_pdf->begin_page_ext($this->_width, $this->_height, "");
-
- $this->_page_number = $this->_page_count = 1;
- $this->_page_text = array();
-
- $this->_imgs = array();
- $this->_fonts = array();
- $this->_objs = array();
-
- // Set up font paths
- $families = Font_Metrics::get_font_families();
- foreach ($families as $files) {
- foreach ($files as $file) {
- $face = basename($file);
- $afm = null;
-
- // Prefer ttfs to afms
- if ( file_exists("$file.ttf") ) {
- $outline = "$file.ttf";
-
- } else if ( file_exists("$file.TTF") ) {
- $outline = "$file.TTF";
-
- } else if ( file_exists("$file.pfb") ) {
- $outline = "$file.pfb";
-
- if ( file_exists("$file.afm") ) {
- $afm = "$file.afm";
- }
-
- } else if ( file_exists("$file.PFB") ) {
- $outline = "$file.PFB";
- if ( file_exists("$file.AFM") ) {
- $afm = "$file.AFM";
- }
- } else {
- continue;
- }
-
- $this->_pdf->set_parameter("FontOutline", "\{$face\}=\{$outline\}");
-
- if ( !is_null($afm) ) {
- $this->_pdf->set_parameter("FontAFM", "\{$face\}=\{$afm\}");
- }
- }
- }
- }
-
- function get_dompdf(){
- return $this->_dompdf;
- }
-
- /**
- * Close the pdf
- */
- protected function _close() {
- $this->_place_objects();
-
- // Close all pages
- $this->_pdf->suspend_page("");
- for ($p = 1; $p <= $this->_page_count; $p++) {
- $this->_pdf->resume_page("pagenumber=$p");
- $this->_pdf->end_page_ext("");
- }
-
- $this->_pdf->end_document("");
- }
-
-
- /**
- * Returns the PDFLib instance
- *
- * @return PDFLib
- */
- function get_pdflib() {
- return $this->_pdf;
- }
-
- /**
- * Add meta information to the PDF
- *
- * @param string $label label of the value (Creator, Producter, etc.)
- * @param string $value the text to set
- */
- function add_info($label, $value) {
- $this->_pdf->set_info($label, $value);
- }
-
- /**
- * Opens a new 'object' (template in PDFLib-speak)
- *
- * While an object is open, all drawing actions are recorded to the
- * object instead of being drawn on the current page. Objects can
- * be added later to a specific page or to several pages.
- *
- * The return value is an integer ID for the new object.
- *
- * @see PDFLib_Adapter::close_object()
- * @see PDFLib_Adapter::add_object()
- *
- * @return int
- */
- function open_object() {
- $this->_pdf->suspend_page("");
- $ret = $this->_pdf->begin_template($this->_width, $this->_height);
- $this->_pdf->save();
- $this->_objs[$ret] = array("start_page" => $this->_page_number);
- return $ret;
- }
-
- /**
- * Reopen an existing object (NOT IMPLEMENTED)
- * PDFLib does not seem to support reopening templates.
- *
- * @param int $object the ID of a previously opened object
- *
- * @throws DOMPDF_Exception
- * @return void
- */
- function reopen_object($object) {
- throw new DOMPDF_Exception("PDFLib does not support reopening objects.");
- }
-
- /**
- * Close the current template
- *
- * @see PDFLib_Adapter::open_object()
- */
- function close_object() {
- $this->_pdf->restore();
- $this->_pdf->end_template();
- $this->_pdf->resume_page("pagenumber=".$this->_page_number);
- }
-
- /**
- * Adds the specified object to the document
- *
- * $where can be one of:
- * - 'add' add to current page only
- * - 'all' add to every page from the current one onwards
- * - 'odd' add to all odd numbered pages from now on
- * - 'even' add to all even numbered pages from now on
- * - 'next' add the object to the next page only
- * - 'nextodd' add to all odd numbered pages from the next one
- * - 'nexteven' add to all even numbered pages from the next one
- *
- * @param int $object the object handle returned by open_object()
- * @param string $where
- */
- function add_object($object, $where = 'all') {
-
- if ( mb_strpos($where, "next") !== false ) {
- $this->_objs[$object]["start_page"]++;
- $where = str_replace("next", "", $where);
- if ( $where == "" )
- $where = "add";
- }
-
- $this->_objs[$object]["where"] = $where;
- }
-
- /**
- * Stops the specified template from appearing in the document.
- *
- * The object will stop being displayed on the page following the
- * current one.
- *
- * @param int $object
- */
- function stop_object($object) {
-
- if ( !isset($this->_objs[$object]) )
- return;
-
- $start = $this->_objs[$object]["start_page"];
- $where = $this->_objs[$object]["where"];
-
- // Place the object on this page if required
- if ( $this->_page_number >= $start &&
- (($this->_page_number % 2 == 0 && $where === "even") ||
- ($this->_page_number % 2 == 1 && $where === "odd") ||
- ($where === "all")) ) {
- $this->_pdf->fit_image($object, 0, 0, "");
- }
-
- $this->_objs[$object] = null;
- unset($this->_objs[$object]);
- }
-
- /**
- * Add all active objects to the current page
- */
- protected function _place_objects() {
-
- foreach ( $this->_objs as $obj => $props ) {
- $start = $props["start_page"];
- $where = $props["where"];
-
- // Place the object on this page if required
- if ( $this->_page_number >= $start &&
- (($this->_page_number % 2 == 0 && $where === "even") ||
- ($this->_page_number % 2 == 1 && $where === "odd") ||
- ($where === "all")) ) {
- $this->_pdf->fit_image($obj,0,0,"");
- }
- }
-
- }
-
- function get_width() { return $this->_width; }
-
- function get_height() { return $this->_height; }
-
- function get_page_number() { return $this->_page_number; }
-
- function get_page_count() { return $this->_page_count; }
-
- function set_page_number($num) { $this->_page_number = (int)$num; }
-
- function set_page_count($count) { $this->_page_count = (int)$count; }
-
-
- /**
- * Sets the line style
- *
- * @param float $width
- * @param $cap
- * @param string $join
- * @param array $dash
- *
- * @return void
- */
- protected function _set_line_style($width, $cap, $join, $dash) {
-
- if ( count($dash) == 1 )
- $dash[] = $dash[0];
-
- if ( count($dash) > 1 )
- $this->_pdf->setdashpattern("dasharray={" . implode(" ", $dash) . "}");
- else
- $this->_pdf->setdash(0,0);
-
- switch ( $join ) {
- case "miter":
- $this->_pdf->setlinejoin(0);
- break;
-
- case "round":
- $this->_pdf->setlinejoin(1);
- break;
-
- case "bevel":
- $this->_pdf->setlinejoin(2);
- break;
-
- default:
- break;
- }
-
- switch ( $cap ) {
- case "butt":
- $this->_pdf->setlinecap(0);
- break;
-
- case "round":
- $this->_pdf->setlinecap(1);
- break;
-
- case "square":
- $this->_pdf->setlinecap(2);
- break;
-
- default:
- break;
- }
-
- $this->_pdf->setlinewidth($width);
-
- }
-
- /**
- * Sets the line color
- *
- * @param array $color array(r,g,b)
- */
- protected function _set_stroke_color($color) {
- if($this->_last_stroke_color == $color)
- return;
-
- $this->_last_stroke_color = $color;
-
- if (isset($color[3])) {
- $type = "cmyk";
- list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], $color[3]);
- }
- elseif (isset($color[2])) {
- $type = "rgb";
- list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], null);
- }
- else {
- $type = "gray";
- list($c1, $c2, $c3, $c4) = array($color[0], $color[1], null, null);
- }
-
- $this->_pdf->setcolor("stroke", $type, $c1, $c2, $c3, $c4);
- }
-
- /**
- * Sets the fill color
- *
- * @param array $color array(r,g,b)
- */
- protected function _set_fill_color($color) {
- if($this->_last_fill_color == $color)
- return;
-
- $this->_last_fill_color = $color;
-
- if (isset($color[3])) {
- $type = "cmyk";
- list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], $color[3]);
- }
- elseif (isset($color[2])) {
- $type = "rgb";
- list($c1, $c2, $c3, $c4) = array($color[0], $color[1], $color[2], null);
- }
- else {
- $type = "gray";
- list($c1, $c2, $c3, $c4) = array($color[0], $color[1], null, null);
- }
-
- $this->_pdf->setcolor("fill", $type, $c1, $c2, $c3, $c4);
- }
-
- /**
- * Sets the opacity
- *
- * @param $opacity
- * @param $mode
- */
- function set_opacity($opacity, $mode = "Normal") {
- if ( $mode === "Normal" ) {
- $gstate = $this->_pdf->create_gstate("opacityfill=$opacity opacitystroke=$opacity");
- $this->_pdf->set_gstate($gstate);
- }
- }
-
- function set_default_view($view, $options = array()) {
- // TODO
- // http://www.pdflib.com/fileadmin/pdflib/pdf/manuals/PDFlib-8.0.2-API-reference.pdf
- /**
- * fitheight Fit the page height to the window, with the x coordinate left at the left edge of the window.
- * fitrect Fit the rectangle specified by left, bottom, right, and top to the window.
- * fitvisible Fit the visible contents of the page (the ArtBox) to the window.
- * fitvisibleheight Fit the visible contents of the page to the window with the x coordinate left at the left edge of the window.
- * fitvisiblewidth Fit the visible contents of the page to the window with the y coordinate top at the top edge of the window.
- * fitwidth Fit the page width to the window, with the y coordinate top at the top edge of the window.
- * fitwindow Fit the complete page to the window.
- * fixed
- */
- //$this->_pdf->set_parameter("openaction", $view);
- }
-
- /**
- * Loads a specific font and stores the corresponding descriptor.
- *
- * @param string $font
- * @param string $encoding
- * @param string $options
- *
- * @return int the font descriptor for the font
- */
- protected function _load_font($font, $encoding = null, $options = "") {
-
- // Check if the font is a native PDF font
- // Embed non-native fonts
- $test = strtolower(basename($font));
- if ( in_array($test, DOMPDF::$native_fonts) ) {
- $font = basename($font);
-
- } else {
- // Embed non-native fonts
- $options .= " embedding=true";
- }
-
- if ( is_null($encoding) ) {
-
- // Unicode encoding is only available for the commerical
- // version of PDFlib and not PDFlib-Lite
- if ( defined("DOMPDF_PDFLIB_LICENSE") )
- $encoding = "unicode";
- else
- $encoding = "auto";
-
- }
-
- $key = "$font:$encoding:$options";
-
- if ( isset($this->_fonts[$key]) )
- return $this->_fonts[$key];
-
- else {
-
- $this->_fonts[$key] = $this->_pdf->load_font($font, $encoding, $options);
- return $this->_fonts[$key];
-
- }
-
- }
-
- /**
- * Remaps y coords from 4th to 1st quadrant
- *
- * @param float $y
- * @return float
- */
- protected function y($y) { return $this->_height - $y; }
-
- //........................................................................
-
- /**
- * @param float $x1
- * @param float $y1
- * @param float $x2
- * @param float $y2
- * @param array $color
- * @param float $width
- * @param array $style
- */
- function line($x1, $y1, $x2, $y2, $color, $width, $style = null) {
- $this->_set_line_style($width, "butt", "", $style);
- $this->_set_stroke_color($color);
-
- $y1 = $this->y($y1);
- $y2 = $this->y($y2);
-
- $this->_pdf->moveto($x1, $y1);
- $this->_pdf->lineto($x2, $y2);
- $this->_pdf->stroke();
- }
-
- function arc($x1, $y1, $r1, $r2, $astart, $aend, $color, $width, $style = array()) {
- $this->_set_line_style($width, "butt", "", $style);
- $this->_set_stroke_color($color);
-
- $y1 = $this->y($y1);
-
- $this->_pdf->arc($x1, $y1, $r1, $astart, $aend);
- $this->_pdf->stroke();
- }
-
- //........................................................................
-
- function rectangle($x1, $y1, $w, $h, $color, $width, $style = null) {
- $this->_set_stroke_color($color);
- $this->_set_line_style($width, "butt", "", $style);
-
- $y1 = $this->y($y1) - $h;
-
- $this->_pdf->rect($x1, $y1, $w, $h);
- $this->_pdf->stroke();
- }
-
- //........................................................................
-
- function filled_rectangle($x1, $y1, $w, $h, $color) {
- $this->_set_fill_color($color);
-
- $y1 = $this->y($y1) - $h;
-
- $this->_pdf->rect(floatval($x1), floatval($y1), floatval($w), floatval($h));
- $this->_pdf->fill();
- }
-
- function clipping_rectangle($x1, $y1, $w, $h) {
- $this->_pdf->save();
-
- $y1 = $this->y($y1) - $h;
-
- $this->_pdf->rect(floatval($x1), floatval($y1), floatval($w), floatval($h));
- $this->_pdf->clip();
- }
-
- function clipping_roundrectangle($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) {
- // @todo
- $this->clipping_rectangle($x1, $y1, $w, $h);
- }
-
- function clipping_end() {
- $this->_pdf->restore();
- }
-
- function save() {
- $this->_pdf->save();
- }
-
- function restore() {
- $this->_pdf->restore();
- }
-
- function rotate($angle, $x, $y) {
- $pdf = $this->_pdf;
- $pdf->translate($x, $this->_height-$y);
- $pdf->rotate(-$angle);
- $pdf->translate(-$x, -$this->_height+$y);
- }
-
- function skew($angle_x, $angle_y, $x, $y) {
- $pdf = $this->_pdf;
- $pdf->translate($x, $this->_height-$y);
- $pdf->skew($angle_y, $angle_x); // Needs to be inverted
- $pdf->translate(-$x, -$this->_height+$y);
- }
-
- function scale($s_x, $s_y, $x, $y) {
- $pdf = $this->_pdf;
- $pdf->translate($x, $this->_height-$y);
- $pdf->scale($s_x, $s_y);
- $pdf->translate(-$x, -$this->_height+$y);
- }
-
- function translate($t_x, $t_y) {
- $this->_pdf->translate($t_x, -$t_y);
- }
-
- function transform($a, $b, $c, $d, $e, $f) {
- $this->_pdf->concat($a, $b, $c, $d, $e, $f);
- }
-
- //........................................................................
-
- function polygon($points, $color, $width = null, $style = null, $fill = false) {
-
- $this->_set_fill_color($color);
- $this->_set_stroke_color($color);
-
- if ( !$fill && isset($width) )
- $this->_set_line_style($width, "square", "miter", $style);
-
- $y = $this->y(array_pop($points));
- $x = array_pop($points);
- $this->_pdf->moveto($x,$y);
-
- while (count($points) > 1) {
- $y = $this->y(array_pop($points));
- $x = array_pop($points);
- $this->_pdf->lineto($x,$y);
- }
-
- if ( $fill )
- $this->_pdf->fill();
- else
- $this->_pdf->closepath_stroke();
- }
-
- //........................................................................
-
- function circle($x, $y, $r, $color, $width = null, $style = null, $fill = false) {
-
- $this->_set_fill_color($color);
- $this->_set_stroke_color($color);
-
- if ( !$fill && isset($width) )
- $this->_set_line_style($width, "round", "round", $style);
-
- $y = $this->y($y);
-
- $this->_pdf->circle($x, $y, $r);
-
- if ( $fill )
- $this->_pdf->fill();
- else
- $this->_pdf->stroke();
-
- }
-
- //........................................................................
-
- function image($img_url, $x, $y, $w, $h, $resolution = "normal") {
- $w = (int)$w;
- $h = (int)$h;
-
- $img_type = Image_Cache::detect_type($img_url, $this->_dompdf->get_http_context());
- $img_ext = Image_Cache::type_to_ext($img_type);
-
- if ( !isset($this->_imgs[$img_url]) ) {
- $this->_imgs[$img_url] = $this->_pdf->load_image($img_ext, $img_url, "");
- }
-
- $img = $this->_imgs[$img_url];
-
- $y = $this->y($y) - $h;
- $this->_pdf->fit_image($img, $x, $y, 'boxsize={'."$w $h".'} fitmethod=entire');
- }
-
- //........................................................................
-
- function text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_spacing = 0, $char_spacing = 0, $angle = 0) {
- $fh = $this->_load_font($font);
-
- $this->_pdf->setfont($fh, $size);
- $this->_set_fill_color($color);
-
- $y = $this->y($y) - Font_Metrics::get_font_height($font, $size);
-
- $word_spacing = (float)$word_spacing;
- $char_spacing = (float)$char_spacing;
- $angle = -(float)$angle;
-
- $this->_pdf->fit_textline($text, $x, $y, "rotate=$angle wordspacing=$word_spacing charspacing=$char_spacing ");
-
- }
-
- //........................................................................
-
- function javascript($code) {
- if ( defined("DOMPDF_PDFLIB_LICENSE") ) {
- $this->_pdf->create_action("JavaScript", $code);
- }
- }
-
- //........................................................................
-
- /**
- * Add a named destination (similar to ... in html)
- *
- * @param string $anchorname The name of the named destination
- */
- function add_named_dest($anchorname) {
- $this->_pdf->add_nameddest($anchorname,"");
- }
-
- //........................................................................
-
- /**
- * Add a link to the pdf
- *
- * @param string $url The url to link to
- * @param float $x The x position of the link
- * @param float $y The y position of the link
- * @param float $width The width of the link
- * @param float $height The height of the link
- */
- function add_link($url, $x, $y, $width, $height) {
-
- $y = $this->y($y) - $height;
- if ( strpos($url, '#') === 0 ) {
- // Local link
- $name = substr($url,1);
- if ( $name )
- $this->_pdf->create_annotation($x, $y, $x + $width, $y + $height, 'Link', "contents={$url} destname=". substr($url,1) . " linewidth=0");
- } else {
-
- list($proto, $host, $path, $file) = explode_url($url);
-
- if ( $proto == "" || $proto === "file://" )
- return; // Local links are not allowed
- $url = build_url($proto, $host, $path, $file);
- $url = '{' . rawurldecode($url) . '}';
-
- $action = $this->_pdf->create_action("URI", "url=" . $url);
- $this->_pdf->create_annotation($x, $y, $x + $width, $y + $height, 'Link', "contents={$url} action={activate=$action} linewidth=0");
- }
- }
-
- //........................................................................
-
- function get_text_width($text, $font, $size, $word_spacing = 0, $letter_spacing = 0) {
- $fh = $this->_load_font($font);
-
- // Determine the additional width due to extra spacing
- $num_spaces = mb_substr_count($text," ");
- $delta = $word_spacing * $num_spaces;
-
- if ( $letter_spacing ) {
- $num_chars = mb_strlen($text);
- $delta += ($num_chars - $num_spaces) * $letter_spacing;
- }
-
- return $this->_pdf->stringwidth($text, $fh, $size) + $delta;
- }
-
- //........................................................................
-
- function get_font_height($font, $size) {
-
- $fh = $this->_load_font($font);
-
- $this->_pdf->setfont($fh, $size);
-
- $asc = $this->_pdf->get_value("ascender", $fh);
- $desc = $this->_pdf->get_value("descender", $fh);
-
- // $desc is usually < 0,
- $ratio = $this->_dompdf->get_option("font_height_ratio");
- return $size * ($asc - $desc) * $ratio;
- }
-
- function get_font_baseline($font, $size) {
- $ratio = $this->_dompdf->get_option("font_height_ratio");
- return $this->get_font_height($font, $size) / $ratio * 1.1;
- }
-
- //........................................................................
-
- /**
- * Writes text at the specified x and y coordinates on every page
- *
- * The strings '{PAGE_NUM}' and '{PAGE_COUNT}' are automatically replaced
- * with their current values.
- *
- * See {@link Style::munge_color()} for the format of the color array.
- *
- * @param float $x
- * @param float $y
- * @param string $text the text to write
- * @param string $font the font file to use
- * @param float $size the font size, in points
- * @param array $color
- * @param float $word_space word spacing adjustment
- * @param float $char_space char spacing adjustment
- * @param float $angle angle to write the text at, measured CW starting from the x-axis
- */
- function page_text($x, $y, $text, $font, $size, $color = array(0,0,0), $word_space = 0.0, $char_space = 0.0, $angle = 0.0) {
- $_t = "text";
- $this->_page_text[] = compact("_t", "x", "y", "text", "font", "size", "color", "word_space", "char_space", "angle");
- }
-
- //........................................................................
-
- /**
- * Processes a script on every page
- *
- * The variables $pdf, $PAGE_NUM, and $PAGE_COUNT are available.
- *
- * This function can be used to add page numbers to all pages
- * after the first one, for example.
- *
- * @param string $code the script code
- * @param string $type the language type for script
- */
- function page_script($code, $type = "text/php") {
- $_t = "script";
- $this->_page_text[] = compact("_t", "code", "type");
- }
-
- //........................................................................
-
- function new_page() {
-
- // Add objects to the current page
- $this->_place_objects();
-
- $this->_pdf->suspend_page("");
- $this->_pdf->begin_page_ext($this->_width, $this->_height, "");
- $this->_page_number = ++$this->_page_count;
-
- }
-
- //........................................................................
-
- /**
- * Add text to each page after rendering is complete
- */
- protected function _add_page_text() {
-
- if ( !count($this->_page_text) )
- return;
-
- $this->_pdf->suspend_page("");
-
- for ($p = 1; $p <= $this->_page_count; $p++) {
- $this->_pdf->resume_page("pagenumber=$p");
-
- foreach ($this->_page_text as $pt) {
- extract($pt);
-
- switch ($_t) {
-
- case "text":
- $text = str_replace(array("{PAGE_NUM}","{PAGE_COUNT}"),
- array($p, $this->_page_count), $text);
- $this->text($x, $y, $text, $font, $size, $color, $word_space, $char_space, $angle);
- break;
-
- case "script":
- if (!$eval) {
- $eval = new PHP_Evaluator($this);
- }
- $eval->evaluate($code, array('PAGE_NUM' => $p, 'PAGE_COUNT' => $this->_page_count));
- break;
- }
- }
-
- $this->_pdf->suspend_page("");
- }
-
- $this->_pdf->resume_page("pagenumber=".$this->_page_number);
- }
-
- //........................................................................
-
- function stream($filename, $options = null) {
-
- // Add page text
- $this->_add_page_text();
-
- if ( isset($options["compress"]) && $options["compress"] != 1 )
- $this->_pdf->set_value("compress", 0);
- else
- $this->_pdf->set_value("compress", 6);
-
- $this->_close();
-
- $data = "";
-
- if ( self::$IN_MEMORY ) {
- $data = $this->_pdf->get_buffer();
- //$size = strlen($data);
- } else {
- //$size = filesize($this->_file);
- }
-
-
- $filename = str_replace(array("\n","'"),"", $filename);
- $attach = (isset($options["Attachment"]) && $options["Attachment"]) ? "attachment" : "inline";
-
- header("Cache-Control: private");
- header("Content-type: application/pdf");
- header("Content-Disposition: $attach; filename=\"$filename\"");
-
- //header("Content-length: " . $size);
-
- if ( self::$IN_MEMORY )
- echo $data;
-
- else {
-
- // Chunked readfile()
- $chunk = (1 << 21); // 2 MB
- $fh = fopen($this->_file, "rb");
- if ( !$fh )
- throw new DOMPDF_Exception("Unable to load temporary PDF file: " . $this->_file);
-
- while ( !feof($fh) )
- echo fread($fh,$chunk);
- fclose($fh);
-
- //debugpng
- if (DEBUGPNG) print '[pdflib stream unlink '.$this->_file.']';
- if (!DEBUGKEEPTEMP)
-
- unlink($this->_file);
- $this->_file = null;
- unset($this->_file);
- }
-
- flush();
- }
-
- //........................................................................
-
- function output($options = null) {
-
- // Add page text
- $this->_add_page_text();
-
- if ( isset($options["compress"]) && $options["compress"] != 1 )
- $this->_pdf->set_value("compress", 0);
- else
- $this->_pdf->set_value("compress", 6);
-
- $this->_close();
-
- if ( self::$IN_MEMORY )
- $data = $this->_pdf->get_buffer();
-
- else {
- $data = file_get_contents($this->_file);
-
- //debugpng
- if (DEBUGPNG) print '[pdflib output unlink '.$this->_file.']';
- if (!DEBUGKEEPTEMP)
-
- unlink($this->_file);
- $this->_file = null;
- unset($this->_file);
- }
-
- return $data;
- }
-}
-
-// Workaround for idiotic limitation on statics...
-PDFLib_Adapter::$PAPER_SIZES = CPDF_Adapter::$PAPER_SIZES;
diff --git a/library/vendor/dompdf/include/php_evaluator.cls.php b/library/vendor/dompdf/include/php_evaluator.cls.php
deleted file mode 100644
index 38896675d..000000000
--- a/library/vendor/dompdf/include/php_evaluator.cls.php
+++ /dev/null
@@ -1,48 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Executes inline PHP code during the rendering process
- *
- * @access private
- * @package dompdf
- */
-class PHP_Evaluator {
-
- /**
- * @var Canvas
- */
- protected $_canvas;
-
- function __construct(Canvas $canvas) {
- $this->_canvas = $canvas;
- }
-
- function evaluate($code, $vars = array()) {
- if ( !$this->_canvas->get_dompdf()->get_option("enable_php") ) {
- return;
- }
-
- // Set up some variables for the inline code
- $pdf = $this->_canvas;
- $PAGE_NUM = $pdf->get_page_number();
- $PAGE_COUNT = $pdf->get_page_count();
-
- // Override those variables if passed in
- foreach ($vars as $k => $v) {
- $$k = $v;
- }
-
- //$code = html_entity_decode($code); // @todo uncomment this when tested
- eval($code);
- }
-
- function render(Frame $frame) {
- $this->evaluate($frame->get_node()->nodeValue);
- }
-}
diff --git a/library/vendor/dompdf/include/positioner.cls.php b/library/vendor/dompdf/include/positioner.cls.php
deleted file mode 100644
index 6a8b9edc1..000000000
--- a/library/vendor/dompdf/include/positioner.cls.php
+++ /dev/null
@@ -1,51 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Base Positioner class
- *
- * Defines postioner interface
- *
- * @access private
- * @package dompdf
- */
-abstract class Positioner {
-
- /**
- * @var Frame_Decorator
- */
- protected $_frame;
-
- //........................................................................
-
- function __construct(Frame_Decorator $frame) {
- $this->_frame = $frame;
- }
-
- /**
- * Class destructor
- */
- function __destruct() {
- clear_object($this);
- }
- //........................................................................
-
- abstract function position();
-
- function move($offset_x, $offset_y, $ignore_self = false) {
- list($x, $y) = $this->_frame->get_position();
-
- if ( !$ignore_self ) {
- $this->_frame->set_position($x + $offset_x, $y + $offset_y);
- }
-
- foreach($this->_frame->get_children() as $child) {
- $child->move($offset_x, $offset_y);
- }
- }
-}
diff --git a/library/vendor/dompdf/include/renderer.cls.php b/library/vendor/dompdf/include/renderer.cls.php
deleted file mode 100644
index ceff4775c..000000000
--- a/library/vendor/dompdf/include/renderer.cls.php
+++ /dev/null
@@ -1,290 +0,0 @@
-
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Concrete renderer
- *
- * Instantiates several specific renderers in order to render any given
- * frame.
- *
- * @access private
- * @package dompdf
- */
-class Renderer extends Abstract_Renderer {
-
- /**
- * Array of renderers for specific frame types
- *
- * @var Abstract_Renderer[]
- */
- protected $_renderers;
-
- /**
- * Cache of the callbacks array
- *
- * @var array
- */
- private $_callbacks;
-
- /**
- * Class destructor
- */
- function __destruct() {
- clear_object($this);
- }
-
- /**
- * Advance the canvas to the next page
- */
- function new_page() {
- $this->_canvas->new_page();
- }
-
- /**
- * Render frames recursively
- *
- * @param Frame $frame the frame to render
- */
- function render(Frame $frame) {
- global $_dompdf_debug;
-
- if ( $_dompdf_debug ) {
- echo $frame;
- flush();
- }
-
- $style = $frame->get_style();
-
- if ( in_array($style->visibility, array("hidden", "collapse")) ) {
- return;
- }
-
- $display = $style->display;
-
- // Starts the CSS transformation
- if ( $style->transform && is_array($style->transform) ) {
- $this->_canvas->save();
- list($x, $y) = $frame->get_padding_box();
- $origin = $style->transform_origin;
-
- foreach($style->transform as $transform) {
- list($function, $values) = $transform;
- if ( $function === "matrix" ) {
- $function = "transform";
- }
-
- $values = array_map("floatval", $values);
- $values[] = $x + $style->length_in_pt($origin[0], $style->width);
- $values[] = $y + $style->length_in_pt($origin[1], $style->height);
-
- call_user_func_array(array($this->_canvas, $function), $values);
- }
- }
-
- switch ($display) {
-
- case "block":
- case "list-item":
- case "inline-block":
- case "table":
- case "inline-table":
- $this->_render_frame("block", $frame);
- break;
-
- case "inline":
- if ( $frame->is_text_node() )
- $this->_render_frame("text", $frame);
- else
- $this->_render_frame("inline", $frame);
- break;
-
- case "table-cell":
- $this->_render_frame("table-cell", $frame);
- break;
-
- case "table-row-group":
- case "table-header-group":
- case "table-footer-group":
- $this->_render_frame("table-row-group", $frame);
- break;
-
- case "-dompdf-list-bullet":
- $this->_render_frame("list-bullet", $frame);
- break;
-
- case "-dompdf-image":
- $this->_render_frame("image", $frame);
- break;
-
- case "none":
- $node = $frame->get_node();
-
- if ( $node->nodeName === "script" ) {
- if ( $node->getAttribute("type") === "text/php" ||
- $node->getAttribute("language") === "php" ) {
- // Evaluate embedded php scripts
- $this->_render_frame("php", $frame);
- }
-
- elseif ( $node->getAttribute("type") === "text/javascript" ||
- $node->getAttribute("language") === "javascript" ) {
- // Insert JavaScript
- $this->_render_frame("javascript", $frame);
- }
- }
-
- // Don't render children, so skip to next iter
- return;
-
- default:
- break;
-
- }
-
- // Starts the overflow: hidden box
- if ( $style->overflow === "hidden" ) {
- list($x, $y, $w, $h) = $frame->get_padding_box();
-
- // get border radii
- $style = $frame->get_style();
- list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
-
- if ( $tl + $tr + $br + $bl > 0 ) {
- $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
- }
- else {
- $this->_canvas->clipping_rectangle($x, $y, $w, $h);
- }
- }
-
- $stack = array();
-
- foreach ($frame->get_children() as $child) {
- // < 0 : nagative z-index
- // = 0 : no z-index, no stacking context
- // = 1 : stacking context without z-index
- // > 1 : z-index
- $child_style = $child->get_style();
- $child_z_index = $child_style->z_index;
- $z_index = 0;
-
- if ( $child_z_index !== "auto" ) {
- $z_index = intval($child_z_index) + 1;
- }
- elseif ( $child_style->float !== "none" || $child->is_positionned()) {
- $z_index = 1;
- }
-
- $stack[$z_index][] = $child;
- }
-
- ksort($stack);
-
- foreach ($stack as $by_index) {
- foreach($by_index as $child) {
- $this->render($child);
- }
- }
-
- // Ends the overflow: hidden box
- if ( $style->overflow === "hidden" ) {
- $this->_canvas->clipping_end();
- }
-
- if ( $style->transform && is_array($style->transform) ) {
- $this->_canvas->restore();
- }
-
- // Check for end frame callback
- $this->_check_callbacks("end_frame", $frame);
- }
-
- /**
- * Check for callbacks that need to be performed when a given event
- * gets triggered on a frame
- *
- * @param string $event the type of event
- * @param Frame $frame the frame that event is triggered on
- */
- protected function _check_callbacks($event, $frame) {
- if (!isset($this->_callbacks)) {
- $this->_callbacks = $this->_dompdf->get_callbacks();
- }
-
- if (is_array($this->_callbacks) && isset($this->_callbacks[$event])) {
- $info = array(0 => $this->_canvas, "canvas" => $this->_canvas,
- 1 => $frame, "frame" => $frame);
- $fs = $this->_callbacks[$event];
- foreach ($fs as $f) {
- if (is_callable($f)) {
- if (is_array($f)) {
- $f[0]->$f[1]($info);
- } else {
- $f($info);
- }
- }
- }
- }
- }
-
- /**
- * Render a single frame
- *
- * Creates Renderer objects on demand
- *
- * @param string $type type of renderer to use
- * @param Frame $frame the frame to render
- */
- protected function _render_frame($type, $frame) {
-
- if ( !isset($this->_renderers[$type]) ) {
-
- switch ($type) {
- case "block":
- $this->_renderers[$type] = new Block_Renderer($this->_dompdf);
- break;
-
- case "inline":
- $this->_renderers[$type] = new Inline_Renderer($this->_dompdf);
- break;
-
- case "text":
- $this->_renderers[$type] = new Text_Renderer($this->_dompdf);
- break;
-
- case "image":
- $this->_renderers[$type] = new Image_Renderer($this->_dompdf);
- break;
-
- case "table-cell":
- $this->_renderers[$type] = new Table_Cell_Renderer($this->_dompdf);
- break;
-
- case "table-row-group":
- $this->_renderers[$type] = new Table_Row_Group_Renderer($this->_dompdf);
- break;
-
- case "list-bullet":
- $this->_renderers[$type] = new List_Bullet_Renderer($this->_dompdf);
- break;
-
- case "php":
- $this->_renderers[$type] = new PHP_Evaluator($this->_canvas);
- break;
-
- case "javascript":
- $this->_renderers[$type] = new Javascript_Embedder($this->_dompdf);
- break;
-
- }
- }
-
- $this->_renderers[$type]->render($frame);
-
- }
-}
diff --git a/library/vendor/dompdf/include/style.cls.php b/library/vendor/dompdf/include/style.cls.php
deleted file mode 100644
index d08fb4baa..000000000
--- a/library/vendor/dompdf/include/style.cls.php
+++ /dev/null
@@ -1,2435 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * Represents CSS properties.
- *
- * The Style class is responsible for handling and storing CSS properties.
- * It includes methods to resolve colors and lengths, as well as getters &
- * setters for many CSS properites.
- *
- * Actual CSS parsing is performed in the {@link Stylesheet} class.
- *
- * @package dompdf
- */
-class Style {
-
- const CSS_IDENTIFIER = "-?[_a-zA-Z]+[_a-zA-Z0-9-]*";
- const CSS_INTEGER = "-?\d+";
-
- /**
- * Default font size, in points.
- *
- * @var float
- */
- static $default_font_size = 12;
-
- /**
- * Default line height, as a fraction of the font size.
- *
- * @var float
- */
- static $default_line_height = 1.2;
-
- /**
- * Default "absolute" font sizes relative to the default font-size
- * http://www.w3.org/TR/css3-fonts/#font-size-the-font-size-property
- * @var array
- */
- static $font_size_keywords = array(
- "xx-small" => 0.6, // 3/5
- "x-small" => 0.75, // 3/4
- "small" => 0.889, // 8/9
- "medium" => 1, // 1
- "large" => 1.2, // 6/5
- "x-large" => 1.5, // 3/2
- "xx-large" => 2.0, // 2/1
- );
-
- /**
- * List of all inline types. Should really be a constant.
- *
- * @var array
- */
- static $INLINE_TYPES = array("inline");
-
- /**
- * List of all block types. Should really be a constant.
- *
- * @var array
- */
- static $BLOCK_TYPES = array("block", "inline-block", "table-cell", "list-item");
-
- /**
- * List of all positionned types. Should really be a constant.
- *
- * @var array
- */
- static $POSITIONNED_TYPES = array("relative", "absolute", "fixed");
-
- /**
- * List of all table types. Should really be a constant.
- *
- * @var array;
- */
- static $TABLE_TYPES = array("table", "inline-table");
-
- /**
- * List of valid border styles. Should also really be a constant.
- *
- * @var array
- */
- static $BORDER_STYLES = array("none", "hidden", "dotted", "dashed", "solid",
- "double", "groove", "ridge", "inset", "outset");
-
- /**
- * Default style values.
- *
- * @link http://www.w3.org/TR/CSS21/propidx.html
- *
- * @var array
- */
- static protected $_defaults = null;
-
- /**
- * List of inherited properties
- *
- * @link http://www.w3.org/TR/CSS21/propidx.html
- *
- * @var array
- */
- static protected $_inherited = null;
-
- /**
- * Caches method_exists result
- *
- * @var array
- */
- static protected $_methods_cache = array();
-
- /**
- * The stylesheet this style belongs to
- *
- * @see Stylesheet
- * @var Stylesheet
- */
- protected $_stylesheet; // stylesheet this style is attached to
-
- /**
- * Main array of all CSS properties & values
- *
- * @var array
- */
- protected $_props;
-
- /* var instead of protected would allow access outside of class */
- protected $_important_props;
-
- /**
- * Cached property values
- *
- * @var array
- */
- protected $_prop_cache;
-
- /**
- * Font size of parent element in document tree. Used for relative font
- * size resolution.
- *
- * @var float
- */
- protected $_parent_font_size; // Font size of parent element
-
- protected $_font_family;
-
- /**
- * @var Frame
- */
- protected $_frame;
-
- /**
- * The origin of the style
- *
- * @var int
- */
- protected $_origin = Stylesheet::ORIG_AUTHOR;
-
- // private members
- /**
- * True once the font size is resolved absolutely
- *
- * @var bool
- */
- private $__font_size_calculated; // Cache flag
-
- /**
- * The computed border radius
- */
- private $_computed_border_radius = null;
-
- /**
- * @var bool
- */
- public $_has_border_radius = false;
-
- /**
- * Class constructor
- *
- * @param Stylesheet $stylesheet the stylesheet this Style is associated with.
- * @param int $origin
- */
- function __construct(Stylesheet $stylesheet, $origin = Stylesheet::ORIG_AUTHOR) {
- $this->_props = array();
- $this->_important_props = array();
- $this->_stylesheet = $stylesheet;
- $this->_origin = $origin;
- $this->_parent_font_size = null;
- $this->__font_size_calculated = false;
-
- if ( !isset(self::$_defaults) ) {
-
- // Shorthand
- $d =& self::$_defaults;
-
- // All CSS 2.1 properties, and their default values
- $d["azimuth"] = "center";
- $d["background_attachment"] = "scroll";
- $d["background_color"] = "transparent";
- $d["background_image"] = "none";
- $d["background_image_resolution"] = "normal";
- $d["_dompdf_background_image_resolution"] = $d["background_image_resolution"];
- $d["background_position"] = "0% 0%";
- $d["background_repeat"] = "repeat";
- $d["background"] = "";
- $d["border_collapse"] = "separate";
- $d["border_color"] = "";
- $d["border_spacing"] = "0";
- $d["border_style"] = "";
- $d["border_top"] = "";
- $d["border_right"] = "";
- $d["border_bottom"] = "";
- $d["border_left"] = "";
- $d["border_top_color"] = "";
- $d["border_right_color"] = "";
- $d["border_bottom_color"] = "";
- $d["border_left_color"] = "";
- $d["border_top_style"] = "none";
- $d["border_right_style"] = "none";
- $d["border_bottom_style"] = "none";
- $d["border_left_style"] = "none";
- $d["border_top_width"] = "medium";
- $d["border_right_width"] = "medium";
- $d["border_bottom_width"] = "medium";
- $d["border_left_width"] = "medium";
- $d["border_width"] = "medium";
- $d["border_bottom_left_radius"] = "";
- $d["border_bottom_right_radius"] = "";
- $d["border_top_left_radius"] = "";
- $d["border_top_right_radius"] = "";
- $d["border_radius"] = "";
- $d["border"] = "";
- $d["bottom"] = "auto";
- $d["caption_side"] = "top";
- $d["clear"] = "none";
- $d["clip"] = "auto";
- $d["color"] = "#000000";
- $d["content"] = "normal";
- $d["counter_increment"] = "none";
- $d["counter_reset"] = "none";
- $d["cue_after"] = "none";
- $d["cue_before"] = "none";
- $d["cue"] = "";
- $d["cursor"] = "auto";
- $d["direction"] = "ltr";
- $d["display"] = "inline";
- $d["elevation"] = "level";
- $d["empty_cells"] = "show";
- $d["float"] = "none";
- $d["font_family"] = $stylesheet->get_dompdf()->get_option("default_font");
- $d["font_size"] = "medium";
- $d["font_style"] = "normal";
- $d["font_variant"] = "normal";
- $d["font_weight"] = "normal";
- $d["font"] = "";
- $d["height"] = "auto";
- $d["image_resolution"] = "normal";
- $d["_dompdf_image_resolution"] = $d["image_resolution"];
- $d["_dompdf_keep"] = "";
- $d["left"] = "auto";
- $d["letter_spacing"] = "normal";
- $d["line_height"] = "normal";
- $d["list_style_image"] = "none";
- $d["list_style_position"] = "outside";
- $d["list_style_type"] = "disc";
- $d["list_style"] = "";
- $d["margin_right"] = "0";
- $d["margin_left"] = "0";
- $d["margin_top"] = "0";
- $d["margin_bottom"] = "0";
- $d["margin"] = "";
- $d["max_height"] = "none";
- $d["max_width"] = "none";
- $d["min_height"] = "0";
- $d["min_width"] = "0";
- $d["opacity"] = "1.0"; // CSS3
- $d["orphans"] = "2";
- $d["outline_color"] = ""; // "invert" special color is not supported
- $d["outline_style"] = "none";
- $d["outline_width"] = "medium";
- $d["outline"] = "";
- $d["overflow"] = "visible";
- $d["padding_top"] = "0";
- $d["padding_right"] = "0";
- $d["padding_bottom"] = "0";
- $d["padding_left"] = "0";
- $d["padding"] = "";
- $d["page_break_after"] = "auto";
- $d["page_break_before"] = "auto";
- $d["page_break_inside"] = "auto";
- $d["pause_after"] = "0";
- $d["pause_before"] = "0";
- $d["pause"] = "";
- $d["pitch_range"] = "50";
- $d["pitch"] = "medium";
- $d["play_during"] = "auto";
- $d["position"] = "static";
- $d["quotes"] = "";
- $d["richness"] = "50";
- $d["right"] = "auto";
- $d["size"] = "auto"; // @page
- $d["speak_header"] = "once";
- $d["speak_numeral"] = "continuous";
- $d["speak_punctuation"] = "none";
- $d["speak"] = "normal";
- $d["speech_rate"] = "medium";
- $d["stress"] = "50";
- $d["table_layout"] = "auto";
- $d["text_align"] = "left";
- $d["text_decoration"] = "none";
- $d["text_indent"] = "0";
- $d["text_transform"] = "none";
- $d["top"] = "auto";
- $d["transform"] = "none"; // CSS3
- $d["transform_origin"] = "50% 50%"; // CSS3
- $d["_webkit_transform"] = $d["transform"]; // CSS3
- $d["_webkit_transform_origin"] = $d["transform_origin"]; // CSS3
- $d["unicode_bidi"] = "normal";
- $d["vertical_align"] = "baseline";
- $d["visibility"] = "visible";
- $d["voice_family"] = "";
- $d["volume"] = "medium";
- $d["white_space"] = "normal";
- $d["word_wrap"] = "normal";
- $d["widows"] = "2";
- $d["width"] = "auto";
- $d["word_spacing"] = "normal";
- $d["z_index"] = "auto";
-
- // for @font-face
- $d["src"] = "";
- $d["unicode_range"] = "";
-
- // Properties that inherit by default
- self::$_inherited = array(
- "azimuth",
- "background_image_resolution",
- "border_collapse",
- "border_spacing",
- "caption_side",
- "color",
- "cursor",
- "direction",
- "elevation",
- "empty_cells",
- "font_family",
- "font_size",
- "font_style",
- "font_variant",
- "font_weight",
- "font",
- "image_resolution",
- "letter_spacing",
- "line_height",
- "list_style_image",
- "list_style_position",
- "list_style_type",
- "list_style",
- "orphans",
- "page_break_inside",
- "pitch_range",
- "pitch",
- "quotes",
- "richness",
- "speak_header",
- "speak_numeral",
- "speak_punctuation",
- "speak",
- "speech_rate",
- "stress",
- "text_align",
- "text_indent",
- "text_transform",
- "visibility",
- "voice_family",
- "volume",
- "white_space",
- "word_wrap",
- "widows",
- "word_spacing",
- );
- }
- }
-
- /**
- * "Destructor": forcibly free all references held by this object
- */
- function dispose() {
- clear_object($this);
- }
-
- function set_frame(Frame $frame) {
- $this->_frame = $frame;
- }
-
- function get_frame() {
- return $this->_frame;
- }
-
- function set_origin($origin) {
- $this->_origin = $origin;
- }
-
- function get_origin() {
- return $this->_origin;
- }
-
- /**
- * returns the {@link Stylesheet} this Style is associated with.
- *
- * @return Stylesheet
- */
- function get_stylesheet() { return $this->_stylesheet; }
-
- /**
- * Converts any CSS length value into an absolute length in points.
- *
- * length_in_pt() takes a single length (e.g. '1em') or an array of
- * lengths and returns an absolute length. If an array is passed, then
- * the return value is the sum of all elements.
- *
- * If a reference size is not provided, the default font size is used
- * ({@link Style::$default_font_size}).
- *
- * @param float|array $length the length or array of lengths to resolve
- * @param float $ref_size an absolute reference size to resolve percentage lengths
- * @return float
- */
- function length_in_pt($length, $ref_size = null) {
- static $cache = array();
-
- if ( !is_array($length) ) {
- $length = array($length);
- }
-
- if ( !isset($ref_size) ) {
- $ref_size = self::$default_font_size;
- }
-
- $key = implode("@", $length)."/$ref_size";
-
- if ( isset($cache[$key]) ) {
- return $cache[$key];
- }
-
- $ret = 0;
- foreach ($length as $l) {
-
- if ( $l === "auto" ) {
- return "auto";
- }
-
- if ( $l === "none" ) {
- return "none";
- }
-
- // Assume numeric values are already in points
- if ( is_numeric($l) ) {
- $ret += $l;
- continue;
- }
-
- if ( $l === "normal" ) {
- $ret += $ref_size;
- continue;
- }
-
- // Border lengths
- if ( $l === "thin" ) {
- $ret += 0.5;
- continue;
- }
-
- if ( $l === "medium" ) {
- $ret += 1.5;
- continue;
- }
-
- if ( $l === "thick" ) {
- $ret += 2.5;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "px")) !== false ) {
- $dpi = $this->_stylesheet->get_dompdf()->get_option("dpi");
- $ret += ( mb_substr($l, 0, $i) * 72 ) / $dpi;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "pt")) !== false ) {
- $ret += (float)mb_substr($l, 0, $i);
- continue;
- }
-
- if ( ($i = mb_strpos($l, "%")) !== false ) {
- $ret += (float)mb_substr($l, 0, $i)/100 * $ref_size;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "rem")) !== false ) {
- $ret += (float)mb_substr($l, 0, $i) * $this->_stylesheet->get_dompdf()->get_tree()->get_root()->get_style()->font_size;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "em")) !== false ) {
- $ret += (float)mb_substr($l, 0, $i) * $this->__get("font_size");
- continue;
- }
-
- if ( ($i = mb_strpos($l, "cm")) !== false ) {
- $ret += mb_substr($l, 0, $i) * 72 / 2.54;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "mm")) !== false ) {
- $ret += mb_substr($l, 0, $i) * 72 / 25.4;
- continue;
- }
-
- // FIXME: em:ex ratio?
- if ( ($i = mb_strpos($l, "ex")) !== false ) {
- $ret += mb_substr($l, 0, $i) * $this->__get("font_size") / 2;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "in")) !== false ) {
- $ret += (float)mb_substr($l, 0, $i) * 72;
- continue;
- }
-
- if ( ($i = mb_strpos($l, "pc")) !== false ) {
- $ret += (float)mb_substr($l, 0, $i) * 12;
- continue;
- }
-
- // Bogus value
- $ret += $ref_size;
- }
-
- return $cache[$key] = $ret;
- }
-
-
- /**
- * Set inherited properties in this style using values in $parent
- *
- * @param Style $parent
- *
- * @return Style
- */
- function inherit(Style $parent) {
-
- // Set parent font size
- $this->_parent_font_size = $parent->get_font_size();
-
- foreach (self::$_inherited as $prop) {
- //inherit the !important property also.
- //if local property is also !important, don't inherit.
- if ( isset($parent->_props[$prop]) &&
- ( !isset($this->_props[$prop]) ||
- ( isset($parent->_important_props[$prop]) && !isset($this->_important_props[$prop]) )
- )
- ) {
- if ( isset($parent->_important_props[$prop]) ) {
- $this->_important_props[$prop] = true;
- }
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$prop] = null;
- $this->_props[$prop] = $parent->_props[$prop];
- }
- }
-
- foreach ($this->_props as $prop => $value) {
- if ( $value === "inherit" ) {
- if ( isset($parent->_important_props[$prop]) ) {
- $this->_important_props[$prop] = true;
- }
- //do not assign direct, but
- //implicite assignment through __set, redirect to specialized, get value with __get
- //This is for computing defaults if the parent setting is also missing.
- //Therefore do not directly assign the value without __set
- //set _important_props before that to be able to propagate.
- //see __set and __get, on all assignments clear cache!
- //$this->_prop_cache[$prop] = null;
- //$this->_props[$prop] = $parent->_props[$prop];
- //props_set for more obvious explicite assignment not implemented, because
- //too many implicite uses.
- // $this->props_set($prop, $parent->$prop);
- $this->__set($prop, $parent->__get($prop));
- }
- }
-
- return $this;
- }
-
- /**
- * Override properties in this style with those in $style
- *
- * @param Style $style
- */
- function merge(Style $style) {
- //treat the !important attribute
- //if old rule has !important attribute, override with new rule only if
- //the new rule is also !important
- foreach($style->_props as $prop => $val ) {
- if (isset($style->_important_props[$prop])) {
- $this->_important_props[$prop] = true;
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$prop] = null;
- $this->_props[$prop] = $val;
- }
- else if ( !isset($this->_important_props[$prop]) ) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$prop] = null;
- $this->_props[$prop] = $val;
- }
- }
-
- if ( isset($style->_props["font_size"]) ) {
- $this->__font_size_calculated = false;
- }
- }
-
- /**
- * Returns an array(r, g, b, "r"=> r, "g"=>g, "b"=>b, "hex"=>"#rrggbb")
- * based on the provided CSS color value.
- *
- * @param string $color
- * @return array
- */
- function munge_color($color) {
- return CSS_Color::parse($color);
- }
-
- /* direct access to _important_props array from outside would work only when declared as
- * 'var $_important_props;' instead of 'protected $_important_props;'
- * Don't call _set/__get on missing attribute. Therefore need a special access.
- * Assume that __set will be also called when this is called, so do not check validity again.
- * Only created, if !important exists -> always set true.
- */
- function important_set($prop) {
- $prop = str_replace("-", "_", $prop);
- $this->_important_props[$prop] = true;
- }
-
- function important_get($prop) {
- return isset($this->_important_props[$prop]);
- }
-
- /**
- * PHP5 overloaded setter
- *
- * This function along with {@link Style::__get()} permit a user of the
- * Style class to access any (CSS) property using the following syntax:
- *
- * Style->margin_top = "1em";
- * echo (Style->margin_top);
- *
- *
- * __set() automatically calls the provided set function, if one exists,
- * otherwise it sets the property directly. Typically, __set() is not
- * called directly from outside of this class.
- *
- * On each modification clear cache to return accurate setting.
- * Also affects direct settings not using __set
- * For easier finding all assignments, attempted to allowing only explicite assignment:
- * Very many uses, e.g. frame_reflower.cls.php -> for now leave as it is
- * function __set($prop, $val) {
- * throw new DOMPDF_Exception("Implicite replacement of assignment by __set. Not good.");
- * }
- * function props_set($prop, $val) { ... }
- *
- * @param string $prop the property to set
- * @param mixed $val the value of the property
- *
- */
- function __set($prop, $val) {
- $prop = str_replace("-", "_", $prop);
- $this->_prop_cache[$prop] = null;
-
- if ( !isset(self::$_defaults[$prop]) ) {
- global $_dompdf_warnings;
- $_dompdf_warnings[] = "'$prop' is not a valid CSS2 property.";
- return;
- }
-
- if ( $prop !== "content" && is_string($val) && strlen($val) > 5 && mb_strpos($val, "url") === false ) {
- $val = mb_strtolower(trim(str_replace(array("\n", "\t"), array(" "), $val)));
- $val = preg_replace("/([0-9]+) (pt|px|pc|em|ex|in|cm|mm|%)/S", "\\1\\2", $val);
- }
-
- $method = "set_$prop";
-
- if ( !isset(self::$_methods_cache[$method]) ) {
- self::$_methods_cache[$method] = method_exists($this, $method);
- }
-
- if ( self::$_methods_cache[$method] ) {
- $this->$method($val);
- }
- else {
- $this->_props[$prop] = $val;
- }
- }
-
- /**
- * PHP5 overloaded getter
- * Along with {@link Style::__set()} __get() provides access to all CSS
- * properties directly. Typically __get() is not called directly outside
- * of this class.
- * On each modification clear cache to return accurate setting.
- * Also affects direct settings not using __set
- *
- * @param string $prop
- *
- * @throws DOMPDF_Exception
- * @return mixed
- */
- function __get($prop) {
- if ( !isset(self::$_defaults[$prop]) ) {
- throw new DOMPDF_Exception("'$prop' is not a valid CSS2 property.");
- }
-
- if ( isset($this->_prop_cache[$prop]) && $this->_prop_cache[$prop] != null ) {
- return $this->_prop_cache[$prop];
- }
-
- $method = "get_$prop";
-
- // Fall back on defaults if property is not set
- if ( !isset($this->_props[$prop]) ) {
- $this->_props[$prop] = self::$_defaults[$prop];
- }
-
- if ( !isset(self::$_methods_cache[$method]) ) {
- self::$_methods_cache[$method] = method_exists($this, $method);
- }
-
- if ( self::$_methods_cache[$method] ) {
- return $this->_prop_cache[$prop] = $this->$method();
- }
-
- return $this->_prop_cache[$prop] = $this->_props[$prop];
- }
-
- function get_font_family_raw(){
- return trim($this->_props["font_family"], " \t\n\r\x0B\"'");
- }
-
- /**
- * Getter for the 'font-family' CSS property.
- * Uses the {@link Font_Metrics} class to resolve the font family into an
- * actual font file.
- *
- * @link http://www.w3.org/TR/CSS21/fonts.html#propdef-font-family
- * @throws DOMPDF_Exception
- *
- * @return string
- */
- function get_font_family() {
- if ( isset($this->_font_family) ) {
- return $this->_font_family;
- }
-
- $DEBUGCSS=DEBUGCSS; //=DEBUGCSS; Allow override of global setting for ad hoc debug
-
- // Select the appropriate font. First determine the subtype, then check
- // the specified font-families for a candidate.
-
- // Resolve font-weight
- $weight = $this->__get("font_weight");
-
- if ( is_numeric($weight) ) {
- if ( $weight < 600 ) {
- $weight = "normal";
- }
- else {
- $weight = "bold";
- }
- }
- else if ( $weight === "bold" || $weight === "bolder" ) {
- $weight = "bold";
- }
- else {
- $weight = "normal";
- }
-
- // Resolve font-style
- $font_style = $this->__get("font_style");
-
- if ( $weight === "bold" && ($font_style === "italic" || $font_style === "oblique") ) {
- $subtype = "bold_italic";
- }
- else if ( $weight === "bold" && $font_style !== "italic" && $font_style !== "oblique" ) {
- $subtype = "bold";
- }
- else if ( $weight !== "bold" && ($font_style === "italic" || $font_style === "oblique") ) {
- $subtype = "italic";
- }
- else {
- $subtype = "normal";
- }
-
- // Resolve the font family
- if ( $DEBUGCSS ) {
- print "[get_font_family:";
- print '('.$this->_props["font_family"].'.'.$font_style.'.'.$this->__get("font_weight").'.'.$weight.'.'.$subtype.')';
- }
-
- $families = preg_split("/\s*,\s*/", $this->_props["font_family"]);
-
- $font = null;
- foreach($families as $family) {
- //remove leading and trailing string delimiters, e.g. on font names with spaces;
- //remove leading and trailing whitespace
- $family = trim($family, " \t\n\r\x0B\"'");
- if ( $DEBUGCSS ) {
- print '('.$family.')';
- }
- $font = Font_Metrics::get_font($family, $subtype);
-
- if ( $font ) {
- if ($DEBUGCSS) print '('.$font.")get_font_family]\n ";
- return $this->_font_family = $font;
- }
- }
-
- $family = null;
- if ( $DEBUGCSS ) {
- print '(default)';
- }
- $font = Font_Metrics::get_font($family, $subtype);
-
- if ( $font ) {
- if ( $DEBUGCSS ) print '('.$font.")get_font_family]\n";
- return$this->_font_family = $font;
- }
-
- throw new DOMPDF_Exception("Unable to find a suitable font replacement for: '" . $this->_props["font_family"] ."'");
-
- }
-
- /**
- * Returns the resolved font size, in points
- *
- * @link http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size
- * @return float
- */
- function get_font_size() {
-
- if ( $this->__font_size_calculated ) {
- return $this->_props["font_size"];
- }
-
- if ( !isset($this->_props["font_size"]) ) {
- $fs = self::$_defaults["font_size"];
- }
- else {
- $fs = $this->_props["font_size"];
- }
-
- if ( !isset($this->_parent_font_size) ) {
- $this->_parent_font_size = self::$default_font_size;
- }
-
- switch ((string)$fs) {
- case "xx-small":
- case "x-small":
- case "small":
- case "medium":
- case "large":
- case "x-large":
- case "xx-large":
- $fs = self::$default_font_size * self::$font_size_keywords[$fs];
- break;
-
- case "smaller":
- $fs = 8/9 * $this->_parent_font_size;
- break;
-
- case "larger":
- $fs = 6/5 * $this->_parent_font_size;
- break;
-
- default:
- break;
- }
-
- // Ensure relative sizes resolve to something
- if ( ($i = mb_strpos($fs, "em")) !== false ) {
- $fs = mb_substr($fs, 0, $i) * $this->_parent_font_size;
- }
- else if ( ($i = mb_strpos($fs, "ex")) !== false ) {
- $fs = mb_substr($fs, 0, $i) * $this->_parent_font_size;
- }
- else {
- $fs = $this->length_in_pt($fs);
- }
-
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["font_size"] = null;
- $this->_props["font_size"] = $fs;
- $this->__font_size_calculated = true;
- return $this->_props["font_size"];
-
- }
-
- /**
- * @link http://www.w3.org/TR/CSS21/text.html#propdef-word-spacing
- * @return float
- */
- function get_word_spacing() {
- if ( $this->_props["word_spacing"] === "normal" ) {
- return 0;
- }
-
- return $this->_props["word_spacing"];
- }
-
- /**
- * @link http://www.w3.org/TR/CSS21/text.html#propdef-letter-spacing
- * @return float
- */
- function get_letter_spacing() {
- if ( $this->_props["letter_spacing"] === "normal" ) {
- return 0;
- }
-
- return $this->_props["letter_spacing"];
- }
-
- /**
- * @link http://www.w3.org/TR/CSS21/visudet.html#propdef-line-height
- * @return float
- */
- function get_line_height() {
- $line_height = $this->_props["line_height"];
-
- if ( $line_height === "normal" ) {
- return self::$default_line_height * $this->get_font_size();
- }
-
- if ( is_numeric($line_height) ) {
- return $this->length_in_pt( $line_height . "em", $this->get_font_size());
- }
-
- return $this->length_in_pt( $line_height, $this->_parent_font_size );
- }
-
- /**
- * Returns the color as an array
- *
- * The array has the following format:
- * array(r,g,b, "r" => r, "g" => g, "b" => b, "hex" => "#rrggbb")
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-color
- * @return array
- */
- function get_color() {
- return $this->munge_color( $this->_props["color"] );
- }
-
- /**
- * Returns the background color as an array
- *
- * The returned array has the same format as {@link Style::get_color()}
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-color
- * @return array
- */
- function get_background_color() {
- return $this->munge_color( $this->_props["background_color"] );
- }
-
- /**
- * Returns the background position as an array
- *
- * The returned array has the following format:
- * array(x,y, "x" => x, "y" => y)
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-position
- * @return array
- */
- function get_background_position() {
- $tmp = explode(" ", $this->_props["background_position"]);
-
- switch ($tmp[0]) {
- case "left":
- $x = "0%";
- break;
-
- case "right":
- $x = "100%";
- break;
-
- case "top":
- $y = "0%";
- break;
-
- case "bottom":
- $y = "100%";
- break;
-
- case "center":
- $x = "50%";
- $y = "50%";
- break;
-
- default:
- $x = $tmp[0];
- break;
- }
-
- if ( isset($tmp[1]) ) {
-
- switch ($tmp[1]) {
- case "left":
- $x = "0%";
- break;
-
- case "right":
- $x = "100%";
- break;
-
- case "top":
- $y = "0%";
- break;
-
- case "bottom":
- $y = "100%";
- break;
-
- case "center":
- if ( $tmp[0] === "left" || $tmp[0] === "right" || $tmp[0] === "center" ) {
- $y = "50%";
- }
- else {
- $x = "50%";
- }
- break;
-
- default:
- $y = $tmp[1];
- break;
- }
-
- }
- else {
- $y = "50%";
- }
-
- if ( !isset($x) ) {
- $x = "0%";
- }
-
- if ( !isset($y) ) {
- $y = "0%";
- }
-
- return array(
- 0 => $x, "x" => $x,
- 1 => $y, "y" => $y,
- );
- }
-
-
- /**
- * Returns the background as it is currently stored
- *
- * (currently anyway only for completeness.
- * not used for further processing)
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-attachment
- * @return string
- */
- function get_background_attachment() {
- return $this->_props["background_attachment"];
- }
-
-
- /**
- * Returns the background_repeat as it is currently stored
- *
- * (currently anyway only for completeness.
- * not used for further processing)
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-repeat
- * @return string
- */
- function get_background_repeat() {
- return $this->_props["background_repeat"];
- }
-
-
- /**
- * Returns the background as it is currently stored
- *
- * (currently anyway only for completeness.
- * not used for further processing, but the individual get_background_xxx)
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background
- * @return string
- */
- function get_background() {
- return $this->_props["background"];
- }
-
-
- /**#@+
- * Returns the border color as an array
- *
- * See {@link Style::get_color()}
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-color-properties
- * @return array
- */
- function get_border_top_color() {
- if ( $this->_props["border_top_color"] === "" ) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["border_top_color"] = null;
- $this->_props["border_top_color"] = $this->__get("color");
- }
-
- return $this->munge_color($this->_props["border_top_color"]);
- }
-
- function get_border_right_color() {
- if ( $this->_props["border_right_color"] === "" ) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["border_right_color"] = null;
- $this->_props["border_right_color"] = $this->__get("color");
- }
-
- return $this->munge_color($this->_props["border_right_color"]);
- }
-
- function get_border_bottom_color() {
- if ( $this->_props["border_bottom_color"] === "" ) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["border_bottom_color"] = null;
- $this->_props["border_bottom_color"] = $this->__get("color");
- }
-
- return $this->munge_color($this->_props["border_bottom_color"]);
- }
-
- function get_border_left_color() {
- if ( $this->_props["border_left_color"] === "" ) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["border_left_color"] = null;
- $this->_props["border_left_color"] = $this->__get("color");
- }
-
- return $this->munge_color($this->_props["border_left_color"]);
- }
-
- /**#@-*/
-
- /**#@+
- * Returns the border width, as it is currently stored
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-width-properties
- * @return float|string
- */
- function get_border_top_width() {
- $style = $this->__get("border_top_style");
- return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_top_width"]) : 0;
- }
-
- function get_border_right_width() {
- $style = $this->__get("border_right_style");
- return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_right_width"]) : 0;
- }
-
- function get_border_bottom_width() {
- $style = $this->__get("border_bottom_style");
- return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_bottom_width"]) : 0;
- }
-
- function get_border_left_width() {
- $style = $this->__get("border_left_style");
- return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["border_left_width"]) : 0;
- }
- /**#@-*/
-
- /**
- * Return an array of all border properties.
- *
- * The returned array has the following structure:
- *
- * array("top" => array("width" => [border-width],
- * "style" => [border-style],
- * "color" => [border-color (array)]),
- * "bottom" ... )
- *
- *
- * @return array
- */
- function get_border_properties() {
- return array(
- "top" => array(
- "width" => $this->__get("border_top_width"),
- "style" => $this->__get("border_top_style"),
- "color" => $this->__get("border_top_color"),
- ),
- "bottom" => array(
- "width" => $this->__get("border_bottom_width"),
- "style" => $this->__get("border_bottom_style"),
- "color" => $this->__get("border_bottom_color"),
- ),
- "right" => array(
- "width" => $this->__get("border_right_width"),
- "style" => $this->__get("border_right_style"),
- "color" => $this->__get("border_right_color"),
- ),
- "left" => array(
- "width" => $this->__get("border_left_width"),
- "style" => $this->__get("border_left_style"),
- "color" => $this->__get("border_left_color"),
- ),
- );
- }
-
- /**
- * Return a single border property
- *
- * @param string $side
- *
- * @return mixed
- */
- protected function _get_border($side) {
- $color = $this->__get("border_" . $side . "_color");
-
- return $this->__get("border_" . $side . "_width") . " " .
- $this->__get("border_" . $side . "_style") . " " . $color["hex"];
- }
-
- /**#@+
- * Return full border properties as a string
- *
- * Border properties are returned just as specified in CSS:
- * [width] [style] [color]
- * e.g. "1px solid blue"
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-shorthand-properties
- * @return string
- */
- function get_border_top() {
- return $this->_get_border("top");
- }
-
- function get_border_right() {
- return $this->_get_border("right");
- }
-
- function get_border_bottom() {
- return $this->_get_border("bottom");
- }
-
- function get_border_left() {
- return $this->_get_border("left");
- }
- /**#@-*/
-
- function get_computed_border_radius($w, $h) {
- if ( !empty($this->_computed_border_radius) ) {
- return $this->_computed_border_radius;
- }
-
- $rTL = $this->__get("border_top_left_radius");
- $rTR = $this->__get("border_top_right_radius");
- $rBL = $this->__get("border_bottom_left_radius");
- $rBR = $this->__get("border_bottom_right_radius");
-
- if ( $rTL + $rTR + $rBL + $rBR == 0 ) {
- return $this->_computed_border_radius = array(
- 0, 0, 0, 0,
- "top-left" => 0,
- "top-right" => 0,
- "bottom-right" => 0,
- "bottom-left" => 0,
- );
- }
-
- $t = $this->__get("border_top_width");
- $r = $this->__get("border_right_width");
- $b = $this->__get("border_bottom_width");
- $l = $this->__get("border_left_width");
-
- $rTL = min($rTL, $h - $rBL - $t/2 - $b/2, $w - $rTR - $l/2 - $r/2);
- $rTR = min($rTR, $h - $rBR - $t/2 - $b/2, $w - $rTL - $l/2 - $r/2);
- $rBL = min($rBL, $h - $rTL - $t/2 - $b/2, $w - $rBR - $l/2 - $r/2);
- $rBR = min($rBR, $h - $rTR - $t/2 - $b/2, $w - $rBL - $l/2 - $r/2);
-
- return $this->_computed_border_radius = array(
- $rTL, $rTR, $rBR, $rBL,
- "top-left" => $rTL,
- "top-right" => $rTR,
- "bottom-right" => $rBR,
- "bottom-left" => $rBL,
- );
- }
- /**#@-*/
-
-
- /**
- * Returns the outline color as an array
- *
- * See {@link Style::get_color()}
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-color-properties
- * @return array
- */
- function get_outline_color() {
- if ( $this->_props["outline_color"] === "" ) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["outline_color"] = null;
- $this->_props["outline_color"] = $this->__get("color");
- }
-
- return $this->munge_color($this->_props["outline_color"]);
- }
-
- /**#@+
- * Returns the outline width, as it is currently stored
- * @return float|string
- */
- function get_outline_width() {
- $style = $this->__get("outline_style");
- return $style !== "none" && $style !== "hidden" ? $this->length_in_pt($this->_props["outline_width"]) : 0;
- }
-
- /**#@+
- * Return full outline properties as a string
- *
- * Outline properties are returned just as specified in CSS:
- * [width] [style] [color]
- * e.g. "1px solid blue"
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-shorthand-properties
- * @return string
- */
- function get_outline() {
- $color = $this->__get("outline_color");
- return
- $this->__get("outline_width") . " " .
- $this->__get("outline_style") . " " .
- $color["hex"];
- }
- /**#@-*/
-
- /**
- * Returns border spacing as an array
- *
- * The array has the format (h_space,v_space)
- *
- * @link http://www.w3.org/TR/CSS21/tables.html#propdef-border-spacing
- * @return array
- */
- function get_border_spacing() {
- $arr = explode(" ", $this->_props["border_spacing"]);
- if ( count($arr) == 1 ) {
- $arr[1] = $arr[0];
- }
- return $arr;
- }
-
-/*==============================*/
-
- /*
- !important attribute
- For basic functionality of the !important attribute with overloading
- of several styles of an element, changes in inherit(), merge() and _parse_properties()
- are sufficient [helpers var $_important_props, __construct(), important_set(), important_get()]
-
- Only for combined attributes extra treatment needed. See below.
-
- div { border: 1px red; }
- div { border: solid; } // Not combined! Only one occurence of same style per context
- //
- div { border: 1px red; }
- div a { border: solid; } // Adding to border style ok by inheritance
- //
- div { border-style: solid; } // Adding to border style ok because of different styles
- div { border: 1px red; }
- //
- div { border-style: solid; !important} // border: overrides, even though not !important
- div { border: 1px dashed red; }
- //
- div { border: 1px red; !important }
- div a { border-style: solid; } // Need to override because not set
-
- Special treatment:
- At individual property like border-top-width need to check whether overriding value is also !important.
- Also store the !important condition for later overrides.
- Since not known who is initiating the override, need to get passed !important as parameter.
- !important Paramter taken as in the original style in the css file.
- When property border !important given, do not mark subsets like border_style as important. Only
- individual properties.
-
- Note:
- Setting individual property directly from css with e.g. set_border_top_style() is not needed, because
- missing set funcions handled by a generic handler __set(), including the !important.
- Setting individual property of as sub-property is handled below.
-
- Implementation see at _set_style_side_type()
- Callers _set_style_sides_type(), _set_style_type, _set_style_type_important()
-
- Related functionality for background, padding, margin, font, list_style
- */
-
- /* Generalized set function for individual attribute of combined style.
- * With check for !important
- * Applicable for background, border, padding, margin, font, list_style
- * Note: $type has a leading underscore (or is empty), the others not.
- */
- protected function _set_style_side_type($style, $side, $type, $val, $important) {
- $prop = $style.'_'.$side.$type;
-
- if ( !isset($this->_important_props[$prop]) || $important) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$prop] = null;
- if ( $important ) {
- $this->_important_props[$prop] = true;
- }
- $this->_props[$prop] = $val;
- }
- }
-
- protected function _set_style_sides_type($style,$top,$right,$bottom,$left,$type,$important) {
- $this->_set_style_side_type($style,'top',$type,$top,$important);
- $this->_set_style_side_type($style,'right',$type,$right,$important);
- $this->_set_style_side_type($style,'bottom',$type,$bottom,$important);
- $this->_set_style_side_type($style,'left',$type,$left,$important);
- }
-
- protected function _set_style_type($style,$type,$val,$important) {
- $val = preg_replace("/\s*\,\s*/", ",", $val); // when rgb() has spaces
- $arr = explode(" ", $val);
-
- switch (count($arr)) {
- case 1: $this->_set_style_sides_type($style,$arr[0],$arr[0],$arr[0],$arr[0],$type,$important); break;
- case 2: $this->_set_style_sides_type($style,$arr[0],$arr[1],$arr[0],$arr[1],$type,$important); break;
- case 3: $this->_set_style_sides_type($style,$arr[0],$arr[1],$arr[2],$arr[1],$type,$important); break;
- case 4: $this->_set_style_sides_type($style,$arr[0],$arr[1],$arr[2],$arr[3],$type,$important); break;
- }
-
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$style.$type] = null;
- $this->_props[$style.$type] = $val;
- }
-
- protected function _set_style_type_important($style,$type,$val) {
- $this->_set_style_type($style,$type,$val,isset($this->_important_props[$style.$type]));
- }
-
- /* Anyway only called if _important matches and is assigned
- * E.g. _set_style_side_type($style,$side,'',str_replace("none", "0px", $val),isset($this->_important_props[$style.'_'.$side]));
- */
- protected function _set_style_side_width_important($style,$side,$val) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$style.'_'.$side] = null;
- $this->_props[$style.'_'.$side] = str_replace("none", "0px", $val);
- }
-
- protected function _set_style($style,$val,$important) {
- if ( !isset($this->_important_props[$style]) || $important) {
- if ( $important ) {
- $this->_important_props[$style] = true;
- }
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$style] = null;
- $this->_props[$style] = $val;
- }
- }
-
- protected function _image($val) {
- $DEBUGCSS=DEBUGCSS;
- $parsed_url = "none";
-
- if ( mb_strpos($val, "url") === false ) {
- $path = "none"; //Don't resolve no image -> otherwise would prefix path and no longer recognize as none
- }
- else {
- $val = preg_replace("/url\(['\"]?([^'\")]+)['\"]?\)/","\\1", trim($val));
-
- // Resolve the url now in the context of the current stylesheet
- $parsed_url = explode_url($val);
- if ( $parsed_url["protocol"] == "" && $this->_stylesheet->get_protocol() == "" ) {
- if ($parsed_url["path"][0] === '/' || $parsed_url["path"][0] === '\\' ) {
- $path = $_SERVER["DOCUMENT_ROOT"].'/';
- }
- else {
- $path = $this->_stylesheet->get_base_path();
- }
-
- $path .= $parsed_url["path"] . $parsed_url["file"];
- $path = realpath($path);
- // If realpath returns FALSE then specifically state that there is no background image
- if ( !$path ) {
- $path = 'none';
- }
- }
- else {
- $path = build_url($this->_stylesheet->get_protocol(),
- $this->_stylesheet->get_host(),
- $this->_stylesheet->get_base_path(),
- $val);
- }
- }
- if ($DEBUGCSS) {
- print "[_image\n";
- print_r($parsed_url);
- print $this->_stylesheet->get_protocol()."\n".$this->_stylesheet->get_base_path()."\n".$path."\n";
- print "_image] ";;
- }
- return $path;
- }
-
-/*======================*/
-
- /**
- * Sets color
- *
- * The color parameter can be any valid CSS color value
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-color
- * @param string $color
- */
- function set_color($color) {
- $col = $this->munge_color($color);
-
- if ( is_null($col) || !isset($col["hex"]) ) {
- $color = "inherit";
- }
- else {
- $color = $col["hex"];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["color"] = null;
- $this->_props["color"] = $color;
- }
-
- /**
- * Sets the background color
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-color
- * @param string $color
- */
- function set_background_color($color) {
- $col = $this->munge_color($color);
-
- if ( is_null($col) ) {
- return;
- //$col = self::$_defaults["background_color"];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["background_color"] = null;
- $this->_props["background_color"] = is_array($col) ? $col["hex"] : $col;
- }
-
- /**
- * Set the background image url
- * @link http://www.w3.org/TR/CSS21/colors.html#background-properties
- *
- * @param string $val
- */
- function set_background_image($val) {
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["background_image"] = null;
- $this->_props["background_image"] = $this->_image($val);
- }
-
- /**
- * Sets the background repeat
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-repeat
- * @param string $val
- */
- function set_background_repeat($val) {
- if ( is_null($val) ) {
- $val = self::$_defaults["background_repeat"];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["background_repeat"] = null;
- $this->_props["background_repeat"] = $val;
- }
-
- /**
- * Sets the background attachment
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-attachment
- * @param string $val
- */
- function set_background_attachment($val) {
- if ( is_null($val) ) {
- $val = self::$_defaults["background_attachment"];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["background_attachment"] = null;
- $this->_props["background_attachment"] = $val;
- }
-
- /**
- * Sets the background position
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background-position
- * @param string $val
- */
- function set_background_position($val) {
- if ( is_null($val) ) {
- $val = self::$_defaults["background_position"];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["background_position"] = null;
- $this->_props["background_position"] = $val;
- }
-
- /**
- * Sets the background - combined options
- *
- * @link http://www.w3.org/TR/CSS21/colors.html#propdef-background
- * @param string $val
- */
- function set_background($val) {
- $val = trim($val);
- $important = isset($this->_important_props["background"]);
-
- if ( $val === "none" ) {
- $this->_set_style("background_image", "none", $important);
- $this->_set_style("background_color", "transparent", $important);
- }
- else {
- $pos = array();
- $tmp = preg_replace("/\s*\,\s*/", ",", $val); // when rgb() has spaces
- $tmp = preg_split("/\s+/", $tmp);
-
- foreach($tmp as $attr) {
- if ( mb_substr($attr, 0, 3) === "url" || $attr === "none" ) {
- $this->_set_style("background_image", $this->_image($attr), $important);
- }
- elseif ( $attr === "fixed" || $attr === "scroll" ) {
- $this->_set_style("background_attachment", $attr, $important);
- }
- elseif ( $attr === "repeat" || $attr === "repeat-x" || $attr === "repeat-y" || $attr === "no-repeat" ) {
- $this->_set_style("background_repeat", $attr, $important);
- }
- elseif ( ($col = $this->munge_color($attr)) != null ) {
- $this->_set_style("background_color", is_array($col) ? $col["hex"] : $col, $important);
- }
- else {
- $pos[] = $attr;
- }
- }
-
- if (count($pos)) {
- $this->_set_style("background_position", implode(" ", $pos), $important);
- }
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["background"] = null;
- $this->_props["background"] = $val;
- }
-
- /**
- * Sets the font size
- *
- * $size can be any acceptable CSS size
- *
- * @link http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size
- * @param string|float $size
- */
- function set_font_size($size) {
- $this->__font_size_calculated = false;
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["font_size"] = null;
- $this->_props["font_size"] = $size;
- }
-
- /**
- * Sets the font style
- *
- * combined attributes
- * set individual attributes also, respecting !important mark
- * exactly this order, separate by space. Multiple fonts separated by comma:
- * font-style, font-variant, font-weight, font-size, line-height, font-family
- *
- * Other than with border and list, existing partial attributes should
- * reset when starting here, even when not mentioned.
- * If individual attribute is !important and explicite or implicite replacement is not,
- * keep individual attribute
- *
- * require whitespace as delimiters for single value attributes
- * On delimiter "/" treat first as font height, second as line height
- * treat all remaining at the end of line as font
- * font-style, font-variant, font-weight, font-size, line-height, font-family
- *
- * missing font-size and font-family might be not allowed, but accept it here and
- * use default (medium size, enpty font name)
- *
- * @link http://www.w3.org/TR/CSS21/generate.html#propdef-list-style
- * @param $val
- */
- function set_font($val) {
- $this->__font_size_calculated = false;
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["font"] = null;
- $this->_props["font"] = $val;
-
- $important = isset($this->_important_props["font"]);
-
- if ( preg_match("/^(italic|oblique|normal)\s*(.*)$/i",$val,$match) ) {
- $this->_set_style("font_style", $match[1], $important);
- $val = $match[2];
- }
- else {
- $this->_set_style("font_style", self::$_defaults["font_style"], $important);
- }
-
- if ( preg_match("/^(small-caps|normal)\s*(.*)$/i",$val,$match) ) {
- $this->_set_style("font_variant", $match[1], $important);
- $val = $match[2];
- }
- else {
- $this->_set_style("font_variant", self::$_defaults["font_variant"], $important);
- }
-
- //matching numeric value followed by unit -> this is indeed a subsequent font size. Skip!
- if ( preg_match("/^(bold|bolder|lighter|100|200|300|400|500|600|700|800|900|normal)\s*(.*)$/i", $val, $match) &&
- !preg_match("/^(?:pt|px|pc|em|ex|in|cm|mm|%)/",$match[2])
- ) {
- $this->_set_style("font_weight", $match[1], $important);
- $val = $match[2];
- }
- else {
- $this->_set_style("font_weight", self::$_defaults["font_weight"], $important);
- }
-
- if ( preg_match("/^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger|\d+\s*(?:pt|px|pc|em|ex|in|cm|mm|%))\s*(.*)$/i",$val,$match) ) {
- $this->_set_style("font_size", $match[1], $important);
- $val = $match[2];
- if ( preg_match("/^\/\s*(\d+\s*(?:pt|px|pc|em|ex|in|cm|mm|%))\s*(.*)$/i", $val, $match ) ) {
- $this->_set_style("line_height", $match[1], $important);
- $val = $match[2];
- }
- else {
- $this->_set_style("line_height", self::$_defaults["line_height"], $important);
- }
- }
- else {
- $this->_set_style("font_size", self::$_defaults["font_size"], $important);
- $this->_set_style("line_height", self::$_defaults["line_height"], $important);
- }
-
- if( strlen($val) != 0 ) {
- $this->_set_style("font_family", $val, $important);
- }
- else {
- $this->_set_style("font_family", self::$_defaults["font_family"], $important);
- }
- }
-
- /**#@+
- * Sets page break properties
- *
- * @link http://www.w3.org/TR/CSS21/page.html#page-breaks
- * @param string $break
- */
- function set_page_break_before($break) {
- if ( $break === "left" || $break === "right" ) {
- $break = "always";
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["page_break_before"] = null;
- $this->_props["page_break_before"] = $break;
- }
-
- function set_page_break_after($break) {
- if ( $break === "left" || $break === "right" ) {
- $break = "always";
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["page_break_after"] = null;
- $this->_props["page_break_after"] = $break;
- }
- /**#@-*/
-
- //........................................................................
-
- /**#@+
- * Sets the margin size
- *
- * @link http://www.w3.org/TR/CSS21/box.html#margin-properties
- * @param $val
- */
- function set_margin_top($val) {
- $this->_set_style_side_width_important('margin','top',$val);
- }
-
- function set_margin_right($val) {
- $this->_set_style_side_width_important('margin','right',$val);
- }
-
- function set_margin_bottom($val) {
- $this->_set_style_side_width_important('margin','bottom',$val);
- }
-
- function set_margin_left($val) {
- $this->_set_style_side_width_important('margin','left',$val);
- }
-
- function set_margin($val) {
- $val = str_replace("none", "0px", $val);
- $this->_set_style_type_important('margin','',$val);
- }
- /**#@-*/
-
- /**#@+
- * Sets the padding size
- *
- * @link http://www.w3.org/TR/CSS21/box.html#padding-properties
- * @param $val
- */
- function set_padding_top($val) {
- $this->_set_style_side_width_important('padding','top',$val);
- }
-
- function set_padding_right($val) {
- $this->_set_style_side_width_important('padding','right',$val);
- }
-
- function set_padding_bottom($val) {
- $this->_set_style_side_width_important('padding','bottom',$val);
- }
-
- function set_padding_left($val) {
- $this->_set_style_side_width_important('padding','left',$val);
- }
-
- function set_padding($val) {
- $val = str_replace("none", "0px", $val);
- $this->_set_style_type_important('padding','',$val);
- }
- /**#@-*/
-
- /**
- * Sets a single border
- *
- * @param string $side
- * @param string $border_spec ([width] [style] [color])
- * @param boolean $important
- */
- protected function _set_border($side, $border_spec, $important) {
- $border_spec = preg_replace("/\s*\,\s*/", ",", $border_spec);
- //$border_spec = str_replace(",", " ", $border_spec); // Why did we have this ?? rbg(10, 102, 10) > rgb(10 102 10)
- $arr = explode(" ", $border_spec);
-
- // FIXME: handle partial values
-
- //For consistency of individal and combined properties, and with ie8 and firefox3
- //reset all attributes, even if only partially given
- $this->_set_style_side_type('border',$side,'_style',self::$_defaults['border_'.$side.'_style'],$important);
- $this->_set_style_side_type('border',$side,'_width',self::$_defaults['border_'.$side.'_width'],$important);
- $this->_set_style_side_type('border',$side,'_color',self::$_defaults['border_'.$side.'_color'],$important);
-
- foreach ($arr as $value) {
- $value = trim($value);
- if ( in_array($value, self::$BORDER_STYLES) ) {
- $this->_set_style_side_type('border',$side,'_style',$value,$important);
- }
- else if ( preg_match("/[.0-9]+(?:px|pt|pc|em|ex|%|in|mm|cm)|(?:thin|medium|thick)/", $value ) ) {
- $this->_set_style_side_type('border',$side,'_width',$value,$important);
- }
- else {
- // must be color
- $this->_set_style_side_type('border',$side,'_color',$value,$important);
- }
- }
-
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache['border_'.$side] = null;
- $this->_props['border_'.$side] = $border_spec;
- }
-
- /**
- * Sets the border styles
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-properties
- * @param string $val
- */
- function set_border_top($val) {
- $this->_set_border("top", $val, isset($this->_important_props['border_top']));
- }
-
- function set_border_right($val) {
- $this->_set_border("right", $val, isset($this->_important_props['border_right']));
- }
-
- function set_border_bottom($val) {
- $this->_set_border("bottom", $val, isset($this->_important_props['border_bottom']));
- }
-
- function set_border_left($val) {
- $this->_set_border("left", $val, isset($this->_important_props['border_left']));
- }
-
- function set_border($val) {
- $important = isset($this->_important_props["border"]);
- $this->_set_border("top", $val, $important);
- $this->_set_border("right", $val, $important);
- $this->_set_border("bottom", $val, $important);
- $this->_set_border("left", $val, $important);
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["border"] = null;
- $this->_props["border"] = $val;
- }
-
- function set_border_width($val) {
- $this->_set_style_type_important('border','_width',$val);
- }
-
- function set_border_color($val) {
- $this->_set_style_type_important('border','_color',$val);
- }
-
- function set_border_style($val) {
- $this->_set_style_type_important('border','_style',$val);
- }
-
- /**
- * Sets the border radius size
- *
- * http://www.w3.org/TR/css3-background/#corners
- */
- function set_border_top_left_radius($val) {
- $this->_set_border_radius_corner($val, "top_left");
- }
-
- function set_border_top_right_radius($val) {
- $this->_set_border_radius_corner($val, "top_right");
- }
-
- function set_border_bottom_left_radius($val) {
- $this->_set_border_radius_corner($val, "bottom_left");
- }
-
- function set_border_bottom_right_radius($val) {
- $this->_set_border_radius_corner($val, "bottom_right");
- }
-
- function set_border_radius($val) {
- $val = preg_replace("/\s*\,\s*/", ",", $val); // when border-radius has spaces
- $arr = explode(" ", $val);
-
- switch (count($arr)) {
- case 1: $this->_set_border_radii($arr[0],$arr[0],$arr[0],$arr[0]); break;
- case 2: $this->_set_border_radii($arr[0],$arr[1],$arr[0],$arr[1]); break;
- case 3: $this->_set_border_radii($arr[0],$arr[1],$arr[2],$arr[1]); break;
- case 4: $this->_set_border_radii($arr[0],$arr[1],$arr[2],$arr[3]); break;
- }
- }
-
- protected function _set_border_radii($val1, $val2, $val3, $val4) {
- $this->_set_border_radius_corner($val1, "top_left");
- $this->_set_border_radius_corner($val2, "top_right");
- $this->_set_border_radius_corner($val3, "bottom_right");
- $this->_set_border_radius_corner($val4, "bottom_left");
- }
-
- protected function _set_border_radius_corner($val, $corner) {
- $this->_has_border_radius = true;
-
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache["border_" . $corner . "_radius"] = null;
-
- $this->_props["border_" . $corner . "_radius"] = $this->length_in_pt($val);
- }
-
- /**
- * Sets the outline styles
- *
- * @link http://www.w3.org/TR/CSS21/ui.html#dynamic-outlines
- * @param string $val
- */
- function set_outline($val) {
- $important = isset($this->_important_props["outline"]);
-
- $props = array(
- "outline_style",
- "outline_width",
- "outline_color",
- );
-
- foreach($props as $prop) {
- $_val = self::$_defaults[$prop];
-
- if ( !isset($this->_important_props[$prop]) || $important) {
- //see __set and __get, on all assignments clear cache!
- $this->_prop_cache[$prop] = null;
- if ( $important ) {
- $this->_important_props[$prop] = true;
- }
- $this->_props[$prop] = $_val;
- }
- }
-
- $val = preg_replace("/\s*\,\s*/", ",", $val); // when rgb() has spaces
- $arr = explode(" ", $val);
- foreach ($arr as $value) {
- $value = trim($value);
-
- if ( in_array($value, self::$BORDER_STYLES) ) {
- $this->set_outline_style($value);
- }
- else if ( preg_match("/[.0-9]+(?:px|pt|pc|em|ex|%|in|mm|cm)|(?:thin|medium|thick)/", $value ) ) {
- $this->set_outline_width($value);
- }
- else {
- // must be color
- $this->set_outline_color($value);
- }
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["outline"] = null;
- $this->_props["outline"] = $val;
- }
-
- function set_outline_width($val) {
- $this->_set_style_type_important('outline','_width',$val);
- }
-
- function set_outline_color($val) {
- $this->_set_style_type_important('outline','_color',$val);
- }
-
- function set_outline_style($val) {
- $this->_set_style_type_important('outline','_style',$val);
- }
-
- /**
- * Sets the border spacing
- *
- * @link http://www.w3.org/TR/CSS21/box.html#border-properties
- * @param float $val
- */
- function set_border_spacing($val) {
- $arr = explode(" ", $val);
-
- if ( count($arr) == 1 ) {
- $arr[1] = $arr[0];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["border_spacing"] = null;
- $this->_props["border_spacing"] = "$arr[0] $arr[1]";
- }
-
- /**
- * Sets the list style image
- *
- * @link http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-image
- * @param $val
- */
- function set_list_style_image($val) {
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["list_style_image"] = null;
- $this->_props["list_style_image"] = $this->_image($val);
- }
-
- /**
- * Sets the list style
- *
- * @link http://www.w3.org/TR/CSS21/generate.html#propdef-list-style
- * @param $val
- */
- function set_list_style($val) {
- $important = isset($this->_important_props["list_style"]);
- $arr = explode(" ", str_replace(",", " ", $val));
-
- static $types = array(
- "disc", "circle", "square",
- "decimal-leading-zero", "decimal", "1",
- "lower-roman", "upper-roman", "a", "A",
- "lower-greek",
- "lower-latin", "upper-latin",
- "lower-alpha", "upper-alpha",
- "armenian", "georgian", "hebrew",
- "cjk-ideographic", "hiragana", "katakana",
- "hiragana-iroha", "katakana-iroha", "none"
- );
-
- static $positions = array("inside", "outside");
-
- foreach ($arr as $value) {
- /* http://www.w3.org/TR/CSS21/generate.html#list-style
- * A value of 'none' for the 'list-style' property sets both 'list-style-type' and 'list-style-image' to 'none'
- */
- if ( $value === "none" ) {
- $this->_set_style("list_style_type", $value, $important);
- $this->_set_style("list_style_image", $value, $important);
- continue;
- }
-
- //On setting or merging or inheriting list_style_image as well as list_style_type,
- //and url exists, then url has precedence, otherwise fall back to list_style_type
- //Firefox is wrong here (list_style_image gets overwritten on explicite list_style_type)
- //Internet Explorer 7/8 and dompdf is right.
-
- if ( mb_substr($value, 0, 3) === "url" ) {
- $this->_set_style("list_style_image", $this->_image($value), $important);
- continue;
- }
-
- if ( in_array($value, $types) ) {
- $this->_set_style("list_style_type", $value, $important);
- }
- else if ( in_array($value, $positions) ) {
- $this->_set_style("list_style_position", $value, $important);
- }
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["list_style"] = null;
- $this->_props["list_style"] = $val;
- }
-
- function set_size($val) {
- $length_re = "/(\d+\s*(?:pt|px|pc|em|ex|in|cm|mm|%))/";
-
- $val = mb_strtolower($val);
-
- if ( $val === "auto" ) {
- return;
- }
-
- $parts = preg_split("/\s+/", $val);
-
- $computed = array();
- if ( preg_match($length_re, $parts[0]) ) {
- $computed[] = $this->length_in_pt($parts[0]);
-
- if ( isset($parts[1]) && preg_match($length_re, $parts[1]) ) {
- $computed[] = $this->length_in_pt($parts[1]);
- }
- else {
- $computed[] = $computed[0];
- }
- }
- elseif ( isset(CPDF_Adapter::$PAPER_SIZES[$parts[0]]) ) {
- $computed = array_slice(CPDF_Adapter::$PAPER_SIZES[$parts[0]], 2, 2);
-
- if ( isset($parts[1]) && $parts[1] === "landscape" ) {
- $computed = array_reverse($computed);
- }
- }
- else {
- return;
- }
-
- $this->_props["size"] = $computed;
- }
-
- /**
- * Sets the CSS3 transform property
- *
- * @link http://www.w3.org/TR/css3-2d-transforms/#transform-property
- * @param string $val
- */
- function set_transform($val) {
- $number = "\s*([^,\s]+)\s*";
- $tr_value = "\s*([^,\s]+)\s*";
- $angle = "\s*([^,\s]+(?:deg|rad)?)\s*";
-
- if ( !preg_match_all("/[a-z]+\([^\)]+\)/i", $val, $parts, PREG_SET_ORDER) ) {
- return;
- }
-
- $functions = array(
- //"matrix" => "\($number,$number,$number,$number,$number,$number\)",
-
- "translate" => "\($tr_value(?:,$tr_value)?\)",
- "translateX" => "\($tr_value\)",
- "translateY" => "\($tr_value\)",
-
- "scale" => "\($number(?:,$number)?\)",
- "scaleX" => "\($number\)",
- "scaleY" => "\($number\)",
-
- "rotate" => "\($angle\)",
-
- "skew" => "\($angle(?:,$angle)?\)",
- "skewX" => "\($angle\)",
- "skewY" => "\($angle\)",
- );
-
- $transforms = array();
-
- foreach($parts as $part) {
- $t = $part[0];
-
- foreach($functions as $name => $pattern) {
- if ( preg_match("/$name\s*$pattern/i", $t, $matches) ) {
- $values = array_slice($matches, 1);
-
- switch($name) {
- // units
- case "rotate":
- case "skew":
- case "skewX":
- case "skewY":
-
- foreach($values as $i => $value) {
- if ( strpos($value, "rad") ) {
- $values[$i] = rad2deg(floatval($value));
- }
- else {
- $values[$i] = floatval($value);
- }
- }
-
- switch($name) {
- case "skew":
- if ( !isset($values[1]) ) {
- $values[1] = 0;
- }
- break;
- case "skewX":
- $name = "skew";
- $values = array($values[0], 0);
- break;
- case "skewY":
- $name = "skew";
- $values = array(0, $values[0]);
- break;
- }
- break;
-
- // units
- case "translate":
- $values[0] = $this->length_in_pt($values[0], $this->width);
-
- if ( isset($values[1]) ) {
- $values[1] = $this->length_in_pt($values[1], $this->height);
- }
- else {
- $values[1] = 0;
- }
- break;
-
- case "translateX":
- $name = "translate";
- $values = array($this->length_in_pt($values[0], $this->width), 0);
- break;
-
- case "translateY":
- $name = "translate";
- $values = array(0, $this->length_in_pt($values[0], $this->height));
- break;
-
- // units
- case "scale":
- if ( !isset($values[1]) ) {
- $values[1] = $values[0];
- }
- break;
-
- case "scaleX":
- $name = "scale";
- $values = array($values[0], 1.0);
- break;
-
- case "scaleY":
- $name = "scale";
- $values = array(1.0, $values[0]);
- break;
- }
-
- $transforms[] = array(
- $name,
- $values,
- );
- }
- }
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["transform"] = null;
- $this->_props["transform"] = $transforms;
- }
-
- function set__webkit_transform($val) {
- $this->set_transform($val);
- }
-
- function set__webkit_transform_origin($val) {
- $this->set_transform_origin($val);
- }
-
- /**
- * Sets the CSS3 transform-origin property
- *
- * @link http://www.w3.org/TR/css3-2d-transforms/#transform-origin
- * @param string $val
- */
- function set_transform_origin($val) {
- $values = preg_split("/\s+/", $val);
-
- if ( count($values) === 0) {
- return;
- }
-
- foreach($values as &$value) {
- if ( in_array($value, array("top", "left")) ) {
- $value = 0;
- }
-
- if ( in_array($value, array("bottom", "right")) ) {
- $value = "100%";
- }
- }
-
- if ( !isset($values[1]) ) {
- $values[1] = $values[0];
- }
-
- //see __set and __get, on all assignments clear cache, not needed on direct set through __set
- $this->_prop_cache["transform_origin"] = null;
- $this->_props["transform_origin"] = $values;
- }
-
- protected function parse_image_resolution($val) {
- // If exif data could be get:
- // $re = '/^\s*(\d+|normal|auto)(?:\s*,\s*(\d+|normal))?\s*$/';
-
- $re = '/^\s*(\d+|normal|auto)\s*$/';
-
- if ( !preg_match($re, $val, $matches) ) {
- return null;
- }
-
- return $matches[1];
- }
-
- // auto | normal | dpi
- function set_background_image_resolution($val) {
- $parsed = $this->parse_image_resolution($val);
-
- $this->_prop_cache["background_image_resolution"] = null;
- $this->_props["background_image_resolution"] = $parsed;
- }
-
- // auto | normal | dpi
- function set_image_resolution($val) {
- $parsed = $this->parse_image_resolution($val);
-
- $this->_prop_cache["image_resolution"] = null;
- $this->_props["image_resolution"] = $parsed;
- }
-
- function set__dompdf_background_image_resolution($val) {
- $this->set_background_image_resolution($val);
- }
-
- function set__dompdf_image_resolution($val) {
- $this->set_image_resolution($val);
- }
-
- function set_z_index($val) {
- if ( round($val) != $val && $val !== "auto" ) {
- return;
- }
-
- $this->_prop_cache["z_index"] = null;
- $this->_props["z_index"] = $val;
- }
-
- function set_counter_increment($val) {
- $val = trim($val);
- $value = null;
-
- if ( in_array($val, array("none", "inherit")) ) {
- $value = $val;
- }
- else {
- if ( preg_match_all("/(".self::CSS_IDENTIFIER.")(?:\s+(".self::CSS_INTEGER."))?/", $val, $matches, PREG_SET_ORDER) ){
- $value = array();
- foreach($matches as $match) {
- $value[$match[1]] = isset($match[2]) ? $match[2] : 1;
- }
- }
- }
-
- $this->_prop_cache["counter_increment"] = null;
- $this->_props["counter_increment"] = $value;
- }
-
- /**
- * Generate a string representation of the Style
- *
- * This dumps the entire property array into a string via print_r. Useful
- * for debugging.
- *
- * @return string
- */
- /*DEBUGCSS print: see below additional debugging util*/
- function __toString() {
- return print_r(array_merge(array("parent_font_size" => $this->_parent_font_size),
- $this->_props), true);
- }
-
-/*DEBUGCSS*/ function debug_print() {
-/*DEBUGCSS*/ print "parent_font_size:".$this->_parent_font_size . ";\n";
-/*DEBUGCSS*/ foreach($this->_props as $prop => $val ) {
-/*DEBUGCSS*/ print $prop.':'.$val;
-/*DEBUGCSS*/ if (isset($this->_important_props[$prop])) {
-/*DEBUGCSS*/ print '!important';
-/*DEBUGCSS*/ }
-/*DEBUGCSS*/ print ";\n";
-/*DEBUGCSS*/ }
-/*DEBUGCSS*/ }
-}
diff --git a/library/vendor/dompdf/include/stylesheet.cls.php b/library/vendor/dompdf/include/stylesheet.cls.php
deleted file mode 100644
index a74956754..000000000
--- a/library/vendor/dompdf/include/stylesheet.cls.php
+++ /dev/null
@@ -1,1418 +0,0 @@
-
- * @author Helmut Tischer
- * @author Fabien Ménager
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
-/**
- * The location of the default built-in CSS file.
- * {@link Stylesheet::DEFAULT_STYLESHEET}
- */
-define('__DEFAULT_STYLESHEET', DOMPDF_LIB_DIR . DIRECTORY_SEPARATOR . "res" . DIRECTORY_SEPARATOR . "html.css");
-
-/**
- * The master stylesheet class
- *
- * The Stylesheet class is responsible for parsing stylesheets and style
- * tags/attributes. It also acts as a registry of the individual Style
- * objects generated by the current set of loaded CSS files and style
- * elements.
- *
- * @see Style
- * @package dompdf
- */
-class Stylesheet {
-
- /**
- * The location of the default built-in CSS file.
- */
- const DEFAULT_STYLESHEET = __DEFAULT_STYLESHEET;
-
- /**
- * User agent stylesheet origin
- *
- * @var int
- */
- const ORIG_UA = 1;
-
- /**
- * User normal stylesheet origin
- *
- * @var int
- */
- const ORIG_USER = 2;
-
- /**
- * Author normal stylesheet origin
- *
- * @var int
- */
- const ORIG_AUTHOR = 3;
-
- private static $_stylesheet_origins = array(
- self::ORIG_UA => -0x0FFFFFFF, // user agent style sheets
- self::ORIG_USER => -0x0000FFFF, // user normal style sheets
- self::ORIG_AUTHOR => 0x00000000, // author normal style sheets
- );
-
- /**
- * Current dompdf instance
- *
- * @var DOMPDF
- */
- private $_dompdf;
-
- /**
- * Array of currently defined styles
- *
- * @var Style[]
- */
- private $_styles;
-
- /**
- * Base protocol of the document being parsed
- * Used to handle relative urls.
- *
- * @var string
- */
- private $_protocol;
-
- /**
- * Base hostname of the document being parsed
- * Used to handle relative urls.
- *
- * @var string
- */
- private $_base_host;
-
- /**
- * Base path of the document being parsed
- * Used to handle relative urls.
- *
- * @var string
- */
- private $_base_path;
-
- /**
- * The styles defined by @page rules
- *
- * @var array
+ $child = $child->nextSibling;
+ }
+ } else {
+ $css = $tag->nodeValue;
+ }
+
+ $this->css->load_css($css);
+ break;
+ }
+ }
+ }
+
+ /**
+ * @param string $cacheId
+ * @deprecated
+ */
+ public function enable_caching($cacheId)
+ {
+ $this->enableCaching($cacheId);
+ }
+
+ /**
+ * Enable experimental caching capability
+ *
+ * @param string $cacheId
+ */
+ public function enableCaching($cacheId)
+ {
+ $this->cacheId = $cacheId;
+ }
+
+ /**
+ * @param string $value
+ * @return bool
+ * @deprecated
+ */
+ public function parse_default_view($value)
+ {
+ return $this->parseDefaultView($value);
+ }
+
+ /**
+ * @param string $value
+ * @return bool
+ */
+ public function parseDefaultView($value)
+ {
+ $valid = array("XYZ", "Fit", "FitH", "FitV", "FitR", "FitB", "FitBH", "FitBV");
+
+ $options = preg_split("/\s*,\s*/", trim($value));
+ $defaultView = array_shift($options);
+
+ if (!in_array($defaultView, $valid)) {
+ return false;
+ }
+
+ $this->setDefaultView($defaultView, $options);
+ return true;
+ }
+
+ /**
+ * Renders the HTML to PDF
+ */
+ public function render()
+ {
+ $this->saveLocale();
+
+ $logOutputFile = $this->options->getLogOutputFile();
+ if ($logOutputFile) {
+ if (!file_exists($logOutputFile) && is_writable(dirname($logOutputFile))) {
+ touch($logOutputFile);
+ }
+
+ $this->startTime = microtime(true);
+ ob_start();
+ }
+
+ $this->processHtml();
+
+ $this->css->apply_styles($this->tree);
+
+ // @page style rules : size, margins
+ $pageStyles = $this->css->get_page_styles();
+
+ $basePageStyle = $pageStyles["base"];
+ unset($pageStyles["base"]);
+
+ foreach ($pageStyles as $pageStyle) {
+ $pageStyle->inherit($basePageStyle);
+ }
+
+ if (is_array($basePageStyle->size)) {
+ $this->setPaper(array(0, 0, $basePageStyle->size[0], $basePageStyle->size[1]));
+ }
+
+ //TODO: We really shouldn't be doing this; properties were already set in the constructor. We should add Canvas methods to set the page size and orientation after instantiaion (see #1059).
+ $this->setCanvas(CanvasFactory::get_instance($this, $this->paperSize, $this->paperOrientation));
+ $this->setFontMetrics(new FontMetrics($this->pdf, $this->getOptions()));
+
+ if ($this->options->isFontSubsettingEnabled() && $this->pdf instanceof CPDF) {
+ foreach ($this->tree->get_frames() as $frame) {
+ $style = $frame->get_style();
+ $node = $frame->get_node();
+
+ // Handle text nodes
+ if ($node->nodeName === "#text") {
+ $this->getCanvas()->register_string_subset($style->font_family, $node->nodeValue);
+ continue;
+ }
+
+ // Handle generated content (list items)
+ if ($style->display === "list-item") {
+ $chars = ListBullet::get_counter_chars($style->list_style_type);
+ $this->getCanvas()->register_string_subset($style->font_family, $chars);
+ continue;
+ }
+
+ // Handle other generated content (pseudo elements)
+ // FIXME: This only captures the text of the stylesheet declaration,
+ // not the actual generated content, and forces all possible counter
+ // values. See notes in issue #750.
+ if ($frame->get_node()->nodeName == "dompdf_generated") {
+ // all possible counter values
+ $chars = ListBullet::get_counter_chars('decimal');
+ $this->getCanvas()->register_string_subset($style->font_family, $chars);
+ $chars = ListBullet::get_counter_chars('upper-alpha');
+ $this->getCanvas()->register_string_subset($style->font_family, $chars);
+ $chars = ListBullet::get_counter_chars('lower-alpha');
+ $this->getCanvas()->register_string_subset($style->font_family, $chars);
+ $chars = ListBullet::get_counter_chars('lower-greek');
+ $this->getCanvas()->register_string_subset($style->font_family, $chars);
+ // the text of the stylesheet declaration
+ $this->getCanvas()->register_string_subset($style->font_family, $style->content);
+ continue;
+ }
+ }
+ }
+
+ $root = null;
+
+ foreach ($this->tree->get_frames() as $frame) {
+ // Set up the root frame
+ if (is_null($root)) {
+ $root = Factory::decorate_root($this->tree->get_root(), $this);
+ continue;
+ }
+
+ // Create the appropriate decorators, reflowers & positioners.
+ Factory::decorate_frame($frame, $this, $root);
+ }
+
+ // Add meta information
+ $title = $this->dom->getElementsByTagName("title");
+ if ($title->length) {
+ $this->getCanvas()->add_info("Title", trim($title->item(0)->nodeValue));
+ }
+
+ $metas = $this->dom->getElementsByTagName("meta");
+ $labels = array(
+ "author" => "Author",
+ "keywords" => "Keywords",
+ "description" => "Subject",
+ );
+ foreach ($metas as $meta) {
+ $name = mb_strtolower($meta->getAttribute("name"));
+ $value = trim($meta->getAttribute("content"));
+
+ if (isset($labels[$name])) {
+ $this->pdf->add_info($labels[$name], $value);
+ continue;
+ }
+
+ if ($name === "dompdf.view" && $this->parseDefaultView($value)) {
+ $this->getCanvas()->set_default_view($this->defaultView, $this->defaultViewOptions);
+ }
+ }
+
+ $root->set_containing_block(0, 0, $this->getCanvas()->get_width(), $this->getCanvas()->get_height());
+ $root->set_renderer(new Renderer($this));
+
+ // This is where the magic happens:
+ $root->reflow();
+
+ // Clean up cached images
+ Cache::clear();
+
+ global $_dompdf_warnings, $_dompdf_show_warnings;
+ if ($_dompdf_show_warnings && isset($_dompdf_warnings)) {
+ echo 'Dompdf Warnings ';
+ foreach ($_dompdf_warnings as $msg) {
+ echo $msg . "\n";
+ }
+ echo $this->getCanvas()->get_cpdf()->messages;
+ echo ' ';
+ flush();
+ }
+
+ $this->restoreLocale();
+ }
+
+ /**
+ * Add meta information to the PDF after rendering
+ */
+ public function add_info($label, $value)
+ {
+ if (!is_null($this->pdf)) {
+ $this->pdf->add_info($label, $value);
+ }
+ }
+
+ /**
+ * Writes the output buffer in the log file
+ *
+ * @return void
+ */
+ private function write_log()
+ {
+ $log_output_file = $this->get_option("log_output_file");
+ if (!$log_output_file || !is_writable($log_output_file)) {
+ return;
+ }
+
+ $frames = Frame::$ID_COUNTER;
+ $memory = memory_get_peak_usage(true) / 1024;
+ $time = (microtime(true) - $this->startTime) * 1000;
+
+ $out = sprintf(
+ "%6d " .
+ "%10.2f KB " .
+ "%10.2f ms " .
+ " " .
+ ($this->quirksmode ? " ON " : "OFF ") .
+ " ", $frames, $memory, $time);
+
+ $out .= ob_get_clean();
+
+ $log_output_file = $this->get_option("log_output_file");
+ file_put_contents($log_output_file, $out);
+ }
+
+ /**
+ * Streams the PDF to the client
+ *
+ * The file will open a download dialog by default. The options
+ * parameter controls the output. Accepted options (array keys) are:
+ *
+ * 'Accept-Ranges' => 1 or 0 (=default): Send an 'Accept-Ranges:'
+ * HTTP header, see https://tools.ietf.org/html/rfc2616#section-14.5
+ * This header seems to have caused some problems, despite the fact
+ * that it is supposed to solve them, so I am leaving it off by default.
+ *
+ * 'compress' = > 1 (=default) or 0:
+ * Apply content stream compression
+ *
+ * 'Attachment' => 1 (=default) or 0:
+ * Set the 'Content-Disposition:' HTTP header to 'attachment'
+ * (thereby causing the browser to open a download dialog)
+ *
+ * @param string $filename the name of the streamed file
+ * @param array $options header options (see above)
+ */
+ public function stream($filename = 'document.pdf', $options = null)
+ {
+ $this->saveLocale();
+
+ $this->write_log();
+
+ if (!is_null($this->pdf)) {
+ $this->pdf->stream($filename, $options);
+ }
+
+ $this->restoreLocale();
+ }
+
+ /**
+ * Returns the PDF as a string
+ *
+ * The file will open a download dialog by default. The options
+ * parameter controls the output. Accepted options are:
+ *
+ *
+ * 'compress' = > 1 or 0 - apply content stream compression, this is
+ * on (1) by default
+ *
+ *
+ * @param array $options options (see above)
+ *
+ * @return string
+ */
+ public function output($options = null)
+ {
+ $this->saveLocale();
+
+ $this->write_log();
+
+ if (is_null($this->pdf)) {
+ return null;
+ }
+
+ $output = $this->pdf->output($options);
+
+ $this->restoreLocale();
+
+ return $output;
+ }
+
+ /**
+ * @return string
+ * @deprecated
+ */
+ public function output_html()
+ {
+ return $this->outputHtml();
+ }
+
+ /**
+ * Returns the underlying HTML document as a string
+ *
+ * @return string
+ */
+ public function outputHtml()
+ {
+ return $this->dom->saveHTML();
+ }
+
+ /**
+ * Get the dompdf option value
+ *
+ * @param string $key
+ * @return mixed
+ * @deprecated
+ */
+ public function get_option($key)
+ {
+ return $this->options->get($key);
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @return $this
+ * @deprecated
+ */
+ public function set_option($key, $value)
+ {
+ $this->options->set($key, $value);
+ return $this;
+ }
+
+ /**
+ * @param array $options
+ * @return $this
+ * @deprecated
+ */
+ public function set_options(array $options)
+ {
+ $this->options->set($options);
+ return $this;
+ }
+
+ /**
+ * @param string $size
+ * @param string $orientation
+ * @deprecated
+ */
+ public function set_paper($size, $orientation = "portrait")
+ {
+ $this->setPaper($size, $orientation);
+ }
+
+ /**
+ * Sets the paper size & orientation
+ *
+ * @param string $size 'letter', 'legal', 'A4', etc. {@link Dompdf\Adapter\CPDF::$PAPER_SIZES}
+ * @param string $orientation 'portrait' or 'landscape'
+ * @return $this
+ */
+ public function setPaper($size, $orientation = "portrait")
+ {
+ $this->paperSize = $size;
+ $this->paperOrientation = $orientation;
+ return $this;
+ }
+
+ /**
+ * @param FrameTree $tree
+ * @return $this
+ */
+ public function setTree(FrameTree $tree)
+ {
+ $this->tree = $tree;
+ return $this;
+ }
+
+ /**
+ * @return FrameTree
+ * @deprecated
+ */
+ public function get_tree()
+ {
+ return $this->getTree();
+ }
+
+ /**
+ * Returns the underlying {@link FrameTree} object
+ *
+ * @return FrameTree
+ */
+ public function getTree()
+ {
+ return $this->tree;
+ }
+
+ /**
+ * @param string $protocol
+ * @return $this
+ * @deprecated
+ */
+ public function set_protocol($protocol)
+ {
+ return $this->setProtocol($protocol);
+ }
+
+ /**
+ * Sets the protocol to use
+ * FIXME validate these
+ *
+ * @param string $protocol
+ * @return $this
+ */
+ public function setProtocol($protocol)
+ {
+ $this->protocol = $protocol;
+ return $this;
+ }
+
+ /**
+ * @return string
+ * @deprecated
+ */
+ public function get_protocol()
+ {
+ return $this->getProtocol();
+ }
+
+ /**
+ * Returns the protocol in use
+ *
+ * @return string
+ */
+ public function getProtocol()
+ {
+ return $this->protocol;
+ }
+
+ /**
+ * @param string $host
+ * @deprecated
+ */
+ public function set_host($host)
+ {
+ $this->setBaseHost($host);
+ }
+
+ /**
+ * Sets the base hostname
+ *
+ * @param string $baseHost
+ * @return $this
+ */
+ public function setBaseHost($baseHost)
+ {
+ $this->baseHost = $baseHost;
+ return $this;
+ }
+
+ /**
+ * @return string
+ * @deprecated
+ */
+ public function get_host()
+ {
+ return $this->getBaseHost();
+ }
+
+ /**
+ * Returns the base hostname
+ *
+ * @return string
+ */
+ public function getBaseHost()
+ {
+ return $this->baseHost;
+ }
+
+ /**
+ * Sets the base path
+ *
+ * @param string $path
+ * @deprecated
+ */
+ public function set_base_path($path)
+ {
+ $this->setBasePath($path);
+ }
+
+ /**
+ * Sets the base path
+ *
+ * @param string $basePath
+ * @return $this
+ */
+ public function setBasePath($basePath)
+ {
+ $this->basePath = $basePath;
+ return $this;
+ }
+
+ /**
+ * @return string
+ * @deprecated
+ */
+ public function get_base_path()
+ {
+ return $this->getBasePath();
+ }
+
+ /**
+ * Returns the base path
+ *
+ * @return string
+ */
+ public function getBasePath()
+ {
+ return $this->basePath;
+ }
+
+ /**
+ * @param string $default_view The default document view
+ * @param array $options The view's options
+ * @return $this
+ * @deprecated
+ */
+ public function set_default_view($default_view, $options)
+ {
+ return $this->setDefaultView($default_view, $options);
+ }
+
+ /**
+ * Sets the default view
+ *
+ * @param string $defaultView The default document view
+ * @param array $options The view's options
+ * @return $this
+ */
+ public function setDefaultView($defaultView, $options)
+ {
+ $this->defaultView = $defaultView;
+ $this->defaultViewOptions = $options;
+ return $this;
+ }
+
+ /**
+ * @param resource $http_context
+ * @return $this
+ * @deprecated
+ */
+ public function set_http_context($http_context)
+ {
+ return $this->setHttpContext($http_context);
+ }
+
+ /**
+ * Sets the HTTP context
+ *
+ * @param resource $httpContext
+ * @return $this
+ */
+ public function setHttpContext($httpContext)
+ {
+ $this->httpContext = $httpContext;
+ return $this;
+ }
+
+ /**
+ * @return resource
+ * @deprecated
+ */
+ public function get_http_context()
+ {
+ return $this->getHttpContext();
+ }
+
+ /**
+ * Returns the HTTP context
+ *
+ * @return resource
+ */
+ public function getHttpContext()
+ {
+ return $this->httpContext;
+ }
+
+ /**
+ * @param Canvas $canvas
+ * @return $this
+ */
+ public function setCanvas(Canvas $canvas)
+ {
+ $this->pdf = $canvas;
+ $this->canvas = $canvas;
+ return $this;
+ }
+
+ /**
+ * @return Canvas
+ * @deprecated
+ */
+ public function get_canvas()
+ {
+ return $this->getCanvas();
+ }
+
+ /**
+ * Return the underlying Canvas instance (e.g. Dompdf\Adapter\CPDF, Dompdf\Adapter\GD)
+ *
+ * @return Canvas
+ */
+ public function getCanvas()
+ {
+ if (null === $this->canvas && null !== $this->pdf) {
+ return $this->pdf;
+ }
+ return $this->canvas;
+ }
+
+ /**
+ * @param Stylesheet $css
+ * @return $this
+ */
+ public function setCss(Stylesheet $css)
+ {
+ $this->css = $css;
+ return $this;
+ }
+
+ /**
+ * @return Stylesheet
+ * @deprecated
+ */
+ public function get_css()
+ {
+ return $this->getCss();
+ }
+
+ /**
+ * Returns the stylesheet
+ *
+ * @return Stylesheet
+ */
+ public function getCss()
+ {
+ return $this->css;
+ }
+
+ /**
+ * @param DOMDocument $dom
+ * @return $this
+ */
+ public function setDom(DOMDocument $dom)
+ {
+ $this->dom = $dom;
+ return $this;
+ }
+
+ /**
+ * @return DOMDocument
+ * @deprecated
+ */
+ public function get_dom()
+ {
+ return $this->getDom();
+ }
+
+ /**
+ * @return DOMDocument
+ */
+ public function getDom()
+ {
+ return $this->dom;
+ }
+
+ /**
+ * @param Options $options
+ * @return $this
+ */
+ public function setOptions(Options $options)
+ {
+ $this->options = $options;
+ $fontMetrics = $this->getFontMetrics();
+ if (isset($fontMetrics)) {
+ $fontMetrics->setOptions($options);
+ }
+ return $this;
+ }
+
+ /**
+ * @return Options
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * @return array
+ * @deprecated
+ */
+ public function get_callbacks()
+ {
+ return $this->getCallbacks();
+ }
+
+ /**
+ * Returns the callbacks array
+ *
+ * @return array
+ */
+ public function getCallbacks()
+ {
+ return $this->callbacks;
+ }
+
+ /**
+ * @param array $callbacks the set of callbacks to set
+ * @deprecated
+ */
+ public function set_callbacks($callbacks)
+ {
+ $this->setCallbacks($callbacks);
+ }
+
+ /**
+ * Sets callbacks for events like rendering of pages and elements.
+ * The callbacks array contains arrays with 'event' set to 'begin_page',
+ * 'end_page', 'begin_frame', or 'end_frame' and 'f' set to a function or
+ * object plus method to be called.
+ *
+ * The function 'f' must take an array as argument, which contains info
+ * about the event.
+ *
+ * @param array $callbacks the set of callbacks to set
+ */
+ public function setCallbacks($callbacks)
+ {
+ if (is_array($callbacks)) {
+ $this->callbacks = array();
+ foreach ($callbacks as $c) {
+ if (is_array($c) && isset($c['event']) && isset($c['f'])) {
+ $event = $c['event'];
+ $f = $c['f'];
+ if (is_callable($f) && is_string($event)) {
+ $this->callbacks[$event][] = $f;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @return boolean
+ * @deprecated
+ */
+ public function get_quirksmode()
+ {
+ return $this->getQuirksmode();
+ }
+
+ /**
+ * Get the quirks mode
+ *
+ * @return boolean true if quirks mode is active
+ */
+ public function getQuirksmode()
+ {
+ return $this->quirksmode;
+ }
+
+ /**
+ * @param FontMetrics $fontMetrics
+ * @return $this
+ */
+ public function setFontMetrics(FontMetrics $fontMetrics)
+ {
+ $this->fontMetrics = $fontMetrics;
+ return $this;
+ }
+
+ /**
+ * @return FontMetrics
+ */
+ public function getFontMetrics()
+ {
+ return $this->fontMetrics;
+ }
+
+ /**
+ * PHP5 overloaded getter
+ * Along with {@link Dompdf::__set()} __get() provides access to all
+ * properties directly. Typically __get() is not called directly outside
+ * of this class.
+ *
+ * @param string $prop
+ *
+ * @throws Exception
+ * @return mixed
+ */
+ function __get($prop)
+ {
+ switch ($prop)
+ {
+ case 'version' :
+ return $this->version;
+ default:
+ throw new Exception( 'Invalid property: ' . $prop );
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Exception.php b/library/vendor/dompdf/src/Exception.php
new file mode 100644
index 000000000..9729dc704
--- /dev/null
+++ b/library/vendor/dompdf/src/Exception.php
@@ -0,0 +1,30 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf;
+
+/**
+ * Standard exception thrown by DOMPDF classes
+ *
+ * @package dompdf
+ */
+class Exception extends \Exception
+{
+
+ /**
+ * Class constructor
+ *
+ * @param string $message Error message
+ * @param int $code Error code
+ */
+ function __construct($message = null, $code = 0)
+ {
+ parent::__construct($message, $code);
+ }
+
+}
diff --git a/library/vendor/dompdf/src/Exception/ImageException.php b/library/vendor/dompdf/src/Exception/ImageException.php
new file mode 100644
index 000000000..62b44b1c8
--- /dev/null
+++ b/library/vendor/dompdf/src/Exception/ImageException.php
@@ -0,0 +1,31 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Exception;
+
+use Dompdf\Exception;
+
+/**
+ * Image exception thrown by DOMPDF
+ *
+ * @package dompdf
+ */
+class ImageException extends Exception
+{
+
+ /**
+ * Class constructor
+ *
+ * @param string $message Error message
+ * @param int $code Error code
+ */
+ function __construct($message = null, $code = 0)
+ {
+ parent::__construct($message, $code);
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FontMetrics.php b/library/vendor/dompdf/src/FontMetrics.php
new file mode 100644
index 000000000..d6601cbb2
--- /dev/null
+++ b/library/vendor/dompdf/src/FontMetrics.php
@@ -0,0 +1,603 @@
+
+ * @author Helmut Tischer
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf;
+
+use FontLib\Font;
+
+/**
+ * The font metrics class
+ *
+ * This class provides information about fonts and text. It can resolve
+ * font names into actual installed font files, as well as determine the
+ * size of text in a particular font and size.
+ *
+ * @static
+ * @package dompdf
+ */
+class FontMetrics
+{
+ /**
+ * Name of the font cache file
+ *
+ * This file must be writable by the webserver process only to update it
+ * with save_font_families() after adding the .afm file references of a new font family
+ * with FontMetrics::saveFontFamilies().
+ * This is typically done only from command line with load_font.php on converting
+ * ttf fonts to ufm with php-font-lib.
+ */
+ const CACHE_FILE = "dompdf_font_family_cache.php";
+
+ /**
+ * @var Canvas
+ * @deprecated
+ */
+ protected $pdf;
+
+ /**
+ * Underlying {@link Canvas} object to perform text size calculations
+ *
+ * @var Canvas
+ */
+ protected $canvas;
+
+ /**
+ * Array of font family names to font files
+ *
+ * Usually cached by the {@link load_font.php} script
+ *
+ * @var array
+ */
+ protected $fontLookup = array();
+
+ /**
+ * @var Options
+ */
+ private $options;
+
+ /**
+ * Class initialization
+ */
+ public function __construct(Canvas $canvas, Options $options)
+ {
+ $this->setCanvas($canvas);
+ $this->setOptions($options);
+ $this->loadFontFamilies();
+ }
+
+ /**
+ * @deprecated
+ */
+ public function save_font_families()
+ {
+ $this->saveFontFamilies();
+ }
+
+ /**
+ * Saves the stored font family cache
+ *
+ * The name and location of the cache file are determined by {@link
+ * FontMetrics::CACHE_FILE}. This file should be writable by the
+ * webserver process.
+ *
+ * @see Font_Metrics::load_font_families()
+ */
+ public function saveFontFamilies()
+ {
+ // replace the path to the DOMPDF font directories with the corresponding constants (allows for more portability)
+ $cacheData = sprintf("fontLookup as $family => $variants) {
+ $cacheData .= sprintf(" '%s' => array(%s", addslashes($family), PHP_EOL);
+ foreach ($variants as $variant => $path) {
+ $path = sprintf("'%s'", $path);
+ $path = str_replace('\'' . $this->getOptions()->getFontDir() , '$fontDir . \'' , $path);
+ $path = str_replace('\'' . $this->getOptions()->getRootDir() , '$rootDir . \'' , $path);
+ $cacheData .= sprintf(" '%s' => %s,%s", $variant, $path, PHP_EOL);
+ }
+ $cacheData .= sprintf(" ),%s", PHP_EOL);
+ }
+ $cacheData .= ") ?>";
+ file_put_contents($this->getCacheFile(), $cacheData);
+ }
+
+ /**
+ * @deprecated
+ */
+ public function load_font_families()
+ {
+ $this->loadFontFamilies();
+ }
+
+ /**
+ * Loads the stored font family cache
+ *
+ * @see save_font_families()
+ */
+ public function loadFontFamilies()
+ {
+ $fontDir = $this->getOptions()->getFontDir();
+ $rootDir = $this->getOptions()->getRootDir();
+
+ // FIXME: tempoarary define constants for cache files <= v0.6.2
+ if (!defined("DOMPDF_DIR")) { define("DOMPDF_DIR", $rootDir); }
+ if (!defined("DOMPDF_FONT_DIR")) { define("DOMPDF_FONT_DIR", $fontDir); }
+
+ $file = $rootDir . "/lib/fonts/dompdf_font_family_cache.dist.php";
+ $distFonts = require $file;
+
+ // FIXME: temporary step for font cache created before the font cache fix
+ if (is_readable($fontDir . DIRECTORY_SEPARATOR . "dompdf_font_family_cache")) {
+ $oldFonts = require $fontDir . DIRECTORY_SEPARATOR . "dompdf_font_family_cache";
+ // If the font family cache is still in the old format
+ if ($oldFonts === 1) {
+ $cacheData = file_get_contents($fontDir . DIRECTORY_SEPARATOR . "dompdf_font_family_cache");
+ file_put_contents($fontDir . DIRECTORY_SEPARATOR . "dompdf_font_family_cache", "<" . "?php return $cacheData ?" . ">");
+ $oldFonts = require $fontDir . DIRECTORY_SEPARATOR . "dompdf_font_family_cache";
+ }
+ $distFonts += $oldFonts;
+ }
+
+ if (!is_readable($this->getCacheFile())) {
+ $this->fontLookup = $distFonts;
+ return;
+ }
+
+ $cacheData = require $this->getCacheFile();
+
+ // If the font family cache is still in the old format
+ if ($cacheData === 1) {
+ $cacheData = file_get_contents($this->getCacheFile());
+ file_put_contents($this->getCacheFile(), "<" . "?php return $cacheData ?" . ">");
+ $this->fontLookup = require $this->getCacheFile();
+ }
+
+ $this->fontLookup = array();
+ foreach ($cacheData as $key => $value) {
+ $this->fontLookup[stripslashes($key)] = $value;
+ }
+
+ // Merge provided fonts
+ $this->fontLookup += $distFonts;
+ }
+
+ /**
+ * @param array $files
+ * @return array
+ * @deprecated
+ */
+ public function install_fonts($files)
+ {
+ return $this->installFonts($files);
+ }
+
+ /**
+ * @param array $files
+ * @return array
+ */
+ public function installFonts(array $files)
+ {
+ $names = array();
+
+ foreach ($files as $file) {
+ $font = Font::load($file);
+ $records = $font->getData("name", "records");
+ $type = $this->getType($records[2]);
+ $names[mb_strtolower($records[1])][$type] = $file;
+ $font->close();
+ }
+
+ return $names;
+ }
+
+ /**
+ * @param array $style
+ * @param string $remote_file
+ * @param resource $context
+ * @return bool
+ * @deprecated
+ */
+ public function register_font($style, $remote_file, $context = null)
+ {
+ return $this->registerFont($style, $remote_file);
+ }
+
+ /**
+ * @param array $style
+ * @param string $remoteFile
+ * @param resource $context
+ * @return bool
+ */
+ public function registerFont($style, $remoteFile, $context = null)
+ {
+ $fontDir = $this->getOptions()->getFontDir();
+ $fontname = mb_strtolower($style["family"]);
+ $families = $this->getFontFamilies();
+
+ $entry = array();
+ if (isset($families[$fontname])) {
+ $entry = $families[$fontname];
+ }
+
+ $localFile = $fontDir . DIRECTORY_SEPARATOR . md5($remoteFile);
+ $localTempFile = $this->options->get('tempDir') . "/" . md5($remoteFile);
+ $cacheEntry = $localFile;
+ $localFile .= ".ttf";
+
+ $styleString = $this->getType("{$style['weight']} {$style['style']}");
+
+ if ( !isset($entry[$styleString]) ) {
+ $entry[$styleString] = $cacheEntry;
+
+ // Download the remote file
+ $remoteFileContent = @file_get_contents($remoteFile, null, $context);
+ if (false === $remoteFileContent) {
+ return false;
+ }
+ file_put_contents($localTempFile, $remoteFileContent);
+
+ $font = Font::load($localTempFile);
+
+ if (!$font) {
+ unlink($localTempFile);
+ return false;
+ }
+
+ $font->parse();
+ $font->saveAdobeFontMetrics("$cacheEntry.ufm");
+ $font->close();
+
+ unlink($localTempFile);
+
+ if ( !file_exists("$cacheEntry.ufm") ) {
+ return false;
+ }
+
+ // Save the changes
+ file_put_contents($localFile, file_get_contents($remoteFile, null, $context));
+
+ if ( !file_exists($localFile) ) {
+ unlink("$cacheEntry.ufm");
+ return false;
+ }
+
+ $this->setFontFamily($fontname, $entry);
+ $this->saveFontFamilies();
+ }
+
+ return true;
+ }
+
+ /**
+ * @param $text
+ * @param $font
+ * @param $size
+ * @param float $word_spacing
+ * @param float $char_spacing
+ * @return float
+ * @deprecated
+ */
+ public function get_text_width($text, $font, $size, $word_spacing = 0.0, $char_spacing = 0.0)
+ {
+ //return self::$_pdf->get_text_width($text, $font, $size, $word_spacing, $char_spacing);
+ return $this->getTextWidth($text, $font, $size, $word_spacing, $char_spacing);
+ }
+
+ /**
+ * Calculates text size, in points
+ *
+ * @param string $text the text to be sized
+ * @param string $font the desired font
+ * @param float $size the desired font size
+ * @param float $wordSpacing
+ * @param float $charSpacing
+ *
+ * @internal param float $spacing word spacing, if any
+ * @return float
+ */
+ public function getTextWidth($text, $font, $size, $wordSpacing = 0.0, $charSpacing = 0.0)
+ {
+ // @todo Make sure this cache is efficient before enabling it
+ static $cache = array();
+
+ if ($text === "") {
+ return 0;
+ }
+
+ // Don't cache long strings
+ $useCache = !isset($text[50]); // Faster than strlen
+
+ $key = "$font/$size/$wordSpacing/$charSpacing";
+
+ if ($useCache && isset($cache[$key][$text])) {
+ return $cache[$key]["$text"];
+ }
+
+ $width = $this->getCanvas()->get_text_width($text, $font, $size, $wordSpacing, $charSpacing);
+
+ if ($useCache) {
+ $cache[$key][$text] = $width;
+ }
+
+ return $width;
+ }
+
+ /**
+ * @param $font
+ * @param $size
+ * @return float
+ * @deprecated
+ */
+ public function get_font_height($font, $size)
+ {
+ return $this->getFontHeight($font, $size);
+ }
+
+ /**
+ * Calculates font height
+ *
+ * @param string $font
+ * @param float $size
+ *
+ * @return float
+ */
+ public function getFontHeight($font, $size)
+ {
+ return $this->getCanvas()->get_font_height($font, $size);
+ }
+
+ /**
+ * @param $family_raw
+ * @param string $subtype_raw
+ * @return string
+ * @deprecated
+ */
+ public function get_font($family_raw, $subtype_raw = "normal")
+ {
+ return $this->getFont($family_raw, $subtype_raw);
+ }
+
+ /**
+ * Resolves a font family & subtype into an actual font file
+ * Subtype can be one of 'normal', 'bold', 'italic' or 'bold_italic'. If
+ * the particular font family has no suitable font file, the default font
+ * ({@link Options::defaultFont}) is used. The font file returned
+ * is the absolute pathname to the font file on the system.
+ *
+ * @param string $familyRaw
+ * @param string $subtypeRaw
+ *
+ * @return string
+ */
+ public function getFont($familyRaw, $subtypeRaw = "normal")
+ {
+ static $cache = array();
+
+ if (isset($cache[$familyRaw][$subtypeRaw])) {
+ return $cache[$familyRaw][$subtypeRaw];
+ }
+
+ /* Allow calling for various fonts in search path. Therefore not immediately
+ * return replacement on non match.
+ * Only when called with NULL try replacement.
+ * When this is also missing there is really trouble.
+ * If only the subtype fails, nevertheless return failure.
+ * Only on checking the fallback font, check various subtypes on same font.
+ */
+
+ $subtype = strtolower($subtypeRaw);
+
+ if ($familyRaw) {
+ $family = str_replace(array("'", '"'), "", strtolower($familyRaw));
+
+ if (isset($this->fontLookup[$family][$subtype])) {
+ return $cache[$familyRaw][$subtypeRaw] = $this->fontLookup[$family][$subtype];
+ }
+
+ return null;
+ }
+
+ $family = "serif";
+
+ if (isset($this->fontLookup[$family][$subtype])) {
+ return $cache[$familyRaw][$subtypeRaw] = $this->fontLookup[$family][$subtype];
+ }
+
+ if (!isset($this->fontLookup[$family])) {
+ return null;
+ }
+
+ $family = $this->fontLookup[$family];
+
+ foreach ($family as $sub => $font) {
+ if (strpos($subtype, $sub) !== false) {
+ return $cache[$familyRaw][$subtypeRaw] = $font;
+ }
+ }
+
+ if ($subtype !== "normal") {
+ foreach ($family as $sub => $font) {
+ if ($sub !== "normal") {
+ return $cache[$familyRaw][$subtypeRaw] = $font;
+ }
+ }
+ }
+
+ $subtype = "normal";
+
+ if (isset($family[$subtype])) {
+ return $cache[$familyRaw][$subtypeRaw] = $family[$subtype];
+ }
+
+ return null;
+ }
+
+ /**
+ * @param $family
+ * @return null|string
+ * @deprecated
+ */
+ public function get_family($family)
+ {
+ return $this->getFamily($family);
+ }
+
+ /**
+ * @param string $family
+ * @return null|string
+ */
+ public function getFamily($family)
+ {
+ $family = str_replace(array("'", '"'), "", mb_strtolower($family));
+
+ if (isset($this->fontLookup[$family])) {
+ return $this->fontLookup[$family];
+ }
+
+ return null;
+ }
+
+ /**
+ * @param $type
+ * @return string
+ * @deprecated
+ */
+ public function get_type($type)
+ {
+ return $this->getType($type);
+ }
+
+ /**
+ * @param string $type
+ * @return string
+ */
+ public function getType($type)
+ {
+ if (preg_match("/bold/i", $type)) {
+ if (preg_match("/italic|oblique/i", $type)) {
+ $type = "bold_italic";
+ } else {
+ $type = "bold";
+ }
+ } elseif (preg_match("/italic|oblique/i", $type)) {
+ $type = "italic";
+ } else {
+ $type = "normal";
+ }
+
+ return $type;
+ }
+
+ /**
+ * @return array
+ * @deprecated
+ */
+ public function get_system_fonts()
+ {
+ return $this->getSystemFonts();
+ }
+
+ /**
+ * @return array
+ */
+ public function getSystemFonts()
+ {
+ $files = glob("/usr/share/fonts/truetype/*.ttf") +
+ glob("/usr/share/fonts/truetype/*/*.ttf") +
+ glob("/usr/share/fonts/truetype/*/*/*.ttf") +
+ glob("C:\\Windows\\fonts\\*.ttf") +
+ glob("C:\\WinNT\\fonts\\*.ttf") +
+ glob("/mnt/c_drive/WINDOWS/Fonts/");
+
+ return $this->installFonts($files);
+ }
+
+ /**
+ * @return array
+ * @deprecated
+ */
+ public function get_font_families()
+ {
+ return $this->getFontFamilies();
+ }
+
+ /**
+ * Returns the current font lookup table
+ *
+ * @return array
+ */
+ public function getFontFamilies()
+ {
+ return $this->fontLookup;
+ }
+
+ /**
+ * @param string $fontname
+ * @param mixed $entry
+ * @deprecated
+ */
+ public function set_font_family($fontname, $entry)
+ {
+ $this->setFontFamily($fontname, $entry);
+ }
+
+ /**
+ * @param string $fontname
+ * @param mixed $entry
+ */
+ public function setFontFamily($fontname, $entry)
+ {
+ $this->fontLookup[mb_strtolower($fontname)] = $entry;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCacheFile()
+ {
+ return $this->getOptions()->getFontDir() . DIRECTORY_SEPARATOR . self::CACHE_FILE;
+ }
+
+ /**
+ * @param Options $options
+ * @return $this
+ */
+ public function setOptions(Options $options)
+ {
+ $this->options = $options;
+ return $this;
+ }
+
+ /**
+ * @return Options
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * @param Canvas $canvas
+ * @return $this
+ */
+ public function setCanvas(Canvas $canvas)
+ {
+ $this->pdf = $canvas;
+ $this->canvas = $canvas;
+ return $this;
+ }
+
+ /**
+ * @return Canvas
+ */
+ public function getCanvas()
+ {
+ return $this->canvas;
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/Frame.php b/library/vendor/dompdf/src/Frame.php
new file mode 100644
index 000000000..6c2491d04
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame.php
@@ -0,0 +1,1109 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+/**
+ * The main Frame class
+ *
+ * This class represents a single HTML element. This class stores
+ * positioning information as well as containing block location and
+ * dimensions. Style information for the element is stored in a {@link
+ * Style} object. Tree structure is maintained via the parent & children
+ * links.
+ *
+ * @package dompdf
+ */
+class Frame
+{
+ const WS_TEXT = 1;
+ const WS_SPACE = 2;
+
+ /**
+ * The DOMElement or DOMText object this frame represents
+ *
+ * @var \DOMElement|\DOMText
+ */
+ protected $_node;
+
+ /**
+ * Unique identifier for this frame. Used to reference this frame
+ * via the node.
+ *
+ * @var string
+ */
+ protected $_id;
+
+ /**
+ * Unique id counter
+ */
+ public static $ID_COUNTER = 0; /*protected*/
+
+ /**
+ * This frame's calculated style
+ *
+ * @var Style
+ */
+ protected $_style;
+
+ /**
+ * This frame's original style. Needed for cases where frames are
+ * split across pages.
+ *
+ * @var Style
+ */
+ protected $_original_style;
+
+ /**
+ * This frame's parent in the document tree.
+ *
+ * @var Frame
+ */
+ protected $_parent;
+
+ /**
+ * This frame's children
+ *
+ * @var Frame[]
+ */
+ protected $_frame_list;
+
+ /**
+ * This frame's first child. All children are handled as a
+ * doubly-linked list.
+ *
+ * @var Frame
+ */
+ protected $_first_child;
+
+ /**
+ * This frame's last child.
+ *
+ * @var Frame
+ */
+ protected $_last_child;
+
+ /**
+ * This frame's previous sibling in the document tree.
+ *
+ * @var Frame
+ */
+ protected $_prev_sibling;
+
+ /**
+ * This frame's next sibling in the document tree.
+ *
+ * @var Frame
+ */
+ protected $_next_sibling;
+
+ /**
+ * This frame's containing block (used in layout): array(x, y, w, h)
+ *
+ * @var float[]
+ */
+ protected $_containing_block;
+
+ /**
+ * Position on the page of the top-left corner of the margin box of
+ * this frame: array(x,y)
+ *
+ * @var float[]
+ */
+ protected $_position;
+
+ /**
+ * Absolute opacity of this frame
+ *
+ * @var float
+ */
+ protected $_opacity;
+
+ /**
+ * This frame's decorator
+ *
+ * @var \Dompdf\FrameDecorator\AbstractFrameDecorator
+ */
+ protected $_decorator;
+
+ /**
+ * This frame's containing line box
+ *
+ * @var LineBox
+ */
+ protected $_containing_line;
+
+ /**
+ * @var array
+ */
+ protected $_is_cache = array();
+
+ /**
+ * Tells wether the frame was already pushed to the next page
+ *
+ * @var bool
+ */
+ public $_already_pushed = false;
+
+ /**
+ * @var bool
+ */
+ public $_float_next_line = false;
+
+ /**
+ * Tells wether the frame was split
+ *
+ * @var bool
+ */
+ public $_splitted;
+
+ /**
+ * @var int
+ */
+ public static $_ws_state = self::WS_SPACE;
+
+ /**
+ * Class constructor
+ *
+ * @param \DOMNode $node the DOMNode this frame represents
+ */
+ public function __construct(\DOMNode $node)
+ {
+ $this->_node = $node;
+
+ $this->_parent = null;
+ $this->_first_child = null;
+ $this->_last_child = null;
+ $this->_prev_sibling = $this->_next_sibling = null;
+
+ $this->_style = null;
+ $this->_original_style = null;
+
+ $this->_containing_block = array(
+ "x" => null,
+ "y" => null,
+ "w" => null,
+ "h" => null,
+ );
+
+ $this->_containing_block[0] =& $this->_containing_block["x"];
+ $this->_containing_block[1] =& $this->_containing_block["y"];
+ $this->_containing_block[2] =& $this->_containing_block["w"];
+ $this->_containing_block[3] =& $this->_containing_block["h"];
+
+ $this->_position = array(
+ "x" => null,
+ "y" => null,
+ );
+
+ $this->_position[0] =& $this->_position["x"];
+ $this->_position[1] =& $this->_position["y"];
+
+ $this->_opacity = 1.0;
+ $this->_decorator = null;
+
+ $this->set_id(self::$ID_COUNTER++);
+ }
+
+ /**
+ * WIP : preprocessing to remove all the unused whitespace
+ */
+ protected function ws_trim()
+ {
+ if ($this->ws_keep()) {
+ return;
+ }
+
+ if (self::$_ws_state === self::WS_SPACE) {
+ $node = $this->_node;
+
+ if ($node->nodeName === "#text" && !empty($node->nodeValue)) {
+ $node->nodeValue = preg_replace("/[ \t\r\n\f]+/u", " ", trim($node->nodeValue));
+ self::$_ws_state = self::WS_TEXT;
+ }
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ protected function ws_keep()
+ {
+ $whitespace = $this->get_style()->white_space;
+
+ return in_array($whitespace, array("pre", "pre-wrap", "pre-line"));
+ }
+
+ /**
+ * @return bool
+ */
+ protected function ws_is_text()
+ {
+ $node = $this->get_node();
+
+ if ($node->nodeName === "img") {
+ return true;
+ }
+
+ if (!$this->is_in_flow()) {
+ return false;
+ }
+
+ if ($this->is_text_node()) {
+ return trim($node->nodeValue) !== "";
+ }
+
+ return true;
+ }
+
+ /**
+ * "Destructor": forcibly free all references held by this frame
+ *
+ * @param bool $recursive if true, call dispose on all children
+ */
+ public function dispose($recursive = false)
+ {
+ if ($recursive) {
+ while ($child = $this->_first_child) {
+ $child->dispose(true);
+ }
+ }
+
+ // Remove this frame from the tree
+ if ($this->_prev_sibling) {
+ $this->_prev_sibling->_next_sibling = $this->_next_sibling;
+ }
+
+ if ($this->_next_sibling) {
+ $this->_next_sibling->_prev_sibling = $this->_prev_sibling;
+ }
+
+ if ($this->_parent && $this->_parent->_first_child === $this) {
+ $this->_parent->_first_child = $this->_next_sibling;
+ }
+
+ if ($this->_parent && $this->_parent->_last_child === $this) {
+ $this->_parent->_last_child = $this->_prev_sibling;
+ }
+
+ if ($this->_parent) {
+ $this->_parent->get_node()->removeChild($this->_node);
+ }
+
+ $this->_style->dispose();
+ $this->_style = null;
+ unset($this->_style);
+
+ $this->_original_style->dispose();
+ $this->_original_style = null;
+ unset($this->_original_style);
+
+ }
+
+ /**
+ * Re-initialize the frame
+ */
+ public function reset()
+ {
+ $this->_position["x"] = null;
+ $this->_position["y"] = null;
+
+ $this->_containing_block["x"] = null;
+ $this->_containing_block["y"] = null;
+ $this->_containing_block["w"] = null;
+ $this->_containing_block["h"] = null;
+
+ $this->_style = null;
+ unset($this->_style);
+ $this->_style = clone $this->_original_style;
+ }
+
+ /**
+ * @return \DOMElement|\DOMText
+ */
+ public function get_node()
+ {
+ return $this->_node;
+ }
+
+ /**
+ * @return string
+ */
+ public function get_id()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * @return Style
+ */
+ public function get_style()
+ {
+ return $this->_style;
+ }
+
+ /**
+ * @return Style
+ */
+ public function get_original_style()
+ {
+ return $this->_original_style;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function get_parent()
+ {
+ return $this->_parent;
+ }
+
+ /**
+ * @return \Dompdf\FrameDecorator\AbstractFrameDecorator
+ */
+ public function get_decorator()
+ {
+ return $this->_decorator;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function get_first_child()
+ {
+ return $this->_first_child;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function get_last_child()
+ {
+ return $this->_last_child;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function get_prev_sibling()
+ {
+ return $this->_prev_sibling;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function get_next_sibling()
+ {
+ return $this->_next_sibling;
+ }
+
+ /**
+ * @return FrameList|Frame[]
+ */
+ public function get_children()
+ {
+ if (isset($this->_frame_list)) {
+ return $this->_frame_list;
+ }
+
+ $this->_frame_list = new FrameList($this);
+
+ return $this->_frame_list;
+ }
+
+ // Layout property accessors
+
+ /**
+ * Containing block dimensions
+ *
+ * @param $i string The key of the wanted containing block's dimension (x, y, x, h)
+ *
+ * @return float[]|float
+ */
+ public function get_containing_block($i = null)
+ {
+ if (isset($i)) {
+ return $this->_containing_block[$i];
+ }
+
+ return $this->_containing_block;
+ }
+
+ /**
+ * Block position
+ *
+ * @param $i string The key of the wanted position value (x, y)
+ *
+ * @return array|float
+ */
+ public function get_position($i = null)
+ {
+ if (isset($i)) {
+ return $this->_position[$i];
+ }
+
+ return $this->_position;
+ }
+
+ //........................................................................
+
+ /**
+ * Return the height of the margin box of the frame, in pt. Meaningless
+ * unless the height has been calculated properly.
+ *
+ * @return float
+ */
+ public function get_margin_height()
+ {
+ $style = $this->_style;
+
+ return $style->length_in_pt(array(
+ $style->height,
+ $style->margin_top,
+ $style->margin_bottom,
+ $style->border_top_width,
+ $style->border_bottom_width,
+ $style->padding_top,
+ $style->padding_bottom
+ ), $this->_containing_block["h"]);
+ }
+
+ /**
+ * Return the width of the margin box of the frame, in pt. Meaningless
+ * unless the width has been calculated properly.
+ *
+ * @return float
+ */
+ public function get_margin_width()
+ {
+ $style = $this->_style;
+
+ return $style->length_in_pt(array(
+ $style->width,
+ $style->margin_left,
+ $style->margin_right,
+ $style->border_left_width,
+ $style->border_right_width,
+ $style->padding_left,
+ $style->padding_right
+ ), $this->_containing_block["w"]);
+ }
+
+ /**
+ * @return float
+ */
+ public function get_break_margins()
+ {
+ $style = $this->_style;
+
+ return $style->length_in_pt(array(
+ //$style->height,
+ $style->margin_top,
+ $style->margin_bottom,
+ $style->border_top_width,
+ $style->border_bottom_width,
+ $style->padding_top,
+ $style->padding_bottom
+ ), $this->_containing_block["h"]);
+ }
+
+ /**
+ * Return the padding box (x,y,w,h) of the frame
+ *
+ * @return array
+ */
+ public function get_padding_box()
+ {
+ $style = $this->_style;
+ $cb = $this->_containing_block;
+
+ $x = $this->_position["x"] +
+ $style->length_in_pt(array($style->margin_left,
+ $style->border_left_width),
+ $cb["w"]);
+
+ $y = $this->_position["y"] +
+ $style->length_in_pt(array($style->margin_top,
+ $style->border_top_width),
+ $cb["h"]);
+
+ $w = $style->length_in_pt(array($style->padding_left,
+ $style->width,
+ $style->padding_right),
+ $cb["w"]);
+
+ $h = $style->length_in_pt(array($style->padding_top,
+ $style->height,
+ $style->padding_bottom),
+ $cb["h"]);
+
+ return array(0 => $x, "x" => $x,
+ 1 => $y, "y" => $y,
+ 2 => $w, "w" => $w,
+ 3 => $h, "h" => $h);
+ }
+
+ /**
+ * Return the border box of the frame
+ *
+ * @return array
+ */
+ public function get_border_box()
+ {
+ $style = $this->_style;
+ $cb = $this->_containing_block;
+
+ $x = $this->_position["x"] + $style->length_in_pt($style->margin_left, $cb["w"]);
+
+ $y = $this->_position["y"] + $style->length_in_pt($style->margin_top, $cb["h"]);
+
+ $w = $style->length_in_pt(array($style->border_left_width,
+ $style->padding_left,
+ $style->width,
+ $style->padding_right,
+ $style->border_right_width),
+ $cb["w"]);
+
+ $h = $style->length_in_pt(array($style->border_top_width,
+ $style->padding_top,
+ $style->height,
+ $style->padding_bottom,
+ $style->border_bottom_width),
+ $cb["h"]);
+
+ return array(0 => $x, "x" => $x,
+ 1 => $y, "y" => $y,
+ 2 => $w, "w" => $w,
+ 3 => $h, "h" => $h);
+ }
+
+ /**
+ * @param null $opacity
+ *
+ * @return float
+ */
+ public function get_opacity($opacity = null)
+ {
+ if ($opacity !== null) {
+ $this->set_opacity($opacity);
+ }
+
+ return $this->_opacity;
+ }
+
+ /**
+ * @return LineBox
+ */
+ public function &get_containing_line()
+ {
+ return $this->_containing_line;
+ }
+
+ //........................................................................
+
+ // Set methods
+ /**
+ * @param $id
+ */
+ public function set_id($id)
+ {
+ $this->_id = $id;
+
+ // We can only set attributes of DOMElement objects (nodeType == 1).
+ // Since these are the only objects that we can assign CSS rules to,
+ // this shortcoming is okay.
+ if ($this->_node->nodeType == XML_ELEMENT_NODE) {
+ $this->_node->setAttribute("frame_id", $id);
+ }
+ }
+
+ /**
+ * @param Style $style
+ */
+ public function set_style(Style $style)
+ {
+ if (is_null($this->_style)) {
+ $this->_original_style = clone $style;
+ }
+
+ //$style->set_frame($this);
+ $this->_style = $style;
+ }
+
+ /**
+ * @param \Dompdf\FrameDecorator\AbstractFrameDecorator $decorator
+ */
+ public function set_decorator(FrameDecorator\AbstractFrameDecorator $decorator)
+ {
+ $this->_decorator = $decorator;
+ }
+
+ /**
+ * @param null $x
+ * @param null $y
+ * @param null $w
+ * @param null $h
+ */
+ public function set_containing_block($x = null, $y = null, $w = null, $h = null)
+ {
+ if (is_array($x)) {
+ foreach ($x as $key => $val) {
+ $$key = $val;
+ }
+ }
+
+ if (is_numeric($x)) {
+ $this->_containing_block["x"] = $x;
+ }
+
+ if (is_numeric($y)) {
+ $this->_containing_block["y"] = $y;
+ }
+
+ if (is_numeric($w)) {
+ $this->_containing_block["w"] = $w;
+ }
+
+ if (is_numeric($h)) {
+ $this->_containing_block["h"] = $h;
+ }
+ }
+
+ /**
+ * @param null $x
+ * @param null $y
+ */
+ public function set_position($x = null, $y = null)
+ {
+ if (is_array($x)) {
+ list($x, $y) = array($x["x"], $x["y"]);
+ }
+
+ if (is_numeric($x)) {
+ $this->_position["x"] = $x;
+ }
+
+ if (is_numeric($y)) {
+ $this->_position["y"] = $y;
+ }
+ }
+
+ /**
+ * @param $opacity
+ */
+ public function set_opacity($opacity)
+ {
+ $parent = $this->get_parent();
+ $base_opacity = (($parent && $parent->_opacity !== null) ? $parent->_opacity : 1.0);
+ $this->_opacity = $base_opacity * $opacity;
+ }
+
+ /**
+ * @param LineBox $line
+ */
+ public function set_containing_line(LineBox $line)
+ {
+ $this->_containing_line = $line;
+ }
+
+ /**
+ * Tells if the frame is a text node
+ *
+ * @return bool
+ */
+ public function is_text_node()
+ {
+ if (isset($this->_is_cache["text_node"])) {
+ return $this->_is_cache["text_node"];
+ }
+
+ return $this->_is_cache["text_node"] = ($this->get_node()->nodeName === "#text");
+ }
+
+ /**
+ * @return bool
+ */
+ public function is_positionned()
+ {
+ if (isset($this->_is_cache["positionned"])) {
+ return $this->_is_cache["positionned"];
+ }
+
+ $position = $this->get_style()->position;
+
+ return $this->_is_cache["positionned"] = in_array($position, Style::$POSITIONNED_TYPES);
+ }
+
+ /**
+ * @return bool
+ */
+ public function is_absolute()
+ {
+ if (isset($this->_is_cache["absolute"])) {
+ return $this->_is_cache["absolute"];
+ }
+
+ $position = $this->get_style()->position;
+
+ return $this->_is_cache["absolute"] = ($position === "absolute" || $position === "fixed");
+ }
+
+ /**
+ * @return bool
+ */
+ public function is_block()
+ {
+ if (isset($this->_is_cache["block"])) {
+ return $this->_is_cache["block"];
+ }
+
+ return $this->_is_cache["block"] = in_array($this->get_style()->display, Style::$BLOCK_TYPES);
+ }
+
+ /**
+ * @return bool
+ */
+ public function is_in_flow()
+ {
+ if (isset($this->_is_cache["in_flow"])) {
+ return $this->_is_cache["in_flow"];
+ }
+ return $this->_is_cache["in_flow"] = !($this->get_style()->float !== "none" || $this->is_absolute());
+ }
+
+ /**
+ * @return bool
+ */
+ public function is_pre()
+ {
+ if (isset($this->_is_cache["pre"])) {
+ return $this->_is_cache["pre"];
+ }
+
+ $white_space = $this->get_style()->white_space;
+
+ return $this->_is_cache["pre"] = in_array($white_space, array("pre", "pre-wrap"));
+ }
+
+ /**
+ * @return bool
+ */
+ public function is_table()
+ {
+ if (isset($this->_is_cache["table"])) {
+ return $this->_is_cache["table"];
+ }
+
+ $display = $this->get_style()->display;
+
+ return $this->_is_cache["table"] = in_array($display, Style::$TABLE_TYPES);
+ }
+
+
+ /**
+ * Inserts a new child at the beginning of the Frame
+ *
+ * @param $child Frame The new Frame to insert
+ * @param $update_node boolean Whether or not to update the DOM
+ */
+ public function prepend_child(Frame $child, $update_node = true)
+ {
+ if ($update_node) {
+ $this->_node->insertBefore($child->_node, $this->_first_child ? $this->_first_child->_node : null);
+ }
+
+ // Remove the child from its parent
+ if ($child->_parent) {
+ $child->_parent->remove_child($child, false);
+ }
+
+ $child->_parent = $this;
+ $child->_prev_sibling = null;
+
+ // Handle the first child
+ if (!$this->_first_child) {
+ $this->_first_child = $child;
+ $this->_last_child = $child;
+ $child->_next_sibling = null;
+ } else {
+ $this->_first_child->_prev_sibling = $child;
+ $child->_next_sibling = $this->_first_child;
+ $this->_first_child = $child;
+ }
+ }
+
+ /**
+ * Inserts a new child at the end of the Frame
+ *
+ * @param $child Frame The new Frame to insert
+ * @param $update_node boolean Whether or not to update the DOM
+ */
+ public function append_child(Frame $child, $update_node = true)
+ {
+ if ($update_node) {
+ $this->_node->appendChild($child->_node);
+ }
+
+ // Remove the child from its parent
+ if ($child->_parent) {
+ $child->_parent->remove_child($child, false);
+ }
+
+ $child->_parent = $this;
+ $child->_next_sibling = null;
+
+ // Handle the first child
+ if (!$this->_last_child) {
+ $this->_first_child = $child;
+ $this->_last_child = $child;
+ $child->_prev_sibling = null;
+ } else {
+ $this->_last_child->_next_sibling = $child;
+ $child->_prev_sibling = $this->_last_child;
+ $this->_last_child = $child;
+ }
+ }
+
+ /**
+ * Inserts a new child immediately before the specified frame
+ *
+ * @param $new_child Frame The new Frame to insert
+ * @param $ref Frame The Frame after the new Frame
+ * @param $update_node boolean Whether or not to update the DOM
+ *
+ * @throws Exception
+ */
+ public function insert_child_before(Frame $new_child, Frame $ref, $update_node = true)
+ {
+ if ($ref === $this->_first_child) {
+ $this->prepend_child($new_child, $update_node);
+
+ return;
+ }
+
+ if (is_null($ref)) {
+ $this->append_child($new_child, $update_node);
+
+ return;
+ }
+
+ if ($ref->_parent !== $this) {
+ throw new Exception("Reference child is not a child of this node.");
+ }
+
+ // Update the node
+ if ($update_node) {
+ $this->_node->insertBefore($new_child->_node, $ref->_node);
+ }
+
+ // Remove the child from its parent
+ if ($new_child->_parent) {
+ $new_child->_parent->remove_child($new_child, false);
+ }
+
+ $new_child->_parent = $this;
+ $new_child->_next_sibling = $ref;
+ $new_child->_prev_sibling = $ref->_prev_sibling;
+
+ if ($ref->_prev_sibling) {
+ $ref->_prev_sibling->_next_sibling = $new_child;
+ }
+
+ $ref->_prev_sibling = $new_child;
+ }
+
+ /**
+ * Inserts a new child immediately after the specified frame
+ *
+ * @param $new_child Frame The new Frame to insert
+ * @param $ref Frame The Frame before the new Frame
+ * @param $update_node boolean Whether or not to update the DOM
+ *
+ * @throws Exception
+ */
+ public function insert_child_after(Frame $new_child, Frame $ref, $update_node = true)
+ {
+ if ($ref === $this->_last_child) {
+ $this->append_child($new_child, $update_node);
+
+ return;
+ }
+
+ if (is_null($ref)) {
+ $this->prepend_child($new_child, $update_node);
+
+ return;
+ }
+
+ if ($ref->_parent !== $this) {
+ throw new Exception("Reference child is not a child of this node.");
+ }
+
+ // Update the node
+ if ($update_node) {
+ if ($ref->_next_sibling) {
+ $next_node = $ref->_next_sibling->_node;
+ $this->_node->insertBefore($new_child->_node, $next_node);
+ } else {
+ $new_child->_node = $this->_node->appendChild($new_child->_node);
+ }
+ }
+
+ // Remove the child from its parent
+ if ($new_child->_parent) {
+ $new_child->_parent->remove_child($new_child, false);
+ }
+
+ $new_child->_parent = $this;
+ $new_child->_prev_sibling = $ref;
+ $new_child->_next_sibling = $ref->_next_sibling;
+
+ if ($ref->_next_sibling) {
+ $ref->_next_sibling->_prev_sibling = $new_child;
+ }
+
+ $ref->_next_sibling = $new_child;
+ }
+
+ /**
+ * Remove a child frame
+ *
+ * @param Frame $child
+ * @param boolean $update_node Whether or not to remove the DOM node
+ *
+ * @throws Exception
+ * @return Frame The removed child frame
+ */
+ public function remove_child(Frame $child, $update_node = true)
+ {
+ if ($child->_parent !== $this) {
+ throw new Exception("Child not found in this frame");
+ }
+
+ if ($update_node) {
+ $this->_node->removeChild($child->_node);
+ }
+
+ if ($child === $this->_first_child) {
+ $this->_first_child = $child->_next_sibling;
+ }
+
+ if ($child === $this->_last_child) {
+ $this->_last_child = $child->_prev_sibling;
+ }
+
+ if ($child->_prev_sibling) {
+ $child->_prev_sibling->_next_sibling = $child->_next_sibling;
+ }
+
+ if ($child->_next_sibling) {
+ $child->_next_sibling->_prev_sibling = $child->_prev_sibling;
+ }
+
+ $child->_next_sibling = null;
+ $child->_prev_sibling = null;
+ $child->_parent = null;
+
+ return $child;
+ }
+
+ //........................................................................
+
+ // Debugging function:
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ // Skip empty text frames
+// if ( $this->is_text_node() &&
+// preg_replace("/\s/", "", $this->_node->data) === "" )
+// return "";
+
+
+ $str = "" . $this->_node->nodeName . ": ";
+ //$str .= spl_object_hash($this->_node) . " ";
+ $str .= "Id: " . $this->get_id() . " ";
+ $str .= "Class: " . get_class($this) . " ";
+
+ if ($this->is_text_node()) {
+ $tmp = htmlspecialchars($this->_node->nodeValue);
+ $str .= "'" . mb_substr($tmp, 0, 70) .
+ (mb_strlen($tmp) > 70 ? "..." : "") . "' ";
+ } elseif ($css_class = $this->_node->getAttribute("class")) {
+ $str .= "CSS class: '$css_class' ";
+ }
+
+ if ($this->_parent) {
+ $str .= "\nParent:" . $this->_parent->_node->nodeName .
+ " (" . spl_object_hash($this->_parent->_node) . ") " .
+ " ";
+ }
+
+ if ($this->_prev_sibling) {
+ $str .= "Prev: " . $this->_prev_sibling->_node->nodeName .
+ " (" . spl_object_hash($this->_prev_sibling->_node) . ") " .
+ " ";
+ }
+
+ if ($this->_next_sibling) {
+ $str .= "Next: " . $this->_next_sibling->_node->nodeName .
+ " (" . spl_object_hash($this->_next_sibling->_node) . ") " .
+ " ";
+ }
+
+ $d = $this->get_decorator();
+ while ($d && $d != $d->get_decorator()) {
+ $str .= "Decorator: " . get_class($d) . " ";
+ $d = $d->get_decorator();
+ }
+
+ $str .= "Position: " . Helpers::pre_r($this->_position, true);
+ $str .= "\nContaining block: " . Helpers::pre_r($this->_containing_block, true);
+ $str .= "\nMargin width: " . Helpers::pre_r($this->get_margin_width(), true);
+ $str .= "\nMargin height: " . Helpers::pre_r($this->get_margin_height(), true);
+
+ $str .= "\nStyle: " . $this->_style->__toString() . " ";
+
+ if ($this->_decorator instanceof FrameDecorator\Block) {
+ $str .= "Lines:";
+ foreach ($this->_decorator->get_line_boxes() as $line) {
+ foreach ($line->get_frames() as $frame) {
+ if ($frame instanceof FrameDecorator\Text) {
+ $str .= "\ntext: ";
+ $str .= "'" . htmlspecialchars($frame->get_text()) . "'";
+ } else {
+ $str .= "\nBlock: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")";
+ }
+ }
+
+ $str .=
+ "\ny => " . $line->y . "\n" .
+ "w => " . $line->w . "\n" .
+ "h => " . $line->h . "\n" .
+ "left => " . $line->left . "\n" .
+ "right => " . $line->right . "\n";
+ }
+ $str .= " ";
+ }
+
+ $str .= "\n";
+ if (php_sapi_name() === "cli") {
+ $str = strip_tags(str_replace(array(" ", "", " "),
+ array("\n", "", ""),
+ $str));
+ }
+
+ return $str;
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/Frame/Factory.php b/library/vendor/dompdf/src/Frame/Factory.php
new file mode 100644
index 000000000..431a5c10c
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame/Factory.php
@@ -0,0 +1,262 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Frame;
+
+use Dompdf\Css\Style;
+use Dompdf\Dompdf;
+use Dompdf\Exception;
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+use DOMXPath;
+use Dompdf\FrameDecorator\Page as PageFrameDecorator;
+use Dompdf\FrameReflower\Page as PageFrameReflower;
+
+/**
+ * Contains frame decorating logic
+ *
+ * This class is responsible for assigning the correct {@link AbstractFrameDecorator},
+ * {@link AbstractPositioner}, and {@link AbstractFrameReflower} objects to {@link Frame}
+ * objects. This is determined primarily by the Frame's display type, but
+ * also by the Frame's node's type (e.g. DomElement vs. #text)
+ *
+ * @access private
+ * @package dompdf
+ */
+class Factory
+{
+
+ /**
+ * Decorate the root Frame
+ *
+ * @param $root Frame The frame to decorate
+ * @param $dompdf Dompdf The dompdf instance
+ *
+ * @return PageFrameDecorator
+ */
+ static function decorate_root(Frame $root, Dompdf $dompdf)
+ {
+ $frame = new PageFrameDecorator($root, $dompdf);
+ $frame->set_reflower(new PageFrameReflower($frame));
+ $root->set_decorator($frame);
+
+ return $frame;
+ }
+
+ /**
+ * Decorate a Frame
+ *
+ * @param Frame $frame The frame to decorate
+ * @param Dompdf $dompdf The dompdf instance
+ * @param Frame $root The frame to decorate
+ *
+ * @throws Exception
+ * @return AbstractFrameDecorator
+ * FIXME: this is admittedly a little smelly...
+ */
+ static function decorate_frame(Frame $frame, Dompdf $dompdf, Frame $root = null)
+ {
+ if (is_null($dompdf)) {
+ throw new Exception("The DOMPDF argument is required");
+ }
+
+ $style = $frame->get_style();
+
+ // Floating (and more generally out-of-flow) elements are blocks
+ // http://coding.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
+ if (!$frame->is_in_flow() && in_array($style->display, Style::$INLINE_TYPES)) {
+ $style->display = "block";
+ }
+
+ $display = $style->display;
+
+ switch ($display) {
+
+ case "block":
+ $positioner = "Block";
+ $decorator = "Block";
+ $reflower = "Block";
+ break;
+
+ case "inline-block":
+ $positioner = "Inline";
+ $decorator = "Block";
+ $reflower = "Block";
+ break;
+
+ case "inline":
+ $positioner = "Inline";
+ if ($frame->is_text_node()) {
+ $decorator = "Text";
+ $reflower = "Text";
+ } else {
+ if ($style->float !== "none") {
+ $decorator = "Block";
+ $reflower = "Block";
+ } else {
+ $decorator = "Inline";
+ $reflower = "Inline";
+ }
+ }
+ break;
+
+ case "table":
+ $positioner = "Block";
+ $decorator = "Table";
+ $reflower = "Table";
+ break;
+
+ case "inline-table":
+ $positioner = "Inline";
+ $decorator = "Table";
+ $reflower = "Table";
+ break;
+
+ case "table-row-group":
+ case "table-header-group":
+ case "table-footer-group":
+ $positioner = "NullPositioner";
+ $decorator = "TableRowGroup";
+ $reflower = "TableRowGroup";
+ break;
+
+ case "table-row":
+ $positioner = "NullPositioner";
+ $decorator = "TableRow";
+ $reflower = "TableRow";
+ break;
+
+ case "table-cell":
+ $positioner = "TableCell";
+ $decorator = "TableCell";
+ $reflower = "TableCell";
+ break;
+
+ case "list-item":
+ $positioner = "Block";
+ $decorator = "Block";
+ $reflower = "Block";
+ break;
+
+ case "-dompdf-list-bullet":
+ if ($style->list_style_position === "inside") {
+ $positioner = "Inline";
+ } else {
+ $positioner = "ListBullet";
+ }
+
+ if ($style->list_style_image !== "none") {
+ $decorator = "ListBulletImage";
+ } else {
+ $decorator = "ListBullet";
+ }
+
+ $reflower = "ListBullet";
+ break;
+
+ case "-dompdf-image":
+ $positioner = "Inline";
+ $decorator = "Image";
+ $reflower = "Image";
+ break;
+
+ case "-dompdf-br":
+ $positioner = "Inline";
+ $decorator = "Inline";
+ $reflower = "Inline";
+ break;
+
+ default:
+ // FIXME: should throw some sort of warning or something?
+ case "none":
+ if ($style->_dompdf_keep !== "yes") {
+ // Remove the node and the frame
+ $frame->get_parent()->remove_child($frame);
+ return;
+ }
+
+ $positioner = "NullPositioner";
+ $decorator = "NullFrameDecorator";
+ $reflower = "NullFrameReflower";
+ break;
+ }
+
+ // Handle CSS position
+ $position = $style->position;
+
+ if ($position === "absolute") {
+ $positioner = "Absolute";
+ } else {
+ if ($position === "fixed") {
+ $positioner = "Fixed";
+ }
+ }
+
+ $node = $frame->get_node();
+
+ // Handle nodeName
+ if ($node->nodeName === "img") {
+ $style->display = "-dompdf-image";
+ $decorator = "Image";
+ $reflower = "Image";
+ }
+
+ $positioner = "Dompdf\\Positioner\\$positioner";
+ $decorator = "Dompdf\\FrameDecorator\\$decorator";
+ $reflower = "Dompdf\\FrameReflower\\$reflower";
+
+ /** @var AbstractFrameDecorator $deco */
+ $deco = new $decorator($frame, $dompdf);
+
+ $deco->set_positioner(new $positioner($deco));
+ $deco->set_reflower(new $reflower($deco, $dompdf->getFontMetrics()));
+
+ if ($root) {
+ $deco->set_root($root);
+ }
+
+ if ($display === "list-item") {
+ // Insert a list-bullet frame
+ $xml = $dompdf->get_dom();
+ $bullet_node = $xml->createElement("bullet"); // arbitrary choice
+ $b_f = new Frame($bullet_node);
+
+ $node = $frame->get_node();
+ $parent_node = $node->parentNode;
+
+ if ($parent_node) {
+ if (!$parent_node->hasAttribute("dompdf-children-count")) {
+ $xpath = new DOMXPath($xml);
+ $count = $xpath->query("li", $parent_node)->length;
+ $parent_node->setAttribute("dompdf-children-count", $count);
+ }
+
+ if (is_numeric($node->getAttribute("value"))) {
+ $index = intval($node->getAttribute("value"));
+ } else {
+ if (!$parent_node->hasAttribute("dompdf-counter")) {
+ $index = ($parent_node->hasAttribute("start") ? $parent_node->getAttribute("start") : 1);
+ } else {
+ $index = $parent_node->getAttribute("dompdf-counter") + 1;
+ }
+ }
+
+ $parent_node->setAttribute("dompdf-counter", $index);
+ $bullet_node->setAttribute("dompdf-counter", $index);
+ }
+
+ $new_style = $dompdf->get_css()->create_style();
+ $new_style->display = "-dompdf-list-bullet";
+ $new_style->inherit($style);
+ $b_f->set_style($new_style);
+
+ $deco->prepend_child(Factory::decorate_frame($b_f, $dompdf, $root));
+ }
+
+ return $deco;
+ }
+}
diff --git a/library/vendor/dompdf/src/Frame/FrameList.php b/library/vendor/dompdf/src/Frame/FrameList.php
new file mode 100644
index 000000000..783600dc7
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame/FrameList.php
@@ -0,0 +1,34 @@
+_frame = $frame;
+ }
+
+ /**
+ * @return FrameListIterator
+ */
+ function getIterator()
+ {
+ return new FrameListIterator($this->_frame);
+ }
+}
diff --git a/library/vendor/dompdf/src/Frame/FrameListIterator.php b/library/vendor/dompdf/src/Frame/FrameListIterator.php
new file mode 100644
index 000000000..ada9dde18
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame/FrameListIterator.php
@@ -0,0 +1,91 @@
+_parent = $frame;
+ $this->_cur = $frame->get_first_child();
+ $this->_num = 0;
+ }
+
+ /**
+ *
+ */
+ public function rewind()
+ {
+ $this->_cur = $this->_parent->get_first_child();
+ $this->_num = 0;
+ }
+
+ /**
+ * @return bool
+ */
+ public function valid()
+ {
+ return isset($this->_cur); // && ($this->_cur->get_prev_sibling() === $this->_prev);
+ }
+
+ /**
+ * @return int
+ */
+ public function key()
+ {
+ return $this->_num;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function current()
+ {
+ return $this->_cur;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function next()
+ {
+ $ret = $this->_cur;
+ if (!$ret) {
+ return null;
+ }
+
+ $this->_cur = $this->_cur->get_next_sibling();
+ $this->_num++;
+ return $ret;
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/Frame/FrameTree.php b/library/vendor/dompdf/src/Frame/FrameTree.php
new file mode 100644
index 000000000..ff882ff33
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame/FrameTree.php
@@ -0,0 +1,300 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+/**
+ * Represents an entire document as a tree of frames
+ *
+ * The FrameTree consists of {@link Frame} objects each tied to specific
+ * DOMNode objects in a specific DomDocument. The FrameTree has the same
+ * structure as the DomDocument, but adds additional capabalities for
+ * styling and layout.
+ *
+ * @package dompdf
+ */
+class FrameTree
+{
+ /**
+ * Tags to ignore while parsing the tree
+ *
+ * @var array
+ */
+ protected static $HIDDEN_TAGS = array(
+ "area",
+ "base",
+ "basefont",
+ "head",
+ "style",
+ "meta",
+ "title",
+ "colgroup",
+ "noembed",
+ "noscript",
+ "param",
+ "#comment"
+ );
+
+ /**
+ * The main DomDocument
+ *
+ * @see http://ca2.php.net/manual/en/ref.dom.php
+ * @var DOMDocument
+ */
+ protected $_dom;
+
+ /**
+ * The root node of the FrameTree.
+ *
+ * @var Frame
+ */
+ protected $_root;
+
+ /**
+ * Subtrees of absolutely positioned elements
+ *
+ * @var array of Frames
+ */
+ protected $_absolute_frames;
+
+ /**
+ * A mapping of {@link Frame} objects to DOMNode objects
+ *
+ * @var array
+ */
+ protected $_registry;
+
+ /**
+ * Class constructor
+ *
+ * @param DOMDocument $dom the main DomDocument object representing the current html document
+ */
+ public function __construct(DomDocument $dom)
+ {
+ $this->_dom = $dom;
+ $this->_root = null;
+ $this->_registry = array();
+ }
+
+ /**
+ * Returns the DOMDocument object representing the curent html document
+ *
+ * @return DOMDocument
+ */
+ public function get_dom()
+ {
+ return $this->_dom;
+ }
+
+ /**
+ * Returns the root frame of the tree
+ *
+ * @return \Dompdf\FrameDecorator\Page
+ */
+ public function get_root()
+ {
+ return $this->_root;
+ }
+
+ /**
+ * Returns a specific frame given its id
+ *
+ * @param string $id
+ *
+ * @return Frame
+ */
+ public function get_frame($id)
+ {
+ return isset($this->_registry[$id]) ? $this->_registry[$id] : null;
+ }
+
+ /**
+ * Returns a post-order iterator for all frames in the tree
+ *
+ * @return FrameTreeList|Frame[]
+ */
+ public function get_frames()
+ {
+ return new FrameTreeList($this->_root);
+ }
+
+ /**
+ * Builds the tree
+ */
+ public function build_tree()
+ {
+ $html = $this->_dom->getElementsByTagName("html")->item(0);
+ if (is_null($html)) {
+ $html = $this->_dom->firstChild;
+ }
+
+ if (is_null($html)) {
+ throw new Exception("Requested HTML document contains no data.");
+ }
+
+ $this->fix_tables();
+
+ $this->_root = $this->_build_tree_r($html);
+ }
+
+ /**
+ * Adds missing TBODYs around TR
+ */
+ protected function fix_tables()
+ {
+ $xp = new DOMXPath($this->_dom);
+
+ // Move table caption before the table
+ // FIXME find a better way to deal with it...
+ $captions = $xp->query("//table/caption");
+ foreach ($captions as $caption) {
+ $table = $caption->parentNode;
+ $table->parentNode->insertBefore($caption, $table);
+ }
+
+ $rows = $xp->query("//table/tr");
+ foreach ($rows as $row) {
+ $tbody = $this->_dom->createElement("tbody");
+ $tbody = $row->parentNode->insertBefore($tbody, $row);
+ $tbody->appendChild($row);
+ }
+ }
+
+ // FIXME: temporary hack, preferably we will improve rendering of sequential #text nodes
+ /**
+ * Remove a child from a node
+ *
+ * Remove a child from a node. If the removed node results in two
+ * adjacent #text nodes then combine them.
+ *
+ * @param DONNode $node the current DOMNode being considered
+ * @param array $children an array of nodes that are the children of $node
+ * @param $index index from the $children array of the node to remove
+ */
+ protected function _remove_node(DOMNode $node, array &$children, $index)
+ {
+ $child = $children[$index];
+ $previousChild = $child->previousSibling;
+ $nextChild = $child->nextSibling;
+ $node->removeChild($child);
+ if (isset($previousChild, $nextChild)) {
+ if ($previousChild->nodeName === "#text" && $nextChild->nodeName === "#text")
+ {
+ $previousChild->nodeValue .= $nextChild->nodeValue;
+ $this->_remove_node($node, $children, $index+1);
+ }
+ }
+ array_splice($children, $index, 1);
+ }
+
+ /**
+ * Recursively adds {@link Frame} objects to the tree
+ *
+ * Recursively build a tree of Frame objects based on a dom tree.
+ * No layout information is calculated at this time, although the
+ * tree may be adjusted (i.e. nodes and frames for generated content
+ * and images may be created).
+ *
+ * @param DOMNode $node the current DOMNode being considered
+ *
+ * @return Frame
+ */
+ protected function _build_tree_r(DOMNode $node)
+ {
+ $frame = new Frame($node);
+ $id = $frame->get_id();
+ $this->_registry[$id] = $frame;
+
+ if (!$node->hasChildNodes()) {
+ return $frame;
+ }
+
+ // Store the children in an array so that the tree can be modified
+ $children = array();
+ $length = $node->childNodes->length;
+ for ($i = 0; $i < $length; $i++) {
+ $children[] = $node->childNodes->item($i);
+ }
+ $index = 0;
+ // INFO: We don't advance $index if a node is removed to avoid skipping nodes
+ while ($index < count($children)) {
+ $child = $children[$index];
+ $nodeName = strtolower($child->nodeName);
+
+ // Skip non-displaying nodes
+ if (in_array($nodeName, self::$HIDDEN_TAGS)) {
+ if ($nodeName !== "head" && $nodeName !== "style") {
+ $this->_remove_node($node, $children, $index);
+ } else {
+ $index++;
+ }
+ continue;
+ }
+ // Skip empty text nodes
+ if ($nodeName === "#text" && $child->nodeValue === "") {
+ $this->_remove_node($node, $children, $index);
+ continue;
+ }
+ // Skip empty image nodes
+ if ($nodeName === "img" && $child->getAttribute("src") === "") {
+ $this->_remove_node($node, $children, $index);
+ continue;
+ }
+
+ if (is_object($child)) {
+ $frame->append_child($this->_build_tree_r($child), false);
+ }
+ $index++;
+ }
+
+ return $frame;
+ }
+
+ /**
+ * @param DOMNode $node
+ * @param DOMNode $new_node
+ * @param string $pos
+ *
+ * @return mixed
+ */
+ public function insert_node(DOMNode $node, DOMNode $new_node, $pos)
+ {
+ if ($pos === "after" || !$node->firstChild) {
+ $node->appendChild($new_node);
+ } else {
+ $node->insertBefore($new_node, $node->firstChild);
+ }
+
+ $this->_build_tree_r($new_node);
+
+ $frame_id = $new_node->getAttribute("frame_id");
+ $frame = $this->get_frame($frame_id);
+
+ $parent_id = $node->getAttribute("frame_id");
+ $parent = $this->get_frame($parent_id);
+
+ if ($parent) {
+ if ($pos === "before") {
+ $parent->prepend_child($frame, false);
+ } else {
+ $parent->append_child($frame, false);
+ }
+ }
+
+ return $frame_id;
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/Frame/FrameTreeIterator.php b/library/vendor/dompdf/src/Frame/FrameTreeIterator.php
new file mode 100644
index 000000000..ebca7e99f
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame/FrameTreeIterator.php
@@ -0,0 +1,96 @@
+_stack[] = $this->_root = $root;
+ $this->_num = 0;
+ }
+
+ /**
+ *
+ */
+ public function rewind()
+ {
+ $this->_stack = array($this->_root);
+ $this->_num = 0;
+ }
+
+ /**
+ * @return bool
+ */
+ public function valid()
+ {
+ return count($this->_stack) > 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function key()
+ {
+ return $this->_num;
+ }
+
+ /**
+ * @return Frame
+ */
+ public function current()
+ {
+ return end($this->_stack);
+ }
+
+ /**
+ * @return Frame
+ */
+ public function next()
+ {
+ $b = end($this->_stack);
+
+ // Pop last element
+ unset($this->_stack[key($this->_stack)]);
+ $this->_num++;
+
+ // Push all children onto the stack in reverse order
+ if ($c = $b->get_last_child()) {
+ $this->_stack[] = $c;
+ while ($c = $c->get_prev_sibling()) {
+ $this->_stack[] = $c;
+ }
+ }
+
+ return $b;
+ }
+}
+
diff --git a/library/vendor/dompdf/src/Frame/FrameTreeList.php b/library/vendor/dompdf/src/Frame/FrameTreeList.php
new file mode 100644
index 000000000..f8b996c68
--- /dev/null
+++ b/library/vendor/dompdf/src/Frame/FrameTreeList.php
@@ -0,0 +1,35 @@
+_root = $root;
+ }
+
+ /**
+ * @return FrameTreeIterator
+ */
+ public function getIterator()
+ {
+ return new FrameTreeIterator($this->_root);
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/AbstractFrameDecorator.php b/library/vendor/dompdf/src/FrameDecorator/AbstractFrameDecorator.php
new file mode 100644
index 000000000..b574991e6
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/AbstractFrameDecorator.php
@@ -0,0 +1,808 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+/**
+ * Base AbstractFrameDecorator class
+ *
+ * @package dompdf
+ */
+abstract class AbstractFrameDecorator extends Frame
+{
+ const DEFAULT_COUNTER = "-dompdf-default-counter";
+
+ public $_counters = array(); // array([id] => counter_value) (for generated content)
+
+ /**
+ * The root node of the DOM tree
+ *
+ * @var Frame
+ */
+ protected $_root;
+
+ /**
+ * The decorated frame
+ *
+ * @var Frame
+ */
+ protected $_frame;
+
+ /**
+ * AbstractPositioner object used to position this frame (Strategy pattern)
+ *
+ * @var AbstractPositioner
+ */
+ protected $_positioner;
+
+ /**
+ * Reflower object used to calculate frame dimensions (Strategy pattern)
+ *
+ * @var \Dompdf\FrameReflower\AbstractFrameReflower
+ */
+ protected $_reflower;
+
+ /**
+ * Reference to the current dompdf instance
+ *
+ * @var Dompdf
+ */
+ protected $_dompdf;
+
+ /**
+ * First block parent
+ *
+ * @var Block
+ */
+ private $_block_parent;
+
+ /**
+ * First positionned parent (position: relative | absolute | fixed)
+ *
+ * @var AbstractFrameDecorator
+ */
+ private $_positionned_parent;
+
+ /**
+ * Class constructor
+ *
+ * @param Frame $frame The decoration target
+ * @param Dompdf $dompdf The Dompdf object
+ */
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ $this->_frame = $frame;
+ $this->_root = null;
+ $this->_dompdf = $dompdf;
+ $frame->set_decorator($this);
+ }
+
+ /**
+ * "Destructor": foribly free all references held by this object
+ *
+ * @param bool $recursive if true, call dispose on all children
+ */
+ function dispose($recursive = false)
+ {
+ if ($recursive) {
+ while ($child = $this->get_first_child()) {
+ $child->dispose(true);
+ }
+ }
+
+ $this->_root = null;
+ unset($this->_root);
+
+ $this->_frame->dispose(true);
+ $this->_frame = null;
+ unset($this->_frame);
+
+ $this->_positioner = null;
+ unset($this->_positioner);
+
+ $this->_reflower = null;
+ unset($this->_reflower);
+ }
+
+ /**
+ * Return a copy of this frame with $node as its node
+ *
+ * @param DOMNode $node
+ *
+ * @return Frame
+ */
+ function copy(DOMNode $node)
+ {
+ $frame = new Frame($node);
+ $frame->set_style(clone $this->_frame->get_original_style());
+
+ return Factory::decorate_frame($frame, $this->_dompdf, $this->_root);
+ }
+
+ /**
+ * Create a deep copy: copy this node and all children
+ *
+ * @return Frame
+ */
+ function deep_copy()
+ {
+ $node = $this->_frame->get_node();
+
+ if ($node instanceof DOMElement && $node->hasAttribute("id")) {
+ $node->setAttribute("data-dompdf-original-id", $node->getAttribute("id"));
+ $node->removeAttribute("id");
+ }
+
+ $frame = new Frame($node->cloneNode());
+ $frame->set_style(clone $this->_frame->get_original_style());
+
+ $deco = Factory::decorate_frame($frame, $this->_dompdf, $this->_root);
+
+ foreach ($this->get_children() as $child) {
+ $deco->append_child($child->deep_copy());
+ }
+
+ return $deco;
+ }
+
+ /**
+ * Delegate calls to decorated frame object
+ */
+ function reset()
+ {
+ $this->_frame->reset();
+
+ $this->_counters = array();
+
+ // Reset all children
+ foreach ($this->get_children() as $child) {
+ $child->reset();
+ }
+ }
+
+ // Getters -----------
+ function get_id()
+ {
+ return $this->_frame->get_id();
+ }
+
+ /**
+ * @return Frame
+ */
+ function get_frame()
+ {
+ return $this->_frame;
+ }
+
+ /**
+ * @return DOMElement|DOMText
+ */
+ function get_node()
+ {
+ return $this->_frame->get_node();
+ }
+
+ /**
+ * @return Style
+ */
+ function get_style()
+ {
+ return $this->_frame->get_style();
+ }
+
+ /**
+ * @return Style
+ */
+ function get_original_style()
+ {
+ return $this->_frame->get_original_style();
+ }
+
+ /**
+ * @param integer $i
+ *
+ * @return array|float
+ */
+ function get_containing_block($i = null)
+ {
+ return $this->_frame->get_containing_block($i);
+ }
+
+ /**
+ * @param integer $i
+ *
+ * @return array|float
+ */
+ function get_position($i = null)
+ {
+ return $this->_frame->get_position($i);
+ }
+
+ /**
+ * @return Dompdf
+ */
+ function get_dompdf()
+ {
+ return $this->_dompdf;
+ }
+
+ /**
+ * @return float
+ */
+ function get_margin_height()
+ {
+ return $this->_frame->get_margin_height();
+ }
+
+ /**
+ * @return float
+ */
+ function get_margin_width()
+ {
+ return $this->_frame->get_margin_width();
+ }
+
+ /**
+ * @return array
+ */
+ function get_padding_box()
+ {
+ return $this->_frame->get_padding_box();
+ }
+
+ /**
+ * @return array
+ */
+ function get_border_box()
+ {
+ return $this->_frame->get_border_box();
+ }
+
+ /**
+ * @param integer $id
+ */
+ function set_id($id)
+ {
+ $this->_frame->set_id($id);
+ }
+
+ /**
+ * @param Style $style
+ */
+ function set_style(Style $style)
+ {
+ $this->_frame->set_style($style);
+ }
+
+ /**
+ * @param float $x
+ * @param float $y
+ * @param float $w
+ * @param float $h
+ */
+ function set_containing_block($x = null, $y = null, $w = null, $h = null)
+ {
+ $this->_frame->set_containing_block($x, $y, $w, $h);
+ }
+
+ /**
+ * @param float $x
+ * @param float $y
+ */
+ function set_position($x = null, $y = null)
+ {
+ $this->_frame->set_position($x, $y);
+ }
+
+ /**
+ * @return string
+ */
+ function __toString()
+ {
+ return $this->_frame->__toString();
+ }
+
+ /**
+ * @param Frame $child
+ * @param bool $update_node
+ */
+ function prepend_child(Frame $child, $update_node = true)
+ {
+ while ($child instanceof AbstractFrameDecorator) {
+ $child = $child->_frame;
+ }
+
+ $this->_frame->prepend_child($child, $update_node);
+ }
+
+ /**
+ * @param Frame $child
+ * @param bool $update_node
+ */
+ function append_child(Frame $child, $update_node = true)
+ {
+ while ($child instanceof AbstractFrameDecorator) {
+ $child = $child->_frame;
+ }
+
+ $this->_frame->append_child($child, $update_node);
+ }
+
+ /**
+ * @param Frame $new_child
+ * @param Frame $ref
+ * @param bool $update_node
+ */
+ function insert_child_before(Frame $new_child, Frame $ref, $update_node = true)
+ {
+ while ($new_child instanceof AbstractFrameDecorator) {
+ $new_child = $new_child->_frame;
+ }
+
+ if ($ref instanceof AbstractFrameDecorator) {
+ $ref = $ref->_frame;
+ }
+
+ $this->_frame->insert_child_before($new_child, $ref, $update_node);
+ }
+
+ /**
+ * @param Frame $new_child
+ * @param Frame $ref
+ * @param bool $update_node
+ */
+ function insert_child_after(Frame $new_child, Frame $ref, $update_node = true)
+ {
+ while ($new_child instanceof AbstractFrameDecorator) {
+ $new_child = $new_child->_frame;
+ }
+
+ while ($ref instanceof AbstractFrameDecorator) {
+ $ref = $ref->_frame;
+ }
+
+ $this->_frame->insert_child_after($new_child, $ref, $update_node);
+ }
+
+ /**
+ * @param Frame $child
+ * @param bool $update_node
+ *
+ * @return Frame
+ */
+ function remove_child(Frame $child, $update_node = true)
+ {
+ while ($child instanceof AbstractFrameDecorator) {
+ $child = $child->_frame;
+ }
+
+ return $this->_frame->remove_child($child, $update_node);
+ }
+
+ /**
+ * @return AbstractFrameDecorator
+ */
+ function get_parent()
+ {
+ $p = $this->_frame->get_parent();
+ if ($p && $deco = $p->get_decorator()) {
+ while ($tmp = $deco->get_decorator()) {
+ $deco = $tmp;
+ }
+
+ return $deco;
+ } else {
+ if ($p) {
+ return $p;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return AbstractFrameDecorator
+ */
+ function get_first_child()
+ {
+ $c = $this->_frame->get_first_child();
+ if ($c && $deco = $c->get_decorator()) {
+ while ($tmp = $deco->get_decorator()) {
+ $deco = $tmp;
+ }
+
+ return $deco;
+ } else {
+ if ($c) {
+ return $c;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return AbstractFrameDecorator
+ */
+ function get_last_child()
+ {
+ $c = $this->_frame->get_last_child();
+ if ($c && $deco = $c->get_decorator()) {
+ while ($tmp = $deco->get_decorator()) {
+ $deco = $tmp;
+ }
+
+ return $deco;
+ } else {
+ if ($c) {
+ return $c;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return AbstractFrameDecorator
+ */
+ function get_prev_sibling()
+ {
+ $s = $this->_frame->get_prev_sibling();
+ if ($s && $deco = $s->get_decorator()) {
+ while ($tmp = $deco->get_decorator()) {
+ $deco = $tmp;
+ }
+
+ return $deco;
+ } else {
+ if ($s) {
+ return $s;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return AbstractFrameDecorator
+ */
+ function get_next_sibling()
+ {
+ $s = $this->_frame->get_next_sibling();
+ if ($s && $deco = $s->get_decorator()) {
+ while ($tmp = $deco->get_decorator()) {
+ $deco = $tmp;
+ }
+
+ return $deco;
+ } else {
+ if ($s) {
+ return $s;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @return FrameTreeList
+ */
+ function get_subtree()
+ {
+ return new FrameTreeList($this);
+ }
+
+ function set_positioner(AbstractPositioner $posn)
+ {
+ $this->_positioner = $posn;
+ if ($this->_frame instanceof AbstractFrameDecorator) {
+ $this->_frame->set_positioner($posn);
+ }
+ }
+
+ function set_reflower(AbstractFrameReflower $reflower)
+ {
+ $this->_reflower = $reflower;
+ if ($this->_frame instanceof AbstractFrameDecorator) {
+ $this->_frame->set_reflower($reflower);
+ }
+ }
+
+ /**
+ * @return \Dompdf\FrameReflower\AbstractFrameReflower
+ */
+ function get_reflower()
+ {
+ return $this->_reflower;
+ }
+
+ /**
+ * @param Frame $root
+ */
+ function set_root(Frame $root)
+ {
+ $this->_root = $root;
+
+ if ($this->_frame instanceof AbstractFrameDecorator) {
+ $this->_frame->set_root($root);
+ }
+ }
+
+ /**
+ * @return Page
+ */
+ function get_root()
+ {
+ return $this->_root;
+ }
+
+ /**
+ * @return Block
+ */
+ function find_block_parent()
+ {
+ // Find our nearest block level parent
+ $p = $this->get_parent();
+
+ while ($p) {
+ if ($p->is_block()) {
+ break;
+ }
+
+ $p = $p->get_parent();
+ }
+
+ return $this->_block_parent = $p;
+ }
+
+ /**
+ * @return AbstractFrameDecorator
+ */
+ function find_positionned_parent()
+ {
+ // Find our nearest relative positionned parent
+ $p = $this->get_parent();
+ while ($p) {
+ if ($p->is_positionned()) {
+ break;
+ }
+
+ $p = $p->get_parent();
+ }
+
+ if (!$p) {
+ $p = $this->_root->get_first_child(); //
+ }
+
+ return $this->_positionned_parent = $p;
+ }
+
+ /**
+ * split this frame at $child.
+ * The current frame is cloned and $child and all children following
+ * $child are added to the clone. The clone is then passed to the
+ * current frame's parent->split() method.
+ *
+ * @param Frame $child
+ * @param boolean $force_pagebreak
+ *
+ * @throws Exception
+ * @return void
+ */
+ function split(Frame $child = null, $force_pagebreak = false)
+ {
+ // decrement any counters that were incremented on the current node, unless that node is the body
+ $style = $this->_frame->get_style();
+ if ($this->_frame->get_node(
+ )->nodeName !== "body" && $style->counter_increment && ($decrement = $style->counter_increment) !== "none"
+ ) {
+ $this->decrement_counters($decrement);
+ }
+
+ if (is_null($child)) {
+ // check for counter increment on :before content (always a child of the selected element @link AbstractFrameReflower::_set_content)
+ // this can push the current node to the next page before counter rules have bubbled up (but only if
+ // it's been rendered, thus the position check)
+ if (!$this->is_text_node() && $this->get_node()->hasAttribute("dompdf_before_frame_id")) {
+ foreach ($this->_frame->get_children() as $child) {
+ if ($this->get_node()->getAttribute("dompdf_before_frame_id") == $child->get_id(
+ ) && $child->get_position('x') !== null
+ ) {
+ $style = $child->get_style();
+ if ($style->counter_increment && ($decrement = $style->counter_increment) !== "none") {
+ $this->decrement_counters($decrement);
+ }
+ }
+ }
+ }
+ $this->get_parent()->split($this, $force_pagebreak);
+
+ return;
+ }
+
+ if ($child->get_parent() !== $this) {
+ throw new Exception("Unable to split: frame is not a child of this one.");
+ }
+
+ $node = $this->_frame->get_node();
+
+ if ($node instanceof DOMElement && $node->hasAttribute("id")) {
+ $node->setAttribute("data-dompdf-original-id", $node->getAttribute("id"));
+ $node->removeAttribute("id");
+ }
+
+ $split = $this->copy($node->cloneNode());
+ $split->reset();
+ $split->get_original_style()->text_indent = 0;
+ $split->_splitted = true;
+
+ // The body's properties must be kept
+ if ($node->nodeName !== "body") {
+ // Style reset on the first and second parts
+ $style = $this->_frame->get_style();
+ $style->margin_bottom = 0;
+ $style->padding_bottom = 0;
+ $style->border_bottom = 0;
+
+ // second
+ $orig_style = $split->get_original_style();
+ $orig_style->text_indent = 0;
+ $orig_style->margin_top = 0;
+ $orig_style->padding_top = 0;
+ $orig_style->border_top = 0;
+ $orig_style->page_break_before = "auto";
+ }
+
+ $this->get_parent()->insert_child_after($split, $this);
+
+ // Add $frame and all following siblings to the new split node
+ $iter = $child;
+ while ($iter) {
+ $frame = $iter;
+ $iter = $iter->get_next_sibling();
+ $frame->reset();
+ $split->append_child($frame);
+ }
+
+ $this->get_parent()->split($split, $force_pagebreak);
+
+ // If this node resets a counter save the current value to use when rendering on the next page
+ if ($style->counter_reset && ($reset = $style->counter_reset) !== "none") {
+ $vars = preg_split('/\s+/', trim($reset), 2);
+ $split->_counters['__' . $vars[0]] = $this->lookup_counter_frame($vars[0])->_counters[$vars[0]];
+ }
+ }
+
+ function reset_counter($id = self::DEFAULT_COUNTER, $value = 0)
+ {
+ $this->get_parent()->_counters[$id] = intval($value);
+ }
+
+ function decrement_counters($counters)
+ {
+ foreach ($counters as $id => $increment) {
+ $this->increment_counter($id, intval($increment) * -1);
+ }
+ }
+
+ function increment_counters($counters)
+ {
+ foreach ($counters as $id => $increment) {
+ $this->increment_counter($id, intval($increment));
+ }
+ }
+
+ function increment_counter($id = self::DEFAULT_COUNTER, $increment = 1)
+ {
+ $counter_frame = $this->lookup_counter_frame($id);
+
+ if ($counter_frame) {
+ if (!isset($counter_frame->_counters[$id])) {
+ $counter_frame->_counters[$id] = 0;
+ }
+
+ $counter_frame->_counters[$id] += $increment;
+ }
+ }
+
+ function lookup_counter_frame($id = self::DEFAULT_COUNTER)
+ {
+ $f = $this->get_parent();
+
+ while ($f) {
+ if (isset($f->_counters[$id])) {
+ return $f;
+ }
+ $fp = $f->get_parent();
+
+ if (!$fp) {
+ return $f;
+ }
+
+ $f = $fp;
+ }
+ }
+
+ // TODO: What version is the best : this one or the one in ListBullet ?
+ function counter_value($id = self::DEFAULT_COUNTER, $type = "decimal")
+ {
+ $type = mb_strtolower($type);
+
+ if (!isset($this->_counters[$id])) {
+ $this->_counters[$id] = 0;
+ }
+
+ $value = $this->_counters[$id];
+
+ switch ($type) {
+ default:
+ case "decimal":
+ return $value;
+
+ case "decimal-leading-zero":
+ return str_pad($value, 2, "0", STR_PAD_LEFT);
+
+ case "lower-roman":
+ return Helpers::dec2roman($value);
+
+ case "upper-roman":
+ return mb_strtoupper(Helpers::dec2roman($value));
+
+ case "lower-latin":
+ case "lower-alpha":
+ return chr(($value % 26) + ord('a') - 1);
+
+ case "upper-latin":
+ case "upper-alpha":
+ return chr(($value % 26) + ord('A') - 1);
+
+ case "lower-greek":
+ return Helpers::unichr($value + 944);
+
+ case "upper-greek":
+ return Helpers::unichr($value + 912);
+ }
+ }
+
+ final function position()
+ {
+ $this->_positioner->position();
+ }
+
+ final function move($offset_x, $offset_y, $ignore_self = false)
+ {
+ $this->_positioner->move($offset_x, $offset_y, $ignore_self);
+ }
+
+ final function reflow(Block $block = null)
+ {
+ // Uncomment this to see the frames before they're laid out, instead of
+ // during rendering.
+ //echo $this->_frame; flush();
+ $this->_reflower->reflow($block);
+ }
+
+ final function get_min_max_width()
+ {
+ return $this->_reflower->get_min_max_width();
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/Block.php b/library/vendor/dompdf/src/FrameDecorator/Block.php
new file mode 100644
index 000000000..c51fe2a80
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/Block.php
@@ -0,0 +1,252 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\LineBox;
+
+/**
+ * Decorates frames for block layout
+ *
+ * @access private
+ * @package dompdf
+ */
+class Block extends AbstractFrameDecorator
+{
+ /**
+ * Current line index
+ *
+ * @var int
+ */
+ protected $_cl;
+
+ /**
+ * The block's line boxes
+ *
+ * @var LineBox[]
+ */
+ protected $_line_boxes;
+
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+
+ $this->_line_boxes = array(new LineBox($this));
+ $this->_cl = 0;
+ }
+
+ function reset()
+ {
+ parent::reset();
+
+ $this->_line_boxes = array(new LineBox($this));
+ $this->_cl = 0;
+ }
+
+ /**
+ * @return LineBox
+ */
+ function get_current_line_box()
+ {
+ return $this->_line_boxes[$this->_cl];
+ }
+
+ /**
+ * @return integer
+ */
+ function get_current_line_number()
+ {
+ return $this->_cl;
+ }
+
+ /**
+ * @return LineBox[]
+ */
+ function get_line_boxes()
+ {
+ return $this->_line_boxes;
+ }
+
+ /**
+ * @param integer $i
+ */
+ function clear_line($i)
+ {
+ if (isset($this->_line_boxes[$i])) {
+ unset($this->_line_boxes[$i]);
+ }
+ }
+
+ /**
+ * @param Frame $frame
+ */
+ function add_frame_to_line(Frame $frame)
+ {
+ if (!$frame->is_in_flow()) {
+ return;
+ }
+
+ $style = $frame->get_style();
+
+ $frame->set_containing_line($this->_line_boxes[$this->_cl]);
+
+ /*
+ // Adds a new line after a block, only if certain conditions are met
+ if ((($frame instanceof Inline && $frame->get_node()->nodeName !== "br") ||
+ $frame instanceof Text && trim($frame->get_text())) &&
+ ($frame->get_prev_sibling() && $frame->get_prev_sibling()->get_style()->display === "block" &&
+ $this->_line_boxes[$this->_cl]->w > 0 )) {
+
+ $this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
+ $this->add_line();
+
+ // Add each child of the inline frame to the line individually
+ foreach ($frame->get_children() as $child)
+ $this->add_frame_to_line( $child );
+ }
+ else*/
+
+ // Handle inline frames (which are effectively wrappers)
+ if ($frame instanceof Inline) {
+
+ // Handle line breaks
+ if ($frame->get_node()->nodeName === "br") {
+ $this->maximize_line_height($style->length_in_pt($style->line_height), $frame);
+ $this->add_line(true);
+ }
+
+ return;
+ }
+
+ // Trim leading text if this is an empty line. Kinda a hack to put it here,
+ // but what can you do...
+ if ($this->get_current_line_box()->w == 0 &&
+ $frame->is_text_node() &&
+ !$frame->is_pre()
+ ) {
+
+ $frame->set_text(ltrim($frame->get_text()));
+ $frame->recalculate_width();
+ }
+
+ $w = $frame->get_margin_width();
+
+ if ($w == 0) {
+ return;
+ }
+
+ // Debugging code:
+ /*
+ Helpers::pre_r("\nAdding frame to line: ");
+
+ // Helpers::pre_r("Me: " . $this->get_node()->nodeName . " (" . spl_object_hash($this->get_node()) . ")");
+ // Helpers::pre_r("Node: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")");
+ if ( $frame->is_text_node() )
+ Helpers::pre_r('"'.$frame->get_node()->nodeValue.'"');
+
+ Helpers::pre_r("Line width: " . $this->_line_boxes[$this->_cl]->w);
+ Helpers::pre_r("Frame: " . get_class($frame));
+ Helpers::pre_r("Frame width: " . $w);
+ Helpers::pre_r("Frame height: " . $frame->get_margin_height());
+ Helpers::pre_r("Containing block width: " . $this->get_containing_block("w"));
+ */
+ // End debugging
+
+ $line = $this->_line_boxes[$this->_cl];
+ if ($line->left + $line->w + $line->right + $w > $this->get_containing_block("w")) {
+ $this->add_line();
+ }
+
+ $frame->position();
+
+ $current_line = $this->_line_boxes[$this->_cl];
+ $current_line->add_frame($frame);
+
+ if ($frame->is_text_node()) {
+ $current_line->wc += count(preg_split("/\s+/", trim($frame->get_text())));
+ }
+
+ $this->increase_line_width($w);
+
+ $this->maximize_line_height($frame->get_margin_height(), $frame);
+ }
+
+ function remove_frames_from_line(Frame $frame)
+ {
+ // Search backwards through the lines for $frame
+ $i = $this->_cl;
+ $j = null;
+
+ while ($i >= 0) {
+ if (($j = in_array($frame, $this->_line_boxes[$i]->get_frames(), true)) !== false) {
+ break;
+ }
+
+ $i--;
+ }
+
+ if ($j === false) {
+ return;
+ }
+
+ // Remove $frame and all frames that follow
+ while ($j < count($this->_line_boxes[$i]->get_frames())) {
+ $frames = $this->_line_boxes[$i]->get_frames();
+ $f = $frames[$j];
+ $frames[$j] = null;
+ unset($frames[$j]);
+ $j++;
+ $this->_line_boxes[$i]->w -= $f->get_margin_width();
+ }
+
+ // Recalculate the height of the line
+ $h = 0;
+ foreach ($this->_line_boxes[$i]->get_frames() as $f) {
+ $h = max($h, $f->get_margin_height());
+ }
+
+ $this->_line_boxes[$i]->h = $h;
+
+ // Remove all lines that follow
+ while ($this->_cl > $i) {
+ $this->_line_boxes[$this->_cl] = null;
+ unset($this->_line_boxes[$this->_cl]);
+ $this->_cl--;
+ }
+ }
+
+ function increase_line_width($w)
+ {
+ $this->_line_boxes[$this->_cl]->w += $w;
+ }
+
+ function maximize_line_height($val, Frame $frame)
+ {
+ if ($val > $this->_line_boxes[$this->_cl]->h) {
+ $this->_line_boxes[$this->_cl]->tallest_frame = $frame;
+ $this->_line_boxes[$this->_cl]->h = $val;
+ }
+ }
+
+ function add_line($br = false)
+ {
+
+// if ( $this->_line_boxes[$this->_cl]["h"] == 0 ) //count($this->_line_boxes[$i]["frames"]) == 0 ||
+// return;
+
+ $this->_line_boxes[$this->_cl]->br = $br;
+ $y = $this->_line_boxes[$this->_cl]->y + $this->_line_boxes[$this->_cl]->h;
+
+ $new_line = new LineBox($this, $y);
+
+ $this->_line_boxes[++$this->_cl] = $new_line;
+ }
+
+ //........................................................................
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/Image.php b/library/vendor/dompdf/src/FrameDecorator/Image.php
new file mode 100644
index 000000000..22a308a4a
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/Image.php
@@ -0,0 +1,90 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\FontMetrics;
+use Dompdf\Image\Cache;
+
+/**
+ * Decorates frames for image layout and rendering
+ *
+ * @package dompdf
+ */
+class Image extends AbstractFrameDecorator
+{
+
+ /**
+ * The path to the image file (note that remote images are
+ * downloaded locally to Options:tempDir).
+ *
+ * @var string
+ */
+ protected $_image_url;
+
+ /**
+ * The image's file error message
+ *
+ * @var string
+ */
+ protected $_image_msg;
+
+ /**
+ * Class constructor
+ *
+ * @param Frame $frame the frame to decorate
+ * @param DOMPDF $dompdf the document's dompdf object (required to resolve relative & remote urls)
+ */
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ $url = $frame->get_node()->getAttribute("src");
+
+ $debug_png = $dompdf->get_option("debug_png");
+ if ($debug_png) print '[__construct ' . $url . ']';
+
+ list($this->_image_url, /*$type*/, $this->_image_msg) = Cache::resolve_url(
+ $url,
+ $dompdf->get_protocol(),
+ $dompdf->get_host(),
+ $dompdf->get_base_path(),
+ $dompdf
+ );
+
+ if (Cache::is_broken($this->_image_url) &&
+ $alt = $frame->get_node()->getAttribute("alt")
+ ) {
+ $style = $frame->get_style();
+ $style->width = (4 / 3) * $dompdf->getFontMetrics()->getTextWidth($alt, $style->font_family, $style->font_size, $style->word_spacing);
+ $style->height = $dompdf->getFontMetrics()->getFontHeight($style->font_family, $style->font_size);
+ }
+ }
+
+ /**
+ * Return the image's url
+ *
+ * @return string The url of this image
+ */
+ function get_image_url()
+ {
+ return $this->_image_url;
+ }
+
+ /**
+ * Return the image's error message
+ *
+ * @return string The image's error message
+ */
+ function get_image_msg()
+ {
+ return $this->_image_msg;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/Inline.php b/library/vendor/dompdf/src/FrameDecorator/Inline.php
new file mode 100644
index 000000000..05920f493
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/Inline.php
@@ -0,0 +1,92 @@
+
+ * @author Helmut Tischer
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\Exception;
+
+/**
+ * Decorates frames for inline layout
+ *
+ * @access private
+ * @package dompdf
+ */
+class Inline extends AbstractFrameDecorator
+{
+
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ }
+
+ function split(Frame $frame = null, $force_pagebreak = false)
+ {
+ if (is_null($frame)) {
+ $this->get_parent()->split($this, $force_pagebreak);
+ return;
+ }
+
+ if ($frame->get_parent() !== $this) {
+ throw new Exception("Unable to split: frame is not a child of this one.");
+ }
+
+ $node = $this->_frame->get_node();
+
+ if ($node instanceof DOMElement && $node->hasAttribute("id")) {
+ $node->setAttribute("data-dompdf-original-id", $node->getAttribute("id"));
+ $node->removeAttribute("id");
+ }
+
+ $split = $this->copy($node->cloneNode());
+ $this->get_parent()->insert_child_after($split, $this);
+
+ // Unset the current node's right style properties
+ $style = $this->_frame->get_style();
+ $style->margin_right = 0;
+ $style->padding_right = 0;
+ $style->border_right_width = 0;
+
+ // Unset the split node's left style properties since we don't want them
+ // to propagate
+ $style = $split->get_style();
+ $style->margin_left = 0;
+ $style->padding_left = 0;
+ $style->border_left_width = 0;
+
+ //On continuation of inline element on next line,
+ //don't repeat non-vertically repeatble background images
+ //See e.g. in testcase image_variants, long desriptions
+ if (($url = $style->background_image) && $url !== "none"
+ && ($repeat = $style->background_repeat) && $repeat !== "repeat" && $repeat !== "repeat-y"
+ ) {
+ $style->background_image = "none";
+ }
+
+ // Add $frame and all following siblings to the new split node
+ $iter = $frame;
+ while ($iter) {
+ $frame = $iter;
+ $iter = $iter->get_next_sibling();
+ $frame->reset();
+ $split->append_child($frame);
+ }
+
+ $page_breaks = array("always", "left", "right");
+ $frame_style = $frame->get_style();
+ if ($force_pagebreak ||
+ in_array($frame_style->page_break_before, $page_breaks) ||
+ in_array($frame_style->page_break_after, $page_breaks)
+ ) {
+
+ $this->get_parent()->split($split, true);
+ }
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/ListBullet.php b/library/vendor/dompdf/src/FrameDecorator/ListBullet.php
new file mode 100644
index 000000000..2f9154625
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/ListBullet.php
@@ -0,0 +1,75 @@
+
+ * @author Helmut Tischer
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+
+/**
+ * Decorates frames for list bullet rendering
+ *
+ * @package dompdf
+ */
+class ListBullet extends AbstractFrameDecorator
+{
+
+ const BULLET_PADDING = 1; // Distance from bullet to text in pt
+ // As fraction of font size (including descent). See also DECO_THICKNESS.
+ const BULLET_THICKNESS = 0.04; // Thickness of bullet outline. Screen: 0.08, print: better less, e.g. 0.04
+ const BULLET_DESCENT = 0.3; //descent of font below baseline. Todo: Guessed for now.
+ const BULLET_SIZE = 0.35; // bullet diameter. For now 0.5 of font_size without descent.
+
+ static $BULLET_TYPES = array("disc", "circle", "square");
+
+ //........................................................................
+
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ }
+
+ function get_margin_width()
+ {
+ $style = $this->_frame->get_style();
+
+ // Small hack to prevent extra indenting of list text on list_style_position === "inside"
+ // and on suppressed bullet
+ if ($style->list_style_position === "outside" ||
+ $style->list_style_type === "none"
+ ) {
+ return 0;
+ }
+
+ return $style->get_font_size() * self::BULLET_SIZE + 2 * self::BULLET_PADDING;
+ }
+
+ //hits only on "inset" lists items, to increase height of box
+ function get_margin_height()
+ {
+ $style = $this->_frame->get_style();
+
+ if ($style->list_style_type === "none") {
+ return 0;
+ }
+
+ return $style->get_font_size() * self::BULLET_SIZE + 2 * self::BULLET_PADDING;
+ }
+
+ function get_width()
+ {
+ return $this->get_margin_height();
+ }
+
+ function get_height()
+ {
+ return $this->get_margin_height();
+ }
+
+ //........................................................................
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/ListBulletImage.php b/library/vendor/dompdf/src/FrameDecorator/ListBulletImage.php
new file mode 100644
index 000000000..159eaec13
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/ListBulletImage.php
@@ -0,0 +1,155 @@
+
+ * @author Helmut Tischer
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\Helpers;
+
+/**
+ * Decorates frames for list bullets with custom images
+ *
+ * @package dompdf
+ */
+class ListBulletImage extends AbstractFrameDecorator
+{
+
+ /**
+ * The underlying image frame
+ *
+ * @var Image
+ */
+ protected $_img;
+
+ /**
+ * The image's width in pixels
+ *
+ * @var int
+ */
+ protected $_width;
+
+ /**
+ * The image's height in pixels
+ *
+ * @var int
+ */
+ protected $_height;
+
+ /**
+ * Class constructor
+ *
+ * @param Frame $frame the bullet frame to decorate
+ * @param Dompdf $dompdf the document's dompdf object
+ */
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ $style = $frame->get_style();
+ $url = $style->list_style_image;
+ $frame->get_node()->setAttribute("src", $url);
+ $this->_img = new Image($frame, $dompdf);
+ parent::__construct($this->_img, $dompdf);
+ list($width, $height) = Helpers::dompdf_getimagesize($this->_img->get_image_url(), $dompdf->getHttpContext());
+
+ // Resample the bullet image to be consistent with 'auto' sized images
+ // See also Image::get_min_max_width
+ // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary.
+ $dpi = $this->_dompdf->get_option("dpi");
+ $this->_width = ((float)rtrim($width, "px") * 72) / $dpi;
+ $this->_height = ((float)rtrim($height, "px") * 72) / $dpi;
+
+ //If an image is taller as the containing block/box, the box should be extended.
+ //Neighbour elements are overwriting the overlapping image areas.
+ //Todo: Where can the box size be extended?
+ //Code below has no effect.
+ //See block_frame_reflower _calculate_restricted_height
+ //See generated_frame_reflower, Dompdf:render() "list-item", "-dompdf-list-bullet"S.
+ //Leave for now
+ //if ($style->min_height < $this->_height ) {
+ // $style->min_height = $this->_height;
+ //}
+ //$style->height = "auto";
+ }
+
+ /**
+ * Return the bullet's width
+ *
+ * @return int
+ */
+ function get_width()
+ {
+ //ignore image width, use same width as on predefined bullet ListBullet
+ //for proper alignment of bullet image and text. Allow image to not fitting on left border.
+ //This controls the distance between bullet image and text
+ //return $this->_width;
+ return $this->_frame->get_style()->get_font_size() * ListBullet::BULLET_SIZE +
+ 2 * ListBullet::BULLET_PADDING;
+ }
+
+ /**
+ * Return the bullet's height
+ *
+ * @return int
+ */
+ function get_height()
+ {
+ //based on image height
+ return $this->_height;
+ }
+
+ /**
+ * Override get_margin_width
+ *
+ * @return int
+ */
+ function get_margin_width()
+ {
+ //ignore image width, use same width as on predefined bullet ListBullet
+ //for proper alignment of bullet image and text. Allow image to not fitting on left border.
+ //This controls the extra indentation of text to make room for the bullet image.
+ //Here use actual image size, not predefined bullet size
+ //return $this->_frame->get_style()->get_font_size()*ListBullet::BULLET_SIZE +
+ // 2 * ListBullet::BULLET_PADDING;
+
+ // Small hack to prevent indenting of list text
+ // Image Might not exist, then position like on list_bullet_frame_decorator fallback to none.
+ if ($this->_frame->get_style()->list_style_position === "outside" ||
+ $this->_width == 0
+ )
+ return 0;
+ //This aligns the "inside" image position with the text.
+ //The text starts to the right of the image.
+ //Between the image and the text there is an added margin of image width.
+ //Where this comes from is unknown.
+ //The corresponding ListBullet sets a smaller margin. bullet size?
+ return $this->_width + 2 * ListBullet::BULLET_PADDING;
+ }
+
+ /**
+ * Override get_margin_height()
+ *
+ * @return int
+ */
+ function get_margin_height()
+ {
+ //Hits only on "inset" lists items, to increase height of box
+ //based on image height
+ return $this->_height + 2 * ListBullet::BULLET_PADDING;
+ }
+
+ /**
+ * Return image url
+ *
+ * @return string
+ */
+ function get_image_url()
+ {
+ return $this->_img->get_image_url();
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/NullFrameDecorator.php b/library/vendor/dompdf/src/FrameDecorator/NullFrameDecorator.php
new file mode 100644
index 000000000..c9f2d94c4
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/NullFrameDecorator.php
@@ -0,0 +1,31 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+
+/**
+ * Dummy decorator
+ *
+ * @package dompdf
+ */
+class NullFrameDecorator extends AbstractFrameDecorator
+{
+
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ $style = $this->_frame->get_style();
+ $style->width = 0;
+ $style->height = 0;
+ $style->margin = 0;
+ $style->padding = 0;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/Page.php b/library/vendor/dompdf/src/FrameDecorator/Page.php
new file mode 100644
index 000000000..0310f60c2
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/Page.php
@@ -0,0 +1,658 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Css\Style;
+use Dompdf\Dompdf;
+use Dompdf\Helpers;
+use Dompdf\Frame;
+use Dompdf\Renderer;
+
+/**
+ * Decorates frames for page layout
+ *
+ * @access private
+ * @package dompdf
+ */
+class Page extends AbstractFrameDecorator
+{
+
+ /**
+ * y value of bottom page margin
+ *
+ * @var float
+ */
+ protected $_bottom_page_margin;
+
+ /**
+ * Flag indicating page is full.
+ *
+ * @var bool
+ */
+ protected $_page_full;
+
+ /**
+ * Number of tables currently being reflowed
+ *
+ * @var int
+ */
+ protected $_in_table;
+
+ /**
+ * The pdf renderer
+ *
+ * @var Renderer
+ */
+ protected $_renderer;
+
+ /**
+ * This page's floating frames
+ *
+ * @var array
+ */
+ protected $_floating_frames = array();
+
+ //........................................................................
+
+ /**
+ * Class constructor
+ *
+ * @param Frame $frame the frame to decorate
+ * @param Dompdf $dompdf
+ */
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ $this->_page_full = false;
+ $this->_in_table = 0;
+ $this->_bottom_page_margin = null;
+ }
+
+ /**
+ * Set the renderer used for this pdf
+ *
+ * @param Renderer $renderer the renderer to use
+ */
+ function set_renderer($renderer)
+ {
+ $this->_renderer = $renderer;
+ }
+
+ /**
+ * Return the renderer used for this pdf
+ *
+ * @return Renderer
+ */
+ function get_renderer()
+ {
+ return $this->_renderer;
+ }
+
+ /**
+ * Set the frame's containing block. Overridden to set $this->_bottom_page_margin.
+ *
+ * @param float $x
+ * @param float $y
+ * @param float $w
+ * @param float $h
+ */
+ function set_containing_block($x = null, $y = null, $w = null, $h = null)
+ {
+ parent::set_containing_block($x, $y, $w, $h);
+ //$w = $this->get_containing_block("w");
+ if (isset($h)) {
+ $this->_bottom_page_margin = $h;
+ } // - $this->_frame->get_style()->length_in_pt($this->_frame->get_style()->margin_bottom, $w);
+ }
+
+ /**
+ * Returns true if the page is full and is no longer accepting frames.
+ *
+ * @return bool
+ */
+ function is_full()
+ {
+ return $this->_page_full;
+ }
+
+ /**
+ * Start a new page by resetting the full flag.
+ */
+ function next_page()
+ {
+ $this->_floating_frames = array();
+ $this->_renderer->new_page();
+ $this->_page_full = false;
+ }
+
+ /**
+ * Indicate to the page that a table is currently being reflowed.
+ */
+ function table_reflow_start()
+ {
+ $this->_in_table++;
+ }
+
+ /**
+ * Indicate to the page that table reflow is finished.
+ */
+ function table_reflow_end()
+ {
+ $this->_in_table--;
+ }
+
+ /**
+ * Return whether we are currently in a nested table or not
+ *
+ * @return bool
+ */
+ function in_nested_table()
+ {
+ return $this->_in_table > 1;
+ }
+
+ /**
+ * Check if a forced page break is required before $frame. This uses the
+ * frame's page_break_before property as well as the preceeding frame's
+ * page_break_after property.
+ *
+ * @link http://www.w3.org/TR/CSS21/page.html#forced
+ *
+ * @param Frame $frame the frame to check
+ *
+ * @return bool true if a page break occured
+ */
+ function check_forced_page_break(Frame $frame)
+ {
+
+ // Skip check if page is already split
+ if ($this->_page_full) {
+ return null;
+ }
+
+ $block_types = array("block", "list-item", "table", "inline");
+ $page_breaks = array("always", "left", "right");
+
+ $style = $frame->get_style();
+
+ if (!in_array($style->display, $block_types)) {
+ return false;
+ }
+
+ // Find the previous block-level sibling
+ $prev = $frame->get_prev_sibling();
+
+ while ($prev && !in_array($prev->get_style()->display, $block_types)) {
+ $prev = $prev->get_prev_sibling();
+ }
+
+
+ if (in_array($style->page_break_before, $page_breaks)) {
+
+ // Prevent cascading splits
+ $frame->split(null, true);
+ // We have to grab the style again here because split() resets
+ // $frame->style to the frame's orignal style.
+ $frame->get_style()->page_break_before = "auto";
+ $this->_page_full = true;
+
+ return true;
+ }
+
+ if ($prev && in_array($prev->get_style()->page_break_after, $page_breaks)) {
+ // Prevent cascading splits
+ $frame->split(null, true);
+ $prev->get_style()->page_break_after = "auto";
+ $this->_page_full = true;
+
+ return true;
+ }
+
+ if ($prev && $prev->get_last_child() && $frame->get_node()->nodeName != "body") {
+ $prev_last_child = $prev->get_last_child();
+ if (in_array($prev_last_child->get_style()->page_break_after, $page_breaks)) {
+ $frame->split(null, true);
+ $prev_last_child->get_style()->page_break_after = "auto";
+ $this->_page_full = true;
+
+ return true;
+ }
+ }
+
+
+ return false;
+ }
+
+ /**
+ * Determine if a page break is allowed before $frame
+ * http://www.w3.org/TR/CSS21/page.html#allowed-page-breaks
+ *
+ * In the normal flow, page breaks can occur at the following places:
+ *
+ * 1. In the vertical margin between block boxes. When a page
+ * break occurs here, the used values of the relevant
+ * 'margin-top' and 'margin-bottom' properties are set to '0'.
+ * 2. Between line boxes inside a block box.
+ *
+ * These breaks are subject to the following rules:
+ *
+ * * Rule A: Breaking at (1) is allowed only if the
+ * 'page-break-after' and 'page-break-before' properties of
+ * all the elements generating boxes that meet at this margin
+ * allow it, which is when at least one of them has the value
+ * 'always', 'left', or 'right', or when all of them are
+ * 'auto'.
+ *
+ * * Rule B: However, if all of them are 'auto' and the
+ * nearest common ancestor of all the elements has a
+ * 'page-break-inside' value of 'avoid', then breaking here is
+ * not allowed.
+ *
+ * * Rule C: Breaking at (2) is allowed only if the number of
+ * line boxes between the break and the start of the enclosing
+ * block box is the value of 'orphans' or more, and the number
+ * of line boxes between the break and the end of the box is
+ * the value of 'widows' or more.
+ *
+ * * Rule D: In addition, breaking at (2) is allowed only if
+ * the 'page-break-inside' property is 'auto'.
+ *
+ * If the above doesn't provide enough break points to keep
+ * content from overflowing the page boxes, then rules B and D are
+ * dropped in order to find additional breakpoints.
+ *
+ * If that still does not lead to sufficient break points, rules A
+ * and C are dropped as well, to find still more break points.
+ *
+ * We will also allow breaks between table rows. However, when
+ * splitting a table, the table headers should carry over to the
+ * next page (but they don't yet).
+ *
+ * @param Frame $frame the frame to check
+ *
+ * @return bool true if a break is allowed, false otherwise
+ */
+ protected function _page_break_allowed(Frame $frame)
+ {
+
+ $block_types = array("block", "list-item", "table", "-dompdf-image");
+ Helpers::dompdf_debug("page-break", "_page_break_allowed(" . $frame->get_node()->nodeName . ")");
+ $display = $frame->get_style()->display;
+
+ // Block Frames (1):
+ if (in_array($display, $block_types)) {
+
+ // Avoid breaks within table-cells
+ if ($this->_in_table) {
+ Helpers::dompdf_debug("page-break", "In table: " . $this->_in_table);
+
+ return false;
+ }
+
+ // Rules A & B
+
+ if ($frame->get_style()->page_break_before === "avoid") {
+ Helpers::dompdf_debug("page-break", "before: avoid");
+
+ return false;
+ }
+
+ // Find the preceeding block-level sibling
+ $prev = $frame->get_prev_sibling();
+ while ($prev && !in_array($prev->get_style()->display, $block_types)) {
+ $prev = $prev->get_prev_sibling();
+ }
+
+ // Does the previous element allow a page break after?
+ if ($prev && $prev->get_style()->page_break_after === "avoid") {
+ Helpers::dompdf_debug("page-break", "after: avoid");
+
+ return false;
+ }
+
+ // If both $prev & $frame have the same parent, check the parent's
+ // page_break_inside property.
+ $parent = $frame->get_parent();
+ if ($prev && $parent && $parent->get_style()->page_break_inside === "avoid") {
+ Helpers::dompdf_debug("page-break", "parent inside: avoid");
+
+ return false;
+ }
+
+ // To prevent cascading page breaks when a top-level element has
+ // page-break-inside: avoid, ensure that at least one frame is
+ // on the page before splitting.
+ if ($parent->get_node()->nodeName === "body" && !$prev) {
+ // We are the body's first child
+ Helpers::dompdf_debug("page-break", "Body's first child.");
+
+ return false;
+ }
+
+ // If the frame is the first block-level frame, use the value from
+ // $frame's parent instead.
+ if (!$prev && $parent) {
+ return $this->_page_break_allowed($parent);
+ }
+
+ Helpers::dompdf_debug("page-break", "block: break allowed");
+
+ return true;
+
+ } // Inline frames (2):
+ else {
+ if (in_array($display, Style::$INLINE_TYPES)) {
+
+ // Avoid breaks within table-cells
+ if ($this->_in_table) {
+ Helpers::dompdf_debug("page-break", "In table: " . $this->_in_table);
+
+ return false;
+ }
+
+ // Rule C
+ $block_parent = $frame->find_block_parent();
+ if (count($block_parent->get_line_boxes()) < $frame->get_style()->orphans) {
+ Helpers::dompdf_debug("page-break", "orphans");
+
+ return false;
+ }
+
+ // FIXME: Checking widows is tricky without having laid out the
+ // remaining line boxes. Just ignore it for now...
+
+ // Rule D
+ $p = $block_parent;
+ while ($p) {
+ if ($p->get_style()->page_break_inside === "avoid") {
+ Helpers::dompdf_debug("page-break", "parent->inside: avoid");
+
+ return false;
+ }
+ $p = $p->find_block_parent();
+ }
+
+ // To prevent cascading page breaks when a top-level element has
+ // page-break-inside: avoid, ensure that at least one frame with
+ // some content is on the page before splitting.
+ $prev = $frame->get_prev_sibling();
+ while ($prev && ($prev->is_text_node() && trim($prev->get_node()->nodeValue) == "")) {
+ $prev = $prev->get_prev_sibling();
+ }
+
+ if ($block_parent->get_node()->nodeName === "body" && !$prev) {
+ // We are the body's first child
+ Helpers::dompdf_debug("page-break", "Body's first child.");
+
+ return false;
+ }
+
+ // Skip breaks on empty text nodes
+ if ($frame->is_text_node() &&
+ $frame->get_node()->nodeValue == ""
+ ) {
+ return false;
+ }
+
+ Helpers::dompdf_debug("page-break", "inline: break allowed");
+
+ return true;
+
+ // Table-rows
+ } else {
+ if ($display === "table-row") {
+
+ // Simply check if the parent table's page_break_inside property is
+ // not 'avoid'
+ $p = Table::find_parent_table($frame);
+
+ while ($p) {
+ if ($p->get_style()->page_break_inside === "avoid") {
+ Helpers::dompdf_debug("page-break", "parent->inside: avoid");
+
+ return false;
+ }
+ $p = $p->find_block_parent();
+ }
+
+ // Avoid breaking after the first row of a table
+ if ($p && $p->get_first_child() === $frame) {
+ Helpers::dompdf_debug("page-break", "table: first-row");
+
+ return false;
+ }
+
+ // If this is a nested table, prevent the page from breaking
+ if ($this->_in_table > 1) {
+ Helpers::dompdf_debug("page-break", "table: nested table");
+
+ return false;
+ }
+
+ Helpers::dompdf_debug("page-break", "table-row/row-groups: break allowed");
+
+ return true;
+
+ } else {
+ if (in_array($display, Table::$ROW_GROUPS)) {
+
+ // Disallow breaks at row-groups: only split at row boundaries
+ return false;
+
+ } else {
+
+ Helpers::dompdf_debug("page-break", "? " . $frame->get_style()->display . "");
+
+ return false;
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Check if $frame will fit on the page. If the frame does not fit,
+ * the frame tree is modified so that a page break occurs in the
+ * correct location.
+ *
+ * @param Frame $frame the frame to check
+ *
+ * @return Frame the frame following the page break
+ */
+ function check_page_break(Frame $frame)
+ {
+ // Do not split if we have already or if the frame was already
+ // pushed to the next page (prevents infinite loops)
+ if ($this->_page_full || $frame->_already_pushed) {
+ return false;
+ }
+
+ // If the frame is absolute of fixed it shouldn't break
+ $p = $frame;
+ do {
+ if ($p->is_absolute())
+ return false;
+ } while ($p = $p->get_parent());
+
+ $margin_height = $frame->get_margin_height();
+
+ // FIXME If the row is taller than the page and
+ // if it the first of the page, we don't break
+ if ($frame->get_style()->display === "table-row" &&
+ !$frame->get_prev_sibling() &&
+ $margin_height > $this->get_margin_height()
+ )
+ return false;
+
+ // Determine the frame's maximum y value
+ $max_y = $frame->get_position("y") + $margin_height;
+
+ // If a split is to occur here, then the bottom margins & paddings of all
+ // parents of $frame must fit on the page as well:
+ $p = $frame->get_parent();
+ while ($p) {
+ $style = $p->get_style();
+ $max_y += $style->length_in_pt(
+ array(
+ $style->margin_bottom,
+ $style->padding_bottom,
+ $style->border_bottom_width
+ )
+ );
+ $p = $p->get_parent();
+ }
+
+
+ // Check if $frame flows off the page
+ if ($max_y <= $this->_bottom_page_margin)
+ // no: do nothing
+ return false;
+
+ Helpers::dompdf_debug("page-break", "check_page_break");
+ Helpers::dompdf_debug("page-break", "in_table: " . $this->_in_table);
+
+ // yes: determine page break location
+ $iter = $frame;
+ $flg = false;
+
+ $in_table = $this->_in_table;
+
+ Helpers::dompdf_debug("page-break", "Starting search");
+ while ($iter) {
+ // echo "\nbacktrack: " .$iter->get_node()->nodeName ." ".spl_object_hash($iter->get_node()). "";
+ if ($iter === $this) {
+ Helpers::dompdf_debug("page-break", "reached root.");
+ // We've reached the root in our search. Just split at $frame.
+ break;
+ }
+
+ if ($this->_page_break_allowed($iter)) {
+ Helpers::dompdf_debug("page-break", "break allowed, splitting.");
+ $iter->split(null, true);
+ $this->_page_full = true;
+ $this->_in_table = $in_table;
+ $frame->_already_pushed = true;
+
+ return true;
+ }
+
+ if (!$flg && $next = $iter->get_last_child()) {
+ Helpers::dompdf_debug("page-break", "following last child.");
+
+ if ($next->is_table())
+ $this->_in_table++;
+
+ $iter = $next;
+ continue;
+ }
+
+ if ($next = $iter->get_prev_sibling()) {
+ Helpers::dompdf_debug("page-break", "following prev sibling.");
+
+ if ($next->is_table() && !$iter->is_table())
+ $this->_in_table++;
+
+ else if (!$next->is_table() && $iter->is_table())
+ $this->_in_table--;
+
+ $iter = $next;
+ $flg = false;
+ continue;
+ }
+
+ if ($next = $iter->get_parent()) {
+ Helpers::dompdf_debug("page-break", "following parent.");
+
+ if ($iter->is_table())
+ $this->_in_table--;
+
+ $iter = $next;
+ $flg = true;
+ continue;
+ }
+
+ break;
+ }
+
+ $this->_in_table = $in_table;
+
+ // No valid page break found. Just break at $frame.
+ Helpers::dompdf_debug("page-break", "no valid break found, just splitting.");
+
+ // If we are in a table, backtrack to the nearest top-level table row
+ if ($this->_in_table) {
+ $iter = $frame;
+ while ($iter && $iter->get_style()->display !== "table-row" && $iter->get_style()->display !== 'table-row-group')
+ $iter = $iter->get_parent();
+
+ $iter->split(null, true);
+ } else {
+ $frame->split(null, true);
+ }
+
+ $this->_page_full = true;
+ $frame->_already_pushed = true;
+
+ return true;
+ }
+
+ //........................................................................
+
+ function split(Frame $frame = null, $force_pagebreak = false)
+ {
+ // Do nothing
+ }
+
+ /**
+ * Add a floating frame
+ *
+ * @param Frame $frame
+ *
+ * @return void
+ */
+ function add_floating_frame(Frame $frame)
+ {
+ array_unshift($this->_floating_frames, $frame);
+ }
+
+ /**
+ * @return Frame[]
+ */
+ function get_floating_frames()
+ {
+ return $this->_floating_frames;
+ }
+
+ public function remove_floating_frame($key)
+ {
+ unset($this->_floating_frames[$key]);
+ }
+
+ public function get_lowest_float_offset(Frame $child)
+ {
+ $style = $child->get_style();
+ $side = $style->clear;
+ $float = $style->float;
+
+ $y = 0;
+
+ foreach ($this->_floating_frames as $key => $frame) {
+ if ($side === "both" || $frame->get_style()->float === $side) {
+ $y = max($y, $frame->get_position("y") + $frame->get_margin_height());
+
+ if ($float !== "none") {
+ $this->remove_floating_frame($key);
+ }
+ }
+ }
+
+ return $y;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/Table.php b/library/vendor/dompdf/src/FrameDecorator/Table.php
new file mode 100644
index 000000000..bdbead59e
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/Table.php
@@ -0,0 +1,370 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Cellmap;
+use DOMNode;
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\Frame\Factory;
+
+/**
+ * Decorates Frames for table layout
+ *
+ * @package dompdf
+ */
+class Table extends AbstractFrameDecorator
+{
+ public static $VALID_CHILDREN = array(
+ "table-row-group",
+ "table-row",
+ "table-header-group",
+ "table-footer-group",
+ "table-column",
+ "table-column-group",
+ "table-caption",
+ "table-cell"
+ );
+
+ public static $ROW_GROUPS = array(
+ 'table-row-group',
+ 'table-header-group',
+ 'table-footer-group'
+ );
+
+ /**
+ * The Cellmap object for this table. The cellmap maps table cells
+ * to rows and columns, and aids in calculating column widths.
+ *
+ * @var \Dompdf\Cellmap
+ */
+ protected $_cellmap;
+
+ /**
+ * The minimum width of the table, in pt
+ *
+ * @var float
+ */
+ protected $_min_width;
+
+ /**
+ * The maximum width of the table, in pt
+ *
+ * @var float
+ */
+ protected $_max_width;
+
+ /**
+ * Table header rows. Each table header is duplicated when a table
+ * spans pages.
+ *
+ * @var array
+ */
+ protected $_headers;
+
+ /**
+ * Table footer rows. Each table footer is duplicated when a table
+ * spans pages.
+ *
+ * @var array
+ */
+ protected $_footers;
+
+ /**
+ * Class constructor
+ *
+ * @param Frame $frame the frame to decorate
+ * @param Dompdf $dompdf
+ */
+ public function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ $this->_cellmap = new Cellmap($this);
+
+ if ($frame->get_style()->table_layout === "fixed") {
+ $this->_cellmap->set_layout_fixed(true);
+ }
+
+ $this->_min_width = null;
+ $this->_max_width = null;
+ $this->_headers = array();
+ $this->_footers = array();
+ }
+
+
+ public function reset()
+ {
+ parent::reset();
+ $this->_cellmap->reset();
+ $this->_min_width = null;
+ $this->_max_width = null;
+ $this->_headers = array();
+ $this->_footers = array();
+ $this->_reflower->reset();
+ }
+
+ //........................................................................
+
+ /**
+ * split the table at $row. $row and all subsequent rows will be
+ * added to the clone. This method is overidden in order to remove
+ * frames from the cellmap properly.
+ *
+ * @param Frame $child
+ * @param bool $force_pagebreak
+ *
+ * @return void
+ */
+ public function split(Frame $child = null, $force_pagebreak = false)
+ {
+ if (is_null($child)) {
+ parent::split();
+
+ return;
+ }
+
+ // If $child is a header or if it is the first non-header row, do
+ // not duplicate headers, simply move the table to the next page.
+ if (count($this->_headers) && !in_array($child, $this->_headers, true) &&
+ !in_array($child->get_prev_sibling(), $this->_headers, true)
+ ) {
+
+ $first_header = null;
+
+ // Insert copies of the table headers before $child
+ foreach ($this->_headers as $header) {
+
+ $new_header = $header->deep_copy();
+
+ if (is_null($first_header)) {
+ $first_header = $new_header;
+ }
+
+ $this->insert_child_before($new_header, $child);
+ }
+
+ parent::split($first_header);
+
+ } elseif (in_array($child->get_style()->display, self::$ROW_GROUPS)) {
+
+ // Individual rows should have already been handled
+ parent::split($child);
+
+ } else {
+
+ $iter = $child;
+
+ while ($iter) {
+ $this->_cellmap->remove_row($iter);
+ $iter = $iter->get_next_sibling();
+ }
+
+ parent::split($child);
+ }
+ }
+
+ /**
+ * Return a copy of this frame with $node as its node
+ *
+ * @param DOMNode $node
+ *
+ * @return Frame
+ */
+ public function copy(DOMNode $node)
+ {
+ $deco = parent::copy($node);
+
+ // In order to keep columns' widths through pages
+ $deco->_cellmap->set_columns($this->_cellmap->get_columns());
+ $deco->_cellmap->lock_columns();
+
+ return $deco;
+ }
+
+ /**
+ * Static function to locate the parent table of a frame
+ *
+ * @param Frame $frame
+ *
+ * @return Table the table that is an ancestor of $frame
+ */
+ public static function find_parent_table(Frame $frame)
+ {
+
+ while ($frame = $frame->get_parent())
+ if ($frame->is_table())
+ break;
+
+ return $frame;
+ }
+
+ /**
+ * Return this table's Cellmap
+ *
+ * @return \Dompdf\Cellmap
+ */
+ public function get_cellmap()
+ {
+ return $this->_cellmap;
+ }
+
+ /**
+ * Return the minimum width of this table
+ *
+ * @return float
+ */
+ public function get_min_width()
+ {
+ return $this->_min_width;
+ }
+
+ /**
+ * Return the maximum width of this table
+ *
+ * @return float
+ */
+ public function get_max_width()
+ {
+ return $this->_max_width;
+ }
+
+ /**
+ * Set the minimum width of the table
+ *
+ * @param float $width the new minimum width
+ */
+ public function set_min_width($width)
+ {
+ $this->_min_width = $width;
+ }
+
+ /**
+ * Set the maximum width of the table
+ *
+ * @param float $width the new maximum width
+ */
+ public function set_max_width($width)
+ {
+ $this->_max_width = $width;
+ }
+
+ /**
+ * Restructure tree so that the table has the correct structure.
+ * Invalid children (i.e. all non-table-rows) are moved below the
+ * table.
+ */
+ public function normalise()
+ {
+ // Store frames generated by invalid tags and move them outside the table
+ $erroneous_frames = array();
+ $anon_row = false;
+ $iter = $this->get_first_child();
+ while ($iter) {
+ $child = $iter;
+ $iter = $iter->get_next_sibling();
+
+ $display = $child->get_style()->display;
+
+ if ($anon_row) {
+
+ if ($display === "table-row") {
+ // Add the previous anonymous row
+ $this->insert_child_before($table_row, $child);
+
+ $table_row->normalise();
+ $child->normalise();
+ $anon_row = false;
+ continue;
+ }
+
+ // add the child to the anonymous row
+ $table_row->append_child($child);
+ continue;
+
+ } else {
+
+ if ($display === "table-row") {
+ $child->normalise();
+ continue;
+ }
+
+ if ($display === "table-cell") {
+ // Create an anonymous table row
+ $tr = $this->get_node()->ownerDocument->createElement("tr");
+
+ $frame = new Frame($tr);
+
+ $css = $this->get_style()->get_stylesheet();
+ $style = $css->create_style();
+ $style->inherit($this->get_style());
+
+ // Lookup styles for tr tags. If the user wants styles to work
+ // better, they should make the tr explicit... I'm not going to
+ // try to guess what they intended.
+ if ($tr_style = $css->lookup("tr")) {
+ $style->merge($tr_style);
+ }
+
+ // Okay, I have absolutely no idea why I need this clone here, but
+ // if it's omitted, php (as of 2004-07-28) segfaults.
+ $frame->set_style(clone $style);
+ $table_row = Factory::decorate_frame($frame, $this->_dompdf, $this->_root);
+
+ // Add the cell to the row
+ $table_row->append_child($child);
+
+ $anon_row = true;
+ continue;
+ }
+
+ if (!in_array($display, self::$VALID_CHILDREN)) {
+ $erroneous_frames[] = $child;
+ continue;
+ }
+
+ // Normalise other table parts (i.e. row groups)
+ foreach ($child->get_children() as $grandchild) {
+ if ($grandchild->get_style()->display === "table-row") {
+ $grandchild->normalise();
+ }
+ }
+
+ // Add headers and footers
+ if ($display === "table-header-group") {
+ $this->_headers[] = $child;
+ } elseif ($display === "table-footer-group") {
+ $this->_footers[] = $child;
+ }
+ }
+ }
+
+ if ($anon_row && $table_row instanceof DOMNode) {
+ // Add the row to the table
+ $this->_frame->append_child($table_row);
+ $table_row->normalise();
+ $this->_cellmap->add_row();
+ }
+
+ foreach ($erroneous_frames as $frame) {
+ $this->move_after($frame);
+ }
+ }
+
+ //........................................................................
+
+ /**
+ * Moves the specified frame and it's corresponding node outside of
+ * the table.
+ *
+ * @param Frame $frame the frame to move
+ */
+ public function move_after(Frame $frame)
+ {
+ $this->get_parent()->insert_child_after($frame, $this);
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/FrameDecorator/TableCell.php b/library/vendor/dompdf/src/FrameDecorator/TableCell.php
new file mode 100644
index 000000000..b8259d72f
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/TableCell.php
@@ -0,0 +1,117 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+
+/**
+ * Decorates table cells for layout
+ *
+ * @package dompdf
+ */
+class TableCell extends BlockFrameDecorator
+{
+
+ protected $_resolved_borders;
+ protected $_content_height;
+
+ //........................................................................
+
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ $this->_resolved_borders = array();
+ $this->_content_height = 0;
+ }
+
+ //........................................................................
+
+ function reset()
+ {
+ parent::reset();
+ $this->_resolved_borders = array();
+ $this->_content_height = 0;
+ $this->_frame->reset();
+ }
+
+ function get_content_height()
+ {
+ return $this->_content_height;
+ }
+
+ function set_content_height($height)
+ {
+ $this->_content_height = $height;
+ }
+
+ function set_cell_height($height)
+ {
+ $style = $this->get_style();
+ $v_space = $style->length_in_pt(array($style->margin_top,
+ $style->padding_top,
+ $style->border_top_width,
+ $style->border_bottom_width,
+ $style->padding_bottom,
+ $style->margin_bottom),
+ $style->width);
+
+ $new_height = $height - $v_space;
+ $style->height = $new_height;
+
+ if ($new_height > $this->_content_height) {
+ $y_offset = 0;
+
+ // Adjust our vertical alignment
+ switch ($style->vertical_align) {
+ default:
+ case "baseline":
+ // FIXME: this isn't right
+
+ case "top":
+ // Don't need to do anything
+ return;
+
+ case "middle":
+ $y_offset = ($new_height - $this->_content_height) / 2;
+ break;
+
+ case "bottom":
+ $y_offset = $new_height - $this->_content_height;
+ break;
+ }
+
+ if ($y_offset) {
+ // Move our children
+ foreach ($this->get_line_boxes() as $line) {
+ foreach ($line->get_frames() as $frame)
+ $frame->move(0, $y_offset);
+ }
+ }
+ }
+
+ }
+
+ function set_resolved_border($side, $border_spec)
+ {
+ $this->_resolved_borders[$side] = $border_spec;
+ }
+
+ //........................................................................
+
+ function get_resolved_border($side)
+ {
+ return $this->_resolved_borders[$side];
+ }
+
+ function get_resolved_borders()
+ {
+ return $this->_resolved_borders;
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/TableRow.php b/library/vendor/dompdf/src/FrameDecorator/TableRow.php
new file mode 100644
index 000000000..7f33082a2
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/TableRow.php
@@ -0,0 +1,52 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Table as TableFrameDecorator;
+
+/**
+ * Decorates Frames for table row layout
+ *
+ * @package dompdf
+ */
+class TableRow extends AbstractFrameDecorator
+{
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ }
+
+ //........................................................................
+
+ /**
+ * Remove all non table-cell frames from this row and move them after
+ * the table.
+ */
+ function normalise()
+ {
+
+ // Find our table parent
+ $p = TableFrameDecorator::find_parent_table($this);
+
+ $erroneous_frames = array();
+ foreach ($this->get_children() as $child) {
+ $display = $child->get_style()->display;
+
+ if ($display !== "table-cell")
+ $erroneous_frames[] = $child;
+ }
+
+ // dump the extra nodes after the table.
+ foreach ($erroneous_frames as $frame)
+ $p->move_after($frame);
+ }
+
+
+}
diff --git a/library/vendor/dompdf/src/FrameDecorator/TableRowGroup.php b/library/vendor/dompdf/src/FrameDecorator/TableRowGroup.php
new file mode 100644
index 000000000..0f2bb7967
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/TableRowGroup.php
@@ -0,0 +1,72 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+
+/**
+ * Table row group decorator
+ *
+ * Overrides split() method for tbody, thead & tfoot elements
+ *
+ * @package dompdf
+ */
+class TableRowGroup extends AbstractFrameDecorator
+{
+
+ /**
+ * Class constructor
+ *
+ * @param Frame $frame Frame to decorate
+ * @param Dompdf $dompdf Current dompdf instance
+ */
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ parent::__construct($frame, $dompdf);
+ }
+
+ /**
+ * Override split() to remove all child rows and this element from the cellmap
+ *
+ * @param Frame $child
+ * @param bool $force_pagebreak
+ *
+ * @return void
+ */
+ function split(Frame $child = null, $force_pagebreak = false)
+ {
+
+ if (is_null($child)) {
+ parent::split();
+ return;
+ }
+
+ // Remove child & all subsequent rows from the cellmap
+ $cellmap = $this->get_parent()->get_cellmap();
+ $iter = $child;
+
+ while ($iter) {
+ $cellmap->remove_row($iter);
+ $iter = $iter->get_next_sibling();
+ }
+
+ // If we are splitting at the first child remove the
+ // table-row-group from the cellmap as well
+ if ($child === $this->get_first_child()) {
+ $cellmap->remove_row_group($this);
+ parent::split();
+ return;
+ }
+
+ $cellmap->update_row_group($this, $child->get_prev_sibling());
+ parent::split($child);
+
+ }
+}
+
diff --git a/library/vendor/dompdf/src/FrameDecorator/Text.php b/library/vendor/dompdf/src/FrameDecorator/Text.php
new file mode 100644
index 000000000..7a78879cb
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameDecorator/Text.php
@@ -0,0 +1,182 @@
+
+ * @author Brian Sweeney
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameDecorator;
+
+use Dompdf\Dompdf;
+use Dompdf\Frame;
+use Dompdf\Exception;
+use DOMText;
+use Dompdf\FontMetrics;
+
+/**
+ * Decorates Frame objects for text layout
+ *
+ * @access private
+ * @package dompdf
+ */
+class Text extends AbstractFrameDecorator
+{
+
+ // protected members
+ protected $_text_spacing;
+
+ function __construct(Frame $frame, Dompdf $dompdf)
+ {
+ if (!$frame->is_text_node()) {
+ throw new Exception("Text_Decorator can only be applied to #text nodes.");
+ }
+
+ parent::__construct($frame, $dompdf);
+ $this->_text_spacing = null;
+ }
+
+ //........................................................................
+
+ function reset()
+ {
+ parent::reset();
+ $this->_text_spacing = null;
+ }
+
+ //........................................................................
+
+ // Accessor methods
+ function get_text_spacing()
+ {
+ return $this->_text_spacing;
+ }
+
+ function get_text()
+ {
+ // FIXME: this should be in a child class (and is incorrect)
+// if ( $this->_frame->get_style()->content !== "normal" ) {
+// $this->_frame->get_node()->data = $this->_frame->get_style()->content;
+// $this->_frame->get_style()->content = "normal";
+// }
+
+// Helpers::pre_r("---");
+// $style = $this->_frame->get_style();
+// var_dump($text = $this->_frame->get_node()->data);
+// var_dump($asc = utf8_decode($text));
+// for ($i = 0; $i < strlen($asc); $i++)
+// Helpers::pre_r("$i: " . $asc[$i] . " - " . ord($asc[$i]));
+// Helpers::pre_r("width: " . $this->_dompdf->getFontMetrics()->getTextWidth($text, $style->font_family, $style->font_size));
+
+ return $this->_frame->get_node()->data;
+ }
+
+ //........................................................................
+
+ // Vertical margins & padding do not apply to text frames
+
+ // http://www.w3.org/TR/CSS21/visudet.html#inline-non-replaced:
+ //
+ // The vertical padding, border and margin of an inline, non-replaced box
+ // start at the top and bottom of the content area, not the
+ // 'line-height'. But only the 'line-height' is used to calculate the
+ // height of the line box.
+ function get_margin_height()
+ {
+ // This function is called in add_frame_to_line() and is used to
+ // determine the line height, so we actually want to return the
+ // 'line-height' property, not the actual margin box
+ $style = $this->get_parent()->get_style();
+ $font = $style->font_family;
+ $size = $style->font_size;
+
+ /*
+ Helpers::pre_r('-----');
+ Helpers::pre_r($style->line_height);
+ Helpers::pre_r($style->font_size);
+ Helpers::pre_r($this->_dompdf->getFontMetrics()->getFontHeight($font, $size));
+ Helpers::pre_r(($style->line_height / $size) * $this->_dompdf->getFontMetrics()->getFontHeight($font, $size));
+ */
+
+ return ($style->line_height / ($size > 0 ? $size : 1)) * $this->_dompdf->getFontMetrics()->getFontHeight($font, $size);
+
+ }
+
+ function get_padding_box()
+ {
+ $pb = $this->_frame->get_padding_box();
+ $pb[3] = $pb["h"] = $this->_frame->get_style()->height;
+
+ return $pb;
+ }
+ //........................................................................
+
+ // Set method
+ function set_text_spacing($spacing)
+ {
+ $style = $this->_frame->get_style();
+
+ $this->_text_spacing = $spacing;
+ $char_spacing = $style->length_in_pt($style->letter_spacing);
+
+ // Re-adjust our width to account for the change in spacing
+ $style->width = $this->_dompdf->getFontMetrics()->getTextWidth($this->get_text(), $style->font_family, $style->font_size, $spacing, $char_spacing);
+ }
+
+ //........................................................................
+
+ // Recalculate the text width
+ function recalculate_width()
+ {
+ $style = $this->get_style();
+ $text = $this->get_text();
+ $size = $style->font_size;
+ $font = $style->font_family;
+ $word_spacing = $style->length_in_pt($style->word_spacing);
+ $char_spacing = $style->length_in_pt($style->letter_spacing);
+
+ return $style->width = $this->_dompdf->getFontMetrics()->getTextWidth($text, $font, $size, $word_spacing, $char_spacing);
+ }
+
+ //........................................................................
+
+ // Text manipulation methods
+
+ // split the text in this frame at the offset specified. The remaining
+ // text is added a sibling frame following this one and is returned.
+ function split_text($offset)
+ {
+ if ($offset == 0) {
+ return null;
+ }
+
+ $split = $this->_frame->get_node()->splitText($offset);
+
+ $deco = $this->copy($split);
+
+ $p = $this->get_parent();
+ $p->insert_child_after($deco, $this, false);
+
+ if ($p instanceof Inline) {
+ $p->split($deco);
+ }
+
+ return $deco;
+ }
+
+ //........................................................................
+
+ function delete_text($offset, $count)
+ {
+ $this->_frame->get_node()->deleteData($offset, $count);
+ }
+
+ //........................................................................
+
+ function set_text($text)
+ {
+ $this->_frame->get_node()->data = $text;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/AbstractFrameReflower.php b/library/vendor/dompdf/src/FrameReflower/AbstractFrameReflower.php
new file mode 100644
index 000000000..281ae44e4
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/AbstractFrameReflower.php
@@ -0,0 +1,460 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\Adapter\CPDF;
+use Dompdf\Css\Style;
+use Dompdf\Dompdf;
+use Dompdf\Helpers;
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block;
+use Dompdf\Frame\Factory;
+
+/**
+ * Base reflower class
+ *
+ * Reflower objects are responsible for determining the width and height of
+ * individual frames. They also create line and page breaks as necessary.
+ *
+ * @package dompdf
+ */
+abstract class AbstractFrameReflower
+{
+
+ /**
+ * Frame for this reflower
+ *
+ * @var Frame
+ */
+ protected $_frame;
+
+ /**
+ * Cached min/max size
+ *
+ * @var array
+ */
+ protected $_min_max_cache;
+
+ function __construct(Frame $frame)
+ {
+ $this->_frame = $frame;
+ $this->_min_max_cache = null;
+ }
+
+ function dispose()
+ {
+ }
+
+ /**
+ * @return Dompdf
+ */
+ function get_dompdf()
+ {
+ return $this->_frame->get_dompdf();
+ }
+
+ /**
+ * Collapse frames margins
+ * http://www.w3.org/TR/CSS2/box.html#collapsing-margins
+ */
+ protected function _collapse_margins()
+ {
+ $frame = $this->_frame;
+ $cb = $frame->get_containing_block();
+ $style = $frame->get_style();
+
+ if (!$frame->is_in_flow()) {
+ return;
+ }
+
+ $t = $style->length_in_pt($style->margin_top, $cb["h"]);
+ $b = $style->length_in_pt($style->margin_bottom, $cb["h"]);
+
+ // Handle 'auto' values
+ if ($t === "auto") {
+ $style->margin_top = "0pt";
+ $t = 0;
+ }
+
+ if ($b === "auto") {
+ $style->margin_bottom = "0pt";
+ $b = 0;
+ }
+
+ // Collapse vertical margins:
+ $n = $frame->get_next_sibling();
+ if ($n && !$n->is_block()) {
+ while ($n = $n->get_next_sibling()) {
+ if ($n->is_block()) {
+ break;
+ }
+
+ if (!$n->get_first_child()) {
+ $n = null;
+ break;
+ }
+ }
+ }
+
+ if ($n) {
+ $n_style = $n->get_style();
+ $b = max($b, $n_style->length_in_pt($n_style->margin_top, $cb["h"]));
+ $n_style->margin_top = "0pt";
+ $style->margin_bottom = $b . "pt";
+ }
+
+ // Collapse our first child's margin
+ /*$f = $this->_frame->get_first_child();
+ if ( $f && !$f->is_block() ) {
+ while ( $f = $f->get_next_sibling() ) {
+ if ( $f->is_block() ) {
+ break;
+ }
+
+ if ( !$f->get_first_child() ) {
+ $f = null;
+ break;
+ }
+ }
+ }
+
+ // Margin are collapsed only between block elements
+ if ( $f ) {
+ $f_style = $f->get_style();
+ $t = max($t, $f_style->length_in_pt($f_style->margin_top, $cb["h"]));
+ $style->margin_top = $t."pt";
+ $f_style->margin_bottom = "0pt";
+ }*/
+ }
+
+ //........................................................................
+
+ abstract function reflow(Block $block = null);
+
+ //........................................................................
+
+ // Required for table layout: Returns an array(0 => min, 1 => max, "min"
+ // => min, "max" => max) of the minimum and maximum widths of this frame.
+ // This provides a basic implementation. Child classes should override
+ // this if necessary.
+ function get_min_max_width()
+ {
+ if (!is_null($this->_min_max_cache)) {
+ return $this->_min_max_cache;
+ }
+
+ $style = $this->_frame->get_style();
+
+ // Account for margins & padding
+ $dims = array($style->padding_left,
+ $style->padding_right,
+ $style->border_left_width,
+ $style->border_right_width,
+ $style->margin_left,
+ $style->margin_right);
+
+ $cb_w = $this->_frame->get_containing_block("w");
+ $delta = $style->length_in_pt($dims, $cb_w);
+
+ // Handle degenerate case
+ if (!$this->_frame->get_first_child()) {
+ return $this->_min_max_cache = array(
+ $delta, $delta,
+ "min" => $delta,
+ "max" => $delta,
+ );
+ }
+
+ $low = array();
+ $high = array();
+
+ for ($iter = $this->_frame->get_children()->getIterator();
+ $iter->valid();
+ $iter->next()) {
+
+ $inline_min = 0;
+ $inline_max = 0;
+
+ // Add all adjacent inline widths together to calculate max width
+ while ($iter->valid() && in_array($iter->current()->get_style()->display, Style::$INLINE_TYPES)) {
+
+ $child = $iter->current();
+
+ $minmax = $child->get_min_max_width();
+
+ if (in_array($iter->current()->get_style()->white_space, array("pre", "nowrap"))) {
+ $inline_min += $minmax["min"];
+ } else {
+ $low[] = $minmax["min"];
+ }
+
+ $inline_max += $minmax["max"];
+ $iter->next();
+
+ }
+
+ if ($inline_max > 0) $high[] = $inline_max;
+ if ($inline_min > 0) $low[] = $inline_min;
+
+ if ($iter->valid()) {
+ list($low[], $high[]) = $iter->current()->get_min_max_width();
+ continue;
+ }
+
+ }
+ $min = count($low) ? max($low) : 0;
+ $max = count($high) ? max($high) : 0;
+
+ // Use specified width if it is greater than the minimum defined by the
+ // content. If the width is a percentage ignore it for now.
+ $width = $style->width;
+ if ($width !== "auto" && !Helpers::is_percent($width)) {
+ $width = $style->length_in_pt($width, $cb_w);
+ if ($min < $width) $min = $width;
+ if ($max < $width) $max = $width;
+ }
+
+ $min += $delta;
+ $max += $delta;
+ return $this->_min_max_cache = array($min, $max, "min" => $min, "max" => $max);
+ }
+
+ /**
+ * Parses a CSS string containing quotes and escaped hex characters
+ *
+ * @param $string string The CSS string to parse
+ * @param $single_trim
+ * @return string
+ */
+ protected function _parse_string($string, $single_trim = false)
+ {
+ if ($single_trim) {
+ $string = preg_replace('/^[\"\']/', "", $string);
+ $string = preg_replace('/[\"\']$/', "", $string);
+ } else {
+ $string = trim($string, "'\"");
+ }
+
+ $string = str_replace(array("\\\n", '\\"', "\\'"),
+ array("", '"', "'"), $string);
+
+ // Convert escaped hex characters into ascii characters (e.g. \A => newline)
+ $string = preg_replace_callback("/\\\\([0-9a-fA-F]{0,6})/",
+ function ($matches) { return \Dompdf\Helpers::unichr(hexdec($matches[1])); },
+ $string);
+ return $string;
+ }
+
+ /**
+ * Parses a CSS "quotes" property
+ *
+ * @return array|null An array of pairs of quotes
+ */
+ protected function _parse_quotes()
+ {
+
+ // Matches quote types
+ $re = '/(\'[^\']*\')|(\"[^\"]*\")/';
+
+ $quotes = $this->_frame->get_style()->quotes;
+
+ // split on spaces, except within quotes
+ if (!preg_match_all($re, "$quotes", $matches, PREG_SET_ORDER)) {
+ return null;
+ }
+
+ $quotes_array = array();
+ foreach ($matches as $_quote) {
+ $quotes_array[] = $this->_parse_string($_quote[0], true);
+ }
+
+ if (empty($quotes_array)) {
+ $quotes_array = array('"', '"');
+ }
+
+ return array_chunk($quotes_array, 2);
+ }
+
+ /**
+ * Parses the CSS "content" property
+ *
+ * @return string|null The resulting string
+ */
+ protected function _parse_content()
+ {
+
+ // Matches generated content
+ $re = "/\n" .
+ "\s(counters?\\([^)]*\\))|\n" .
+ "\A(counters?\\([^)]*\\))|\n" .
+ "\s([\"']) ( (?:[^\"']|\\\\[\"'])+ )(?_frame->get_style()->content;
+
+ $quotes = $this->_parse_quotes();
+
+ // split on spaces, except within quotes
+ if (!preg_match_all($re, $content, $matches, PREG_SET_ORDER)) {
+ return null;
+ }
+
+ $text = "";
+
+ foreach ($matches as $match) {
+
+ if (isset($match[2]) && $match[2] !== "") {
+ $match[1] = $match[2];
+ }
+
+ if (isset($match[6]) && $match[6] !== "") {
+ $match[4] = $match[6];
+ }
+
+ if (isset($match[8]) && $match[8] !== "") {
+ $match[7] = $match[8];
+ }
+
+ if (isset($match[1]) && $match[1] !== "") {
+
+ // counters?(...)
+ $match[1] = mb_strtolower(trim($match[1]));
+
+ // Handle counter() references:
+ // http://www.w3.org/TR/CSS21/generate.html#content
+
+ $i = mb_strpos($match[1], ")");
+ if ($i === false) {
+ continue;
+ }
+
+ preg_match('/(counters?)(^\()*?\(\s*([^\s,]+)\s*(,\s*["\']?([^"\'\)]+)["\']?\s*(,\s*([^\s)]+)\s*)?)?\)/i', $match[1], $args);
+ $counter_id = $args[3];
+ if (strtolower($args[1]) == 'counter') {
+ // counter(name [,style])
+ if (isset($args[5])) {
+ $type = trim($args[5]);
+ } else {
+ $type = null;
+ }
+ $p = $this->_frame->lookup_counter_frame($counter_id);
+
+ $text .= $p->counter_value($counter_id, $type);
+
+ } else if (strtolower($args[1]) == 'counters') {
+ // counters(name, string [,style])
+ if (isset($args[5])) {
+ $string = $this->_parse_string($args[5]);
+ } else {
+ $string = "";
+ }
+
+ if (isset($args[7])) {
+ $type = trim($args[7]);
+ } else {
+ $type = null;
+ }
+
+ $p = $this->_frame->lookup_counter_frame($counter_id);
+ $tmp = array();
+ while ($p) {
+ // We only want to use the counter values when they actually increment the counter
+ if (array_key_exists($counter_id, $p->_counters)) {
+ array_unshift($tmp, $p->counter_value($counter_id, $type));
+ }
+ $p = $p->lookup_counter_frame($counter_id);
+
+ }
+ $text .= implode($string, $tmp);
+
+ } else {
+ // countertops?
+ continue;
+ }
+
+ } else if (isset($match[4]) && $match[4] !== "") {
+ // String match
+ $text .= $this->_parse_string($match[4]);
+ } else if (isset($match[7]) && $match[7] !== "") {
+ // Directive match
+
+ if ($match[7] === "open-quote") {
+ // FIXME: do something here
+ $text .= $quotes[0][0];
+ } else if ($match[7] === "close-quote") {
+ // FIXME: do something else here
+ $text .= $quotes[0][1];
+ } else if ($match[7] === "no-open-quote") {
+ // FIXME:
+ } else if ($match[7] === "no-close-quote") {
+ // FIXME:
+ } else if (mb_strpos($match[7], "attr(") === 0) {
+
+ $i = mb_strpos($match[7], ")");
+ if ($i === false) {
+ continue;
+ }
+
+ $attr = mb_substr($match[7], 5, $i - 5);
+ if ($attr == "") {
+ continue;
+ }
+
+ $text .= $this->_frame->get_parent()->get_node()->getAttribute($attr);
+ } else {
+ continue;
+ }
+ }
+ }
+
+ return $text;
+ }
+
+ /**
+ * Sets the generated content of a generated frame
+ */
+ protected function _set_content()
+ {
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+
+ // if the element was pushed to a new page use the saved counter value, otherwise use the CSS reset value
+ if ($style->counter_reset && ($reset = $style->counter_reset) !== "none") {
+ $vars = preg_split('/\s+/', trim($reset), 2);
+ $frame->reset_counter($vars[0], (isset($frame->_counters['__' . $vars[0]]) ? $frame->_counters['__' . $vars[0]] : (isset($vars[1]) ? $vars[1] : 0)));
+ }
+
+ if ($style->counter_increment && ($increment = $style->counter_increment) !== "none") {
+ $frame->increment_counters($increment);
+ }
+
+ if ($style->content && !$frame->get_first_child() && $frame->get_node()->nodeName === "dompdf_generated") {
+ $content = $this->_parse_content();
+ // add generated content to the font subset
+ // FIXME: This is currently too late because the font subset has already been generated.
+ // See notes in issue #750.
+ if ($frame->get_dompdf()->get_option("enable_font_subsetting") && $frame->get_dompdf()->get_canvas() instanceof CPDF) {
+ $frame->get_dompdf()->get_canvas()->register_string_subset($style->font_family, $content);
+ }
+
+ $node = $frame->get_node()->ownerDocument->createTextNode($content);
+
+ $new_style = $style->get_stylesheet()->create_style();
+ $new_style->inherit($style);
+
+ $new_frame = new Frame($node);
+ $new_frame->set_style($new_style);
+
+ Factory::decorate_frame($new_frame, $frame->get_dompdf(), $frame->get_root());
+ $frame->append_child($new_frame);
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/Block.php b/library/vendor/dompdf/src/FrameReflower/Block.php
new file mode 100644
index 000000000..db5da39c9
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/Block.php
@@ -0,0 +1,793 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FontMetrics;
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Text as TextFrameDecorator;
+use Dompdf\Exception;
+
+/**
+ * Reflows block frames
+ *
+ * @package dompdf
+ */
+class Block extends AbstractFrameReflower
+{
+ // Minimum line width to justify, as fraction of available width
+ const MIN_JUSTIFY_WIDTH = 0.80;
+
+ /**
+ * @var BlockFrameDecorator
+ */
+ protected $_frame;
+
+ function __construct(BlockFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ /**
+ * Calculate the ideal used value for the width property as per:
+ * http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins
+ *
+ * @param float $width
+ *
+ * @return array
+ */
+ protected function _calculate_width($width)
+ {
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+ $w = $frame->get_containing_block("w");
+
+ if ($style->position === "fixed") {
+ $w = $frame->get_parent()->get_containing_block("w");
+ }
+
+ $rm = $style->length_in_pt($style->margin_right, $w);
+ $lm = $style->length_in_pt($style->margin_left, $w);
+
+ $left = $style->length_in_pt($style->left, $w);
+ $right = $style->length_in_pt($style->right, $w);
+
+ // Handle 'auto' values
+ $dims = array($style->border_left_width,
+ $style->border_right_width,
+ $style->padding_left,
+ $style->padding_right,
+ $width !== "auto" ? $width : 0,
+ $rm !== "auto" ? $rm : 0,
+ $lm !== "auto" ? $lm : 0);
+
+ // absolutely positioned boxes take the 'left' and 'right' properties into account
+ if ($frame->is_absolute()) {
+ $absolute = true;
+ $dims[] = $left !== "auto" ? $left : 0;
+ $dims[] = $right !== "auto" ? $right : 0;
+ } else {
+ $absolute = false;
+ }
+
+ $sum = $style->length_in_pt($dims, $w);
+
+ // Compare to the containing block
+ $diff = $w - $sum;
+
+ if ($diff > 0) {
+
+ if ($absolute) {
+
+ // resolve auto properties: see
+ // http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
+
+ if ($width === "auto" && $left === "auto" && $right === "auto") {
+
+ if ($lm === "auto") $lm = 0;
+ if ($rm === "auto") $rm = 0;
+
+ // Technically, the width should be "shrink-to-fit" i.e. based on the
+ // preferred width of the content... a little too costly here as a
+ // special case. Just get the width to take up the slack:
+ $left = 0;
+ $right = 0;
+ $width = $diff;
+ } else if ($width === "auto") {
+
+ if ($lm === "auto") $lm = 0;
+ if ($rm === "auto") $rm = 0;
+ if ($left === "auto") $left = 0;
+ if ($right === "auto") $right = 0;
+
+ $width = $diff;
+ } else if ($left === "auto") {
+
+ if ($lm === "auto") $lm = 0;
+ if ($rm === "auto") $rm = 0;
+ if ($right === "auto") $right = 0;
+
+ $left = $diff;
+ } else if ($right === "auto") {
+
+ if ($lm === "auto") $lm = 0;
+ if ($rm === "auto") $rm = 0;
+
+ $right = $diff;
+ }
+
+ } else {
+
+ // Find auto properties and get them to take up the slack
+ if ($width === "auto") {
+ $width = $diff;
+ } else if ($lm === "auto" && $rm === "auto") {
+ $lm = $rm = round($diff / 2);
+ } else if ($lm === "auto") {
+ $lm = $diff;
+ } else if ($rm === "auto") {
+ $rm = $diff;
+ }
+ }
+
+ } else if ($diff < 0) {
+
+ // We are over constrained--set margin-right to the difference
+ $rm = $diff;
+
+ }
+
+ return array(
+ "width" => $width,
+ "margin_left" => $lm,
+ "margin_right" => $rm,
+ "left" => $left,
+ "right" => $right,
+ );
+ }
+
+ /**
+ * Call the above function, but resolve max/min widths
+ *
+ * @throws Exception
+ * @return array
+ */
+ protected function _calculate_restricted_width()
+ {
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+ $cb = $frame->get_containing_block();
+
+ if ($style->position === "fixed") {
+ $cb = $frame->get_root()->get_containing_block();
+ }
+
+ //if ( $style->position === "absolute" )
+ // $cb = $frame->find_positionned_parent()->get_containing_block();
+
+ if (!isset($cb["w"])) {
+ throw new Exception("Box property calculation requires containing block width");
+ }
+
+ // Treat width 100% as auto
+ if ($style->width === "100%") {
+ $width = "auto";
+ } else {
+ $width = $style->length_in_pt($style->width, $cb["w"]);
+ }
+
+ extract($this->_calculate_width($width));
+
+ // Handle min/max width
+ $min_width = $style->length_in_pt($style->min_width, $cb["w"]);
+ $max_width = $style->length_in_pt($style->max_width, $cb["w"]);
+
+ if ($max_width !== "none" && $min_width > $max_width) {
+ list($max_width, $min_width) = array($min_width, $max_width);
+ }
+
+ if ($max_width !== "none" && $width > $max_width) {
+ extract($this->_calculate_width($max_width));
+ }
+
+ if ($width < $min_width) {
+ extract($this->_calculate_width($min_width));
+ }
+
+ return array($width, $margin_left, $margin_right, $left, $right);
+ }
+
+ /**
+ * Determine the unrestricted height of content within the block
+ * not by adding each line's height, but by getting the last line's position.
+ * This because lines could have been pushed lower by a clearing element.
+ *
+ * @return float
+ */
+ protected function _calculate_content_height()
+ {
+ $lines = $this->_frame->get_line_boxes();
+ $height = 0;
+
+ foreach ($lines as $line) {
+ $height += $line->h;
+ }
+
+ /*
+ $first_line = reset($lines);
+ $last_line = end($lines);
+ $height2 = $last_line->y + $last_line->h - $first_line->y;
+ */
+
+ return $height;
+ }
+
+ /**
+ * Determine the frame's restricted height
+ *
+ * @return array
+ */
+ protected function _calculate_restricted_height()
+ {
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+ $content_height = $this->_calculate_content_height();
+ $cb = $frame->get_containing_block();
+
+ $height = $style->length_in_pt($style->height, $cb["h"]);
+
+ $top = $style->length_in_pt($style->top, $cb["h"]);
+ $bottom = $style->length_in_pt($style->bottom, $cb["h"]);
+
+ $margin_top = $style->length_in_pt($style->margin_top, $cb["h"]);
+ $margin_bottom = $style->length_in_pt($style->margin_bottom, $cb["h"]);
+
+ if ($frame->is_absolute()) {
+
+ // see http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-height
+
+ $dims = array($top !== "auto" ? $top : 0,
+ $style->margin_top !== "auto" ? $style->margin_top : 0,
+ $style->padding_top,
+ $style->border_top_width,
+ $height !== "auto" ? $height : 0,
+ $style->border_bottom_width,
+ $style->padding_bottom,
+ $style->margin_bottom !== "auto" ? $style->margin_bottom : 0,
+ $bottom !== "auto" ? $bottom : 0);
+
+ $sum = $style->length_in_pt($dims, $cb["h"]);
+
+ $diff = $cb["h"] - $sum;
+
+ if ($diff > 0) {
+
+ if ($height === "auto" && $top === "auto" && $bottom === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $height = $diff;
+ } else if ($height === "auto" && $top === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $height = $content_height;
+ $top = $diff - $content_height;
+ } else if ($height === "auto" && $bottom === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $height = $content_height;
+ $bottom = $diff - $content_height;
+ } else if ($top === "auto" && $bottom === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $bottom = $diff;
+ } else if ($top === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $top = $diff;
+ } else if ($height === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $height = $diff;
+ } else if ($bottom === "auto") {
+
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+
+ $bottom = $diff;
+ } else {
+
+ if ($style->overflow === "visible") {
+ // set all autos to zero
+ if ($margin_top === "auto") $margin_top = 0;
+ if ($margin_bottom === "auto") $margin_bottom = 0;
+ if ($top === "auto") $top = 0;
+ if ($bottom === "auto") $bottom = 0;
+ if ($height === "auto") $height = $content_height;
+ }
+
+ // FIXME: overflow hidden
+ }
+
+ }
+
+ } else {
+
+ // Expand the height if overflow is visible
+ if ($height === "auto" && $content_height > $height /* && $style->overflow === "visible" */) {
+ $height = $content_height;
+ }
+
+ // FIXME: this should probably be moved to a seperate function as per
+ // _calculate_restricted_width
+
+ // Only handle min/max height if the height is independent of the frame's content
+ if (!($style->overflow === "visible" ||
+ ($style->overflow === "hidden" && $height === "auto"))
+ ) {
+
+ $min_height = $style->min_height;
+ $max_height = $style->max_height;
+
+ if (isset($cb["h"])) {
+ $min_height = $style->length_in_pt($min_height, $cb["h"]);
+ $max_height = $style->length_in_pt($max_height, $cb["h"]);
+
+ } else if (isset($cb["w"])) {
+
+ if (mb_strpos($min_height, "%") !== false) {
+ $min_height = 0;
+ } else {
+ $min_height = $style->length_in_pt($min_height, $cb["w"]);
+ }
+
+ if (mb_strpos($max_height, "%") !== false) {
+ $max_height = "none";
+ } else {
+ $max_height = $style->length_in_pt($max_height, $cb["w"]);
+ }
+ }
+
+ if ($max_height !== "none" && $min_height > $max_height) {
+ // Swap 'em
+ list($max_height, $min_height) = array($min_height, $max_height);
+ }
+
+ if ($max_height !== "none" && $height > $max_height) {
+ $height = $max_height;
+ }
+
+ if ($height < $min_height) {
+ $height = $min_height;
+ }
+ }
+
+ }
+
+ return array($height, $margin_top, $margin_bottom, $top, $bottom);
+
+ }
+
+ /**
+ * Adjust the justification of each of our lines.
+ * http://www.w3.org/TR/CSS21/text.html#propdef-text-align
+ */
+ protected function _text_align()
+ {
+ $style = $this->_frame->get_style();
+ $w = $this->_frame->get_containing_block("w");
+ $width = $style->length_in_pt($style->width, $w);
+
+ switch ($style->text_align) {
+ default:
+ case "left":
+ foreach ($this->_frame->get_line_boxes() as $line) {
+ if (!$line->left) {
+ continue;
+ }
+
+ foreach ($line->get_frames() as $frame) {
+ if ($frame instanceof BlockFrameDecorator) {
+ continue;
+ }
+ $frame->set_position($frame->get_position("x") + $line->left);
+ }
+ }
+ return;
+
+ case "right":
+ foreach ($this->_frame->get_line_boxes() as $line) {
+ // Move each child over by $dx
+ $dx = $width - $line->w - $line->right;
+
+ foreach ($line->get_frames() as $frame) {
+ // Block frames are not aligned by text-align
+ if ($frame instanceof BlockFrameDecorator) {
+ continue;
+ }
+
+ $frame->set_position($frame->get_position("x") + $dx);
+ }
+ }
+ break;
+
+
+ case "justify":
+ // We justify all lines except the last one
+ $lines = $this->_frame->get_line_boxes(); // needs to be a variable (strict standards)
+ array_pop($lines);
+
+ foreach ($lines as $i => $line) {
+ if ($line->br) {
+ unset($lines[$i]);
+ }
+ }
+
+ // One space character's width. Will be used to get a more accurate spacing
+ $space_width = $this->get_dompdf()->getFontMetrics()->getTextWidth(" ", $style->font_family, $style->font_size);
+
+ foreach ($lines as $line) {
+ if ($line->left) {
+ foreach ($line->get_frames() as $frame) {
+ if (!$frame instanceof TextFrameDecorator) {
+ continue;
+ }
+
+ $frame->set_position($frame->get_position("x") + $line->left);
+ }
+ }
+
+ // Only set the spacing if the line is long enough. This is really
+ // just an aesthetic choice ;)
+ //if ( $line["left"] + $line["w"] + $line["right"] > self::MIN_JUSTIFY_WIDTH * $width ) {
+
+ // Set the spacing for each child
+ if ($line->wc > 1) {
+ $spacing = ($width - ($line->left + $line->w + $line->right) + $space_width) / ($line->wc - 1);
+ } else {
+ $spacing = 0;
+ }
+
+ $dx = 0;
+ foreach ($line->get_frames() as $frame) {
+ if (!$frame instanceof TextFrameDecorator) {
+ continue;
+ }
+
+ $text = $frame->get_text();
+ $spaces = mb_substr_count($text, " ");
+
+ $char_spacing = $style->length_in_pt($style->letter_spacing);
+ $_spacing = $spacing + $char_spacing;
+
+ $frame->set_position($frame->get_position("x") + $dx);
+ $frame->set_text_spacing($_spacing);
+
+ $dx += $spaces * $_spacing;
+ }
+
+ // The line (should) now occupy the entire width
+ $line->w = $width;
+
+ //}
+ }
+ break;
+
+ case "center":
+ case "centre":
+ foreach ($this->_frame->get_line_boxes() as $line) {
+ // Centre each line by moving each frame in the line by:
+ $dx = ($width + $line->left - $line->w - $line->right) / 2;
+
+ foreach ($line->get_frames() as $frame) {
+ // Block frames are not aligned by text-align
+ if ($frame instanceof BlockFrameDecorator) {
+ continue;
+ }
+
+ $frame->set_position($frame->get_position("x") + $dx);
+ }
+ }
+ break;
+ }
+ }
+
+ /**
+ * Align inline children vertically.
+ * Aligns each child vertically after each line is reflowed
+ */
+ function vertical_align()
+ {
+
+ $canvas = null;
+
+ foreach ($this->_frame->get_line_boxes() as $line) {
+
+ $height = $line->h;
+
+ foreach ($line->get_frames() as $frame) {
+ $style = $frame->get_style();
+
+ if ($style->display !== "inline") {
+ continue;
+ }
+
+ $align = $frame->get_parent()->get_style()->vertical_align;
+
+ if (!isset($canvas)) {
+ $canvas = $frame->get_root()->get_dompdf()->get_canvas();
+ }
+
+ $baseline = $canvas->get_font_baseline($style->font_family, $style->font_size);
+ $y_offset = 0;
+
+ switch ($align) {
+ case "baseline":
+ $y_offset = $height * 0.8 - $baseline; // The 0.8 ratio is arbitrary until we find it's meaning
+ break;
+
+ case "middle":
+ $y_offset = ($height * 0.8 - $baseline) / 2;
+ break;
+
+ case "sub":
+ $y_offset = 0.3 * $height;
+ break;
+
+ case "super":
+ $y_offset = -0.2 * $height;
+ break;
+
+ case "text-top":
+ case "top": // Not strictly accurate, but good enough for now
+ break;
+
+ case "text-bottom":
+ case "bottom":
+ $y_offset = $height * 0.8 - $baseline;
+ break;
+ }
+
+ if ($y_offset) {
+ $frame->move(0, $y_offset);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param Frame $child
+ */
+ function process_clear(Frame $child)
+ {
+ $child_style = $child->get_style();
+ $root = $this->_frame->get_root();
+
+ // Handle "clear"
+ if ($child_style->clear !== "none") {
+ $lowest_y = $root->get_lowest_float_offset($child);
+
+ // If a float is still applying, we handle it
+ if ($lowest_y) {
+ if ($child->is_in_flow()) {
+ $line_box = $this->_frame->get_current_line_box();
+ $line_box->y = $lowest_y + $child->get_margin_height();
+ $line_box->left = 0;
+ $line_box->right = 0;
+ }
+
+ $child->move(0, $lowest_y - $child->get_position("y"));
+ }
+ }
+ }
+
+ /**
+ * @param Frame $child
+ * @param float $cb_x
+ * @param float $cb_w
+ */
+ function process_float(Frame $child, $cb_x, $cb_w)
+ {
+ $child_style = $child->get_style();
+ $root = $this->_frame->get_root();
+
+ // Handle "float"
+ if ($child_style->float !== "none") {
+ $root->add_floating_frame($child);
+
+ // Remove next frame's beginning whitespace
+ $next = $child->get_next_sibling();
+ if ($next && $next instanceof TextFrameDecorator) {
+ $next->set_text(ltrim($next->get_text()));
+ }
+
+ $line_box = $this->_frame->get_current_line_box();
+ list($old_x, $old_y) = $child->get_position();
+
+ $float_x = $cb_x;
+ $float_y = $old_y;
+ $float_w = $child->get_margin_width();
+
+ if ($child_style->clear === "none") {
+ switch ($child_style->float) {
+ case "left":
+ $float_x += $line_box->left;
+ break;
+ case "right":
+ $float_x += ($cb_w - $line_box->right - $float_w);
+ break;
+ }
+ } else {
+ if ($child_style->float === "right") {
+ $float_x += ($cb_w - $float_w);
+ }
+ }
+
+ if ($cb_w < $float_x + $float_w - $old_x) {
+ // TODO handle when floating elements don't fit
+ }
+
+ $line_box->get_float_offsets();
+
+ if ($child->_float_next_line) {
+ $float_y += $line_box->h;
+ }
+
+ $child->set_position($float_x, $float_y);
+ $child->move($float_x - $old_x, $float_y - $old_y, true);
+ }
+ }
+
+ /**
+ * @param BlockFrameDecorator $block
+ */
+ function reflow(BlockFrameDecorator $block = null)
+ {
+
+ // Check if a page break is forced
+ $page = $this->_frame->get_root();
+ $page->check_forced_page_break($this->_frame);
+
+ // Bail if the page is full
+ if ($page->is_full()) {
+ return;
+ }
+
+ // Generated content
+ $this->_set_content();
+
+ // Collapse margins if required
+ $this->_collapse_margins();
+
+ $style = $this->_frame->get_style();
+ $cb = $this->_frame->get_containing_block();
+
+ if ($style->position === "fixed") {
+ $cb = $this->_frame->get_root()->get_containing_block();
+ }
+
+ // Determine the constraints imposed by this frame: calculate the width
+ // of the content area:
+ list($w, $left_margin, $right_margin, $left, $right) = $this->_calculate_restricted_width();
+
+ // Store the calculated properties
+ $style->width = $w . "pt";
+ $style->margin_left = $left_margin . "pt";
+ $style->margin_right = $right_margin . "pt";
+ $style->left = $left . "pt";
+ $style->right = $right . "pt";
+
+ // Update the position
+ $this->_frame->position();
+ list($x, $y) = $this->_frame->get_position();
+
+ // Adjust the first line based on the text-indent property
+ $indent = $style->length_in_pt($style->text_indent, $cb["w"]);
+ $this->_frame->increase_line_width($indent);
+
+ // Determine the content edge
+ $top = $style->length_in_pt(array($style->margin_top,
+ $style->padding_top,
+ $style->border_top_width), $cb["h"]);
+
+ $bottom = $style->length_in_pt(array($style->border_bottom_width,
+ $style->margin_bottom,
+ $style->padding_bottom), $cb["h"]);
+
+ $cb_x = $x + $left_margin + $style->length_in_pt(array($style->border_left_width,
+ $style->padding_left), $cb["w"]);
+
+ $cb_y = $y + $top;
+
+ $cb_h = ($cb["h"] + $cb["y"]) - $bottom - $cb_y;
+
+ // Set the y position of the first line in this block
+ $line_box = $this->_frame->get_current_line_box();
+ $line_box->y = $cb_y;
+ $line_box->get_float_offsets();
+
+ // Set the containing blocks and reflow each child
+ foreach ($this->_frame->get_children() as $child) {
+
+ // Bail out if the page is full
+ if ($page->is_full()) {
+ break;
+ }
+
+ $child->set_containing_block($cb_x, $cb_y, $w, $cb_h);
+
+ $this->process_clear($child);
+
+ $child->reflow($this->_frame);
+
+ // Don't add the child to the line if a page break has occurred
+ if ($page->check_page_break($child)) {
+ break;
+ }
+
+ $this->process_float($child, $cb_x, $w);
+ }
+
+ // Determine our height
+ list($height, $margin_top, $margin_bottom, $top, $bottom) = $this->_calculate_restricted_height();
+ $style->height = $height;
+ $style->margin_top = $margin_top;
+ $style->margin_bottom = $margin_bottom;
+ $style->top = $top;
+ $style->bottom = $bottom;
+
+ $needs_reposition = ($style->position === "absolute" && ($style->right !== "auto" || $style->bottom !== "auto"));
+
+ // Absolute positioning measurement
+ if ($needs_reposition) {
+ $orig_style = $this->_frame->get_original_style();
+ if ($orig_style->width === "auto" && ($orig_style->left === "auto" || $orig_style->right === "auto")) {
+ $width = 0;
+ foreach ($this->_frame->get_line_boxes() as $line) {
+ $width = max($line->w, $width);
+ }
+ $style->width = $width;
+ }
+
+ $style->left = $orig_style->left;
+ $style->right = $orig_style->right;
+ }
+
+ $this->_text_align();
+ $this->vertical_align();
+
+ // Absolute positioning
+ if ($needs_reposition) {
+ list($x, $y) = $this->_frame->get_position();
+ $this->_frame->position();
+ list($new_x, $new_y) = $this->_frame->get_position();
+ $this->_frame->move($new_x - $x, $new_y - $y, true);
+ }
+
+ if ($block && $this->_frame->is_in_flow()) {
+ $block->add_frame_to_line($this->_frame);
+
+ // May be inline-block
+ if ($style->display === "block") {
+ $block->add_line();
+ }
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/Image.php b/library/vendor/dompdf/src/FrameReflower/Image.php
new file mode 100644
index 000000000..c59814d5c
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/Image.php
@@ -0,0 +1,195 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\Helpers;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Image as ImageFrameDecorator;
+
+/**
+ * Image reflower class
+ *
+ * @package dompdf
+ */
+class Image extends AbstractFrameReflower
+{
+
+ function __construct(ImageFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $this->_frame->position();
+
+ //FLOAT
+ //$frame = $this->_frame;
+ //$page = $frame->get_root();
+
+ //if ($frame->get_style()->float !== "none" ) {
+ // $page->add_floating_frame($this);
+ //}
+
+ // Set the frame's width
+ $this->get_min_max_width();
+
+ if ($block) {
+ $block->add_frame_to_line($this->_frame);
+ }
+ }
+
+ function get_min_max_width()
+ {
+ if ($this->get_dompdf()->get_option("debugPng")) {
+ // Determine the image's size. Time consuming. Only when really needed?
+ list($img_width, $img_height) = Helpers::dompdf_getimagesize($this->_frame->get_image_url(), $this->get_dompdf()->getHttpContext());
+ print "get_min_max_width() " .
+ $this->_frame->get_style()->width . ' ' .
+ $this->_frame->get_style()->height . ';' .
+ $this->_frame->get_parent()->get_style()->width . " " .
+ $this->_frame->get_parent()->get_style()->height . ";" .
+ $this->_frame->get_parent()->get_parent()->get_style()->width . ' ' .
+ $this->_frame->get_parent()->get_parent()->get_style()->height . ';' .
+ $img_width . ' ' .
+ $img_height . '|';
+ }
+
+ $style = $this->_frame->get_style();
+
+ $width_forced = true;
+ $height_forced = true;
+
+ //own style auto or invalid value: use natural size in px
+ //own style value: ignore suffix text including unit, use given number as px
+ //own style %: walk up parent chain until found available space in pt; fill available space
+ //
+ //special ignored unit: e.g. 10ex: e treated as exponent; x ignored; 10e completely invalid ->like auto
+
+ $width = ($style->width > 0 ? $style->width : 0);
+ if (Helpers::is_percent($width)) {
+ $t = 0.0;
+ for ($f = $this->_frame->get_parent(); $f; $f = $f->get_parent()) {
+ $f_style = $f->get_style();
+ $t = $f_style->length_in_pt($f_style->width);
+ if ($t != 0) {
+ break;
+ }
+ }
+ $width = ((float)rtrim($width, "%") * $t) / 100; //maybe 0
+ } elseif (!mb_strpos($width, 'pt')) {
+ // Don't set image original size if "%" branch was 0 or size not given.
+ // Otherwise aspect changed on %/auto combination for width/height
+ // Resample according to px per inch
+ // See also ListBulletImage::__construct
+ $width = $style->length_in_pt($width);
+ }
+
+ $height = ($style->height > 0 ? $style->height : 0);
+ if (Helpers::is_percent($height)) {
+ $t = 0.0;
+ for ($f = $this->_frame->get_parent(); $f; $f = $f->get_parent()) {
+ $f_style = $f->get_style();
+ $t = $f_style->length_in_pt($f_style->height);
+ if ($t != 0) {
+ break;
+ }
+ }
+ $height = ((float)rtrim($height, "%") * $t) / 100; //maybe 0
+ } elseif (!mb_strpos($height, 'pt')) {
+ // Don't set image original size if "%" branch was 0 or size not given.
+ // Otherwise aspect changed on %/auto combination for width/height
+ // Resample according to px per inch
+ // See also ListBulletImage::__construct
+ $height = $style->length_in_pt($height);
+ }
+
+ if ($width == 0 || $height == 0) {
+ // Determine the image's size. Time consuming. Only when really needed!
+ list($img_width, $img_height) = Helpers::dompdf_getimagesize($this->_frame->get_image_url(), $this->get_dompdf()->getHttpContext());
+
+ // don't treat 0 as error. Can be downscaled or can be catched elsewhere if image not readable.
+ // Resample according to px per inch
+ // See also ListBulletImage::__construct
+ if ($width == 0 && $height == 0) {
+ $dpi = $this->_frame->get_dompdf()->get_option("dpi");
+ $width = (float)($img_width * 72) / $dpi;
+ $height = (float)($img_height * 72) / $dpi;
+ $width_forced = false;
+ $height_forced = false;
+ } elseif ($height == 0 && $width != 0) {
+ $height_forced = false;
+ $height = ($width / $img_width) * $img_height; //keep aspect ratio
+ } elseif ($width == 0 && $height != 0) {
+ $width_forced = false;
+ $width = ($height / $img_height) * $img_width; //keep aspect ratio
+ }
+ }
+
+ // Handle min/max width/height
+ if ($style->min_width !== "none" ||
+ $style->max_width !== "none" ||
+ $style->min_height !== "none" ||
+ $style->max_height !== "none"
+ ) {
+
+ list( /*$x*/, /*$y*/, $w, $h) = $this->_frame->get_containing_block();
+
+ $min_width = $style->length_in_pt($style->min_width, $w);
+ $max_width = $style->length_in_pt($style->max_width, $w);
+ $min_height = $style->length_in_pt($style->min_height, $h);
+ $max_height = $style->length_in_pt($style->max_height, $h);
+
+ if ($max_width !== "none" && $width > $max_width) {
+ if (!$height_forced) {
+ $height *= $max_width / $width;
+ }
+
+ $width = $max_width;
+ }
+
+ if ($min_width !== "none" && $width < $min_width) {
+ if (!$height_forced) {
+ $height *= $min_width / $width;
+ }
+
+ $width = $min_width;
+ }
+
+ if ($max_height !== "none" && $height > $max_height) {
+ if (!$width_forced) {
+ $width *= $max_height / $height;
+ }
+
+ $height = $max_height;
+ }
+
+ if ($min_height !== "none" && $height < $min_height) {
+ if (!$width_forced) {
+ $width *= $min_height / $height;
+ }
+
+ $height = $min_height;
+ }
+ }
+
+ if ($this->get_dompdf()->get_option("debugPng")) print $width . ' ' . $height . ';';
+
+ $style->width = $width . "pt";
+ $style->height = $height . "pt";
+
+ $style->min_width = "none";
+ $style->max_width = "none";
+ $style->min_height = "none";
+ $style->max_height = "none";
+
+ return array($width, $width, "min" => $width, "max" => $width);
+
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/Inline.php b/library/vendor/dompdf/src/FrameReflower/Inline.php
new file mode 100644
index 000000000..1f05fa9ef
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/Inline.php
@@ -0,0 +1,76 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Text as TextFrameDecorator;
+
+/**
+ * Reflows inline frames
+ *
+ * @package dompdf
+ */
+class Inline extends AbstractFrameReflower
+{
+
+ function __construct(Frame $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $frame = $this->_frame;
+
+ // Check if a page break is forced
+ $page = $frame->get_root();
+ $page->check_forced_page_break($frame);
+
+ if ($page->is_full()) {
+ return;
+ }
+
+ $style = $frame->get_style();
+
+ // Generated content
+ $this->_set_content();
+
+ $frame->position();
+
+ $cb = $frame->get_containing_block();
+
+ // Add our margin, padding & border to the first and last children
+ if (($f = $frame->get_first_child()) && $f instanceof TextFrameDecorator) {
+ $f_style = $f->get_style();
+ $f_style->margin_left = $style->margin_left;
+ $f_style->padding_left = $style->padding_left;
+ $f_style->border_left = $style->border_left;
+ }
+
+ if (($l = $frame->get_last_child()) && $l instanceof TextFrameDecorator) {
+ $l_style = $l->get_style();
+ $l_style->margin_right = $style->margin_right;
+ $l_style->padding_right = $style->padding_right;
+ $l_style->border_right = $style->border_right;
+ }
+
+ if ($block) {
+ $block->add_frame_to_line($this->_frame);
+ }
+
+ // Set the containing blocks and reflow each child. The containing
+ // block is not changed by line boxes.
+ foreach ($frame->get_children() as $child) {
+ $child->set_containing_block($cb);
+ $child->reflow($block);
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/ListBullet.php b/library/vendor/dompdf/src/FrameReflower/ListBullet.php
new file mode 100644
index 000000000..553195db5
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/ListBullet.php
@@ -0,0 +1,41 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Reflows list bullets
+ *
+ * @package dompdf
+ */
+class ListBullet extends AbstractFrameReflower
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $style = $this->_frame->get_style();
+
+ $style->width = $this->_frame->get_width();
+ $this->_frame->position();
+
+ if ($style->list_style_position === "inside") {
+ $p = $this->_frame->find_block_parent();
+ $p->add_frame_to_line($this->_frame);
+ }
+
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/NullFrameReflower.php b/library/vendor/dompdf/src/FrameReflower/NullFrameReflower.php
new file mode 100644
index 000000000..1f9d2e2c0
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/NullFrameReflower.php
@@ -0,0 +1,32 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\FrameReflower;
+
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+
+/**
+ * Dummy reflower
+ *
+ * @package dompdf
+ */
+class NullFrameReflower extends AbstractFrameReflower
+{
+
+ function __construct(Frame $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ return;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/Page.php b/library/vendor/dompdf/src/FrameReflower/Page.php
new file mode 100644
index 000000000..770eb6c83
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/Page.php
@@ -0,0 +1,199 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Page as PageFrameDecorator;
+
+/**
+ * Reflows pages
+ *
+ * @package dompdf
+ */
+class Page extends AbstractFrameReflower
+{
+
+ /**
+ * Cache of the callbacks array
+ *
+ * @var array
+ */
+ private $_callbacks;
+
+ /**
+ * Cache of the canvas
+ *
+ * @var \Dompdf\Canvas
+ */
+ private $_canvas;
+
+ function __construct(PageFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function apply_page_style(Frame $frame, $page_number)
+ {
+ $style = $frame->get_style();
+ $page_styles = $style->get_stylesheet()->get_page_styles();
+
+ // http://www.w3.org/TR/CSS21/page.html#page-selectors
+ if (count($page_styles) > 1) {
+ $odd = $page_number % 2 == 1;
+ $first = $page_number == 1;
+
+ $style = clone $page_styles["base"];
+
+ // FIXME RTL
+ if ($odd && isset($page_styles[":right"])) {
+ $style->merge($page_styles[":right"]);
+ }
+
+ if ($odd && isset($page_styles[":odd"])) {
+ $style->merge($page_styles[":odd"]);
+ }
+
+ // FIXME RTL
+ if (!$odd && isset($page_styles[":left"])) {
+ $style->merge($page_styles[":left"]);
+ }
+
+ if (!$odd && isset($page_styles[":even"])) {
+ $style->merge($page_styles[":even"]);
+ }
+
+ if ($first && isset($page_styles[":first"])) {
+ $style->merge($page_styles[":first"]);
+ }
+
+ $frame->set_style($style);
+ }
+ }
+
+ //........................................................................
+
+ /**
+ * Paged layout:
+ * http://www.w3.org/TR/CSS21/page.html
+ */
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $fixed_children = array();
+ $prev_child = null;
+ $child = $this->_frame->get_first_child();
+ $current_page = 0;
+
+ while ($child) {
+ $this->apply_page_style($this->_frame, $current_page + 1);
+
+ $style = $this->_frame->get_style();
+
+ // Pages are only concerned with margins
+ $cb = $this->_frame->get_containing_block();
+ $left = $style->length_in_pt($style->margin_left, $cb["w"]);
+ $right = $style->length_in_pt($style->margin_right, $cb["w"]);
+ $top = $style->length_in_pt($style->margin_top, $cb["h"]);
+ $bottom = $style->length_in_pt($style->margin_bottom, $cb["h"]);
+
+ $content_x = $cb["x"] + $left;
+ $content_y = $cb["y"] + $top;
+ $content_width = $cb["w"] - $left - $right;
+ $content_height = $cb["h"] - $top - $bottom;
+
+ // Only if it's the first page, we save the nodes with a fixed position
+ if ($current_page == 0) {
+ $children = $child->get_children();
+ foreach ($children as $onechild) {
+ if ($onechild->get_style()->position === "fixed") {
+ $fixed_children[] = $onechild->deep_copy();
+ }
+ }
+ $fixed_children = array_reverse($fixed_children);
+ }
+
+ $child->set_containing_block($content_x, $content_y, $content_width, $content_height);
+
+ // Check for begin reflow callback
+ $this->_check_callbacks("begin_page_reflow", $child);
+
+ //Insert a copy of each node which have a fixed position
+ if ($current_page >= 1) {
+ foreach ($fixed_children as $fixed_child) {
+ $child->insert_child_before($fixed_child->deep_copy(), $child->get_first_child());
+ }
+ }
+
+ $child->reflow();
+ $next_child = $child->get_next_sibling();
+
+ // Check for begin render callback
+ $this->_check_callbacks("begin_page_render", $child);
+
+ // Render the page
+ $this->_frame->get_renderer()->render($child);
+
+ // Check for end render callback
+ $this->_check_callbacks("end_page_render", $child);
+
+ if ($next_child) {
+ $this->_frame->next_page();
+ }
+
+ // Wait to dispose of all frames on the previous page
+ // so callback will have access to them
+ if ($prev_child) {
+ $prev_child->dispose(true);
+ }
+ $prev_child = $child;
+ $child = $next_child;
+ $current_page++;
+ }
+
+ // Dispose of previous page if it still exists
+ if ($prev_child) {
+ $prev_child->dispose(true);
+ }
+ }
+
+ //........................................................................
+
+ /**
+ * Check for callbacks that need to be performed when a given event
+ * gets triggered on a page
+ *
+ * @param string $event the type of event
+ * @param Frame $frame the frame that event is triggered on
+ */
+ protected function _check_callbacks($event, $frame)
+ {
+ if (!isset($this->_callbacks)) {
+ $dompdf = $this->_frame->get_dompdf();
+ $this->_callbacks = $dompdf->get_callbacks();
+ $this->_canvas = $dompdf->get_canvas();
+ }
+
+ if (is_array($this->_callbacks) && isset($this->_callbacks[$event])) {
+ $info = array(
+ 0 => $this->_canvas, "canvas" => $this->_canvas,
+ 1 => $frame, "frame" => $frame,
+ );
+ $fs = $this->_callbacks[$event];
+ foreach ($fs as $f) {
+ if (is_callable($f)) {
+ if (is_array($f)) {
+ $f[0]->{$f[1]}($info);
+ } else {
+ $f($info);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/Table.php b/library/vendor/dompdf/src/FrameReflower/Table.php
new file mode 100644
index 000000000..a3626d8c7
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/Table.php
@@ -0,0 +1,587 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Table as TableFrameDecorator;
+
+/**
+ * Reflows tables
+ *
+ * @access private
+ * @package dompdf
+ */
+class Table extends AbstractFrameReflower
+{
+ /**
+ * Frame for this reflower
+ *
+ * @var TableFrameDecorator
+ */
+ protected $_frame;
+
+ /**
+ * Cache of results between call to get_min_max_width and assign_widths
+ *
+ * @var array
+ */
+ protected $_state;
+
+ function __construct(TableFrameDecorator $frame)
+ {
+ $this->_state = null;
+ parent::__construct($frame);
+ }
+
+ /**
+ * State is held here so it needs to be reset along with the decorator
+ */
+ function reset()
+ {
+ $this->_state = null;
+ $this->_min_max_cache = null;
+ }
+
+ //........................................................................
+
+ protected function _assign_widths()
+ {
+ $style = $this->_frame->get_style();
+
+ // Find the min/max width of the table and sort the columns into
+ // absolute/percent/auto arrays
+ $min_width = $this->_state["min_width"];
+ $max_width = $this->_state["max_width"];
+ $percent_used = $this->_state["percent_used"];
+ $absolute_used = $this->_state["absolute_used"];
+ $auto_min = $this->_state["auto_min"];
+
+ $absolute =& $this->_state["absolute"];
+ $percent =& $this->_state["percent"];
+ $auto =& $this->_state["auto"];
+
+ // Determine the actual width of the table
+ $cb = $this->_frame->get_containing_block();
+ $columns =& $this->_frame->get_cellmap()->get_columns();
+
+ $width = $style->width;
+
+ // Calculate padding & border fudge factor
+ $left = $style->margin_left;
+ $right = $style->margin_right;
+
+ $centered = ($left === "auto" && $right === "auto");
+
+ $left = $left === "auto" ? 0 : $style->length_in_pt($left, $cb["w"]);
+ $right = $right === "auto" ? 0 : $style->length_in_pt($right, $cb["w"]);
+
+ $delta = $left + $right;
+
+ if (!$centered) {
+ $delta += $style->length_in_pt(array(
+ $style->padding_left,
+ $style->border_left_width,
+ $style->border_right_width,
+ $style->padding_right),
+ $cb["w"]);
+ }
+
+ $min_table_width = $style->length_in_pt($style->min_width, $cb["w"] - $delta);
+
+ // min & max widths already include borders & padding
+ $min_width -= $delta;
+ $max_width -= $delta;
+
+ if ($width !== "auto") {
+
+ $preferred_width = $style->length_in_pt($width, $cb["w"]) - $delta;
+
+ if ($preferred_width < $min_table_width)
+ $preferred_width = $min_table_width;
+
+ if ($preferred_width > $min_width)
+ $width = $preferred_width;
+ else
+ $width = $min_width;
+
+ } else {
+
+ if ($max_width + $delta < $cb["w"])
+ $width = $max_width;
+ else if ($cb["w"] - $delta > $min_width)
+ $width = $cb["w"] - $delta;
+ else
+ $width = $min_width;
+
+ if ($width < $min_table_width)
+ $width = $min_table_width;
+
+ }
+
+ // Store our resolved width
+ $style->width = $width;
+
+ $cellmap = $this->_frame->get_cellmap();
+
+ if ($cellmap->is_columns_locked()) {
+ return;
+ }
+
+ // If the whole table fits on the page, then assign each column it's max width
+ if ($width == $max_width) {
+
+ foreach (array_keys($columns) as $i)
+ $cellmap->set_column_width($i, $columns[$i]["max-width"]);
+
+ return;
+ }
+
+ // Determine leftover and assign it evenly to all columns
+ if ($width > $min_width) {
+
+ // We have four cases to deal with:
+ //
+ // 1. All columns are auto--no widths have been specified. In this
+ // case we distribute extra space across all columns weighted by max-width.
+ //
+ // 2. Only absolute widths have been specified. In this case we
+ // distribute any extra space equally among 'width: auto' columns, or all
+ // columns if no auto columns have been specified.
+ //
+ // 3. Only percentage widths have been specified. In this case we
+ // normalize the percentage values and distribute any remaining % to
+ // width: auto columns. We then proceed to assign widths as fractions
+ // of the table width.
+ //
+ // 4. Both absolute and percentage widths have been specified.
+
+ $increment = 0;
+
+ // Case 1:
+ if ($absolute_used == 0 && $percent_used == 0) {
+ $increment = $width - $min_width;
+
+ foreach (array_keys($columns) as $i) {
+ $cellmap->set_column_width($i, $columns[$i]["min-width"] + $increment * ($columns[$i]["max-width"] / $max_width));
+ }
+ return;
+ }
+
+
+ // Case 2
+ if ($absolute_used > 0 && $percent_used == 0) {
+
+ if (count($auto) > 0)
+ $increment = ($width - $auto_min - $absolute_used) / count($auto);
+
+ // Use the absolutely specified width or the increment
+ foreach (array_keys($columns) as $i) {
+
+ if ($columns[$i]["absolute"] > 0 && count($auto))
+ $cellmap->set_column_width($i, $columns[$i]["min-width"]);
+ else if (count($auto))
+ $cellmap->set_column_width($i, $columns[$i]["min-width"] + $increment);
+ else {
+ // All absolute columns
+ $increment = ($width - $absolute_used) * $columns[$i]["absolute"] / $absolute_used;
+
+ $cellmap->set_column_width($i, $columns[$i]["min-width"] + $increment);
+ }
+
+ }
+ return;
+ }
+
+
+ // Case 3:
+ if ($absolute_used == 0 && $percent_used > 0) {
+
+ $scale = null;
+ $remaining = null;
+
+ // Scale percent values if the total percentage is > 100, or if all
+ // values are specified as percentages.
+ if ($percent_used > 100 || count($auto) == 0)
+ $scale = 100 / $percent_used;
+ else
+ $scale = 1;
+
+ // Account for the minimum space used by the unassigned auto columns
+ $used_width = $auto_min;
+
+ foreach ($percent as $i) {
+ $columns[$i]["percent"] *= $scale;
+
+ $slack = $width - $used_width;
+
+ $w = min($columns[$i]["percent"] * $width / 100, $slack);
+
+ if ($w < $columns[$i]["min-width"])
+ $w = $columns[$i]["min-width"];
+
+ $cellmap->set_column_width($i, $w);
+ $used_width += $w;
+
+ }
+
+ // This works because $used_width includes the min-width of each
+ // unassigned column
+ if (count($auto) > 0) {
+ $increment = ($width - $used_width) / count($auto);
+
+ foreach ($auto as $i)
+ $cellmap->set_column_width($i, $columns[$i]["min-width"] + $increment);
+
+ }
+ return;
+ }
+
+ // Case 4:
+
+ // First-come, first served
+ if ($absolute_used > 0 && $percent_used > 0) {
+
+ $used_width = $auto_min;
+
+ foreach ($absolute as $i) {
+ $cellmap->set_column_width($i, $columns[$i]["min-width"]);
+ $used_width += $columns[$i]["min-width"];
+ }
+
+ // Scale percent values if the total percentage is > 100 or there
+ // are no auto values to take up slack
+ if ($percent_used > 100 || count($auto) == 0)
+ $scale = 100 / $percent_used;
+ else
+ $scale = 1;
+
+ $remaining_width = $width - $used_width;
+
+ foreach ($percent as $i) {
+ $slack = $remaining_width - $used_width;
+
+ $columns[$i]["percent"] *= $scale;
+ $w = min($columns[$i]["percent"] * $remaining_width / 100, $slack);
+
+ if ($w < $columns[$i]["min-width"])
+ $w = $columns[$i]["min-width"];
+
+ $columns[$i]["used-width"] = $w;
+ $used_width += $w;
+ }
+
+ if (count($auto) > 0) {
+ $increment = ($width - $used_width) / count($auto);
+
+ foreach ($auto as $i)
+ $cellmap->set_column_width($i, $columns[$i]["min-width"] + $increment);
+
+ }
+
+ return;
+ }
+
+
+ } else { // we are over constrained
+
+ // Each column gets its minimum width
+ foreach (array_keys($columns) as $i)
+ $cellmap->set_column_width($i, $columns[$i]["min-width"]);
+
+ }
+ }
+
+ //........................................................................
+
+ // Determine the frame's height based on min/max height
+ protected function _calculate_height()
+ {
+
+ $style = $this->_frame->get_style();
+ $height = $style->height;
+
+ $cellmap = $this->_frame->get_cellmap();
+ $cellmap->assign_frame_heights();
+ $rows = $cellmap->get_rows();
+
+ // Determine our content height
+ $content_height = 0;
+ foreach ($rows as $r)
+ $content_height += $r["height"];
+
+ $cb = $this->_frame->get_containing_block();
+
+ if (!($style->overflow === "visible" ||
+ ($style->overflow === "hidden" && $height === "auto"))
+ ) {
+
+ // Only handle min/max height if the height is independent of the frame's content
+
+ $min_height = $style->min_height;
+ $max_height = $style->max_height;
+
+ if (isset($cb["h"])) {
+ $min_height = $style->length_in_pt($min_height, $cb["h"]);
+ $max_height = $style->length_in_pt($max_height, $cb["h"]);
+
+ } else if (isset($cb["w"])) {
+
+ if (mb_strpos($min_height, "%") !== false)
+ $min_height = 0;
+ else
+ $min_height = $style->length_in_pt($min_height, $cb["w"]);
+
+ if (mb_strpos($max_height, "%") !== false)
+ $max_height = "none";
+ else
+ $max_height = $style->length_in_pt($max_height, $cb["w"]);
+ }
+
+ if ($max_height !== "none" && $min_height > $max_height)
+ // Swap 'em
+ list($max_height, $min_height) = array($min_height, $max_height);
+
+ if ($max_height !== "none" && $height > $max_height)
+ $height = $max_height;
+
+ if ($height < $min_height)
+ $height = $min_height;
+
+ } else {
+
+ // Use the content height or the height value, whichever is greater
+ if ($height !== "auto") {
+ $height = $style->length_in_pt($height, $cb["h"]);
+
+ if ($height <= $content_height)
+ $height = $content_height;
+ else
+ $cellmap->set_frame_heights($height, $content_height);
+
+ } else
+ $height = $content_height;
+
+ }
+
+ return $height;
+
+ }
+ //........................................................................
+
+ /**
+ * @param BlockFrameDecorator $block
+ */
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ /** @var TableFrameDecorator */
+ $frame = $this->_frame;
+
+ // Check if a page break is forced
+ $page = $frame->get_root();
+ $page->check_forced_page_break($frame);
+
+ // Bail if the page is full
+ if ($page->is_full())
+ return;
+
+ // Let the page know that we're reflowing a table so that splits
+ // are suppressed (simply setting page-break-inside: avoid won't
+ // work because we may have an arbitrary number of block elements
+ // inside tds.)
+ $page->table_reflow_start();
+
+ // Collapse vertical margins, if required
+ $this->_collapse_margins();
+
+ $frame->position();
+
+ // Table layout algorithm:
+ // http://www.w3.org/TR/CSS21/tables.html#auto-table-layout
+
+ if (is_null($this->_state))
+ $this->get_min_max_width();
+
+ $cb = $frame->get_containing_block();
+ $style = $frame->get_style();
+
+ // This is slightly inexact, but should be okay. Add half the
+ // border-spacing to the table as padding. The other half is added to
+ // the cells themselves.
+ if ($style->border_collapse === "separate") {
+ list($h, $v) = $style->border_spacing;
+
+ $v = $style->length_in_pt($v) / 2;
+ $h = $style->length_in_pt($h) / 2;
+
+ $style->padding_left = $style->length_in_pt($style->padding_left, $cb["w"]) + $h;
+ $style->padding_right = $style->length_in_pt($style->padding_right, $cb["w"]) + $h;
+ $style->padding_top = $style->length_in_pt($style->padding_top, $cb["h"]) + $v;
+ $style->padding_bottom = $style->length_in_pt($style->padding_bottom, $cb["h"]) + $v;
+
+ }
+
+ $this->_assign_widths();
+
+ // Adjust left & right margins, if they are auto
+ $width = $style->width;
+ $left = $style->margin_left;
+ $right = $style->margin_right;
+
+ $diff = $cb["w"] - $width;
+
+ if ($left === "auto" && $right === "auto") {
+ if ($diff < 0) {
+ $left = 0;
+ $right = $diff;
+ } else {
+ $left = $right = $diff / 2;
+ }
+
+ $style->margin_left = "$left pt";
+ $style->margin_right = "$right pt";
+
+ } else {
+ if ($left === "auto") {
+ $left = $style->length_in_pt($cb["w"] - $right - $width, $cb["w"]);
+ }
+ if ($right === "auto") {
+ $left = $style->length_in_pt($left, $cb["w"]);
+ }
+ }
+
+ list($x, $y) = $frame->get_position();
+
+ // Determine the content edge
+ $content_x = $x + $left + $style->length_in_pt(array($style->padding_left,
+ $style->border_left_width), $cb["w"]);
+ $content_y = $y + $style->length_in_pt(array($style->margin_top,
+ $style->border_top_width,
+ $style->padding_top), $cb["h"]);
+
+ if (isset($cb["h"]))
+ $h = $cb["h"];
+ else
+ $h = null;
+
+ $cellmap = $frame->get_cellmap();
+ $col =& $cellmap->get_column(0);
+ $col["x"] = $content_x;
+
+ $row =& $cellmap->get_row(0);
+ $row["y"] = $content_y;
+
+ $cellmap->assign_x_positions();
+
+ // Set the containing block of each child & reflow
+ foreach ($frame->get_children() as $child) {
+
+ // Bail if the page is full
+ if (!$page->in_nested_table() && $page->is_full())
+ break;
+
+ $child->set_containing_block($content_x, $content_y, $width, $h);
+ $child->reflow();
+
+ if (!$page->in_nested_table())
+ // Check if a split has occured
+ $page->check_page_break($child);
+
+ }
+
+ // Assign heights to our cells:
+ $style->height = $this->_calculate_height();
+
+ if ($style->border_collapse === "collapse") {
+ // Unset our borders because our cells are now using them
+ $style->border_style = "none";
+ }
+
+ $page->table_reflow_end();
+
+ // Debugging:
+ //echo ($this->_frame->get_cellmap());
+
+ if ($block && $style->float === "none" && $frame->is_in_flow()) {
+ $block->add_frame_to_line($frame);
+ $block->add_line();
+ }
+ }
+
+ //........................................................................
+
+ function get_min_max_width()
+ {
+
+ if (!is_null($this->_min_max_cache))
+ return $this->_min_max_cache;
+
+ $style = $this->_frame->get_style();
+
+ $this->_frame->normalise();
+
+ // Add the cells to the cellmap (this will calcluate column widths as
+ // frames are added)
+ $this->_frame->get_cellmap()->add_frame($this->_frame);
+
+ // Find the min/max width of the table and sort the columns into
+ // absolute/percent/auto arrays
+ $this->_state = array();
+ $this->_state["min_width"] = 0;
+ $this->_state["max_width"] = 0;
+
+ $this->_state["percent_used"] = 0;
+ $this->_state["absolute_used"] = 0;
+ $this->_state["auto_min"] = 0;
+
+ $this->_state["absolute"] = array();
+ $this->_state["percent"] = array();
+ $this->_state["auto"] = array();
+
+ $columns =& $this->_frame->get_cellmap()->get_columns();
+ foreach (array_keys($columns) as $i) {
+ $this->_state["min_width"] += $columns[$i]["min-width"];
+ $this->_state["max_width"] += $columns[$i]["max-width"];
+
+ if ($columns[$i]["absolute"] > 0) {
+ $this->_state["absolute"][] = $i;
+ $this->_state["absolute_used"] += $columns[$i]["absolute"];
+
+ } else if ($columns[$i]["percent"] > 0) {
+ $this->_state["percent"][] = $i;
+ $this->_state["percent_used"] += $columns[$i]["percent"];
+
+ } else {
+ $this->_state["auto"][] = $i;
+ $this->_state["auto_min"] += $columns[$i]["min-width"];
+ }
+ }
+
+ // Account for margins & padding
+ $dims = array($style->border_left_width,
+ $style->border_right_width,
+ $style->padding_left,
+ $style->padding_right,
+ $style->margin_left,
+ $style->margin_right);
+
+ if ($style->border_collapse !== "collapse")
+ list($dims[]) = $style->border_spacing;
+
+ $delta = $style->length_in_pt($dims, $this->_frame->get_containing_block("w"));
+
+ $this->_state["min_width"] += $delta;
+ $this->_state["max_width"] += $delta;
+
+ return $this->_min_max_cache = array(
+ $this->_state["min_width"],
+ $this->_state["max_width"],
+ "min" => $this->_state["min_width"],
+ "max" => $this->_state["max_width"],
+ );
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/TableCell.php b/library/vendor/dompdf/src/FrameReflower/TableCell.php
new file mode 100644
index 000000000..0dc74a1f3
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/TableCell.php
@@ -0,0 +1,120 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Table as TableFrameDecorator;
+
+/**
+ * Reflows table cells
+ *
+ * @package dompdf
+ */
+class TableCell extends Block
+{
+ function __construct(BlockFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+
+ $style = $this->_frame->get_style();
+
+ $table = TableFrameDecorator::find_parent_table($this->_frame);
+ $cellmap = $table->get_cellmap();
+
+ list($x, $y) = $cellmap->get_frame_position($this->_frame);
+ $this->_frame->set_position($x, $y);
+
+ $cells = $cellmap->get_spanned_cells($this->_frame);
+
+ $w = 0;
+ foreach ($cells["columns"] as $i) {
+ $col = $cellmap->get_column($i);
+ $w += $col["used-width"];
+ }
+
+ //FIXME?
+ $h = $this->_frame->get_containing_block("h");
+
+ $left_space = $style->length_in_pt(array($style->margin_left,
+ $style->padding_left,
+ $style->border_left_width),
+ $w);
+
+ $right_space = $style->length_in_pt(array($style->padding_right,
+ $style->margin_right,
+ $style->border_right_width),
+ $w);
+
+ $top_space = $style->length_in_pt(array($style->margin_top,
+ $style->padding_top,
+ $style->border_top_width),
+ $h);
+ $bottom_space = $style->length_in_pt(array($style->margin_bottom,
+ $style->padding_bottom,
+ $style->border_bottom_width),
+ $h);
+
+ $style->width = $cb_w = $w - $left_space - $right_space;
+
+ $content_x = $x + $left_space;
+ $content_y = $line_y = $y + $top_space;
+
+ // Adjust the first line based on the text-indent property
+ $indent = $style->length_in_pt($style->text_indent, $w);
+ $this->_frame->increase_line_width($indent);
+
+ $page = $this->_frame->get_root();
+
+ // Set the y position of the first line in the cell
+ $line_box = $this->_frame->get_current_line_box();
+ $line_box->y = $line_y;
+
+ // Set the containing blocks and reflow each child
+ foreach ($this->_frame->get_children() as $child) {
+
+ if ($page->is_full())
+ break;
+
+ $child->set_containing_block($content_x, $content_y, $cb_w, $h);
+
+ $this->process_clear($child);
+
+ $child->reflow($this->_frame);
+
+ $this->process_float($child, $x + $left_space, $w - $right_space - $left_space);
+ }
+
+ // Determine our height
+ $style_height = $style->length_in_pt($style->height, $h);
+
+ $this->_frame->set_content_height($this->_calculate_content_height());
+
+ $height = max($style_height, $this->_frame->get_content_height());
+
+ // Let the cellmap know our height
+ $cell_height = $height / count($cells["rows"]);
+
+ if ($style_height <= $height)
+ $cell_height += $top_space + $bottom_space;
+
+ foreach ($cells["rows"] as $i)
+ $cellmap->set_row_height($i, $cell_height);
+
+ $style->height = $height;
+
+ $this->_text_align();
+
+ $this->vertical_align();
+
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/TableRow.php b/library/vendor/dompdf/src/FrameReflower/TableRow.php
new file mode 100644
index 000000000..7f2de4cff
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/TableRow.php
@@ -0,0 +1,68 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Table as TableFrameDecorator;
+use Dompdf\FrameDecorator\TableRow as TableRowFrameDecorator;
+use Dompdf\Exception;
+
+/**
+ * Reflows table rows
+ *
+ * @package dompdf
+ */
+class TableRow extends AbstractFrameReflower
+{
+ function __construct(TableRowFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $page = $this->_frame->get_root();
+
+ if ($page->is_full())
+ return;
+
+ $this->_frame->position();
+ $style = $this->_frame->get_style();
+ $cb = $this->_frame->get_containing_block();
+
+ foreach ($this->_frame->get_children() as $child) {
+
+ if ($page->is_full())
+ return;
+
+ $child->set_containing_block($cb);
+ $child->reflow();
+
+ }
+
+ if ($page->is_full())
+ return;
+
+ $table = TableFrameDecorator::find_parent_table($this->_frame);
+ $cellmap = $table->get_cellmap();
+ $style->width = $cellmap->get_frame_width($this->_frame);
+ $style->height = $cellmap->get_frame_height($this->_frame);
+
+ $this->_frame->set_position($cellmap->get_frame_position($this->_frame));
+
+ }
+
+ //........................................................................
+
+ function get_min_max_width()
+ {
+ throw new Exception("Min/max width is undefined for table rows");
+ }
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/TableRowGroup.php b/library/vendor/dompdf/src/FrameReflower/TableRowGroup.php
new file mode 100644
index 000000000..eb13dd599
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/TableRowGroup.php
@@ -0,0 +1,65 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Table as TableFrameDecorator;
+
+/**
+ * Reflows table row groups (e.g. tbody tags)
+ *
+ * @package dompdf
+ */
+class TableRowGroup extends AbstractFrameReflower
+{
+
+ function __construct($frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $page = $this->_frame->get_root();
+
+ $style = $this->_frame->get_style();
+
+ // Our width is equal to the width of our parent table
+ $table = TableFrameDecorator::find_parent_table($this->_frame);
+
+ $cb = $this->_frame->get_containing_block();
+
+ foreach ($this->_frame->get_children() as $child) {
+ // Bail if the page is full
+ if ($page->is_full())
+ return;
+
+ $child->set_containing_block($cb["x"], $cb["y"], $cb["w"], $cb["h"]);
+ $child->reflow();
+
+ // Check if a split has occured
+ $page->check_page_break($child);
+
+ }
+
+ if ($page->is_full())
+ return;
+
+ $cellmap = $table->get_cellmap();
+ $style->width = $cellmap->get_frame_width($this->_frame);
+ $style->height = $cellmap->get_frame_height($this->_frame);
+
+ $this->_frame->set_position($cellmap->get_frame_position($this->_frame));
+
+ if ($table->get_style()->border_collapse === "collapse")
+ // Unset our borders because our cells are now using them
+ $style->border_style = "none";
+
+ }
+
+}
diff --git a/library/vendor/dompdf/src/FrameReflower/Text.php b/library/vendor/dompdf/src/FrameReflower/Text.php
new file mode 100644
index 000000000..950f7fae9
--- /dev/null
+++ b/library/vendor/dompdf/src/FrameReflower/Text.php
@@ -0,0 +1,487 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\FrameReflower;
+
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\FrameDecorator\Text as TextFrameDecorator;
+use Dompdf\FontMetrics;
+
+/**
+ * Reflows text frames.
+ *
+ * @package dompdf
+ */
+class Text extends AbstractFrameReflower
+{
+
+ /**
+ * @var BlockFrameDecorator
+ */
+ protected $_block_parent; // Nearest block-level ancestor
+
+ /**
+ * @var TextFrameDecorator
+ */
+ protected $_frame;
+
+ public static $_whitespace_pattern = "/[ \t\r\n\f]+/u";
+
+ /**
+ * @var FontMetrics
+ */
+ private $fontMetrics;
+
+ /**
+ * @param TextFrameDecorator $frame
+ * @param FontMetrics $fontMetrics
+ */
+ public function __construct(TextFrameDecorator $frame, FontMetrics $fontMetrics)
+ {
+ parent::__construct($frame);
+ $this->setFontMetrics($fontMetrics);
+ }
+
+ //........................................................................
+
+ protected function _collapse_white_space($text)
+ {
+ //$text = $this->_frame->get_text();
+// if ( $this->_block_parent->get_current_line_box->w == 0 )
+// $text = ltrim($text, " \n\r\t");
+ return preg_replace(self::$_whitespace_pattern, " ", $text);
+ }
+
+ //........................................................................
+
+ protected function _line_break($text)
+ {
+ $style = $this->_frame->get_style();
+ $size = $style->font_size;
+ $font = $style->font_family;
+ $current_line = $this->_block_parent->get_current_line_box();
+
+ // Determine the available width
+ $line_width = $this->_frame->get_containing_block("w");
+ $current_line_width = $current_line->left + $current_line->w + $current_line->right;
+
+ $available_width = $line_width - $current_line_width;
+
+ // Account for word-spacing
+ $word_spacing = $style->length_in_pt($style->word_spacing);
+ $char_spacing = $style->length_in_pt($style->letter_spacing);
+
+ // Determine the frame width including margin, padding & border
+ $text_width = $this->getFontMetrics()->getTextWidth($text, $font, $size, $word_spacing, $char_spacing);
+ $mbp_width =
+ $style->length_in_pt(array($style->margin_left,
+ $style->border_left_width,
+ $style->padding_left,
+ $style->padding_right,
+ $style->border_right_width,
+ $style->margin_right), $line_width);
+
+ $frame_width = $text_width + $mbp_width;
+
+// Debugging:
+// Helpers::pre_r("Text: '" . htmlspecialchars($text). "'");
+// Helpers::pre_r("width: " .$frame_width);
+// Helpers::pre_r("textwidth + delta: $text_width + $mbp_width");
+// Helpers::pre_r("font-size: $size");
+// Helpers::pre_r("cb[w]: " .$line_width);
+// Helpers::pre_r("available width: " . $available_width);
+// Helpers::pre_r("current line width: " . $current_line_width);
+
+// Helpers::pre_r($words);
+
+ if ($frame_width <= $available_width)
+ return false;
+
+ // split the text into words
+ $words = preg_split('/([\s-]+)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $wc = count($words);
+
+ // Determine the split point
+ $width = 0;
+ $str = "";
+ reset($words);
+
+ // @todo support ,
+ for ($i = 0; $i < $wc; $i += 2) {
+ $word = $words[$i] . (isset($words[$i + 1]) ? $words[$i + 1] : "");
+ $word_width = $this->getFontMetrics()->getTextWidth($word, $font, $size, $word_spacing, $char_spacing);
+ if ($width + $word_width + $mbp_width > $available_width)
+ break;
+
+ $width += $word_width;
+ $str .= $word;
+ }
+
+ $break_word = ($style->word_wrap === "break-word");
+
+ // The first word has overflowed. Force it onto the line
+ if ($current_line_width == 0 && $width == 0) {
+
+ $s = "";
+ $last_width = 0;
+
+ if ($break_word) {
+ for ($j = 0; $j < strlen($word); $j++) {
+ $s .= $word[$j];
+ $_width = $this->getFontMetrics()->getTextWidth($s, $font, $size, $word_spacing, $char_spacing);
+ if ($_width > $available_width) {
+ break;
+ }
+
+ $last_width = $_width;
+ }
+ }
+
+ if ($break_word && $last_width > 0) {
+ $width += $last_width;
+ $str .= substr($s, 0, -1);
+ } else {
+ $width += $word_width;
+ $str .= $word;
+ }
+ }
+
+ $offset = mb_strlen($str);
+
+// More debugging:
+// var_dump($str);
+// print_r("Width: ". $width);
+// print_r("Offset: " . $offset);
+
+ return $offset;
+
+ }
+
+ //........................................................................
+
+ protected function _newline_break($text)
+ {
+
+ if (($i = mb_strpos($text, "\n")) === false)
+ return false;
+
+ return $i + 1;
+
+ }
+
+ //........................................................................
+
+ protected function _layout_line()
+ {
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+ $text = $frame->get_text();
+ $size = $style->font_size;
+ $font = $style->font_family;
+
+ // Determine the text height
+ $style->height = $this->getFontMetrics()->getFontHeight($font, $size);
+
+ $split = false;
+ $add_line = false;
+
+ // Handle text transform:
+ // http://www.w3.org/TR/CSS21/text.html#propdef-text-transform
+ switch (strtolower($style->text_transform)) {
+ default:
+ break;
+ case "capitalize":
+ $text = mb_convert_case($text, MB_CASE_TITLE);
+ break;
+ case "uppercase":
+ $text = mb_convert_case($text, MB_CASE_UPPER);
+ break;
+ case "lowercase":
+ $text = mb_convert_case($text, MB_CASE_LOWER);
+ break;
+ }
+
+ // Handle white-space property:
+ // http://www.w3.org/TR/CSS21/text.html#propdef-white-space
+ switch ($style->white_space) {
+
+ default:
+ case "normal":
+ $frame->set_text($text = $this->_collapse_white_space($text));
+ if ($text == "")
+ break;
+
+ $split = $this->_line_break($text);
+ break;
+
+ case "pre":
+ $split = $this->_newline_break($text);
+ $add_line = $split !== false;
+ break;
+
+ case "nowrap":
+ $frame->set_text($text = $this->_collapse_white_space($text));
+ break;
+
+ case "pre-wrap":
+ $split = $this->_newline_break($text);
+
+ if (($tmp = $this->_line_break($text)) !== false) {
+ $add_line = $split < $tmp;
+ $split = min($tmp, $split);
+ } else
+ $add_line = true;
+
+ break;
+
+ case "pre-line":
+ // Collapse white-space except for \n
+ $frame->set_text($text = preg_replace("/[ \t]+/u", " ", $text));
+
+ if ($text == "")
+ break;
+
+ $split = $this->_newline_break($text);
+
+ if (($tmp = $this->_line_break($text)) !== false) {
+ $add_line = $split < $tmp;
+ $split = min($tmp, $split);
+ } else
+ $add_line = true;
+
+ break;
+
+ }
+
+ // Handle degenerate case
+ if ($text === "")
+ return;
+
+ if ($split !== false) {
+
+ // Handle edge cases
+ if ($split == 0 && $text === " ") {
+ $frame->set_text("");
+ return;
+ }
+
+ if ($split == 0) {
+
+ // Trim newlines from the beginning of the line
+ //$this->_frame->set_text(ltrim($text, "\n\r"));
+
+ $this->_block_parent->add_line();
+ $frame->position();
+
+ // Layout the new line
+ $this->_layout_line();
+
+ } else if ($split < mb_strlen($frame->get_text())) {
+ // split the line if required
+ $frame->split_text($split);
+
+ $t = $frame->get_text();
+
+ // Remove any trailing newlines
+ if ($split > 1 && $t[$split - 1] === "\n" && !$frame->is_pre())
+ $frame->set_text(mb_substr($t, 0, -1));
+
+ // Do we need to trim spaces on wrapped lines? This might be desired, however, we
+ // can't trim the lines here or the layout will be affected if trimming the line
+ // leaves enough space to fit the next word in the text stream (because pdf layout
+ // is performed elsewhere).
+ /*if (!$this->_frame->get_prev_sibling() && !$this->_frame->get_next_sibling()) {
+ $t = $this->_frame->get_text();
+ $this->_frame->set_text( trim($t) );
+ }*/
+ }
+
+ if ($add_line) {
+ $this->_block_parent->add_line();
+ $frame->position();
+ }
+
+ } else {
+
+ // Remove empty space from start and end of line, but only where there isn't an inline sibling
+ // and the parent node isn't an inline element with siblings
+ // FIXME: Include non-breaking spaces?
+ $t = $frame->get_text();
+ $parent = $frame->get_parent();
+ $is_inline_frame = get_class($parent) === 'Inline_Frame_Decorator';
+
+ if ((!$is_inline_frame && !$frame->get_next_sibling()) /* ||
+ ( $is_inline_frame && !$parent->get_next_sibling())*/
+ ) { // fails BOLD UNDERLINED becomes BOLDUNDERLINED
+ $t = rtrim($t);
+ }
+
+ if ((!$is_inline_frame && !$frame->get_prev_sibling()) /* ||
+ ( $is_inline_frame && !$parent->get_prev_sibling())*/
+ ) { // AB C fails (the whitespace is removed)
+ $t = ltrim($t);
+ }
+
+ $frame->set_text($t);
+
+ }
+
+ // Set our new width
+ $width = $frame->recalculate_width();
+ }
+
+ //........................................................................
+
+ function reflow(BlockFrameDecorator $block = null)
+ {
+ $frame = $this->_frame;
+ $page = $frame->get_root();
+ $page->check_forced_page_break($this->_frame);
+
+ if ($page->is_full())
+ return;
+
+ $this->_block_parent = /*isset($block) ? $block : */
+ $frame->find_block_parent();
+
+ // Left trim the text if this is the first text on the line and we're
+ // collapsing white space
+// if ( $this->_block_parent->get_current_line()->w == 0 &&
+// ($frame->get_style()->white_space !== "pre" ||
+// $frame->get_style()->white_space !== "pre-wrap") ) {
+// $frame->set_text( ltrim( $frame->get_text() ) );
+// }
+
+ $frame->position();
+
+ $this->_layout_line();
+
+ if ($block) {
+ $block->add_frame_to_line($frame);
+ }
+ }
+
+ //........................................................................
+
+ // Returns an array(0 => min, 1 => max, "min" => min, "max" => max) of the
+ // minimum and maximum widths of this frame
+ function get_min_max_width()
+ {
+ /*if ( !is_null($this->_min_max_cache) )
+ return $this->_min_max_cache;*/
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+ $this->_block_parent = $frame->find_block_parent();
+ $line_width = $frame->get_containing_block("w");
+
+ $str = $text = $frame->get_text();
+ $size = $style->font_size;
+ $font = $style->font_family;
+
+ $word_spacing = $style->length_in_pt($style->word_spacing);
+ $char_spacing = $style->length_in_pt($style->letter_spacing);
+
+ switch ($style->white_space) {
+
+ default:
+ case "normal":
+ $str = preg_replace(self::$_whitespace_pattern, " ", $str);
+ case "pre-wrap":
+ case "pre-line":
+
+ // Find the longest word (i.e. minimum length)
+
+ // This technique (using arrays & an anonymous function) is actually
+ // faster than doing a single-pass character by character scan. Heh,
+ // yes I took the time to bench it ;)
+ $words = array_flip(preg_split("/[\s-]+/u", $str, -1, PREG_SPLIT_DELIM_CAPTURE));
+ $root = $this;
+ array_walk($words, function(&$val, $str) use ($font, $size, $word_spacing, $char_spacing, $root) {
+ $val = $root->getFontMetrics()->getTextWidth($str, $font, $size, $word_spacing, $char_spacing);
+ });
+
+ arsort($words);
+ $min = reset($words);
+ break;
+
+ case "pre":
+ $lines = array_flip(preg_split("/\n/u", $str));
+ $root = $this;
+ array_walk($lines, function(&$val, $str) use ($font, $size, $word_spacing, $char_spacing, $root) {
+ $val = $root->getFontMetrics()->getTextWidth($str, $font, $size, $word_spacing, $char_spacing);
+ });
+
+ arsort($lines);
+ $min = reset($lines);
+ break;
+
+ case "nowrap":
+ $min = $this->getFontMetrics()->getTextWidth($this->_collapse_white_space($str), $font, $size, $word_spacing, $char_spacing);
+ break;
+
+ }
+
+ switch ($style->white_space) {
+
+ default:
+ case "normal":
+ case "nowrap":
+ $str = preg_replace(self::$_whitespace_pattern, " ", $text);
+ break;
+
+ case "pre-line":
+ //XXX: Is this correct?
+ $str = preg_replace("/[ \t]+/u", " ", $text);
+
+ case "pre-wrap":
+ // Find the longest word (i.e. minimum length)
+ $lines = array_flip(preg_split("/\n/", $text));
+ $root = $this;
+ array_walk($lines, function(&$val, $str) use ($font, $size, $word_spacing, $char_spacing, $root) {
+ $val = $root->getFontMetrics()->getTextWidth($str, $font, $size, $word_spacing, $char_spacing);
+ });
+ arsort($lines);
+ reset($lines);
+ $str = key($lines);
+ break;
+
+ }
+
+ $max = $this->getFontMetrics()->getTextWidth($str, $font, $size, $word_spacing, $char_spacing);
+
+ $delta = $style->length_in_pt(array($style->margin_left,
+ $style->border_left_width,
+ $style->padding_left,
+ $style->padding_right,
+ $style->border_right_width,
+ $style->margin_right), $line_width);
+ $min += $delta;
+ $max += $delta;
+
+ return $this->_min_max_cache = array($min, $max, "min" => $min, "max" => $max);
+
+ }
+
+ /**
+ * @param FontMetrics $fontMetrics
+ * @return $this
+ */
+ public function setFontMetrics(FontMetrics $fontMetrics)
+ {
+ $this->fontMetrics = $fontMetrics;
+ return $this;
+ }
+
+ /**
+ * @return FontMetrics
+ */
+ public function getFontMetrics()
+ {
+ return $this->fontMetrics;
+ }
+}
diff --git a/library/vendor/dompdf/src/Helpers.php b/library/vendor/dompdf/src/Helpers.php
new file mode 100644
index 000000000..5b19f6812
--- /dev/null
+++ b/library/vendor/dompdf/src/Helpers.php
@@ -0,0 +1,733 @@
+ tags if the current sapi is not 'cli'.
+ * Returns the output string instead of displaying it if $return is true.
+ *
+ * @param mixed $mixed variable or expression to display
+ * @param bool $return
+ *
+ * @return string
+ */
+ public static function pre_r($mixed, $return = false)
+ {
+ if ($return) {
+ return "" . print_r($mixed, true) . " ";
+ }
+
+ if (php_sapi_name() !== "cli") {
+ echo "";
+ }
+
+ print_r($mixed);
+
+ if (php_sapi_name() !== "cli") {
+ echo " ";
+ } else {
+ echo "\n";
+ }
+
+ flush();
+ }
+
+ /**
+ * builds a full url given a protocol, hostname, base path and url
+ *
+ * @param string $protocol
+ * @param string $host
+ * @param string $base_path
+ * @param string $url
+ * @return string
+ *
+ * Initially the trailing slash of $base_path was optional, and conditionally appended.
+ * However on dynamically created sites, where the page is given as url parameter,
+ * the base path might not end with an url.
+ * Therefore do not append a slash, and **require** the $base_url to ending in a slash
+ * when needed.
+ * Vice versa, on using the local file system path of a file, make sure that the slash
+ * is appended (o.k. also for Windows)
+ */
+ public static function build_url($protocol, $host, $base_path, $url)
+ {
+ $protocol = mb_strtolower($protocol);
+ if (strlen($url) == 0) {
+ //return $protocol . $host . rtrim($base_path, "/\\") . "/";
+ return $protocol . $host . $base_path;
+ }
+
+ // Is the url already fully qualified, a Data URI, or a reference to a named anchor?
+ if (mb_strpos($url, "://") !== false || mb_substr($url, 0, 1) === "#" || mb_strpos($url, "data:") === 0 || mb_strpos($url, "mailto:") === 0) {
+ return $url;
+ }
+
+ $ret = $protocol;
+
+ if (!in_array(mb_strtolower($protocol), array("http://", "https://", "ftp://", "ftps://"))) {
+ //On Windows local file, an abs path can begin also with a '\' or a drive letter and colon
+ //drive: followed by a relative path would be a drive specific default folder.
+ //not known in php app code, treat as abs path
+ //($url[1] !== ':' || ($url[2]!=='\\' && $url[2]!=='/'))
+ if ($url[0] !== '/' && (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' || ($url[0] !== '\\' && $url[1] !== ':'))) {
+ // For rel path and local acess we ignore the host, and run the path through realpath()
+ $ret .= realpath($base_path) . '/';
+ }
+ $ret .= $url;
+ $ret = preg_replace('/\?(.*)$/', "", $ret);
+ return $ret;
+ }
+
+ // Protocol relative urls (e.g. "//example.org/style.css")
+ if (strpos($url, '//') === 0) {
+ $ret .= substr($url, 2);
+ //remote urls with backslash in html/css are not really correct, but lets be genereous
+ } elseif ($url[0] === '/' || $url[0] === '\\') {
+ // Absolute path
+ $ret .= $host . $url;
+ } else {
+ // Relative path
+ //$base_path = $base_path !== "" ? rtrim($base_path, "/\\") . "/" : "";
+ $ret .= $host . $base_path . $url;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Converts decimal numbers to roman numerals
+ *
+ * @param int $num
+ *
+ * @throws Exception
+ * @return string
+ */
+ public static function dec2roman($num)
+ {
+
+ static $ones = array("", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix");
+ static $tens = array("", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc");
+ static $hund = array("", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm");
+ static $thou = array("", "m", "mm", "mmm");
+
+ if (!is_numeric($num)) {
+ throw new Exception("dec2roman() requires a numeric argument.");
+ }
+
+ if ($num > 4000 || $num < 0) {
+ return "(out of range)";
+ }
+
+ $num = strrev((string)$num);
+
+ $ret = "";
+ switch (mb_strlen($num)) {
+ case 4:
+ $ret .= $thou[$num[3]];
+ case 3:
+ $ret .= $hund[$num[2]];
+ case 2:
+ $ret .= $tens[$num[1]];
+ case 1:
+ $ret .= $ones[$num[0]];
+ default:
+ break;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Determines whether $value is a percentage or not
+ *
+ * @param float $value
+ *
+ * @return bool
+ */
+ public static function is_percent($value)
+ {
+ return false !== mb_strpos($value, "%");
+ }
+
+ /**
+ * Parses a data URI scheme
+ * http://en.wikipedia.org/wiki/Data_URI_scheme
+ *
+ * @param string $data_uri The data URI to parse
+ *
+ * @return array The result with charset, mime type and decoded data
+ */
+ public static function parse_data_uri($data_uri)
+ {
+ if (!preg_match('/^data:(?P[a-z0-9\/+-.]+)(;charset=(?P[a-z0-9-])+)?(?P;base64)?\,(?P.*)?/is', $data_uri, $match)) {
+ return false;
+ }
+
+ $match['data'] = rawurldecode($match['data']);
+ $result = array(
+ 'charset' => $match['charset'] ? $match['charset'] : 'US-ASCII',
+ 'mime' => $match['mime'] ? $match['mime'] : 'text/plain',
+ 'data' => $match['base64'] ? base64_decode($match['data']) : $match['data'],
+ );
+
+ return $result;
+ }
+
+ /**
+ * Decoder for RLE8 compression in windows bitmaps
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
+ *
+ * @param string $str Data to decode
+ * @param integer $width Image width
+ *
+ * @return string
+ */
+ public static function rle8_decode($str, $width)
+ {
+ $lineWidth = $width + (3 - ($width - 1) % 4);
+ $out = '';
+ $cnt = strlen($str);
+
+ for ($i = 0; $i < $cnt; $i++) {
+ $o = ord($str[$i]);
+ switch ($o) {
+ case 0: # ESCAPE
+ $i++;
+ switch (ord($str[$i])) {
+ case 0: # NEW LINE
+ $padCnt = $lineWidth - strlen($out) % $lineWidth;
+ if ($padCnt < $lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
+ break;
+ case 1: # END OF FILE
+ $padCnt = $lineWidth - strlen($out) % $lineWidth;
+ if ($padCnt < $lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
+ break 3;
+ case 2: # DELTA
+ $i += 2;
+ break;
+ default: # ABSOLUTE MODE
+ $num = ord($str[$i]);
+ for ($j = 0; $j < $num; $j++)
+ $out .= $str[++$i];
+ if ($num % 2) $i++;
+ }
+ break;
+ default:
+ $out .= str_repeat($str[++$i], $o);
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Decoder for RLE4 compression in windows bitmaps
+ * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
+ *
+ * @param string $str Data to decode
+ * @param integer $width Image width
+ *
+ * @return string
+ */
+ public static function rle4_decode($str, $width)
+ {
+ $w = floor($width / 2) + ($width % 2);
+ $lineWidth = $w + (3 - (($width - 1) / 2) % 4);
+ $pixels = array();
+ $cnt = strlen($str);
+ $c = 0;
+
+ for ($i = 0; $i < $cnt; $i++) {
+ $o = ord($str[$i]);
+ switch ($o) {
+ case 0: # ESCAPE
+ $i++;
+ switch (ord($str[$i])) {
+ case 0: # NEW LINE
+ while (count($pixels) % $lineWidth != 0) {
+ $pixels[] = 0;
+ }
+ break;
+ case 1: # END OF FILE
+ while (count($pixels) % $lineWidth != 0) {
+ $pixels[] = 0;
+ }
+ break 3;
+ case 2: # DELTA
+ $i += 2;
+ break;
+ default: # ABSOLUTE MODE
+ $num = ord($str[$i]);
+ for ($j = 0; $j < $num; $j++) {
+ if ($j % 2 == 0) {
+ $c = ord($str[++$i]);
+ $pixels[] = ($c & 240) >> 4;
+ } else {
+ $pixels[] = $c & 15;
+ }
+ }
+
+ if ($num % 2 == 0) {
+ $i++;
+ }
+ }
+ break;
+ default:
+ $c = ord($str[++$i]);
+ for ($j = 0; $j < $o; $j++) {
+ $pixels[] = ($j % 2 == 0 ? ($c & 240) >> 4 : $c & 15);
+ }
+ }
+ }
+
+ $out = '';
+ if (count($pixels) % 2) {
+ $pixels[] = 0;
+ }
+
+ $cnt = count($pixels) / 2;
+
+ for ($i = 0; $i < $cnt; $i++) {
+ $out .= chr(16 * $pixels[2 * $i] + $pixels[2 * $i + 1]);
+ }
+
+ return $out;
+ }
+
+ /**
+ * parse a full url or pathname and return an array(protocol, host, path,
+ * file + query + fragment)
+ *
+ * @param string $url
+ * @return array
+ */
+ public static function explode_url($url)
+ {
+ $protocol = "";
+ $host = "";
+ $path = "";
+ $file = "";
+
+ $arr = parse_url($url);
+ if ( isset($arr["scheme"]) ) {
+ $arr["scheme"] = mb_strtolower($arr["scheme"]);
+ }
+
+ // Exclude windows drive letters...
+ if (isset($arr["scheme"]) && $arr["scheme"] !== "file" && strlen($arr["scheme"]) > 1) {
+ $protocol = $arr["scheme"] . "://";
+
+ if (isset($arr["user"])) {
+ $host .= $arr["user"];
+
+ if (isset($arr["pass"])) {
+ $host .= ":" . $arr["pass"];
+ }
+
+ $host .= "@";
+ }
+
+ if (isset($arr["host"])) {
+ $host .= $arr["host"];
+ }
+
+ if (isset($arr["port"])) {
+ $host .= ":" . $arr["port"];
+ }
+
+ if (isset($arr["path"]) && $arr["path"] !== "") {
+ // Do we have a trailing slash?
+ if ($arr["path"][mb_strlen($arr["path"]) - 1] === "/") {
+ $path = $arr["path"];
+ $file = "";
+ } else {
+ $path = rtrim(dirname($arr["path"]), '/\\') . "/";
+ $file = basename($arr["path"]);
+ }
+ }
+
+ if (isset($arr["query"])) {
+ $file .= "?" . $arr["query"];
+ }
+
+ if (isset($arr["fragment"])) {
+ $file .= "#" . $arr["fragment"];
+ }
+
+ } else {
+
+ $i = mb_stripos($url, "file://");
+ if ($i !== false) {
+ $url = mb_substr($url, $i + 7);
+ }
+
+ $protocol = ""; // "file://"; ? why doesn't this work... It's because of
+ // network filenames like //COMPU/SHARENAME
+
+ $host = ""; // localhost, really
+ $file = basename($url);
+
+ $path = dirname($url);
+
+ // Check that the path exists
+ if ($path !== false) {
+ $path .= '/';
+
+ } else {
+ // generate a url to access the file if no real path found.
+ $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
+
+ $host = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : php_uname("n");
+
+ if (substr($arr["path"], 0, 1) === '/') {
+ $path = dirname($arr["path"]);
+ } else {
+ $path = '/' . rtrim(dirname($_SERVER["SCRIPT_NAME"]), '/') . '/' . $arr["path"];
+ }
+ }
+ }
+
+ $ret = array($protocol, $host, $path, $file,
+ "protocol" => $protocol,
+ "host" => $host,
+ "path" => $path,
+ "file" => $file);
+ return $ret;
+ }
+
+ /**
+ * Print debug messages
+ *
+ * @param string $type The type of debug messages to print
+ * @param string $msg The message to show
+ */
+ public static function dompdf_debug($type, $msg)
+ {
+ global $_DOMPDF_DEBUG_TYPES, $_dompdf_show_warnings, $_dompdf_debug;
+ if (isset($_DOMPDF_DEBUG_TYPES[$type]) && ($_dompdf_show_warnings || $_dompdf_debug)) {
+ $arr = debug_backtrace();
+
+ echo basename($arr[0]["file"]) . " (" . $arr[0]["line"] . "): " . $arr[1]["function"] . ": ";
+ Helpers::pre_r($msg);
+ }
+ }
+
+ /**
+ * Stores warnings in an array for display later
+ * This function allows warnings generated by the DomDocument parser
+ * and CSS loader ({@link Stylesheet}) to be captured and displayed
+ * later. Without this function, errors are displayed immediately and
+ * PDF streaming is impossible.
+ * @see http://www.php.net/manual/en/function.set-error_handler.php
+ *
+ * @param int $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param string $errline
+ *
+ * @throws Exception
+ */
+ public static function record_warnings($errno, $errstr, $errfile, $errline)
+ {
+ // Not a warning or notice
+ if (!($errno & (E_WARNING | E_NOTICE | E_USER_NOTICE | E_USER_WARNING))) {
+ throw new Exception($errstr . " $errno");
+ }
+
+ global $_dompdf_warnings;
+ global $_dompdf_show_warnings;
+
+ if ($_dompdf_show_warnings) {
+ echo $errstr . "\n";
+ }
+
+ $_dompdf_warnings[] = $errstr;
+ }
+
+ /**
+ * @param $c
+ * @return bool|string
+ */
+ public static function unichr($c)
+ {
+ if ($c <= 0x7F) {
+ return chr($c);
+ } else if ($c <= 0x7FF) {
+ return chr(0xC0 | $c >> 6) . chr(0x80 | $c & 0x3F);
+ } else if ($c <= 0xFFFF) {
+ return chr(0xE0 | $c >> 12) . chr(0x80 | $c >> 6 & 0x3F)
+ . chr(0x80 | $c & 0x3F);
+ } else if ($c <= 0x10FFFF) {
+ return chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F)
+ . chr(0x80 | $c >> 6 & 0x3F)
+ . chr(0x80 | $c & 0x3F);
+ }
+ return false;
+ }
+
+ /**
+ * Converts a CMYK color to RGB
+ *
+ * @param float|float[] $c
+ * @param float $m
+ * @param float $y
+ * @param float $k
+ *
+ * @return float[]
+ */
+ public static function cmyk_to_rgb($c, $m = null, $y = null, $k = null)
+ {
+ if (is_array($c)) {
+ list($c, $m, $y, $k) = $c;
+ }
+
+ $c *= 255;
+ $m *= 255;
+ $y *= 255;
+ $k *= 255;
+
+ $r = (1 - round(2.55 * ($c + $k)));
+ $g = (1 - round(2.55 * ($m + $k)));
+ $b = (1 - round(2.55 * ($y + $k)));
+
+ if ($r < 0) $r = 0;
+ if ($g < 0) $g = 0;
+ if ($b < 0) $b = 0;
+
+ return array(
+ $r, $g, $b,
+ "r" => $r, "g" => $g, "b" => $b
+ );
+ }
+
+ /**
+ * getimagesize doesn't give a good size for 32bit BMP image v5
+ *
+ * @param string $filename
+ * @return array The same format as getimagesize($filename)
+ */
+ public static function dompdf_getimagesize($filename, $context = null)
+ {
+ static $cache = array();
+
+ if (isset($cache[$filename])) {
+ return $cache[$filename];
+ }
+
+ list($width, $height, $type) = getimagesize($filename);
+
+ // Custom types
+ $types = array(
+ IMAGETYPE_JPEG => "jpeg",
+ IMAGETYPE_GIF => "gif",
+ IMAGETYPE_BMP => "bmp",
+ IMAGETYPE_PNG => "png",
+ );
+
+ $type = isset($types[$type]) ? $types[$type] : null;
+
+ if ($width == null || $height == null) {
+ $data = file_get_contents($filename, null, $context, 0, 26);
+
+ if (substr($data, 0, 2) === "BM") {
+ $meta = unpack('vtype/Vfilesize/Vreserved/Voffset/Vheadersize/Vwidth/Vheight', $data);
+ $width = (int)$meta['width'];
+ $height = (int)$meta['height'];
+ $type = "bmp";
+ }
+ else {
+ if (strpos(file_get_contents($filename), "loadFile($filename);
+
+ list($width, $height) = $doc->getDimensions();
+ $type = "svg";
+ }
+ }
+
+ }
+
+ return $cache[$filename] = array($width, $height, $type);
+ }
+
+ /**
+ * Credit goes to mgutt
+ * http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm
+ * Modified by Fabien Menager to support RGB555 BMP format
+ */
+ public static function imagecreatefrombmp($filename, $context = null)
+ {
+ if (!function_exists("imagecreatetruecolor")) {
+ trigger_error("The PHP GD extension is required, but is not installed.", E_ERROR);
+ return false;
+ }
+
+ // version 1.00
+ if (!($fh = fopen($filename, 'rb'))) {
+ trigger_error('imagecreatefrombmp: Can not open ' . $filename, E_USER_WARNING);
+ return false;
+ }
+
+ $bytes_read = 0;
+
+ // read file header
+ $meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14));
+
+ // check for bitmap
+ if ($meta['type'] != 19778) {
+ trigger_error('imagecreatefrombmp: ' . $filename . ' is not a bitmap!', E_USER_WARNING);
+ return false;
+ }
+
+ // read image header
+ $meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread($fh, 40));
+ $bytes_read += 40;
+
+ // read additional bitfield header
+ if ($meta['compression'] == 3) {
+ $meta += unpack('VrMask/VgMask/VbMask', fread($fh, 12));
+ $bytes_read += 12;
+ }
+
+ // set bytes and padding
+ $meta['bytes'] = $meta['bits'] / 8;
+ $meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4) - floor($meta['width'] * $meta['bytes'] / 4)));
+ if ($meta['decal'] == 4) {
+ $meta['decal'] = 0;
+ }
+
+ // obtain imagesize
+ if ($meta['imagesize'] < 1) {
+ $meta['imagesize'] = $meta['filesize'] - $meta['offset'];
+ // in rare cases filesize is equal to offset so we need to read physical size
+ if ($meta['imagesize'] < 1) {
+ $meta['imagesize'] = @filesize($filename) - $meta['offset'];
+ if ($meta['imagesize'] < 1) {
+ trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING);
+ return false;
+ }
+ }
+ }
+
+ // calculate colors
+ $meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors'];
+
+ // read color palette
+ $palette = array();
+ if ($meta['bits'] < 16) {
+ $palette = unpack('l' . $meta['colors'], fread($fh, $meta['colors'] * 4));
+ // in rare cases the color value is signed
+ if ($palette[1] < 0) {
+ foreach ($palette as $i => $color) {
+ $palette[$i] = $color + 16777216;
+ }
+ }
+ }
+
+ // ignore extra bitmap headers
+ if ($meta['headersize'] > $bytes_read) {
+ fread($fh, $meta['headersize'] - $bytes_read);
+ }
+
+ // create gd image
+ $im = imagecreatetruecolor($meta['width'], $meta['height']);
+ $data = fread($fh, $meta['imagesize']);
+
+ // uncompress data
+ switch ($meta['compression']) {
+ case 1:
+ $data = Helpers::rle8_decode($data, $meta['width']);
+ break;
+ case 2:
+ $data = Helpers::rle4_decode($data, $meta['width']);
+ break;
+ }
+
+ $p = 0;
+ $vide = chr(0);
+ $y = $meta['height'] - 1;
+ $error = 'imagecreatefrombmp: ' . $filename . ' has not enough data!';
+
+ // loop through the image data beginning with the lower left corner
+ while ($y >= 0) {
+ $x = 0;
+ while ($x < $meta['width']) {
+ switch ($meta['bits']) {
+ case 32:
+ case 24:
+ if (!($part = substr($data, $p, 3 /*$meta['bytes']*/))) {
+ trigger_error($error, E_USER_WARNING);
+ return $im;
+ }
+ $color = unpack('V', $part . $vide);
+ break;
+ case 16:
+ if (!($part = substr($data, $p, 2 /*$meta['bytes']*/))) {
+ trigger_error($error, E_USER_WARNING);
+ return $im;
+ }
+ $color = unpack('v', $part);
+
+ if (empty($meta['rMask']) || $meta['rMask'] != 0xf800) {
+ $color[1] = (($color[1] & 0x7c00) >> 7) * 65536 + (($color[1] & 0x03e0) >> 2) * 256 + (($color[1] & 0x001f) << 3); // 555
+ } else {
+ $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3); // 565
+ }
+ break;
+ case 8:
+ $color = unpack('n', $vide . substr($data, $p, 1));
+ $color[1] = $palette[$color[1] + 1];
+ break;
+ case 4:
+ $color = unpack('n', $vide . substr($data, floor($p), 1));
+ $color[1] = ($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F;
+ $color[1] = $palette[$color[1] + 1];
+ break;
+ case 1:
+ $color = unpack('n', $vide . substr($data, floor($p), 1));
+ switch (($p * 8) % 8) {
+ case 0:
+ $color[1] = $color[1] >> 7;
+ break;
+ case 1:
+ $color[1] = ($color[1] & 0x40) >> 6;
+ break;
+ case 2:
+ $color[1] = ($color[1] & 0x20) >> 5;
+ break;
+ case 3:
+ $color[1] = ($color[1] & 0x10) >> 4;
+ break;
+ case 4:
+ $color[1] = ($color[1] & 0x8) >> 3;
+ break;
+ case 5:
+ $color[1] = ($color[1] & 0x4) >> 2;
+ break;
+ case 6:
+ $color[1] = ($color[1] & 0x2) >> 1;
+ break;
+ case 7:
+ $color[1] = ($color[1] & 0x1);
+ break;
+ }
+ $color[1] = $palette[$color[1] + 1];
+ break;
+ default:
+ trigger_error('imagecreatefrombmp: ' . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', E_USER_WARNING);
+ return false;
+ }
+ imagesetpixel($im, $x, $y, $color[1]);
+ $x++;
+ $p += $meta['bytes'];
+ }
+ $y--;
+ $p += $meta['decal'];
+ }
+ fclose($fh);
+ return $im;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/Image/Cache.php b/library/vendor/dompdf/src/Image/Cache.php
new file mode 100644
index 000000000..8e9e70e49
--- /dev/null
+++ b/library/vendor/dompdf/src/Image/Cache.php
@@ -0,0 +1,186 @@
+
+ * @author Helmut Tischer
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Image;
+
+use Dompdf\Dompdf;
+use Dompdf\Helpers;
+use Dompdf\Exception\ImageException;
+
+/**
+ * Static class that resolves image urls and downloads and caches
+ * remote images if required.
+ *
+ * @package dompdf
+ */
+class Cache
+{
+ /**
+ * Array of downloaded images. Cached so that identical images are
+ * not needlessly downloaded.
+ *
+ * @var array
+ */
+ protected static $_cache = array();
+
+ /**
+ * The url to the "broken image" used when images can't be loaded
+ *
+ * @var string
+ */
+ public static $broken_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAAA3NCSVQICAjb4U/gAAAAHlBMVEWZmZn////g4OCkpKS1tbXv7++9vb2tra3m5ub5+fkFnN6oAAAACXBIWXMAAAsSAAALEgHS3X78AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M0BrLToAAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNC8xMi8xMRPnI58AAAGZSURBVEiJhZbPasMwDMbTw2DHKhDQcbDQPsEge4BAjg0Mxh5gkBcY7Niwkpx32PvOjv9JspX60It/+fxJsqxW1b11gN11rA7N3v6vAd5nfR9fDYCTDiyzAeA6qgKd9QDNoAtsAKyKCxzAAfhdBuyHGwC3oovNvQOaxxJwnSNg3ZQFAlBy4ax7AG6ZBLrgA5Cn038SAPgREiaJHJASwXYEhEQQIACyikTTCWCBJJoANBfpPAKQdBLHFMBYkctcBKIE9lAGggt6gRjgA2GV44CL7m1WgS08fAAdsPHxyyMAIyHujgRwEldHArCKy5cBz90+gNOyf8TTyKOUQN2LPEmgnWWPcKD+sr+rnuqTK1avAcHfRSv3afTgVAbqmCPiggLtGM8aSkBNOidVjADrmIDYebT1PoGsWJEE8Oc0b96aZoe4iMBZPiADB6RAzEUA2vwRmyiAL3Lfv6MBSEmUEg7ALt/3LhxwLgj4QNw4UCbKEsaBNpPsyRbgVRASFig78BIGyJNIJQyQTwIi0RvgT98H+Mi6W67j3X8H/427u5bfpQGVAAAAAElFTkSuQmCC";
+
+ /**
+ * Current dompdf instance
+ *
+ * @var Dompdf
+ */
+ protected static $_dompdf;
+
+ /**
+ * Resolve and fetch an image for use.
+ *
+ * @param string $url The url of the image
+ * @param string $protocol Default protocol if none specified in $url
+ * @param string $host Default host if none specified in $url
+ * @param string $base_path Default path if none specified in $url
+ * @param Dompdf $dompdf The Dompdf instance
+ *
+ * @throws ImageException
+ * @return array An array with two elements: The local path to the image and the image extension
+ */
+ static function resolve_url($url, $protocol, $host, $base_path, Dompdf $dompdf)
+ {
+ self::$_dompdf = $dompdf;
+
+ $protocol = mb_strtolower($protocol);
+ $parsed_url = Helpers::explode_url($url);
+ $message = null;
+
+ $remote = ($protocol && $protocol !== "file://") || ($parsed_url['protocol'] != "");
+
+ $data_uri = strpos($parsed_url['protocol'], "data:") === 0;
+ $full_url = null;
+ $enable_remote = $dompdf->get_option("enable_remote");
+
+ try {
+
+ // Remote not allowed and is not DataURI
+ if (!$enable_remote && $remote && !$data_uri) {
+ throw new ImageException("Remote file access is disabled.", E_WARNING);
+ } // Remote allowed or DataURI
+ else {
+ if ($enable_remote && $remote || $data_uri) {
+ // Download remote files to a temporary directory
+ $full_url = Helpers::build_url($protocol, $host, $base_path, $url);
+
+ // From cache
+ if (isset(self::$_cache[$full_url])) {
+ $resolved_url = self::$_cache[$full_url];
+ } // From remote
+ else {
+ $tmp_dir = $dompdf->get_option("temp_dir");
+ $resolved_url = tempnam($tmp_dir, "ca_dompdf_img_");
+ $image = "";
+
+ if ($data_uri) {
+ if ($parsed_data_uri = Helpers::parse_data_uri($url)) {
+ $image = $parsed_data_uri['data'];
+ }
+ } else {
+ set_error_handler(array("\\Dompdf\\Helpers", "record_warnings"));
+ $image = file_get_contents($full_url, null, $dompdf->getHttpContext());
+ restore_error_handler();
+ }
+
+ // Image not found or invalid
+ if (strlen($image) == 0) {
+ $msg = ($data_uri ? "Data-URI could not be parsed" : "Image not found");
+ throw new ImageException($msg, E_WARNING);
+ } // Image found, put in cache and process
+ else {
+ //e.g. fetch.php?media=url.jpg&cache=1
+ //- Image file name might be one of the dynamic parts of the url, don't strip off!
+ //- a remote url does not need to have a file extension at all
+ //- local cached file does not have a matching file extension
+ //Therefore get image type from the content
+ file_put_contents($resolved_url, $image);
+ }
+ }
+ } // Not remote, local image
+ else {
+ $resolved_url = Helpers::build_url($protocol, $host, $base_path, $url);
+ }
+ }
+
+ // Check if the local file is readable
+ if (!is_readable($resolved_url) || !filesize($resolved_url)) {
+ throw new ImageException("Image not readable or empty", E_WARNING);
+ } // Check is the file is an image
+ else {
+ list($width, $height, $type) = Helpers::dompdf_getimagesize($resolved_url, $dompdf->getHttpContext());
+
+ // Known image type
+ if ($width && $height && in_array($type, array("gif", "png", "jpeg", "bmp", "svg"))) {
+ //Don't put replacement image into cache - otherwise it will be deleted on cache cleanup.
+ //Only execute on successful caching of remote image.
+ if ($enable_remote && $remote || $data_uri) {
+ self::$_cache[$full_url] = $resolved_url;
+ }
+ } // Unknown image type
+ else {
+ throw new ImageException("Image type unknown", E_WARNING);
+ }
+ }
+ } catch (ImageException $e) {
+ $resolved_url = self::$broken_image;
+ $type = "png";
+ $message = "Image not found or type unknown";
+ Helpers::record_warnings($e->getCode(), $e->getMessage() . " \n $url", $e->getFile(), $e->getLine());
+ }
+
+ return array($resolved_url, $type, $message);
+ }
+
+ /**
+ * Unlink all cached images (i.e. temporary images either downloaded
+ * or converted)
+ */
+ static function clear()
+ {
+ if (empty(self::$_cache) || self::$_dompdf->get_option("debugKeepTemp")) {
+ return;
+ }
+
+ foreach (self::$_cache as $file) {
+ if (self::$_dompdf->get_option("debugPng")) {
+ print "[clear unlink $file]";
+ }
+ unlink($file);
+ }
+
+ self::$_cache = array();
+ }
+
+ static function detect_type($file, $context = null)
+ {
+ list(, , $type) = Helpers::dompdf_getimagesize($file, $context);
+
+ return $type;
+ }
+
+ static function is_broken($url)
+ {
+ return $url === self::$broken_image;
+ }
+}
+
+if (file_exists(realpath(__DIR__ . "/../../lib/res/broken_image.png"))) {
+ Cache::$broken_image = realpath(__DIR__ . "/../../lib/res/broken_image.png");
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/JavascriptEmbedder.php b/library/vendor/dompdf/src/JavascriptEmbedder.php
new file mode 100644
index 000000000..1463f2315
--- /dev/null
+++ b/library/vendor/dompdf/src/JavascriptEmbedder.php
@@ -0,0 +1,43 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf;
+
+use Dompdf\Frame;
+
+/**
+ * Embeds Javascript into the PDF document
+ *
+ * @package dompdf
+ */
+class JavascriptEmbedder
+{
+
+ /**
+ * @var Dompdf
+ */
+ protected $_dompdf;
+
+ function __construct(Dompdf $dompdf)
+ {
+ $this->_dompdf = $dompdf;
+ }
+
+ function insert($script)
+ {
+ $this->_dompdf->get_canvas()->javascript($script);
+ }
+
+ function render(Frame $frame)
+ {
+ if (!$this->_dompdf->get_option("enable_javascript")) {
+ return;
+ }
+
+ $this->insert($frame->get_node()->nodeValue);
+ }
+}
diff --git a/library/vendor/dompdf/src/LineBox.php b/library/vendor/dompdf/src/LineBox.php
new file mode 100644
index 000000000..b94e08917
--- /dev/null
+++ b/library/vendor/dompdf/src/LineBox.php
@@ -0,0 +1,260 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf;
+
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Block;
+use Dompdf\FrameDecorator\Page;
+
+/**
+ * The line box class
+ *
+ * This class represents a line box
+ * http://www.w3.org/TR/CSS2/visuren.html#line-box
+ *
+ * @package dompdf
+ */
+class LineBox
+{
+
+ /**
+ * @var Block
+ */
+ protected $_block_frame;
+
+ /**
+ * @var Frame[]
+ */
+ protected $_frames = array();
+
+ /**
+ * @var integer
+ */
+ public $wc = 0;
+
+ /**
+ * @var float
+ */
+ public $y = null;
+
+ /**
+ * @var float
+ */
+ public $w = 0.0;
+
+ /**
+ * @var float
+ */
+ public $h = 0.0;
+
+ /**
+ * @var float
+ */
+ public $left = 0.0;
+
+ /**
+ * @var float
+ */
+ public $right = 0.0;
+
+ /**
+ * @var Frame
+ */
+ public $tallest_frame = null;
+
+ /**
+ * @var bool[]
+ */
+ public $floating_blocks = array();
+
+ /**
+ * @var bool
+ */
+ public $br = false;
+
+ /**
+ * Class constructor
+ *
+ * @param Block $frame the Block containing this line
+ */
+ function __construct(Block $frame, $y = 0)
+ {
+ $this->_block_frame = $frame;
+ $this->_frames = array();
+ $this->y = $y;
+
+ $this->get_float_offsets();
+ }
+
+ /**
+ * Returns the floating elements inside the first floating parent
+ *
+ * @param Page $root
+ *
+ * @return Frame[]
+ */
+ function get_floats_inside(Page $root)
+ {
+ $floating_frames = $root->get_floating_frames();
+
+ if (count($floating_frames) == 0) {
+ return $floating_frames;
+ }
+
+ // Find nearest floating element
+ $p = $this->_block_frame;
+ while ($p->get_style()->float === "none") {
+ $parent = $p->get_parent();
+
+ if (!$parent) {
+ break;
+ }
+
+ $p = $parent;
+ }
+
+ if ($p == $root) {
+ return $floating_frames;
+ }
+
+ $parent = $p;
+
+ $childs = array();
+
+ foreach ($floating_frames as $_floating) {
+ $p = $_floating->get_parent();
+
+ while (($p = $p->get_parent()) && $p !== $parent) ;
+
+ if ($p) {
+ $childs[] = $p;
+ }
+ }
+
+ return $childs;
+ }
+
+ function get_float_offsets()
+ {
+ static $anti_infinite_loop = 500; // FIXME smelly hack
+
+ $reflower = $this->_block_frame->get_reflower();
+
+ if (!$reflower) {
+ return;
+ }
+
+ $cb_w = null;
+
+ $block = $this->_block_frame;
+ $root = $block->get_root();
+
+ if (!$root) {
+ return;
+ }
+
+ $floating_frames = $this->get_floats_inside($root);
+
+ foreach ($floating_frames as $child_key => $floating_frame) {
+ $id = $floating_frame->get_id();
+
+ if (isset($this->floating_blocks[$id])) {
+ continue;
+ }
+
+ $floating_style = $floating_frame->get_style();
+ $float = $floating_style->float;
+
+ $floating_width = $floating_frame->get_margin_width();
+
+ if (!$cb_w) {
+ $cb_w = $floating_frame->get_containing_block("w");
+ }
+
+ $line_w = $this->get_width();
+
+ if (!$floating_frame->_float_next_line && ($cb_w <= $line_w + $floating_width) && ($cb_w > $line_w)) {
+ $floating_frame->_float_next_line = true;
+ continue;
+ }
+
+ // If the child is still shifted by the floating element
+ if ($anti_infinite_loop-- > 0 &&
+ $floating_frame->get_position("y") + $floating_frame->get_margin_height() > $this->y &&
+ $block->get_position("x") + $block->get_margin_width() > $floating_frame->get_position("x")
+ ) {
+ if ($float === "left") {
+ $this->left += $floating_width;
+ } else {
+ $this->right += $floating_width;
+ }
+
+ $this->floating_blocks[$id] = true;
+ } // else, the floating element won't shift anymore
+ else {
+ $root->remove_floating_frame($child_key);
+ }
+ }
+ }
+
+ /**
+ * @return float
+ */
+ function get_width()
+ {
+ return $this->left + $this->w + $this->right;
+ }
+
+ /**
+ * @return Block
+ */
+ function get_block_frame()
+ {
+ return $this->_block_frame;
+ }
+
+ /**
+ * @return Frame[]
+ */
+ function &get_frames()
+ {
+ return $this->_frames;
+ }
+
+ /**
+ * @param Frame $frame
+ */
+ function add_frame(Frame $frame)
+ {
+ $this->_frames[] = $frame;
+ }
+
+ function __toString()
+ {
+ $props = array("wc", "y", "w", "h", "left", "right", "br");
+ $s = "";
+ foreach ($props as $prop) {
+ $s .= "$prop: " . $this->$prop . "\n";
+ }
+ $s .= count($this->_frames) . " frames\n";
+
+ return $s;
+ }
+ /*function __get($prop) {
+ if (!isset($this->{"_$prop"})) return;
+ return $this->{"_$prop"};
+ }*/
+}
+
+/*
+class LineBoxList implements Iterator {
+ private $_p = 0;
+ private $_lines = array();
+
+}
+*/
diff --git a/library/vendor/dompdf/src/Options.php b/library/vendor/dompdf/src/Options.php
new file mode 100644
index 000000000..d46914517
--- /dev/null
+++ b/library/vendor/dompdf/src/Options.php
@@ -0,0 +1,974 @@
+ ... tags.
+ *
+ * ==== IMPORTANT ====
+ * Enabling this for documents you do not trust (e.g. arbitrary remote html
+ * pages) is a security risk. Embedded scripts are run with the same level of
+ * system access available to dompdf. Set this option to false (recommended)
+ * if you wish to process untrusted documents.
+ *
+ * This setting may increase the risk of system exploit. Do not change
+ * this settings without understanding the consequences. Additional
+ * documentation is available on the dompdf wiki at:
+ * https://github.com/dompdf/dompdf/wiki
+ *
+ * @var bool
+ */
+ private $isPhpEnabled = false;
+
+ /**
+ * Enable remote file access
+ *
+ * If this setting is set to true, DOMPDF will access remote sites for
+ * images and CSS files as required.
+ *
+ * ==== IMPORTANT ====
+ * This can be a security risk, in particular in combination with isPhpEnabled and
+ * allowing remote html code to be passed to $dompdf = new DOMPDF(); $dompdf->load_html(...);
+ * This allows anonymous users to download legally doubtful internet content which on
+ * tracing back appears to being downloaded by your server, or allows malicious php code
+ * in remote html pages to be executed by your server with your account privileges.
+ *
+ * This setting may increase the risk of system exploit. Do not change
+ * this settings without understanding the consequences. Additional
+ * documentation is available on the dompdf wiki at:
+ * https://github.com/dompdf/dompdf/wiki
+ *
+ * @var bool
+ */
+ private $isRemoteEnabled = false;
+
+ /**
+ * Enable inline Javascript
+ *
+ * If this setting is set to true then DOMPDF will automatically insert
+ * JavaScript code contained within tags.
+ *
+ * @var bool
+ */
+ private $isJavascriptEnabled = true;
+
+ /**
+ * Use the more-than-experimental HTML5 Lib parser
+ *
+ * @var bool
+ */
+ private $isHtml5ParserEnabled = false;
+
+ /**
+ * Whether to enable font subsetting or not.
+ *
+ * @var is_bool
+ */
+ private $isFontSubsettingEnabled = false;
+
+ /**
+ * @var bool
+ */
+ private $debugPng = false;
+
+ /**
+ * @var bool
+ */
+ private $debugKeepTemp = false;
+
+ /**
+ * @var bool
+ */
+ private $debugCss = false;
+
+ /**
+ * @var bool
+ */
+ private $debugLayout = false;
+
+ /**
+ * @var bool
+ */
+ private $debugLayoutLines = true;
+
+ /**
+ * @var bool
+ */
+ private $debugLayoutBlocks = true;
+
+ /**
+ * @var bool
+ */
+ private $debugLayoutInline = true;
+
+ /**
+ * @var bool
+ */
+ private $debugLayoutPaddingBox = true;
+
+ /**
+ * The PDF rendering backend to use
+ *
+ * Valid settings are 'PDFLib', 'CPDF', 'GD', and 'auto'. 'auto' will
+ * look for PDFLib and use it if found, or if not it will fall back on
+ * CPDF. 'GD' renders PDFs to graphic files. {@link Dompdf\CanvasFactory}
+ * ultimately determines which rendering class to instantiate
+ * based on this setting.
+ *
+ * @var string
+ */
+ private $pdfBackend = "CPDF";
+
+ /**
+ * PDFlib license key
+ *
+ * If you are using a licensed, commercial version of PDFlib, specify
+ * your license key here. If you are using PDFlib-Lite or are evaluating
+ * the commercial version of PDFlib, comment out this setting.
+ *
+ * @link http://www.pdflib.com
+ *
+ * If pdflib present in web server and auto or selected explicitely above,
+ * a real license code must exist!
+ *
+ * @var string
+ */
+ private $pdflibLicense = "";
+
+ /**
+ * @var string
+ * @deprecated
+ */
+ private $adminUsername = "user";
+
+ /**
+ * @var string
+ * @deprecated
+ */
+ private $adminPassword = "password";
+
+ /**
+ * @param array $attributes
+ */
+ public function __construct(array $attributes = null)
+ {
+ $this->setChroot(realpath(__DIR__ . "/../"));
+ $this->setRootDir($this->getChroot());
+ $this->setTempDir(sys_get_temp_dir());
+ $this->setFontDir($this->chroot . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "fonts");
+ $this->setFontCache($this->getFontDir());
+ $this->setLogOutputFile($this->getTempDir() . DIRECTORY_SEPARATOR . "log.htm");
+
+ if (null !== $attributes) {
+ $this->set($attributes);
+ }
+ }
+
+ /**
+ * @param array|string $attributes
+ * @param null|mixed $value
+ * @return $this
+ */
+ public function set($attributes, $value = null)
+ {
+ if (!is_array($attributes)) {
+ $attributes = array($attributes => $value);
+ }
+ foreach ($attributes as $key => $value) {
+ if ($key === 'tempDir' || $key === 'temp_dir') {
+ $this->setTempDir($value);
+ } elseif ($key === 'fontDir' || $key === 'font_dir') {
+ $this->setFontDir($value);
+ } elseif ($key === 'fontCache' || $key === 'font_cache') {
+ $this->setFontCache($value);
+ } elseif ($key === 'chroot') {
+ $this->setChroot($value);
+ } elseif ($key === 'logOutputFile' || $key === 'log_output_file') {
+ $this->setLogOutputFile($value);
+ } elseif ($key === 'defaultMediaType' || $key === 'default_media_type') {
+ $this->setDefaultMediaType($value);
+ } elseif ($key === 'defaultPaperSize' || $key === 'default_paper_size') {
+ $this->setDefaultPaperSize($value);
+ } elseif ($key === 'defaultFont' || $key === 'default_font') {
+ $this->setDefaultFont($value);
+ } elseif ($key === 'dpi') {
+ $this->setDpi($value);
+ } elseif ($key === 'fontHeightRatio' || $key === 'font_height_ratio') {
+ $this->setFontHeightRatio($value);
+ } elseif ($key === 'isPhpEnabled' || $key === 'is_php_enabled' || $key === 'enable_php') {
+ $this->setIsPhpEnabled($value);
+ } elseif ($key === 'isRemoteEnabled' || $key === 'is_remote_enabled' || $key === 'enable_remote') {
+ $this->setIsRemoteEnabled($value);
+ } elseif ($key === 'isJavascriptEnabled' || $key === 'is_javascript_enabled' || $key === 'enable_javascript') {
+ $this->setIsJavascriptEnabled($value);
+ } elseif ($key === 'isHtml5ParserEnabled' || $key === 'is_html5_parser_enabled' || $key === 'enable_html5_parser') {
+ $this->setIsHtml5ParserEnabled($value);
+ } elseif ($key === 'isFontSubsettingEnabled' || $key === 'is_font_subsetting_enabled' || $key === 'enable_font_subsetting') {
+ $this->setIsFontSubsettingEnabled($value);
+ } elseif ($key === 'debugPng' || $key === 'debug_png') {
+ $this->setDebugPng($value);
+ } elseif ($key === 'debugKeepTemp' || $key === 'debug_keep_temp') {
+ $this->setDebugKeepTemp($value);
+ } elseif ($key === 'debugCss' || $key === 'debug_css') {
+ $this->setDebugCss($value);
+ } elseif ($key === 'debugLayout' || $key === 'debug_layout') {
+ $this->setDebugLayout($value);
+ } elseif ($key === 'debugLayoutLines' || $key === 'debug_layout_lines') {
+ $this->setDebugLayoutLines($value);
+ } elseif ($key === 'debugLayoutBlocks' || $key === 'debug_layout_blocks') {
+ $this->setDebugLayoutBlocks($value);
+ } elseif ($key === 'debugLayoutInline' || $key === 'debug_layout_inline') {
+ $this->setDebugLayoutInline($value);
+ } elseif ($key === 'debugLayoutPaddingBox' || $key === 'debug_layout_padding_box') {
+ $this->setDebugLayoutPaddingBox($value);
+ } elseif ($key === 'pdfBackend' || $key === 'pdf_backend') {
+ $this->setPdfBackend($value);
+ } elseif ($key === 'pdflibLicense' || $key === 'pdflib_license') {
+ $this->setPdflibLicense($value);
+ } elseif ($key === 'adminUsername' || $key === 'admin_username') {
+ $this->setAdminUsername($value);
+ } elseif ($key === 'adminPassword' || $key === 'admin_password') {
+ $this->setAdminPassword($value);
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ public function get($key)
+ {
+ if ($key === 'tempDir' || $key === 'temp_dir') {
+ return $this->getTempDir();
+ } elseif ($key === 'fontDir' || $key === 'font_dir') {
+ return $this->getFontDir();
+ } elseif ($key === 'fontCache' || $key === 'font_cache') {
+ return $this->getFontCache();
+ } elseif ($key === 'chroot') {
+ return $this->getChroot();
+ } elseif ($key === 'logOutputFile' || $key === 'log_output_file') {
+ return $this->getLogOutputFile();
+ } elseif ($key === 'defaultMediaType' || $key === 'default_media_type') {
+ return $this->getDefaultMediaType();
+ } elseif ($key === 'defaultPaperSize' || $key === 'default_paper_size') {
+ return $this->getDefaultPaperSize();
+ } elseif ($key === 'defaultFont' || $key === 'default_font') {
+ return $this->getDefaultFont();
+ } elseif ($key === 'dpi') {
+ return $this->getDpi();
+ } elseif ($key === 'fontHeightRatio' || $key === 'font_height_ratio') {
+ return $this->getFontHeightRatio();
+ } elseif ($key === 'isPhpEnabled' || $key === 'is_php_enabled' || $key === 'enable_php') {
+ return $this->getIsPhpEnabled();
+ } elseif ($key === 'isRemoteEnabled' || $key === 'is_remote_enabled' || $key === 'enable_remote') {
+ return $this->getIsRemoteEnabled();
+ } elseif ($key === 'isJavascriptEnabled' || $key === 'is_javascript_enabled' || $key === 'enable_javascript') {
+ return $this->getIsJavascriptEnabled();
+ } elseif ($key === 'isHtml5ParserEnabled' || $key === 'is_html5_parser_enabled' || $key === 'enable_html5_parser') {
+ return $this->getIsHtml5ParserEnabled();
+ } elseif ($key === 'isFontSubsettingEnabled' || $key === 'is_font_subsetting_enabled' || $key === 'enable_font_subsetting') {
+ return $this->getIsFontSubsettingEnabled();
+ } elseif ($key === 'debugPng' || $key === 'debug_png') {
+ return $this->getDebugPng();
+ } elseif ($key === 'debugKeepTemp' || $key === 'debug_keep_temp') {
+ return $this->getDebugKeepTemp();
+ } elseif ($key === 'debugCss' || $key === 'debug_css') {
+ return $this->getDebugCss();
+ } elseif ($key === 'debugLayout' || $key === 'debug_layout') {
+ return $this->getDebugLayout();
+ } elseif ($key === 'debugLayoutLines' || $key === 'debug_layout_lines') {
+ return $this->getDebugLayoutLines();
+ } elseif ($key === 'debugLayoutBlocks' || $key === 'debug_layout_blocks') {
+ return $this->getDebugLayoutBlocks();
+ } elseif ($key === 'debugLayoutInline' || $key === 'debug_layout_inline') {
+ return $this->getDebugLayoutInline();
+ } elseif ($key === 'debugLayoutPaddingBox' || $key === 'debug_layout_padding_box') {
+ return $this->getDebugLayoutPaddingBox();
+ } elseif ($key === 'pdfBackend' || $key === 'pdf_backend') {
+ return $this->getPdfBackend();
+ } elseif ($key === 'pdflibLicense' || $key === 'pdflib_license') {
+ return $this->getPdflibLicense();
+ } elseif ($key === 'adminUsername' || $key === 'admin_username') {
+ return $this->getAdminUsername();
+ } elseif ($key === 'adminPassword' || $key === 'admin_password') {
+ return $this->getAdminPassword();
+ }
+ return null;
+ }
+
+ /**
+ * @param string $adminPassword
+ * @return $this
+ */
+ public function setAdminPassword($adminPassword)
+ {
+ $this->adminPassword = $adminPassword;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAdminPassword()
+ {
+ return $this->adminPassword;
+ }
+
+ /**
+ * @param string $adminUsername
+ * @return $this
+ */
+ public function setAdminUsername($adminUsername)
+ {
+ $this->adminUsername = $adminUsername;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAdminUsername()
+ {
+ return $this->adminUsername;
+ }
+
+ /**
+ * @param string $pdfBackend
+ * @return $this
+ */
+ public function setPdfBackend($pdfBackend)
+ {
+ $this->pdfBackend = $pdfBackend;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPdfBackend()
+ {
+ return $this->pdfBackend;
+ }
+
+ /**
+ * @param string $pdflibLicense
+ * @return $this
+ */
+ public function setPdflibLicense($pdflibLicense)
+ {
+ $this->pdflibLicense = $pdflibLicense;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPdflibLicense()
+ {
+ return $this->pdflibLicense;
+ }
+
+ /**
+ * @param string $chroot
+ * @return $this
+ */
+ public function setChroot($chroot)
+ {
+ $this->chroot = $chroot;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getChroot()
+ {
+ return $this->chroot;
+ }
+
+ /**
+ * @param boolean $debugCss
+ * @return $this
+ */
+ public function setDebugCss($debugCss)
+ {
+ $this->debugCss = $debugCss;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugCss()
+ {
+ return $this->debugCss;
+ }
+
+ /**
+ * @param boolean $debugKeepTemp
+ * @return $this
+ */
+ public function setDebugKeepTemp($debugKeepTemp)
+ {
+ $this->debugKeepTemp = $debugKeepTemp;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugKeepTemp()
+ {
+ return $this->debugKeepTemp;
+ }
+
+ /**
+ * @param boolean $debugLayout
+ * @return $this
+ */
+ public function setDebugLayout($debugLayout)
+ {
+ $this->debugLayout = $debugLayout;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugLayout()
+ {
+ return $this->debugLayout;
+ }
+
+ /**
+ * @param boolean $debugLayoutBlocks
+ * @return $this
+ */
+ public function setDebugLayoutBlocks($debugLayoutBlocks)
+ {
+ $this->debugLayoutBlocks = $debugLayoutBlocks;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugLayoutBlocks()
+ {
+ return $this->debugLayoutBlocks;
+ }
+
+ /**
+ * @param boolean $debugLayoutInline
+ * @return $this
+ */
+ public function setDebugLayoutInline($debugLayoutInline)
+ {
+ $this->debugLayoutInline = $debugLayoutInline;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugLayoutInline()
+ {
+ return $this->debugLayoutInline;
+ }
+
+ /**
+ * @param boolean $debugLayoutLines
+ * @return $this
+ */
+ public function setDebugLayoutLines($debugLayoutLines)
+ {
+ $this->debugLayoutLines = $debugLayoutLines;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugLayoutLines()
+ {
+ return $this->debugLayoutLines;
+ }
+
+ /**
+ * @param boolean $debugLayoutPaddingBox
+ * @return $this
+ */
+ public function setDebugLayoutPaddingBox($debugLayoutPaddingBox)
+ {
+ $this->debugLayoutPaddingBox = $debugLayoutPaddingBox;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugLayoutPaddingBox()
+ {
+ return $this->debugLayoutPaddingBox;
+ }
+
+ /**
+ * @param boolean $debugPng
+ * @return $this
+ */
+ public function setDebugPng($debugPng)
+ {
+ $this->debugPng = $debugPng;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getDebugPng()
+ {
+ return $this->debugPng;
+ }
+
+ /**
+ * @param string $defaultFont
+ * @return $this
+ */
+ public function setDefaultFont($defaultFont)
+ {
+ $this->defaultFont = $defaultFont;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDefaultFont()
+ {
+ return $this->defaultFont;
+ }
+
+ /**
+ * @param string $defaultMediaType
+ * @return $this
+ */
+ public function setDefaultMediaType($defaultMediaType)
+ {
+ $this->defaultMediaType = $defaultMediaType;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDefaultMediaType()
+ {
+ return $this->defaultMediaType;
+ }
+
+ /**
+ * @param string $defaultPaperSize
+ * @return $this
+ */
+ public function setDefaultPaperSize($defaultPaperSize)
+ {
+ $this->defaultPaperSize = $defaultPaperSize;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDefaultPaperSize()
+ {
+ return $this->defaultPaperSize;
+ }
+
+ /**
+ * @param int $dpi
+ * @return $this
+ */
+ public function setDpi($dpi)
+ {
+ $this->dpi = $dpi;
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getDpi()
+ {
+ return $this->dpi;
+ }
+
+ /**
+ * @param string $fontCache
+ * @return $this
+ */
+ public function setFontCache($fontCache)
+ {
+ $this->fontCache = $fontCache;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFontCache()
+ {
+ return $this->fontCache;
+ }
+
+ /**
+ * @param string $fontDir
+ * @return $this
+ */
+ public function setFontDir($fontDir)
+ {
+ $this->fontDir = $fontDir;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFontDir()
+ {
+ return $this->fontDir;
+ }
+
+ /**
+ * @param float $fontHeightRatio
+ * @return $this
+ */
+ public function setFontHeightRatio($fontHeightRatio)
+ {
+ $this->fontHeightRatio = $fontHeightRatio;
+ return $this;
+ }
+
+ /**
+ * @return float
+ */
+ public function getFontHeightRatio()
+ {
+ return $this->fontHeightRatio;
+ }
+
+ /**
+ * @param boolean $isFontSubsettingEnabled
+ * @return $this
+ */
+ public function setIsFontSubsettingEnabled($isFontSubsettingEnabled)
+ {
+ $this->isFontSubsettingEnabled = $isFontSubsettingEnabled;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getIsFontSubsettingEnabled()
+ {
+ return $this->isFontSubsettingEnabled;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isFontSubsettingEnabled()
+ {
+ return $this->getIsFontSubsettingEnabled();
+ }
+
+ /**
+ * @param boolean $isHtml5ParserEnabled
+ * @return $this
+ */
+ public function setIsHtml5ParserEnabled($isHtml5ParserEnabled)
+ {
+ $this->isHtml5ParserEnabled = $isHtml5ParserEnabled;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getIsHtml5ParserEnabled()
+ {
+ return $this->isHtml5ParserEnabled;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isHtml5ParserEnabled()
+ {
+ return $this->getIsHtml5ParserEnabled();
+ }
+
+ /**
+ * @param boolean $isJavascriptEnabled
+ * @return $this
+ */
+ public function setIsJavascriptEnabled($isJavascriptEnabled)
+ {
+ $this->isJavascriptEnabled = $isJavascriptEnabled;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getIsJavascriptEnabled()
+ {
+ return $this->isJavascriptEnabled;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isJavascriptEnabled()
+ {
+ return $this->getIsJavascriptEnabled();
+ }
+
+ /**
+ * @param boolean $isPhpEnabled
+ * @return $this
+ */
+ public function setIsPhpEnabled($isPhpEnabled)
+ {
+ $this->isPhpEnabled = $isPhpEnabled;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getIsPhpEnabled()
+ {
+ return $this->isPhpEnabled;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isPhpEnabled()
+ {
+ return $this->getIsPhpEnabled();
+ }
+
+ /**
+ * @param boolean $isRemoteEnabled
+ * @return $this
+ */
+ public function setIsRemoteEnabled($isRemoteEnabled)
+ {
+ $this->isRemoteEnabled = $isRemoteEnabled;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function getIsRemoteEnabled()
+ {
+ return $this->isRemoteEnabled;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isRemoteEnabled()
+ {
+ return $this->getIsRemoteEnabled();
+ }
+
+ /**
+ * @param string $logOutputFile
+ * @return $this
+ */
+ public function setLogOutputFile($logOutputFile)
+ {
+ $this->logOutputFile = $logOutputFile;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLogOutputFile()
+ {
+ return $this->logOutputFile;
+ }
+
+ /**
+ * @param string $tempDir
+ * @return $this
+ */
+ public function setTempDir($tempDir)
+ {
+ $this->tempDir = $tempDir;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTempDir()
+ {
+ return $this->tempDir;
+ }
+
+ /**
+ * @param string $rootDir
+ * @return $this
+ */
+ public function setRootDir($rootDir)
+ {
+ $this->rootDir = $rootDir;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRootDir()
+ {
+ return $this->rootDir;
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/PhpEvaluator.php b/library/vendor/dompdf/src/PhpEvaluator.php
new file mode 100644
index 000000000..c7b877729
--- /dev/null
+++ b/library/vendor/dompdf/src/PhpEvaluator.php
@@ -0,0 +1,55 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf;
+
+use Dompdf\Frame;
+
+/**
+ * Executes inline PHP code during the rendering process
+ *
+ * @package dompdf
+ */
+class PhpEvaluator
+{
+
+ /**
+ * @var Canvas
+ */
+ protected $_canvas;
+
+ function __construct(Canvas $canvas)
+ {
+ $this->_canvas = $canvas;
+ }
+
+ function evaluate($code, $vars = array())
+ {
+ if (!$this->_canvas->get_dompdf()->get_option("enable_php")) {
+ return;
+ }
+
+ // Set up some variables for the inline code
+ $pdf = $this->_canvas;
+ $fontMetrics = $pdf->get_dompdf()->getFontMetrics();
+ $PAGE_NUM = $pdf->get_page_number();
+ $PAGE_COUNT = $pdf->get_page_count();
+
+ // Override those variables if passed in
+ foreach ($vars as $k => $v) {
+ $$k = $v;
+ }
+
+ //$code = html_entity_decode($code); // @todo uncomment this when tested
+ eval($code);
+ }
+
+ function render(Frame $frame)
+ {
+ $this->evaluate($frame->get_node()->nodeValue);
+ }
+}
diff --git a/library/vendor/dompdf/src/Positioner/Absolute.php b/library/vendor/dompdf/src/Positioner/Absolute.php
new file mode 100644
index 000000000..4feae8208
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/Absolute.php
@@ -0,0 +1,123 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Positions absolutely positioned frames
+ */
+class Absolute extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function position()
+ {
+
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+
+ $p = $frame->find_positionned_parent();
+
+ list($x, $y, $w, $h) = $frame->get_containing_block();
+
+ $top = $style->length_in_pt($style->top, $h);
+ $right = $style->length_in_pt($style->right, $w);
+ $bottom = $style->length_in_pt($style->bottom, $h);
+ $left = $style->length_in_pt($style->left, $w);
+
+ if ($p && !($left === "auto" && $right === "auto")) {
+ // Get the parent's padding box (see http://www.w3.org/TR/CSS21/visuren.html#propdef-top)
+ list($x, $y, $w, $h) = $p->get_padding_box();
+ }
+
+ list($width, $height) = array($frame->get_margin_width(), $frame->get_margin_height());
+
+ $orig_style = $this->_frame->get_original_style();
+ $orig_width = $orig_style->width;
+ $orig_height = $orig_style->height;
+
+ /****************************
+ *
+ * Width auto:
+ * ____________| left=auto | left=fixed |
+ * right=auto | A | B |
+ * right=fixed | C | D |
+ *
+ * Width fixed:
+ * ____________| left=auto | left=fixed |
+ * right=auto | E | F |
+ * right=fixed | G | H |
+ *****************************/
+
+ if ($left === "auto") {
+ if ($right === "auto") {
+ // A or E - Keep the frame at the same position
+ $x = $x + $frame->find_block_parent()->get_current_line_box()->w;
+ } else {
+ if ($orig_width === "auto") {
+ // C
+ $x += $w - $width - $right;
+ } else {
+ // G
+ $x += $w - $width - $right;
+ }
+ }
+ } else {
+ if ($right === "auto") {
+ // B or F
+ $x += $left;
+ } else {
+ if ($orig_width === "auto") {
+ // D - TODO change width
+ $x += $left;
+ } else {
+ // H - Everything is fixed: left + width win
+ $x += $left;
+ }
+ }
+ }
+
+ // The same vertically
+ if ($top === "auto") {
+ if ($bottom === "auto") {
+ // A or E - Keep the frame at the same position
+ $y = $frame->find_block_parent()->get_current_line_box()->y;
+ } else {
+ if ($orig_height === "auto") {
+ // C
+ $y += $h - $height - $bottom;
+ } else {
+ // G
+ $y += $h - $height - $bottom;
+ }
+ }
+ } else {
+ if ($bottom === "auto") {
+ // B or F
+ $y += $top;
+ } else {
+ if ($orig_height === "auto") {
+ // D - TODO change height
+ $y += $top;
+ } else {
+ // H - Everything is fixed: top + height win
+ $y += $top;
+ }
+ }
+ }
+
+ $frame->set_position($x, $y);
+
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/Positioner/AbstractPositioner.php b/library/vendor/dompdf/src/Positioner/AbstractPositioner.php
new file mode 100644
index 000000000..1c19356f8
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/AbstractPositioner.php
@@ -0,0 +1,52 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Base AbstractPositioner class
+ *
+ * Defines postioner interface
+ *
+ * @access private
+ * @package dompdf
+ */
+abstract class AbstractPositioner
+{
+
+ /**
+ * @var \Dompdf\FrameDecorator\AbstractFrameDecorator
+ */
+ protected $_frame;
+
+ //........................................................................
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ $this->_frame = $frame;
+ }
+
+ //........................................................................
+
+ abstract function position();
+
+ function move($offset_x, $offset_y, $ignore_self = false)
+ {
+ list($x, $y) = $this->_frame->get_position();
+
+ if (!$ignore_self) {
+ $this->_frame->set_position($x + $offset_x, $y + $offset_y);
+ }
+
+ foreach ($this->_frame->get_children() as $child) {
+ $child->move($offset_x, $offset_y);
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Positioner/Block.php b/library/vendor/dompdf/src/Positioner/Block.php
new file mode 100644
index 000000000..fdb418096
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/Block.php
@@ -0,0 +1,63 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Positions block frames
+ *
+ * @access private
+ * @package dompdf
+ */
+class Block extends AbstractPositioner {
+
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function position()
+ {
+ $frame = $this->_frame;
+ $style = $frame->get_style();
+ $cb = $frame->get_containing_block();
+ $p = $frame->find_block_parent();
+
+ if ($p) {
+ $float = $style->float;
+
+ if (!$float || $float === "none") {
+ $p->add_line(true);
+ }
+ $y = $p->get_current_line_box()->y;
+
+ } else {
+ $y = $cb["y"];
+ }
+
+ $x = $cb["x"];
+
+ // Relative positionning
+ if ($style->position === "relative") {
+ $top = $style->length_in_pt($style->top, $cb["h"]);
+ //$right = $style->length_in_pt($style->right, $cb["w"]);
+ //$bottom = $style->length_in_pt($style->bottom, $cb["h"]);
+ $left = $style->length_in_pt($style->left, $cb["w"]);
+
+ $x += $left;
+ $y += $top;
+ }
+
+ $frame->set_position($x, $y);
+ }
+}
diff --git a/library/vendor/dompdf/src/Positioner/Fixed.php b/library/vendor/dompdf/src/Positioner/Fixed.php
new file mode 100644
index 000000000..018f66c57
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/Fixed.php
@@ -0,0 +1,95 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Positions fixely positioned frames
+ */
+class Fixed extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function position()
+ {
+
+ $frame = $this->_frame;
+ $style = $frame->get_original_style();
+ $root = $frame->get_root();
+ $initialcb = $root->get_containing_block();
+ $initialcb_style = $root->get_style();
+
+ $p = $frame->find_block_parent();
+ if ($p) {
+ $p->add_line();
+ }
+
+ // Compute the margins of the @page style
+ $margin_top = $initialcb_style->length_in_pt($initialcb_style->margin_top, $initialcb["h"]);
+ $margin_right = $initialcb_style->length_in_pt($initialcb_style->margin_right, $initialcb["w"]);
+ $margin_bottom = $initialcb_style->length_in_pt($initialcb_style->margin_bottom, $initialcb["h"]);
+ $margin_left = $initialcb_style->length_in_pt($initialcb_style->margin_left, $initialcb["w"]);
+
+ // The needed computed style of the element
+ $height = $style->length_in_pt($style->height, $initialcb["h"]);
+ $width = $style->length_in_pt($style->width, $initialcb["w"]);
+
+ $top = $style->length_in_pt($style->top, $initialcb["h"]);
+ $right = $style->length_in_pt($style->right, $initialcb["w"]);
+ $bottom = $style->length_in_pt($style->bottom, $initialcb["h"]);
+ $left = $style->length_in_pt($style->left, $initialcb["w"]);
+
+ $y = $margin_top;
+ if (isset($top)) {
+ $y = $top + $margin_top;
+ if ($top === "auto") {
+ $y = $margin_top;
+ if (isset($bottom) && $bottom !== "auto") {
+ $y = $initialcb["h"] - $bottom - $margin_bottom;
+ $margin_height = $this->_frame->get_margin_height();
+ if ($margin_height !== "auto") {
+ $y -= $margin_height;
+ } else {
+ $y -= $height;
+ }
+ }
+ }
+ }
+
+ $x = $margin_left;
+ if (isset($left)) {
+ $x = $left + $margin_left;
+ if ($left === "auto") {
+ $x = $margin_left;
+ if (isset($right) && $right !== "auto") {
+ $x = $initialcb["w"] - $right - $margin_right;
+ $margin_width = $this->_frame->get_margin_width();
+ if ($margin_width !== "auto") {
+ $x -= $margin_width;
+ } else {
+ $x -= $width;
+ }
+ }
+ }
+ }
+
+ $frame->set_position($x, $y);
+
+ $children = $frame->get_children();
+ foreach ($children as $child) {
+ $child->set_position($x, $y);
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/vendor/dompdf/src/Positioner/Inline.php b/library/vendor/dompdf/src/Positioner/Inline.php
new file mode 100644
index 000000000..80eb677ba
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/Inline.php
@@ -0,0 +1,82 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+use Dompdf\FrameDecorator\Inline as InlineFrameDecorator;
+use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
+use Dompdf\Exception;
+
+/**
+ * Positions inline frames
+ *
+ * @package dompdf
+ */
+class Inline extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function position()
+ {
+ /**
+ * Find our nearest block level parent and access its lines property.
+ * @var BlockFrameDecorator
+ */
+ $p = $this->_frame->find_block_parent();
+
+ // Debugging code:
+
+// Helpers::pre_r("\nPositioning:");
+// Helpers::pre_r("Me: " . $this->_frame->get_node()->nodeName . " (" . spl_object_hash($this->_frame->get_node()) . ")");
+// Helpers::pre_r("Parent: " . $p->get_node()->nodeName . " (" . spl_object_hash($p->get_node()) . ")");
+
+ // End debugging
+
+ if (!$p)
+ throw new Exception("No block-level parent found. Not good.");
+
+ $f = $this->_frame;
+
+ $cb = $f->get_containing_block();
+ $line = $p->get_current_line_box();
+
+ // Skip the page break if in a fixed position element
+ $is_fixed = false;
+ while ($f = $f->get_parent()) {
+ if ($f->get_style()->position === "fixed") {
+ $is_fixed = true;
+ break;
+ }
+ }
+
+ $f = $this->_frame;
+
+ if (!$is_fixed && $f->get_parent() &&
+ $f->get_parent() instanceof InlineFrameDecorator &&
+ $f->is_text_node()
+ ) {
+
+ $min_max = $f->get_reflower()->get_min_max_width();
+
+ // If the frame doesn't fit in the current line, a line break occurs
+ if ($min_max["min"] > ($cb["w"] - $line->left - $line->w - $line->right)) {
+ $p->add_line();
+ }
+ }
+
+ $f->set_position($cb["x"] + $line->w, $line->y);
+
+ }
+}
diff --git a/library/vendor/dompdf/src/Positioner/ListBullet.php b/library/vendor/dompdf/src/Positioner/ListBullet.php
new file mode 100644
index 000000000..117c52182
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/ListBullet.php
@@ -0,0 +1,81 @@
+
+ * @author Helmut Tischer
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Positions list bullets
+ *
+ * @package dompdf
+ */
+class ListBullet extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function position()
+ {
+
+ // Bullets & friends are positioned an absolute distance to the left of
+ // the content edge of their parent element
+ $cb = $this->_frame->get_containing_block();
+
+ // Note: this differs from most frames in that we must position
+ // ourselves after determining our width
+ $x = $cb["x"] - $this->_frame->get_width();
+
+ $p = $this->_frame->find_block_parent();
+
+ $y = $p->get_current_line_box()->y;
+
+ // This is a bit of a hack...
+ $n = $this->_frame->get_next_sibling();
+ if ($n) {
+ $style = $n->get_style();
+ $line_height = $style->length_in_pt($style->line_height, $style->get_font_size());
+ $offset = $style->length_in_pt($line_height, $n->get_containing_block("h")) - $this->_frame->get_height();
+ $y += $offset / 2;
+ }
+
+ // Now the position is the left top of the block which should be marked with the bullet.
+ // We tried to find out the y of the start of the first text character within the block.
+ // But the top margin/padding does not fit, neither from this nor from the next sibling
+ // The "bit of a hack" above does not work also.
+
+ // Instead let's position the bullet vertically centered to the block which should be marked.
+ // But for get_next_sibling() the get_containing_block is all zero, and for find_block_parent()
+ // the get_containing_block is paper width and the entire list as height.
+
+ // if ($p) {
+ // //$cb = $n->get_containing_block();
+ // $cb = $p->get_containing_block();
+ // $y += $cb["h"]/2;
+ // print 'cb:'.$cb["x"].':'.$cb["y"].':'.$cb["w"].':'.$cb["h"].':';
+ // }
+
+ // Todo:
+ // For now give up on the above. Use Guesswork with font y-pos in the middle of the line spacing
+
+ /*$style = $p->get_style();
+ $font_size = $style->get_font_size();
+ $line_height = $style->length_in_pt($style->line_height, $font_size);
+ $y += ($line_height - $font_size) / 2; */
+
+ //Position is x-end y-top of character position of the bullet.
+ $this->_frame->set_position($x, $y);
+
+ }
+}
diff --git a/library/vendor/dompdf/src/Positioner/NullPositioner.php b/library/vendor/dompdf/src/Positioner/NullPositioner.php
new file mode 100644
index 000000000..6b27f1949
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/NullPositioner.php
@@ -0,0 +1,31 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Dummy positioner
+ *
+ * @package dompdf
+ */
+class NullPositioner extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ function position()
+ {
+ return;
+ }
+
+}
diff --git a/library/vendor/dompdf/src/Positioner/TableCell.php b/library/vendor/dompdf/src/Positioner/TableCell.php
new file mode 100644
index 000000000..1fda93d54
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/TableCell.php
@@ -0,0 +1,37 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+use Dompdf\FrameDecorator\Table;
+
+/**
+ * Positions table cells
+ *
+ * @package dompdf
+ */
+class TableCell extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function position()
+ {
+
+ $table = Table::find_parent_table($this->_frame);
+ $cellmap = $table->get_cellmap();
+ $this->_frame->set_position($cellmap->get_frame_position($this->_frame));
+
+ }
+}
diff --git a/library/vendor/dompdf/src/Positioner/TableRow.php b/library/vendor/dompdf/src/Positioner/TableRow.php
new file mode 100644
index 000000000..4dce49452
--- /dev/null
+++ b/library/vendor/dompdf/src/Positioner/TableRow.php
@@ -0,0 +1,43 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+namespace Dompdf\Positioner;
+
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+
+/**
+ * Positions table rows
+ *
+ * @package dompdf
+ */
+class TableRow extends AbstractPositioner
+{
+
+ function __construct(AbstractFrameDecorator $frame)
+ {
+ parent::__construct($frame);
+ }
+
+ //........................................................................
+
+ function position()
+ {
+
+ $cb = $this->_frame->get_containing_block();
+ $p = $this->_frame->get_prev_sibling();
+
+ if ($p)
+ $y = $p->get_position("y") + $p->get_margin_height();
+
+ else
+ $y = $cb["y"];
+
+ $this->_frame->set_position($cb["x"], $y);
+
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer.php b/library/vendor/dompdf/src/Renderer.php
new file mode 100644
index 000000000..492a52364
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer.php
@@ -0,0 +1,296 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf;
+
+use Dompdf\Renderer\AbstractRenderer;
+use Dompdf\Renderer\Block;
+use Dompdf\Renderer\Image;
+use Dompdf\Renderer\ListBullet;
+use Dompdf\Renderer\TableCell;
+use Dompdf\Renderer\TableRowGroup;
+use Dompdf\Renderer\Text;
+
+use Dompdf\Frame;
+
+/**
+ * Concrete renderer
+ *
+ * Instantiates several specific renderers in order to render any given frame.
+ *
+ * @package dompdf
+ */
+class Renderer extends AbstractRenderer
+{
+
+ /**
+ * Array of renderers for specific frame types
+ *
+ * @var AbstractRenderer[]
+ */
+ protected $_renderers;
+
+ /**
+ * Cache of the callbacks array
+ *
+ * @var array
+ */
+ private $_callbacks;
+
+ /**
+ * Advance the canvas to the next page
+ */
+ function new_page()
+ {
+ $this->_canvas->new_page();
+ }
+
+ /**
+ * Render frames recursively
+ *
+ * @param Frame $frame the frame to render
+ */
+ function render(Frame $frame)
+ {
+ global $_dompdf_debug;
+
+ if ($_dompdf_debug) {
+ echo $frame;
+ flush();
+ }
+
+ $style = $frame->get_style();
+
+ if (in_array($style->visibility, array("hidden", "collapse"))) {
+ return;
+ }
+
+ $display = $style->display;
+
+ // Starts the CSS transformation
+ if ($style->transform && is_array($style->transform)) {
+ $this->_canvas->save();
+ list($x, $y) = $frame->get_padding_box();
+ $origin = $style->transform_origin;
+
+ foreach ($style->transform as $transform) {
+ list($function, $values) = $transform;
+ if ($function === "matrix") {
+ $function = "transform";
+ }
+
+ $values = array_map("floatval", $values);
+ $values[] = $x + $style->length_in_pt($origin[0], $style->width);
+ $values[] = $y + $style->length_in_pt($origin[1], $style->height);
+
+ call_user_func_array(array($this->_canvas, $function), $values);
+ }
+ }
+
+ switch ($display) {
+
+ case "block":
+ case "list-item":
+ case "inline-block":
+ case "table":
+ case "inline-table":
+ $this->_render_frame("block", $frame);
+ break;
+
+ case "inline":
+ if ($frame->is_text_node()) {
+ $this->_render_frame("text", $frame);
+ } else {
+ $this->_render_frame("inline", $frame);
+ }
+ break;
+
+ case "table-cell":
+ $this->_render_frame("table-cell", $frame);
+ break;
+
+ case "table-row-group":
+ case "table-header-group":
+ case "table-footer-group":
+ $this->_render_frame("table-row-group", $frame);
+ break;
+
+ case "-dompdf-list-bullet":
+ $this->_render_frame("list-bullet", $frame);
+ break;
+
+ case "-dompdf-image":
+ $this->_render_frame("image", $frame);
+ break;
+
+ case "none":
+ $node = $frame->get_node();
+
+ if ($node->nodeName === "script") {
+ if ($node->getAttribute("type") === "text/php" ||
+ $node->getAttribute("language") === "php"
+ ) {
+ // Evaluate embedded php scripts
+ $this->_render_frame("php", $frame);
+ } elseif ($node->getAttribute("type") === "text/javascript" ||
+ $node->getAttribute("language") === "javascript"
+ ) {
+ // Insert JavaScript
+ $this->_render_frame("javascript", $frame);
+ }
+ }
+
+ // Don't render children, so skip to next iter
+ return;
+
+ default:
+ break;
+
+ }
+
+ // Starts the overflow: hidden box
+ if ($style->overflow === "hidden") {
+ list($x, $y, $w, $h) = $frame->get_padding_box();
+
+ // get border radii
+ $style = $frame->get_style();
+ list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
+
+ if ($tl + $tr + $br + $bl > 0) {
+ $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
+ } else {
+ $this->_canvas->clipping_rectangle($x, $y, $w, $h);
+ }
+ }
+
+ $stack = array();
+
+ foreach ($frame->get_children() as $child) {
+ // < 0 : nagative z-index
+ // = 0 : no z-index, no stacking context
+ // = 1 : stacking context without z-index
+ // > 1 : z-index
+ $child_style = $child->get_style();
+ $child_z_index = $child_style->z_index;
+ $z_index = 0;
+
+ if ($child_z_index !== "auto") {
+ $z_index = intval($child_z_index) + 1;
+ } elseif ($child_style->float !== "none" || $child->is_positionned()) {
+ $z_index = 1;
+ }
+
+ $stack[$z_index][] = $child;
+ }
+
+ ksort($stack);
+
+ foreach ($stack as $by_index) {
+ foreach ($by_index as $child) {
+ $this->render($child);
+ }
+ }
+
+ // Ends the overflow: hidden box
+ if ($style->overflow === "hidden") {
+ $this->_canvas->clipping_end();
+ }
+
+ if ($style->transform && is_array($style->transform)) {
+ $this->_canvas->restore();
+ }
+
+ // Check for end frame callback
+ $this->_check_callbacks("end_frame", $frame);
+ }
+
+ /**
+ * Check for callbacks that need to be performed when a given event
+ * gets triggered on a frame
+ *
+ * @param string $event the type of event
+ * @param Frame $frame the frame that event is triggered on
+ */
+ protected function _check_callbacks($event, $frame)
+ {
+ if (!isset($this->_callbacks)) {
+ $this->_callbacks = $this->_dompdf->get_callbacks();
+ }
+
+ if (is_array($this->_callbacks) && isset($this->_callbacks[$event])) {
+ $info = array(0 => $this->_canvas, "canvas" => $this->_canvas,
+ 1 => $frame, "frame" => $frame);
+ $fs = $this->_callbacks[$event];
+ foreach ($fs as $f) {
+ if (is_callable($f)) {
+ if (is_array($f)) {
+ $f[0]->{$f[1]}($info);
+ } else {
+ $f($info);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Render a single frame
+ *
+ * Creates Renderer objects on demand
+ *
+ * @param string $type type of renderer to use
+ * @param Frame $frame the frame to render
+ */
+ protected function _render_frame($type, $frame)
+ {
+
+ if (!isset($this->_renderers[$type])) {
+
+ switch ($type) {
+ case "block":
+ $this->_renderers[$type] = new Block($this->_dompdf);
+ break;
+
+ case "inline":
+ $this->_renderers[$type] = new Renderer\Inline($this->_dompdf);
+ break;
+
+ case "text":
+ $this->_renderers[$type] = new Text($this->_dompdf);
+ break;
+
+ case "image":
+ $this->_renderers[$type] = new Image($this->_dompdf);
+ break;
+
+ case "table-cell":
+ $this->_renderers[$type] = new TableCell($this->_dompdf);
+ break;
+
+ case "table-row-group":
+ $this->_renderers[$type] = new TableRowGroup($this->_dompdf);
+ break;
+
+ case "list-bullet":
+ $this->_renderers[$type] = new ListBullet($this->_dompdf);
+ break;
+
+ case "php":
+ $this->_renderers[$type] = new PhpEvaluator($this->_canvas);
+ break;
+
+ case "javascript":
+ $this->_renderers[$type] = new JavascriptEmbedder($this->_dompdf);
+ break;
+
+ }
+ }
+
+ $this->_renderers[$type]->render($frame);
+
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/AbstractRenderer.php b/library/vendor/dompdf/src/Renderer/AbstractRenderer.php
new file mode 100644
index 000000000..31b595fd4
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/AbstractRenderer.php
@@ -0,0 +1,768 @@
+
+ * @author Helmut Tischer
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Adapter\CPDF;
+use Dompdf\Css\Color;
+use Dompdf\Css\Style;
+use Dompdf\Dompdf;
+use Dompdf\Helpers;
+use Dompdf\Frame;
+use Dompdf\Image\Cache;
+
+/**
+ * Base renderer class
+ *
+ * @package dompdf
+ */
+abstract class AbstractRenderer
+{
+
+ /**
+ * Rendering backend
+ *
+ * @var \Dompdf\Canvas
+ */
+ protected $_canvas;
+
+ /**
+ * Current dompdf instance
+ *
+ * @var Dompdf
+ */
+ protected $_dompdf;
+
+ /**
+ * Class constructor
+ *
+ * @param Dompdf $dompdf The current dompdf instance
+ */
+ function __construct(Dompdf $dompdf)
+ {
+ $this->_dompdf = $dompdf;
+ $this->_canvas = $dompdf->get_canvas();
+ }
+
+ /**
+ * Render a frame.
+ *
+ * Specialized in child classes
+ *
+ * @param Frame $frame The frame to render
+ */
+ abstract function render(Frame $frame);
+
+ //........................................................................
+
+ /**
+ * Render a background image over a rectangular area
+ *
+ * @param string $url The background image to load
+ * @param float $x The left edge of the rectangular area
+ * @param float $y The top edge of the rectangular area
+ * @param float $width The width of the rectangular area
+ * @param float $height The height of the rectangular area
+ * @param Style $style The associated Style object
+ *
+ * @throws \Exception
+ */
+ protected function _background_image($url, $x, $y, $width, $height, $style)
+ {
+ if (!function_exists("imagecreatetruecolor")) {
+ throw new \Exception("The PHP GD extension is required, but is not installed.");
+ }
+
+ $sheet = $style->get_stylesheet();
+
+ // Skip degenerate cases
+ if ($width == 0 || $height == 0) {
+ return;
+ }
+
+ $box_width = $width;
+ $box_height = $height;
+
+ //debugpng
+ if ($this->_dompdf->get_option("debugPng")) print '[_background_image ' . $url . ']';
+
+ list($img, $type, /*$msg*/) = Cache::resolve_url(
+ $url,
+ $sheet->get_protocol(),
+ $sheet->get_host(),
+ $sheet->get_base_path(),
+ $this->_dompdf
+ );
+
+ // Bail if the image is no good
+ if (Cache::is_broken($img)) {
+ return;
+ }
+
+ //Try to optimize away reading and composing of same background multiple times
+ //Postponing read with imagecreatefrom ...()
+ //final composition parameters and name not known yet
+ //Therefore read dimension directly from file, instead of creating gd object first.
+ //$img_w = imagesx($src); $img_h = imagesy($src);
+
+ list($img_w, $img_h) = Helpers::dompdf_getimagesize($img, $this->_dompdf->getHttpContext());
+ if (!isset($img_w) || $img_w == 0 || !isset($img_h) || $img_h == 0) {
+ return;
+ }
+
+ $repeat = $style->background_repeat;
+ $dpi = $this->_dompdf->get_option("dpi");
+
+ //Increase background resolution and dependent box size according to image resolution to be placed in
+ //Then image can be copied in without resize
+ $bg_width = round((float)($width * $dpi) / 72);
+ $bg_height = round((float)($height * $dpi) / 72);
+
+ //Need %bg_x, $bg_y as background pos, where img starts, converted to pixel
+
+ list($bg_x, $bg_y) = $style->background_position;
+
+ if (Helpers::is_percent($bg_x)) {
+ // The point $bg_x % from the left edge of the image is placed
+ // $bg_x % from the left edge of the background rectangle
+ $p = ((float)$bg_x) / 100.0;
+ $x1 = $p * $img_w;
+ $x2 = $p * $bg_width;
+
+ $bg_x = $x2 - $x1;
+ } else {
+ $bg_x = (float)($style->length_in_pt($bg_x) * $dpi) / 72;
+ }
+
+ $bg_x = round($bg_x + $style->length_in_pt($style->border_left_width) * $dpi / 72);
+
+ if (Helpers::is_percent($bg_y)) {
+ // The point $bg_y % from the left edge of the image is placed
+ // $bg_y % from the left edge of the background rectangle
+ $p = ((float)$bg_y) / 100.0;
+ $y1 = $p * $img_h;
+ $y2 = $p * $bg_height;
+
+ $bg_y = $y2 - $y1;
+ } else {
+ $bg_y = (float)($style->length_in_pt($bg_y) * $dpi) / 72;
+ }
+
+ $bg_y = round($bg_y + $style->length_in_pt($style->border_top_width) * $dpi / 72);
+
+ //clip background to the image area on partial repeat. Nothing to do if img off area
+ //On repeat, normalize start position to the tile at immediate left/top or 0/0 of area
+ //On no repeat with positive offset: move size/start to have offset==0
+ //Handle x/y Dimensions separately
+
+ if ($repeat !== "repeat" && $repeat !== "repeat-x") {
+ //No repeat x
+ if ($bg_x < 0) {
+ $bg_width = $img_w + $bg_x;
+ } else {
+ $x += ($bg_x * 72) / $dpi;
+ $bg_width = $bg_width - $bg_x;
+ if ($bg_width > $img_w) {
+ $bg_width = $img_w;
+ }
+ $bg_x = 0;
+ }
+
+ if ($bg_width <= 0) {
+ return;
+ }
+
+ $width = (float)($bg_width * 72) / $dpi;
+ } else {
+ //repeat x
+ if ($bg_x < 0) {
+ $bg_x = -((-$bg_x) % $img_w);
+ } else {
+ $bg_x = $bg_x % $img_w;
+ if ($bg_x > 0) {
+ $bg_x -= $img_w;
+ }
+ }
+ }
+
+ if ($repeat !== "repeat" && $repeat !== "repeat-y") {
+ //no repeat y
+ if ($bg_y < 0) {
+ $bg_height = $img_h + $bg_y;
+ } else {
+ $y += ($bg_y * 72) / $dpi;
+ $bg_height = $bg_height - $bg_y;
+ if ($bg_height > $img_h) {
+ $bg_height = $img_h;
+ }
+ $bg_y = 0;
+ }
+ if ($bg_height <= 0) {
+ return;
+ }
+ $height = (float)($bg_height * 72) / $dpi;
+ } else {
+ //repeat y
+ if ($bg_y < 0) {
+ $bg_y = -((-$bg_y) % $img_h);
+ } else {
+ $bg_y = $bg_y % $img_h;
+ if ($bg_y > 0) {
+ $bg_y -= $img_h;
+ }
+ }
+ }
+
+ //Optimization, if repeat has no effect
+ if ($repeat === "repeat" && $bg_y <= 0 && $img_h + $bg_y >= $bg_height) {
+ $repeat = "repeat-x";
+ }
+
+ if ($repeat === "repeat" && $bg_x <= 0 && $img_w + $bg_x >= $bg_width) {
+ $repeat = "repeat-y";
+ }
+
+ if (($repeat === "repeat-x" && $bg_x <= 0 && $img_w + $bg_x >= $bg_width) ||
+ ($repeat === "repeat-y" && $bg_y <= 0 && $img_h + $bg_y >= $bg_height)
+ ) {
+ $repeat = "no-repeat";
+ }
+
+ //Use filename as indicator only
+ //different names for different variants to have different copies in the pdf
+ //This is not dependent of background color of box! .'_'.(is_array($bg_color) ? $bg_color["hex"] : $bg_color)
+ //Note: Here, bg_* are the start values, not end values after going through the tile loops!
+
+ $filedummy = $img;
+
+ $is_png = false;
+ $filedummy .= '_' . $bg_width . '_' . $bg_height . '_' . $bg_x . '_' . $bg_y . '_' . $repeat;
+
+ //Optimization to avoid multiple times rendering the same image.
+ //If check functions are existing and identical image already cached,
+ //then skip creation of duplicate, because it is not needed by addImagePng
+ if ($this->_canvas instanceof CPDF &&
+ $this->_canvas->get_cpdf()->image_iscached($filedummy)
+ ) {
+ $bg = null;
+ } else {
+
+ // Create a new image to fit over the background rectangle
+ $bg = imagecreatetruecolor($bg_width, $bg_height);
+
+ switch (strtolower($type)) {
+ case "png":
+ $is_png = true;
+ imagesavealpha($bg, true);
+ imagealphablending($bg, false);
+ $src = imagecreatefrompng($img);
+ break;
+
+ case "jpeg":
+ $src = imagecreatefromjpeg($img);
+ break;
+
+ case "gif":
+ $src = imagecreatefromgif($img);
+ break;
+
+ case "bmp":
+ $src = Helpers::imagecreatefrombmp($img);
+ break;
+
+ default:
+ return; // Unsupported image type
+ }
+
+ if ($src == null) {
+ return;
+ }
+
+ //Background color if box is not relevant here
+ //Non transparent image: box clipped to real size. Background non relevant.
+ //Transparent image: The image controls the transparency and lets shine through whatever background.
+ //However on transparent image preset the composed image with the transparency color,
+ //to keep the transparency when copying over the non transparent parts of the tiles.
+ $ti = imagecolortransparent($src);
+
+ if ($ti >= 0) {
+ $tc = imagecolorsforindex($src, $ti);
+ $ti = imagecolorallocate($bg, $tc['red'], $tc['green'], $tc['blue']);
+ imagefill($bg, 0, 0, $ti);
+ imagecolortransparent($bg, $ti);
+ }
+
+ //This has only an effect for the non repeatable dimension.
+ //compute start of src and dest coordinates of the single copy
+ if ($bg_x < 0) {
+ $dst_x = 0;
+ $src_x = -$bg_x;
+ } else {
+ $src_x = 0;
+ $dst_x = $bg_x;
+ }
+
+ if ($bg_y < 0) {
+ $dst_y = 0;
+ $src_y = -$bg_y;
+ } else {
+ $src_y = 0;
+ $dst_y = $bg_y;
+ }
+
+ //For historical reasons exchange meanings of variables:
+ //start_* will be the start values, while bg_* will be the temporary start values in the loops
+ $start_x = $bg_x;
+ $start_y = $bg_y;
+
+ // Copy regions from the source image to the background
+ if ($repeat === "no-repeat") {
+
+ // Simply place the image on the background
+ imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $img_w, $img_h);
+
+ } else if ($repeat === "repeat-x") {
+
+ for ($bg_x = $start_x; $bg_x < $bg_width; $bg_x += $img_w) {
+ if ($bg_x < 0) {
+ $dst_x = 0;
+ $src_x = -$bg_x;
+ $w = $img_w + $bg_x;
+ } else {
+ $dst_x = $bg_x;
+ $src_x = 0;
+ $w = $img_w;
+ }
+ imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $w, $img_h);
+ }
+
+ } else if ($repeat === "repeat-y") {
+
+ for ($bg_y = $start_y; $bg_y < $bg_height; $bg_y += $img_h) {
+ if ($bg_y < 0) {
+ $dst_y = 0;
+ $src_y = -$bg_y;
+ $h = $img_h + $bg_y;
+ } else {
+ $dst_y = $bg_y;
+ $src_y = 0;
+ $h = $img_h;
+ }
+ imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $img_w, $h);
+
+ }
+
+ } else if ($repeat === "repeat") {
+
+ for ($bg_y = $start_y; $bg_y < $bg_height; $bg_y += $img_h) {
+ for ($bg_x = $start_x; $bg_x < $bg_width; $bg_x += $img_w) {
+
+ if ($bg_x < 0) {
+ $dst_x = 0;
+ $src_x = -$bg_x;
+ $w = $img_w + $bg_x;
+ } else {
+ $dst_x = $bg_x;
+ $src_x = 0;
+ $w = $img_w;
+ }
+
+ if ($bg_y < 0) {
+ $dst_y = 0;
+ $src_y = -$bg_y;
+ $h = $img_h + $bg_y;
+ } else {
+ $dst_y = $bg_y;
+ $src_y = 0;
+ $h = $img_h;
+ }
+ imagecopy($bg, $src, $dst_x, $dst_y, $src_x, $src_y, $w, $h);
+ }
+ }
+ } else {
+ print 'Unknown repeat!';
+ }
+
+ imagedestroy($src);
+
+ } /* End optimize away creation of duplicates */
+
+ $this->_canvas->clipping_rectangle($x, $y, $box_width, $box_height);
+
+ //img: image url string
+ //img_w, img_h: original image size in px
+ //width, height: box size in pt
+ //bg_width, bg_height: box size in px
+ //x, y: left/top edge of box on page in pt
+ //start_x, start_y: placement of image relative to pattern
+ //$repeat: repeat mode
+ //$bg: GD object of result image
+ //$src: GD object of original image
+ //When using cpdf and optimization to direct png creation from gd object is available,
+ //don't create temp file, but place gd object directly into the pdf
+ if (!$is_png && $this->_canvas instanceof CPDF) {
+ // Note: CPDF_Adapter image converts y position
+ $this->_canvas->get_cpdf()->addImagePng($filedummy, $x, $this->_canvas->get_height() - $y - $height, $width, $height, $bg);
+ } else {
+ $tmp_dir = $this->_dompdf->get_option("temp_dir");
+ $tmp_name = tempnam($tmp_dir, "bg_dompdf_img_");
+ @unlink($tmp_name);
+ $tmp_file = "$tmp_name.png";
+
+ //debugpng
+ if ($this->_dompdf->get_option("debugPng")) print '[_background_image ' . $tmp_file . ']';
+
+ imagepng($bg, $tmp_file);
+ $this->_canvas->image($tmp_file, $x, $y, $width, $height);
+ imagedestroy($bg);
+
+ //debugpng
+ if ($this->_dompdf->get_option("debugPng")) print '[_background_image unlink ' . $tmp_file . ']';
+
+ if (!$this->_dompdf->get_option("debugKeepTemp")) {
+ unlink($tmp_file);
+ }
+ }
+
+ $this->_canvas->clipping_end();
+ }
+
+ protected function _get_dash_pattern($style, $width)
+ {
+ $pattern = array();
+
+ switch ($style) {
+ default:
+ /*case "solid":
+ case "double":
+ case "groove":
+ case "inset":
+ case "outset":
+ case "ridge":*/
+ case "none":
+ break;
+
+ case "dotted":
+ if ($width <= 1)
+ $pattern = array($width, $width * 2);
+ else
+ $pattern = array($width);
+ break;
+
+ case "dashed":
+ $pattern = array(3 * $width);
+ break;
+ }
+
+ return $pattern;
+ }
+
+ protected function _border_none($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ return;
+ }
+
+ protected function _border_hidden($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ return;
+ }
+
+ // Border rendering functions
+
+ protected function _border_dotted($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ $this->_border_line($x, $y, $length, $color, $widths, $side, $corner_style, "dotted", $r1, $r2);
+ }
+
+
+ protected function _border_dashed($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ $this->_border_line($x, $y, $length, $color, $widths, $side, $corner_style, "dashed", $r1, $r2);
+ }
+
+
+ protected function _border_solid($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ // TODO: Solve rendering where one corner is beveled (radius == 0), one corner isn't.
+ if ($corner_style !== "bevel" || $r1 > 0 || $r2 > 0) {
+ // do it the simple way
+ $this->_border_line($x, $y, $length, $color, $widths, $side, $corner_style, "solid", $r1, $r2);
+ return;
+ }
+
+ list($top, $right, $bottom, $left) = $widths;
+
+ // All this polygon business is for beveled corners...
+ switch ($side) {
+ case "top":
+ $points = array($x, $y,
+ $x + $length, $y,
+ $x + $length - $right, $y + $top,
+ $x + $left, $y + $top);
+ $this->_canvas->polygon($points, $color, null, null, true);
+ break;
+
+ case "bottom":
+ $points = array($x, $y,
+ $x + $length, $y,
+ $x + $length - $right, $y - $bottom,
+ $x + $left, $y - $bottom);
+ $this->_canvas->polygon($points, $color, null, null, true);
+ break;
+
+ case "left":
+ $points = array($x, $y,
+ $x, $y + $length,
+ $x + $left, $y + $length - $bottom,
+ $x + $left, $y + $top);
+ $this->_canvas->polygon($points, $color, null, null, true);
+ break;
+
+ case "right":
+ $points = array($x, $y,
+ $x, $y + $length,
+ $x - $right, $y + $length - $bottom,
+ $x - $right, $y + $top);
+ $this->_canvas->polygon($points, $color, null, null, true);
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ protected function _apply_ratio($side, $ratio, $top, $right, $bottom, $left, &$x, &$y, &$length, &$r1, &$r2)
+ {
+ switch ($side) {
+
+ case "top":
+ $r1 -= $left * $ratio;
+ $r2 -= $right * $ratio;
+ $x += $left * $ratio;
+ $y += $top * $ratio;
+ $length -= $left * $ratio + $right * $ratio;
+ break;
+
+ case "bottom":
+ $r1 -= $right * $ratio;
+ $r2 -= $left * $ratio;
+ $x += $left * $ratio;
+ $y -= $bottom * $ratio;
+ $length -= $left * $ratio + $right * $ratio;
+ break;
+
+ case "left":
+ $r1 -= $top * $ratio;
+ $r2 -= $bottom * $ratio;
+ $x += $left * $ratio;
+ $y += $top * $ratio;
+ $length -= $top * $ratio + $bottom * $ratio;
+ break;
+
+ case "right":
+ $r1 -= $bottom * $ratio;
+ $r2 -= $top * $ratio;
+ $x -= $right * $ratio;
+ $y += $top * $ratio;
+ $length -= $top * $ratio + $bottom * $ratio;
+ break;
+
+ default:
+ return;
+
+ }
+ }
+
+ protected function _border_double($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ list($top, $right, $bottom, $left) = $widths;
+
+ $third_widths = array($top / 3, $right / 3, $bottom / 3, $left / 3);
+
+ // draw the outer border
+ $this->_border_solid($x, $y, $length, $color, $third_widths, $side, $corner_style, $r1, $r2);
+
+ $this->_apply_ratio($side, 2 / 3, $top, $right, $bottom, $left, $x, $y, $length, $r1, $r2);
+
+ $this->_border_solid($x, $y, $length, $color, $third_widths, $side, $corner_style, $r1, $r2);
+ }
+
+ protected function _border_groove($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ list($top, $right, $bottom, $left) = $widths;
+
+ $half_widths = array($top / 2, $right / 2, $bottom / 2, $left / 2);
+
+ $this->_border_inset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
+
+ $this->_apply_ratio($side, 0.5, $top, $right, $bottom, $left, $x, $y, $length, $r1, $r2);
+
+ $this->_border_outset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
+
+ }
+
+ protected function _border_ridge($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ list($top, $right, $bottom, $left) = $widths;
+
+ $half_widths = array($top / 2, $right / 2, $bottom / 2, $left / 2);
+
+ $this->_border_outset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
+
+ $this->_apply_ratio($side, 0.5, $top, $right, $bottom, $left, $x, $y, $length, $r1, $r2);
+
+ $this->_border_inset($x, $y, $length, $color, $half_widths, $side, $corner_style, $r1, $r2);
+
+ }
+
+ protected function _tint($c)
+ {
+ if (!is_numeric($c))
+ return $c;
+
+ return min(1, $c + 0.16);
+ }
+
+ protected function _shade($c)
+ {
+ if (!is_numeric($c))
+ return $c;
+
+ return max(0, $c - 0.33);
+ }
+
+ protected function _border_inset($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ switch ($side) {
+ case "top":
+ case "left":
+ $shade = array_map(array($this, "_shade"), $color);
+ $this->_border_solid($x, $y, $length, $shade, $widths, $side, $corner_style, $r1, $r2);
+ break;
+
+ case "bottom":
+ case "right":
+ $tint = array_map(array($this, "_tint"), $color);
+ $this->_border_solid($x, $y, $length, $tint, $widths, $side, $corner_style, $r1, $r2);
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ protected function _border_outset($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $r1 = 0, $r2 = 0)
+ {
+ switch ($side) {
+ case "top":
+ case "left":
+ $tint = array_map(array($this, "_tint"), $color);
+ $this->_border_solid($x, $y, $length, $tint, $widths, $side, $corner_style, $r1, $r2);
+ break;
+
+ case "bottom":
+ case "right":
+ $shade = array_map(array($this, "_shade"), $color);
+ $this->_border_solid($x, $y, $length, $shade, $widths, $side, $corner_style, $r1, $r2);
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ // Draws a solid, dotted, or dashed line, observing the border radius
+ protected function _border_line($x, $y, $length, $color, $widths, $side, $corner_style = "bevel", $pattern_name, $r1 = 0, $r2 = 0)
+ {
+ list($top, $right, $bottom, $left) = $widths;
+
+ $width = $$side;
+ $pattern = $this->_get_dash_pattern($pattern_name, $width);
+
+ $half_width = $width / 2;
+ $r1 -= $half_width;
+ $r2 -= $half_width;
+ $adjust = $r1 / 80;
+ $length -= $width;
+
+ switch ($side) {
+ case "top":
+ $x += $half_width;
+ $y += $half_width;
+
+ if ($r1 > 0) {
+ $this->_canvas->arc($x + $r1, $y + $r1, $r1, $r1, 90 - $adjust, 135 + $adjust, $color, $width, $pattern);
+ }
+
+ $this->_canvas->line($x + $r1, $y, $x + $length - $r2, $y, $color, $width, $pattern);
+
+ if ($r2 > 0) {
+ $this->_canvas->arc($x + $length - $r2, $y + $r2, $r2, $r2, 45 - $adjust, 90 + $adjust, $color, $width, $pattern);
+ }
+ break;
+
+ case "bottom":
+ $x += $half_width;
+ $y -= $half_width;
+
+ if ($r1 > 0) {
+ $this->_canvas->arc($x + $r1, $y - $r1, $r1, $r1, 225 - $adjust, 270 + $adjust, $color, $width, $pattern);
+ }
+
+ $this->_canvas->line($x + $r1, $y, $x + $length - $r2, $y, $color, $width, $pattern);
+
+ if ($r2 > 0) {
+ $this->_canvas->arc($x + $length - $r2, $y - $r2, $r2, $r2, 270 - $adjust, 315 + $adjust, $color, $width, $pattern);
+ }
+ break;
+
+ case "left":
+ $y += $half_width;
+ $x += $half_width;
+
+ if ($r1 > 0) {
+ $this->_canvas->arc($x + $r1, $y + $r1, $r1, $r1, 135 - $adjust, 180 + $adjust, $color, $width, $pattern);
+ }
+
+ $this->_canvas->line($x, $y + $r1, $x, $y + $length - $r2, $color, $width, $pattern);
+
+ if ($r2 > 0) {
+ $this->_canvas->arc($x + $r2, $y + $length - $r2, $r2, $r2, 180 - $adjust, 225 + $adjust, $color, $width, $pattern);
+ }
+ break;
+
+ case "right":
+ $y += $half_width;
+ $x -= $half_width;
+
+ if ($r1 > 0) {
+ $this->_canvas->arc($x - $r1, $y + $r1, $r1, $r1, 0 - $adjust, 45 + $adjust, $color, $width, $pattern);
+ }
+
+ $this->_canvas->line($x, $y + $r1, $x, $y + $length - $r2, $color, $width, $pattern);
+
+ if ($r2 > 0) {
+ $this->_canvas->arc($x - $r2, $y + $length - $r2, $r2, $r2, 315 - $adjust, 360 + $adjust, $color, $width, $pattern);
+ }
+ break;
+ }
+ }
+
+ protected function _set_opacity($opacity)
+ {
+ if (is_numeric($opacity) && $opacity <= 1.0 && $opacity >= 0.0) {
+ $this->_canvas->set_opacity($opacity);
+ }
+ }
+
+ protected function _debug_layout($box, $color = "red", $style = array())
+ {
+ $this->_canvas->rectangle($box[0], $box[1], $box[2], $box[3], Color::parse($color), 0.1, $style);
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/Block.php b/library/vendor/dompdf/src/Renderer/Block.php
new file mode 100644
index 000000000..d16212307
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/Block.php
@@ -0,0 +1,240 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\AbstractFrameDecorator;
+use Dompdf\Helpers;
+
+/**
+ * Renders block frames
+ *
+ * @package dompdf
+ */
+class Block extends AbstractRenderer
+{
+
+ //........................................................................
+
+ function render(Frame $frame)
+ {
+ $style = $frame->get_style();
+ $node = $frame->get_node();
+
+ list($x, $y, $w, $h) = $frame->get_border_box();
+
+ $this->_set_opacity($frame->get_opacity($style->opacity));
+
+ if ($node->nodeName === "body") {
+ $h = $frame->get_containing_block("h") - $style->length_in_pt(array(
+ $style->margin_top,
+ $style->border_top_width,
+ $style->border_bottom_width,
+ $style->margin_bottom),
+ $style->width);
+ }
+
+ // Handle anchors & links
+ if ($node->nodeName === "a" && $href = $node->getAttribute("href")) {
+ $href = Helpers::build_url($this->_dompdf->getProtocol(), $this->_dompdf->getBaseHost(), $this->_dompdf->getBasePath(), $href);
+ $this->_canvas->add_link($href, $x, $y, $w, $h);
+ }
+
+ // Draw our background, border and content
+ list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
+
+ if ($tl + $tr + $br + $bl > 0) {
+ $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
+ }
+
+ if (($bg = $style->background_color) !== "transparent") {
+ $this->_canvas->filled_rectangle($x, $y, $w, $h, $bg);
+ }
+
+ if (($url = $style->background_image) && $url !== "none") {
+ $this->_background_image($url, $x, $y, $w, $h, $style);
+ }
+
+ if ($tl + $tr + $br + $bl > 0) {
+ $this->_canvas->clipping_end();
+ }
+
+ $border_box = array($x, $y, $w, $h);
+ $this->_render_border($frame, $border_box);
+ $this->_render_outline($frame, $border_box);
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutBlocks")) {
+ $this->_debug_layout($frame->get_border_box(), "red");
+ if ($this->_dompdf->get_option("debugLayoutPaddingBox")) {
+ $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
+ }
+ }
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutLines") && $frame->get_decorator()) {
+ foreach ($frame->get_decorator()->get_line_boxes() as $line) {
+ $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
+ }
+ }
+ }
+
+ protected function _render_border(AbstractFrameDecorator $frame, $border_box = null, $corner_style = "bevel")
+ {
+ $style = $frame->get_style();
+ $bp = $style->get_border_properties();
+
+ if (empty($border_box)) {
+ $border_box = $frame->get_border_box();
+ }
+
+ // find the radius
+ $radius = $style->get_computed_border_radius($border_box[2], $border_box[3]); // w, h
+
+ // Short-cut: If all the borders are "solid" with the same color and style, and no radius, we'd better draw a rectangle
+ if (
+ in_array($bp["top"]["style"], array("solid", "dashed", "dotted")) &&
+ $bp["top"] == $bp["right"] &&
+ $bp["right"] == $bp["bottom"] &&
+ $bp["bottom"] == $bp["left"] &&
+ array_sum($radius) == 0
+ ) {
+ $props = $bp["top"];
+ if ($props["color"] === "transparent" || $props["width"] <= 0) return;
+
+ list($x, $y, $w, $h) = $border_box;
+ $width = $style->length_in_pt($props["width"]);
+ $pattern = $this->_get_dash_pattern($props["style"], $width);
+ $this->_canvas->rectangle($x + $width / 2, $y + $width / 2, $w - $width, $h - $width, $props["color"], $width, $pattern);
+ return;
+ }
+
+ // Do it the long way
+ $widths = array($style->length_in_pt($bp["top"]["width"]),
+ $style->length_in_pt($bp["right"]["width"]),
+ $style->length_in_pt($bp["bottom"]["width"]),
+ $style->length_in_pt($bp["left"]["width"]));
+
+ foreach ($bp as $side => $props) {
+ list($x, $y, $w, $h) = $border_box;
+ $length = 0;
+ $r1 = 0;
+ $r2 = 0;
+
+ if (!$props["style"] ||
+ $props["style"] === "none" ||
+ $props["width"] <= 0 ||
+ $props["color"] == "transparent"
+ )
+ continue;
+
+ switch ($side) {
+ case "top":
+ $length = $w;
+ $r1 = $radius["top-left"];
+ $r2 = $radius["top-right"];
+ break;
+
+ case "bottom":
+ $length = $w;
+ $y += $h;
+ $r1 = $radius["bottom-left"];
+ $r2 = $radius["bottom-right"];
+ break;
+
+ case "left":
+ $length = $h;
+ $r1 = $radius["top-left"];
+ $r2 = $radius["bottom-left"];
+ break;
+
+ case "right":
+ $length = $h;
+ $x += $w;
+ $r1 = $radius["top-right"];
+ $r2 = $radius["bottom-right"];
+ break;
+ default:
+ break;
+ }
+ $method = "_border_" . $props["style"];
+
+ // draw rounded corners
+ $this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style, $r1, $r2);
+ }
+ }
+
+ protected function _render_outline(AbstractFrameDecorator $frame, $border_box = null, $corner_style = "bevel")
+ {
+ $style = $frame->get_style();
+
+ $props = array(
+ "width" => $style->outline_width,
+ "style" => $style->outline_style,
+ "color" => $style->outline_color,
+ );
+
+ if (!$props["style"] || $props["style"] === "none" || $props["width"] <= 0)
+ return;
+
+ if (empty($border_box)) {
+ $border_box = $frame->get_border_box();
+ }
+
+ $offset = $style->length_in_pt($props["width"]);
+ $pattern = $this->_get_dash_pattern($props["style"], $offset);
+
+ // If the outline style is "solid" we'd better draw a rectangle
+ if (in_array($props["style"], array("solid", "dashed", "dotted"))) {
+ $border_box[0] -= $offset / 2;
+ $border_box[1] -= $offset / 2;
+ $border_box[2] += $offset;
+ $border_box[3] += $offset;
+
+ list($x, $y, $w, $h) = $border_box;
+ $this->_canvas->rectangle($x, $y, $w, $h, $props["color"], $offset, $pattern);
+ return;
+ }
+
+ $border_box[0] -= $offset;
+ $border_box[1] -= $offset;
+ $border_box[2] += $offset * 2;
+ $border_box[3] += $offset * 2;
+
+ $method = "_border_" . $props["style"];
+ $widths = array_fill(0, 4, $props["width"]);
+ $sides = array("top", "right", "left", "bottom");
+ $length = 0;
+
+ foreach ($sides as $side) {
+ list($x, $y, $w, $h) = $border_box;
+
+ switch ($side) {
+ case "top":
+ $length = $w;
+ break;
+
+ case "bottom":
+ $length = $w;
+ $y += $h;
+ break;
+
+ case "left":
+ $length = $h;
+ break;
+
+ case "right":
+ $length = $h;
+ $x += $w;
+ break;
+ default:
+ break;
+ }
+
+ $this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style);
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/Image.php b/library/vendor/dompdf/src/Renderer/Image.php
new file mode 100644
index 000000000..1630794a4
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/Image.php
@@ -0,0 +1,125 @@
+
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Frame;
+use Dompdf\Image\Cache;
+
+/**
+ * Image renderer
+ *
+ * @access private
+ * @package dompdf
+ */
+class Image extends Block
+{
+
+ function render(Frame $frame)
+ {
+ // Render background & borders
+ $style = $frame->get_style();
+ $cb = $frame->get_containing_block();
+ list($x, $y, $w, $h) = $frame->get_border_box();
+
+ $this->_set_opacity($frame->get_opacity($style->opacity));
+
+ list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
+
+ $has_border_radius = $tl + $tr + $br + $bl > 0;
+
+ if ($has_border_radius) {
+ $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
+ }
+
+ if (($bg = $style->background_color) !== "transparent") {
+ $this->_canvas->filled_rectangle($x, $y, $w, $h, $bg);
+ }
+
+ if (($url = $style->background_image) && $url !== "none") {
+ $this->_background_image($url, $x, $y, $w, $h, $style);
+ }
+
+ if ($has_border_radius) {
+ $this->_canvas->clipping_end();
+ }
+
+ $this->_render_border($frame);
+ $this->_render_outline($frame);
+
+ list($x, $y) = $frame->get_padding_box();
+
+ $x += $style->length_in_pt($style->padding_left, $cb["w"]);
+ $y += $style->length_in_pt($style->padding_top, $cb["h"]);
+
+ $w = $style->length_in_pt($style->width, $cb["w"]);
+ $h = $style->length_in_pt($style->height, $cb["h"]);
+
+ if ($has_border_radius) {
+ list($wt, $wr, $wb, $wl) = array(
+ $style->border_top_width,
+ $style->border_right_width,
+ $style->border_bottom_width,
+ $style->border_left_width,
+ );
+
+ // we have to get the "inner" radius
+ if ($tl > 0) {
+ $tl -= ($wt + $wl) / 2;
+ }
+ if ($tr > 0) {
+ $tr -= ($wt + $wr) / 2;
+ }
+ if ($br > 0) {
+ $br -= ($wb + $wr) / 2;
+ }
+ if ($bl > 0) {
+ $bl -= ($wb + $wl) / 2;
+ }
+
+ $this->_canvas->clipping_roundrectangle($x, $y, $w, $h, $tl, $tr, $br, $bl);
+ }
+
+ $src = $frame->get_image_url();
+ $alt = null;
+
+ if (Cache::is_broken($src) &&
+ $alt = $frame->get_node()->getAttribute("alt")
+ ) {
+ $font = $style->font_family;
+ $size = $style->font_size;
+ $spacing = $style->word_spacing;
+ $this->_canvas->text($x, $y, $alt,
+ $font, $size,
+ $style->color, $spacing);
+ } else {
+ $this->_canvas->image($src, $x, $y, $w, $h, $style->image_resolution);
+ }
+
+ if ($has_border_radius) {
+ $this->_canvas->clipping_end();
+ }
+
+ if ($msg = $frame->get_image_msg()) {
+ $parts = preg_split("/\s*\n\s*/", $msg);
+ $height = 10;
+ $_y = $alt ? $y + $h - count($parts) * $height : $y;
+
+ foreach ($parts as $i => $_part) {
+ $this->_canvas->text($x, $_y + $i * $height, $_part, "times", $height * 0.8, array(0.5, 0.5, 0.5));
+ }
+ }
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutBlocks")) {
+ $this->_debug_layout($frame->get_border_box(), "blue");
+ if ($this->_dompdf->get_option("debugLayoutPaddingBox")) {
+ $this->_debug_layout($frame->get_padding_box(), "blue", array(0.5, 0.5));
+ }
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/Inline.php b/library/vendor/dompdf/src/Renderer/Inline.php
new file mode 100644
index 000000000..a7c8fd107
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/Inline.php
@@ -0,0 +1,198 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Frame;
+use Dompdf\Helpers;
+
+/**
+ * Renders inline frames
+ *
+ * @access private
+ * @package dompdf
+ */
+class Inline extends AbstractRenderer
+{
+
+ //........................................................................
+
+ function render(Frame $frame)
+ {
+ $style = $frame->get_style();
+
+ if (!$frame->get_first_child())
+ return; // No children, no service
+
+ // Draw the left border if applicable
+ $bp = $style->get_border_properties();
+ $widths = array($style->length_in_pt($bp["top"]["width"]),
+ $style->length_in_pt($bp["right"]["width"]),
+ $style->length_in_pt($bp["bottom"]["width"]),
+ $style->length_in_pt($bp["left"]["width"]));
+
+ // Draw the background & border behind each child. To do this we need
+ // to figure out just how much space each child takes:
+ list($x, $y) = $frame->get_first_child()->get_position();
+ $w = null;
+ $h = 0;
+// $x += $widths[3];
+// $y += $widths[0];
+
+ $this->_set_opacity($frame->get_opacity($style->opacity));
+
+ $first_row = true;
+
+ foreach ($frame->get_children() as $child) {
+ list($child_x, $child_y, $child_w, $child_h) = $child->get_padding_box();
+
+ if (!is_null($w) && $child_x < $x + $w) {
+ //This branch seems to be supposed to being called on the first part
+ //of an inline html element, and the part after the if clause for the
+ //parts after a line break.
+ //But because $w initially mostly is 0, and gets updated only on the next
+ //round, this seem to be never executed and the common close always.
+
+ // The next child is on another line. Draw the background &
+ // borders on this line.
+
+ // Background:
+ if (($bg = $style->background_color) !== "transparent")
+ $this->_canvas->filled_rectangle($x, $y, $w, $h, $bg);
+
+ if (($url = $style->background_image) && $url !== "none") {
+ $this->_background_image($url, $x, $y, $w, $h, $style);
+ }
+
+ // If this is the first row, draw the left border
+ if ($first_row) {
+
+ if ($bp["left"]["style"] !== "none" && $bp["left"]["color"] !== "transparent" && $bp["left"]["width"] > 0) {
+ $method = "_border_" . $bp["left"]["style"];
+ $this->$method($x, $y, $h + $widths[0] + $widths[2], $bp["left"]["color"], $widths, "left");
+ }
+ $first_row = false;
+ }
+
+ // Draw the top & bottom borders
+ if ($bp["top"]["style"] !== "none" && $bp["top"]["color"] !== "transparent" && $bp["top"]["width"] > 0) {
+ $method = "_border_" . $bp["top"]["style"];
+ $this->$method($x, $y, $w + $widths[1] + $widths[3], $bp["top"]["color"], $widths, "top");
+ }
+
+ if ($bp["bottom"]["style"] !== "none" && $bp["bottom"]["color"] !== "transparent" && $bp["bottom"]["width"] > 0) {
+ $method = "_border_" . $bp["bottom"]["style"];
+ $this->$method($x, $y + $h + $widths[0] + $widths[2], $w + $widths[1] + $widths[3], $bp["bottom"]["color"], $widths, "bottom");
+ }
+
+ // Handle anchors & links
+ $link_node = null;
+ if ($frame->get_node()->nodeName === "a") {
+ $link_node = $frame->get_node();
+ } else if ($frame->get_parent()->get_node()->nodeName === "a") {
+ $link_node = $frame->get_parent()->get_node();
+ }
+
+ if ($link_node && $href = $link_node->getAttribute("href")) {
+ $href = Helpers::build_url($this->_dompdf->getProtocol(), $this->_dompdf->getBaseHost(), $this->_dompdf->getBasePath(), $href);
+ $this->_canvas->add_link($href, $x, $y, $w, $h);
+ }
+
+ $x = $child_x;
+ $y = $child_y;
+ $w = $child_w;
+ $h = $child_h;
+ continue;
+ }
+
+ if (is_null($w))
+ $w = $child_w;
+ else
+ $w += $child_w;
+
+ $h = max($h, $child_h);
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutInline")) {
+ $this->_debug_layout($child->get_border_box(), "blue");
+ if ($this->_dompdf->get_option("debugLayoutPaddingBox")) {
+ $this->_debug_layout($child->get_padding_box(), "blue", array(0.5, 0.5));
+ }
+ }
+ }
+
+
+ // Handle the last child
+ if (($bg = $style->background_color) !== "transparent")
+ $this->_canvas->filled_rectangle($x + $widths[3], $y + $widths[0], $w, $h, $bg);
+
+ //On continuation lines (after line break) of inline elements, the style got copied.
+ //But a non repeatable background image should not be repeated on the next line.
+ //But removing the background image above has never an effect, and removing it below
+ //removes it always, even on the initial line.
+ //Need to handle it elsewhere, e.g. on certain ...clone()... usages.
+ // Repeat not given: default is Style::__construct
+ // ... && (!($repeat = $style->background_repeat) || $repeat === "repeat" ...
+ //different position? $this->_background_image($url, $x, $y, $w, $h, $style);
+ if (($url = $style->background_image) && $url !== "none")
+ $this->_background_image($url, $x + $widths[3], $y + $widths[0], $w, $h, $style);
+
+ // Add the border widths
+ $w += $widths[1] + $widths[3];
+ $h += $widths[0] + $widths[2];
+
+ // make sure the border and background start inside the left margin
+ $left_margin = $style->length_in_pt($style->margin_left);
+ $x += $left_margin;
+
+ // If this is the first row, draw the left border too
+ if ($first_row && $bp["left"]["style"] !== "none" && $bp["left"]["color"] !== "transparent" && $widths[3] > 0) {
+ $method = "_border_" . $bp["left"]["style"];
+ $this->$method($x, $y, $h, $bp["left"]["color"], $widths, "left");
+ }
+
+ // Draw the top & bottom borders
+ if ($bp["top"]["style"] !== "none" && $bp["top"]["color"] !== "transparent" && $widths[0] > 0) {
+ $method = "_border_" . $bp["top"]["style"];
+ $this->$method($x, $y, $w, $bp["top"]["color"], $widths, "top");
+ }
+
+ if ($bp["bottom"]["style"] !== "none" && $bp["bottom"]["color"] !== "transparent" && $widths[2] > 0) {
+ $method = "_border_" . $bp["bottom"]["style"];
+ $this->$method($x, $y + $h, $w, $bp["bottom"]["color"], $widths, "bottom");
+ }
+
+ // Helpers::var_dump(get_class($frame->get_next_sibling()));
+ // $last_row = get_class($frame->get_next_sibling()) !== 'Inline';
+ // Draw the right border if this is the last row
+ if ($bp["right"]["style"] !== "none" && $bp["right"]["color"] !== "transparent" && $widths[1] > 0) {
+ $method = "_border_" . $bp["right"]["style"];
+ $this->$method($x + $w, $y, $h, $bp["right"]["color"], $widths, "right");
+ }
+
+ // Only two levels of links frames
+ $link_node = null;
+ if ($frame->get_node()->nodeName === "a") {
+ $link_node = $frame->get_node();
+
+ if (($name = $link_node->getAttribute("name")) || ($name = $link_node->getAttribute("id"))) {
+ $this->_canvas->add_named_dest($name);
+ }
+ }
+
+ if ($frame->get_parent() && $frame->get_parent()->get_node()->nodeName === "a") {
+ $link_node = $frame->get_parent()->get_node();
+ }
+
+ // Handle anchors & links
+ if ($link_node) {
+ if ($href = $link_node->getAttribute("href")) {
+ $href = Helpers::build_url($this->_dompdf->getProtocol(), $this->_dompdf->getBaseHost(), $this->_dompdf->getBasePath(), $href);
+ $this->_canvas->add_link($href, $x, $y, $w, $h);
+ }
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/ListBullet.php b/library/vendor/dompdf/src/Renderer/ListBullet.php
new file mode 100644
index 000000000..c7fcc89b5
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/ListBullet.php
@@ -0,0 +1,248 @@
+
+ * @author Helmut Tischer
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Helpers;
+use Dompdf\FontMetrics;
+use Dompdf\Frame;
+use Dompdf\Image\Cache;
+use Dompdf\FrameDecorator\ListBullet as ListBulletFrameDecorator;
+
+/**
+ * Renders list bullets
+ *
+ * @access private
+ * @package dompdf
+ */
+class ListBullet extends AbstractRenderer
+{
+ static function get_counter_chars($type)
+ {
+ static $cache = array();
+
+ if (isset($cache[$type])) {
+ return $cache[$type];
+ }
+
+ $uppercase = false;
+ $text = "";
+
+ switch ($type) {
+ case "decimal-leading-zero":
+ case "decimal":
+ case "1":
+ return "0123456789";
+
+ case "upper-alpha":
+ case "upper-latin":
+ case "A":
+ $uppercase = true;
+ case "lower-alpha":
+ case "lower-latin":
+ case "a":
+ $text = "abcdefghijklmnopqrstuvwxyz";
+ break;
+
+ case "upper-roman":
+ case "I":
+ $uppercase = true;
+ case "lower-roman":
+ case "i":
+ $text = "ivxlcdm";
+ break;
+
+ case "lower-greek":
+ for ($i = 0; $i < 24; $i++) {
+ $text .= Helpers::unichr($i + 944);
+ }
+ break;
+ }
+
+ if ($uppercase) {
+ $text = strtoupper($text);
+ }
+
+ return $cache[$type] = "$text.";
+ }
+
+ /**
+ * @param integer $n
+ * @param string $type
+ * @param integer $pad
+ *
+ * @return string
+ */
+ private function make_counter($n, $type, $pad = null)
+ {
+ $n = intval($n);
+ $text = "";
+ $uppercase = false;
+
+ switch ($type) {
+ case "decimal-leading-zero":
+ case "decimal":
+ case "1":
+ if ($pad)
+ $text = str_pad($n, $pad, "0", STR_PAD_LEFT);
+ else
+ $text = $n;
+ break;
+
+ case "upper-alpha":
+ case "upper-latin":
+ case "A":
+ $uppercase = true;
+ case "lower-alpha":
+ case "lower-latin":
+ case "a":
+ $text = chr(($n % 26) + ord('a') - 1);
+ break;
+
+ case "upper-roman":
+ case "I":
+ $uppercase = true;
+ case "lower-roman":
+ case "i":
+ $text = Helpers::dec2roman($n);
+ break;
+
+ case "lower-greek":
+ $text = Helpers::unichr($n + 944);
+ break;
+ }
+
+ if ($uppercase) {
+ $text = strtoupper($text);
+ }
+
+ return "$text.";
+ }
+
+ function render(Frame $frame)
+ {
+ $style = $frame->get_style();
+ $font_size = $style->get_font_size();
+ $line_height = $style->length_in_pt($style->line_height, $frame->get_containing_block("w"));
+
+ $this->_set_opacity($frame->get_opacity($style->opacity));
+
+ $li = $frame->get_parent();
+
+ // Don't render bullets twice if if was split
+ if ($li->_splitted) {
+ return;
+ }
+
+ // Handle list-style-image
+ // If list style image is requested but missing, fall back to predefined types
+ if ($style->list_style_image !== "none" &&
+ !Cache::is_broken($img = $frame->get_image_url())
+ ) {
+
+ list($x, $y) = $frame->get_position();
+
+ //For expected size and aspect, instead of box size, use image natural size scaled to DPI.
+ // Resample the bullet image to be consistent with 'auto' sized images
+ // See also Image::get_min_max_width
+ // Tested php ver: value measured in px, suffix "px" not in value: rtrim unnecessary.
+ //$w = $frame->get_width();
+ //$h = $frame->get_height();
+ list($width, $height) = Helpers::dompdf_getimagesize($img, $this->_dompdf->getHttpContext());
+ $dpi = $this->_dompdf->get_option("dpi");
+ $w = ((float)rtrim($width, "px") * 72) / $dpi;
+ $h = ((float)rtrim($height, "px") * 72) / $dpi;
+
+ $x -= $w;
+ $y -= ($line_height - $font_size) / 2; //Reverse hinting of list_bullet_positioner
+
+ $this->_canvas->image($img, $x, $y, $w, $h);
+
+ } else {
+
+ $bullet_style = $style->list_style_type;
+
+ $fill = false;
+
+ switch ($bullet_style) {
+
+ default:
+ case "disc":
+ $fill = true;
+
+ case "circle":
+ list($x, $y) = $frame->get_position();
+ $r = ($font_size * (ListBulletFrameDecorator::BULLET_SIZE /*-ListBulletFrameDecorator::BULLET_THICKNESS*/)) / 2;
+ $x -= $font_size * (ListBulletFrameDecorator::BULLET_SIZE / 2);
+ $y += ($font_size * (1 - ListBulletFrameDecorator::BULLET_DESCENT)) / 2;
+ $o = $font_size * ListBulletFrameDecorator::BULLET_THICKNESS;
+ $this->_canvas->circle($x, $y, $r, $style->color, $o, null, $fill);
+ break;
+
+ case "square":
+ list($x, $y) = $frame->get_position();
+ $w = $font_size * ListBulletFrameDecorator::BULLET_SIZE;
+ $x -= $w;
+ $y += ($font_size * (1 - ListBulletFrameDecorator::BULLET_DESCENT - ListBulletFrameDecorator::BULLET_SIZE)) / 2;
+ $this->_canvas->filled_rectangle($x, $y, $w, $w, $style->color);
+ break;
+
+ case "decimal-leading-zero":
+ case "decimal":
+ case "lower-alpha":
+ case "lower-latin":
+ case "lower-roman":
+ case "lower-greek":
+ case "upper-alpha":
+ case "upper-latin":
+ case "upper-roman":
+ case "1": // HTML 4.0 compatibility
+ case "a":
+ case "i":
+ case "A":
+ case "I":
+ $pad = null;
+ if ($bullet_style === "decimal-leading-zero") {
+ $pad = strlen($li->get_parent()->get_node()->getAttribute("dompdf-children-count"));
+ }
+
+ $node = $frame->get_node();
+
+ if (!$node->hasAttribute("dompdf-counter")) {
+ return;
+ }
+
+ $index = $node->getAttribute("dompdf-counter");
+ $text = $this->make_counter($index, $bullet_style, $pad);
+
+ if (trim($text) == "") {
+ return;
+ }
+
+ $spacing = 0;
+ $font_family = $style->font_family;
+
+ $line = $li->get_containing_line();
+ list($x, $y) = array($frame->get_position("x"), $line->y);
+
+ $x -= $this->_dompdf->getFontMetrics()->getTextWidth($text, $font_family, $font_size, $spacing);
+
+ // Take line-height into account
+ $line_height = $style->line_height;
+ $y += ($line_height - $font_size) / 4; // FIXME I thought it should be 2, but 4 gives better results
+
+ $this->_canvas->text($x, $y, $text,
+ $font_family, $font_size,
+ $style->color, $spacing);
+
+ case "none":
+ break;
+ }
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/TableCell.php b/library/vendor/dompdf/src/Renderer/TableCell.php
new file mode 100644
index 000000000..541b9cd7c
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/TableCell.php
@@ -0,0 +1,160 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Frame;
+use Dompdf\FrameDecorator\Table;
+
+/**
+ * Renders table cells
+ *
+ * @package dompdf
+ */
+class TableCell extends Block
+{
+
+ //........................................................................
+
+ function render(Frame $frame)
+ {
+ $style = $frame->get_style();
+
+ if (trim($frame->get_node()->nodeValue) === "" && $style->empty_cells === "hide") {
+ return;
+ }
+
+ $this->_set_opacity($frame->get_opacity($style->opacity));
+ list($x, $y, $w, $h) = $frame->get_border_box();
+
+ // Draw our background, border and content
+ if (($bg = $style->background_color) !== "transparent") {
+ $this->_canvas->filled_rectangle($x, $y, $w, $h, $bg);
+ }
+
+ if (($url = $style->background_image) && $url !== "none") {
+ $this->_background_image($url, $x, $y, $w, $h, $style);
+ }
+
+ $table = Table::find_parent_table($frame);
+
+ if ($table->get_style()->border_collapse !== "collapse") {
+ $this->_render_border($frame);
+ $this->_render_outline($frame);
+ return;
+ }
+
+ // The collapsed case is slightly complicated...
+ // @todo Add support for outlines here
+
+ $cellmap = $table->get_cellmap();
+ $cells = $cellmap->get_spanned_cells($frame);
+ $num_rows = $cellmap->get_num_rows();
+ $num_cols = $cellmap->get_num_cols();
+
+ // Determine the top row spanned by this cell
+ $i = $cells["rows"][0];
+ $top_row = $cellmap->get_row($i);
+
+ // Determine if this cell borders on the bottom of the table. If so,
+ // then we draw its bottom border. Otherwise the next row down will
+ // draw its top border instead.
+ if (in_array($num_rows - 1, $cells["rows"])) {
+ $draw_bottom = true;
+ $bottom_row = $cellmap->get_row($num_rows - 1);
+ } else
+ $draw_bottom = false;
+
+
+ // Draw the horizontal borders
+ foreach ($cells["columns"] as $j) {
+ $bp = $cellmap->get_border_properties($i, $j);
+
+ $y = $top_row["y"] - $bp["top"]["width"] / 2;
+
+ $col = $cellmap->get_column($j);
+ $x = $col["x"] - $bp["left"]["width"] / 2;
+ $w = $col["used-width"] + ($bp["left"]["width"] + $bp["right"]["width"]) / 2;
+
+ if ($bp["top"]["style"] !== "none" && $bp["top"]["width"] > 0) {
+ $widths = array($bp["top"]["width"],
+ $bp["right"]["width"],
+ $bp["bottom"]["width"],
+ $bp["left"]["width"]);
+ $method = "_border_" . $bp["top"]["style"];
+ $this->$method($x, $y, $w, $bp["top"]["color"], $widths, "top", "square");
+ }
+
+ if ($draw_bottom) {
+ $bp = $cellmap->get_border_properties($num_rows - 1, $j);
+ if ($bp["bottom"]["style"] === "none" || $bp["bottom"]["width"] <= 0)
+ continue;
+
+ $y = $bottom_row["y"] + $bottom_row["height"] + $bp["bottom"]["width"] / 2;
+
+ $widths = array($bp["top"]["width"],
+ $bp["right"]["width"],
+ $bp["bottom"]["width"],
+ $bp["left"]["width"]);
+ $method = "_border_" . $bp["bottom"]["style"];
+ $this->$method($x, $y, $w, $bp["bottom"]["color"], $widths, "bottom", "square");
+
+ }
+ }
+
+ $j = $cells["columns"][0];
+
+ $left_col = $cellmap->get_column($j);
+
+ if (in_array($num_cols - 1, $cells["columns"])) {
+ $draw_right = true;
+ $right_col = $cellmap->get_column($num_cols - 1);
+ } else
+ $draw_right = false;
+
+ // Draw the vertical borders
+ foreach ($cells["rows"] as $i) {
+ $bp = $cellmap->get_border_properties($i, $j);
+
+ $x = $left_col["x"] - $bp["left"]["width"] / 2;
+
+ $row = $cellmap->get_row($i);
+
+ $y = $row["y"] - $bp["top"]["width"] / 2;
+ $h = $row["height"] + ($bp["top"]["width"] + $bp["bottom"]["width"]) / 2;
+
+ if ($bp["left"]["style"] !== "none" && $bp["left"]["width"] > 0) {
+
+ $widths = array($bp["top"]["width"],
+ $bp["right"]["width"],
+ $bp["bottom"]["width"],
+ $bp["left"]["width"]);
+
+ $method = "_border_" . $bp["left"]["style"];
+ $this->$method($x, $y, $h, $bp["left"]["color"], $widths, "left", "square");
+ }
+
+ if ($draw_right) {
+ $bp = $cellmap->get_border_properties($i, $num_cols - 1);
+ if ($bp["right"]["style"] === "none" || $bp["right"]["width"] <= 0)
+ continue;
+
+ $x = $right_col["x"] + $right_col["used-width"] + $bp["right"]["width"] / 2;
+
+ $widths = array($bp["top"]["width"],
+ $bp["right"]["width"],
+ $bp["bottom"]["width"],
+ $bp["left"]["width"]);
+
+ $method = "_border_" . $bp["right"]["style"];
+ $this->$method($x, $y, $h, $bp["right"]["color"], $widths, "right", "square");
+
+ }
+ }
+
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/TableRowGroup.php b/library/vendor/dompdf/src/Renderer/TableRowGroup.php
new file mode 100644
index 000000000..9b29babfd
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/TableRowGroup.php
@@ -0,0 +1,44 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Frame;
+
+/**
+ * Renders block frames
+ *
+ * @package dompdf
+ */
+class TableRowGroup extends Block
+{
+
+ //........................................................................
+
+ function render(Frame $frame)
+ {
+ $style = $frame->get_style();
+
+ $this->_set_opacity($frame->get_opacity($style->opacity));
+
+ $this->_render_border($frame);
+ $this->_render_outline($frame);
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutBlocks")) {
+ $this->_debug_layout($frame->get_border_box(), "red");
+ if ($this->_dompdf->get_option("debugLayoutPaddingBox")) {
+ $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
+ }
+ }
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutLines") && $frame->get_decorator()) {
+ foreach ($frame->get_decorator()->get_line_boxes() as $line) {
+ $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
+ }
+ }
+ }
+}
diff --git a/library/vendor/dompdf/src/Renderer/Text.php b/library/vendor/dompdf/src/Renderer/Text.php
new file mode 100644
index 000000000..3072a1792
--- /dev/null
+++ b/library/vendor/dompdf/src/Renderer/Text.php
@@ -0,0 +1,158 @@
+
+ * @author Helmut Tischer
+ * @author Fabien Ménager
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+namespace Dompdf\Renderer;
+
+use Dompdf\Adapter\CPDF;
+use Dompdf\FontMetrics;
+use Dompdf\Frame;
+
+/**
+ * Renders text frames
+ *
+ * @package dompdf
+ */
+class Text extends AbstractRenderer
+{
+
+ const DECO_THICKNESS = 0.02; // Thickness of underline. Screen: 0.08, print: better less, e.g. 0.04
+
+ //Tweaking if $base and $descent are not accurate.
+ //Check method_exists( $this->_canvas, "get_cpdf" )
+ //- For cpdf these can and must stay 0, because font metrics are used directly.
+ //- For other renderers, if different values are wanted, separate the parameter sets.
+ // But $size and $size-$height seem to be accurate enough
+ const UNDERLINE_OFFSET = 0.0; // Relative to bottom of text, as fraction of height.
+ const OVERLINE_OFFSET = 0.0; // Relative to top of text
+ const LINETHROUGH_OFFSET = 0.0; // Relative to centre of text.
+ const DECO_EXTENSION = 0.0; // How far to extend lines past either end, in pt
+
+ //........................................................................
+
+ /**
+ * @param \Dompdf\FrameDecorator\Text $frame
+ */
+ function render(Frame $frame)
+ {
+ $text = $frame->get_text();
+ if (trim($text) === "")
+ return;
+
+ $style = $frame->get_style();
+ list($x, $y) = $frame->get_position();
+ $cb = $frame->get_containing_block();
+
+ if (($ml = $style->margin_left) === "auto" || $ml === "none")
+ $ml = 0;
+
+ if (($pl = $style->padding_left) === "auto" || $pl === "none")
+ $pl = 0;
+
+ if (($bl = $style->border_left_width) === "auto" || $bl === "none")
+ $bl = 0;
+
+ $x += $style->length_in_pt(array($ml, $pl, $bl), $cb["w"]);
+
+ $font = $style->font_family;
+ $size = $frame_font_size = $style->font_size;
+ $height = $style->height;
+ $word_spacing = $frame->get_text_spacing() + $style->length_in_pt($style->word_spacing);
+ $char_spacing = $style->length_in_pt($style->letter_spacing);
+ $width = $style->width;
+
+ /*$text = str_replace(
+ array("{PAGE_NUM}"),
+ array($this->_canvas->get_page_number()),
+ $text
+ );*/
+
+ $this->_canvas->text($x, $y, $text,
+ $font, $size,
+ $style->color, $word_spacing, $char_spacing);
+
+ $line = $frame->get_containing_line();
+
+ // FIXME Instead of using the tallest frame to position,
+ // the decoration, the text should be well placed
+ if (false && $line->tallest_frame) {
+ $base_frame = $line->tallest_frame;
+ $style = $base_frame->get_style();
+ $size = $style->font_size;
+ $height = $line->h * ($size / $style->line_height);
+ }
+
+ $line_thickness = $size * self::DECO_THICKNESS;
+ $underline_offset = $size * self::UNDERLINE_OFFSET;
+ $overline_offset = $size * self::OVERLINE_OFFSET;
+ $linethrough_offset = $size * self::LINETHROUGH_OFFSET;
+ $underline_position = -0.08;
+
+ if ($this->_canvas instanceof CPDF) {
+ $cpdf_font = $this->_canvas->get_cpdf()->fonts[$style->font_family];
+
+ if (isset($cpdf_font["UnderlinePosition"])) {
+ $underline_position = $cpdf_font["UnderlinePosition"] / 1000;
+ }
+
+ if (isset($cpdf_font["UnderlineThickness"])) {
+ $line_thickness = $size * ($cpdf_font["UnderlineThickness"] / 1000);
+ }
+ }
+
+ $descent = $size * $underline_position;
+ $base = $size;
+
+ // Handle text decoration:
+ // http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration
+
+ // Draw all applicable text-decorations. Start with the root and work our way down.
+ $p = $frame;
+ $stack = array();
+ while ($p = $p->get_parent())
+ $stack[] = $p;
+
+ while (isset($stack[0])) {
+ $f = array_pop($stack);
+
+ if (($text_deco = $f->get_style()->text_decoration) === "none")
+ continue;
+
+ $deco_y = $y; //$line->y;
+ $color = $f->get_style()->color;
+
+ switch ($text_deco) {
+
+ default:
+ continue;
+
+ case "underline":
+ $deco_y += $base - $descent + $underline_offset + $line_thickness / 2;
+ break;
+
+ case "overline":
+ $deco_y += $overline_offset + $line_thickness / 2;
+ break;
+
+ case "line-through":
+ $deco_y += $base * 0.7 + $linethrough_offset;
+ break;
+ }
+
+ $dx = 0;
+ $x1 = $x - self::DECO_EXTENSION;
+ $x2 = $x + $width + $dx + self::DECO_EXTENSION;
+ $this->_canvas->line($x1, $deco_y, $x2, $deco_y, $color, $line_thickness);
+ }
+
+ if ($this->_dompdf->get_option("debugLayout") && $this->_dompdf->get_option("debugLayoutLines")) {
+ $text_width = $this->_dompdf->getFontMetrics()->getTextWidth($text, $font, $frame_font_size);
+ $this->_debug_layout(array($x, $y, $text_width + ($line->wc - 1) * $word_spacing, $frame_font_size), "orange", array(0.5, 0.5));
+ }
+ }
+}
diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php
index fafd94656..030e90465 100644
--- a/modules/doc/application/controllers/ModuleController.php
+++ b/modules/doc/application/controllers/ModuleController.php
@@ -91,7 +91,7 @@ class ModuleController extends DocController
$module = $this->params->getRequired('moduleName');
$this->assertModuleInstalled($module);
$moduleManager = Icinga::app()->getModuleManager();
- $name = $moduleManager->getModule($module)->getTitle();
+ $name = $moduleManager->getModule($module, false)->getTitle();
try {
$this->renderToc(
$this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
diff --git a/modules/doc/public/img/doc/markdown.png b/modules/doc/doc/img/markdown.png
similarity index 100%
rename from modules/doc/public/img/doc/markdown.png
rename to modules/doc/doc/img/markdown.png
diff --git a/modules/doc/module.info b/modules/doc/module.info
index e69a16605..10d96a7cf 100644
--- a/modules/doc/module.info
+++ b/modules/doc/module.info
@@ -1,4 +1,4 @@
Module: doc
-Version: 2.3.2
+Version: 2.3.4
Description: Documentation module
Extracts, shows and exports documentation for Icinga Web 2 and its modules.
diff --git a/modules/monitoring/application/controllers/ActionsController.php b/modules/monitoring/application/controllers/ActionsController.php
index 06bbc8e61..1ec5fe102 100644
--- a/modules/monitoring/application/controllers/ActionsController.php
+++ b/modules/monitoring/application/controllers/ActionsController.php
@@ -61,7 +61,7 @@ class Monitoring_ActionsController extends Controller
$filter = $this->getFilterOrExitIfEmpty();
$downtimes = $this->backend
->select()
- ->from('downtime', array('host_name', 'id' => 'downtime_internal_id'))
+ ->from('downtime', array('host_name', 'id' => 'downtime_internal_id', 'name' => 'downtime_name'))
->where('object_type', 'host')
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->applyFilter($filter);
@@ -110,7 +110,10 @@ class Monitoring_ActionsController extends Controller
$filter = $this->getFilterOrExitIfEmpty();
$downtimes = $this->backend
->select()
- ->from('downtime', array('host_name', 'service_description', 'id' => 'downtime_internal_id'))
+ ->from(
+ 'downtime',
+ array('host_name', 'service_description', 'id' => 'downtime_internal_id', 'name' => 'downtime_name')
+ )
->where('object_type', 'service')
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->applyFilter($filter);
diff --git a/modules/monitoring/application/controllers/ChartController.php b/modules/monitoring/application/controllers/ChartController.php
deleted file mode 100644
index a92a8bcdb..000000000
--- a/modules/monitoring/application/controllers/ChartController.php
+++ /dev/null
@@ -1,405 +0,0 @@
-alignTopLeft();
- $chart->setAxisLabel('X axis label', 'Y axis label')
- ->setYAxis(new LogarithmicUnit());
-
- for ($i = -15; $i < 15; $i++) {
- $data1[] = array($i, -$i * rand(1, 10) * pow(2, rand(1, 2)));
- }
- for ($i = -15; $i < 15; $i++) {
- $data2[] = array($i, 1000 + $i * rand(1, 35) * pow(2, rand(1, 2)));
- }
- for ($i = -15; $i < 15; $i++) {
- $data3[] = array($i, $i * rand(1, 100) * pow(2, rand(1, 10)) - 1000);
- }
-
- $chart->drawLines(
- array(
- 'label' => 'Random 1',
- 'color' => '#F56',
- 'data' => $data1,
- 'showPoints' => true
- )
- );
- $chart->drawLines(
- array(
- 'label' => 'Random 2',
- 'color' => '#fa4',
- 'data' => $data2,
- 'showPoints' => true
- )
- );
- $chart->drawLines(
- array(
- 'label' => 'Random 3',
- 'color' => '#4b7',
- 'data' => $data3,
- 'showPoints' => true
- )
- );
- return $chart;
- }
-
- private function drawLogChart2()
- {
- $chart = new GridChart();
- $chart->alignTopLeft();
- $chart->setAxisLabel('X axis label', 'Y axis label')
- ->setYAxis(new LogarithmicUnit());
-
- for ($i = -10; $i < 10; $i++) {
- $sign = $i > 0 ? 1 :
- ($i < 0 ? -1 : 0);
- $data[] = array($i, $sign * pow(10, abs($i)));
- }
- $chart->drawLines(
- array(
- 'label' => 'f(x): sign(x) * 10^|x|',
- 'color' => '#F56',
- 'data' => $data,
- 'showPoints' => true
- )
- );
- return $chart;
- }
- private function drawLogChart3()
- {
- $chart = new GridChart();
- $chart->alignTopLeft();
- $chart->setAxisLabel('X axis label', 'Y axis label')
- ->setYAxis(new LogarithmicUnit());
-
- for ($i = -2; $i < 3; $i++) {
- $sign = $i > 0 ? 1 :
- ($i < 0 ? -1 : 0);
- $data[] = array($i, $sign * pow(10, abs($i)));
- }
- $chart->drawLines(
- array(
- 'label' => 'f(x): sign(x) * 10^|x|',
- 'color' => '#F56',
- 'data' => $data,
- 'showPoints' => true
- )
- );
- return $chart;
- }
-
- public function testAction()
- {
- $this->chart = new GridChart();
- $this->chart->alignTopLeft();
- $this->chart->setAxisLabel('X axis label', 'Y axis label')->setXAxis(new StaticAxis());
- $data1 = array();
- $data2 = array();
- $data3 = array();
- for ($i = 0; $i < 50; $i++) {
- $data3[] = array('Label ' . $i, rand(0, 30));
- }
-
- /*
- $this->chart->drawLines(
- array(
- 'label' => 'Nr of outtakes',
- 'color' => '#F56',
- 'width' => '5',
-
- 'data' => $data
- ), array(
- 'label' => 'Some line',
- 'color' => '#fa4',
- 'width' => '4',
-
- 'data' => $data3,
- 'showPoints' => true
- )
- );
-*/
- $this->chart->drawBars(
- array(
- 'label' => 'A big amount of data',
- 'color' => '#4b7',
- 'data' => $data3,
- 'showPoints' => true
- )
- );
-/*
- $this->chart->drawLines(
- array(
- 'label' => 'Nr of outtakes',
- 'color' => 'yellow',
- 'width' => '5',
- 'data' => $data2
- )
- );
-*/
- $this->view->svgs = array();
- $this->view->svgs[] = $this->drawLogChart1();
- $this->view->svgs[] = $this->drawLogChart2();
- $this->view->svgs[] = $this->drawLogChart3();
- $this->view->svgs[] = $this->chart;
- }
-
- public function hostgroupAction()
- {
- $query = $this->backend->select()->from(
- 'hostgroupsummary',
- array(
- 'hostgroup',
- 'hosts_up',
- 'hosts_unreachable_handled',
- 'hosts_unreachable_unhandled',
- 'hosts_down_handled',
- 'hosts_down_unhandled',
- 'hosts_pending',
- 'services_ok',
- 'services_unknown_handled',
- 'services_unknown_unhandled',
- 'services_critical_handled',
- 'services_critical_unhandled',
- 'services_warning_handled',
- 'services_warning_unhandled',
- 'services_pending'
- )
- )->order('hostgroup')->getQuery()->fetchAll();
- $this->view->height = intval($this->getParam('height', 500));
- $this->view->width = intval($this->getParam('width', 500));
- if (count($query) === 1) {
- $this->drawHostGroupPie($query[0]);
- } else {
- $this->drawHostGroupChart($query);
- }
- }
-
- public function servicegroupAction()
- {
- $query = $this->backend->select()->from(
- 'servicegroupsummary',
- array(
- 'servicegroup',
- 'services_ok',
- 'services_unknown_handled',
- 'services_unknown_unhandled',
- 'services_critical_handled',
- 'services_critical_unhandled',
- 'services_warning_handled',
- 'services_warning_unhandled',
- 'services_pending'
- )
- )->order('servicegroup')->getQuery()->fetchAll();
- $this->view->height = intval($this->getParam('height', 500));
- $this->view->width = intval($this->getParam('width', 500));
-
-
- if (count($query) === 1) {
- $this->drawServiceGroupPie($query[0]);
- } else {
- $this->drawServiceGroupChart($query);
- }
- }
-
- private function drawServiceGroupChart($query)
- {
- $okBars = array();
- $warningBars = array();
- $critBars = array();
- $unknownBars = array();
- foreach ($query as $servicegroup) {
- $okBars[] = array($servicegroup->servicegroup, $servicegroup->services_ok);
- $warningBars[] = array($servicegroup->servicegroup, $servicegroup->services_warning_unhandled);
- $critBars[] = array($servicegroup->servicegroup, $servicegroup->services_critical_unhandled);
- $unknownBars[] = array($servicegroup->servicegroup, $servicegroup->services_unknown_unhandled);
- }
- $this->view->chart = new GridChart();
- $this->view->chart->title = $this->translate('Service Group Chart');
- $this->view->chart->description = $this->translate('Contains service states for each service group.');
-
- $this->view->chart->alignTopLeft();
- $this->view->chart->setAxisLabel('', $this->translate('Services'))
- ->setXAxis(new StaticAxis())
- ->setAxisMin(null, 0);
-
- $tooltip = $this->translate('{title}: {value} of {sum} services are {label}');
- $this->view->chart->drawBars(
- array(
- 'label' => $this->translate('Ok'),
- 'color' => '#44bb77',
- 'stack' => 'stack1',
- 'data' => $okBars,
- 'tooltip' => $tooltip
- ),
- array(
- 'label' => $this->translate('Warning'),
- 'color' => '#ffaa44',
- 'stack' => 'stack1',
- 'data' => $warningBars,
- 'tooltip' => $tooltip
- ),
- array(
- 'label' => $this->translate('Critical'),
- 'color' => '#ff5566',
- 'stack' => 'stack1',
- 'data' => $critBars,
- 'tooltip' => $tooltip
- ),
- array(
- 'label' => $this->translate('Unknown'),
- 'color' => '#dd66ff',
- 'stack' => 'stack1',
- 'data' => $unknownBars,
- 'tooltip' => $tooltip
- )
- );
- }
-
- private function drawHostGroupChart($query)
- {
- $upBars = array();
- $downBars = array();
- $unreachableBars = array();
- for ($i = 0; $i < 50; $i++) {
- $upBars[] = array(
- (string)$i, rand(1, 200), rand(1, 200)
- );
- $downBars[] = array(
- (string)$i, rand(1, 200), rand(1, 200)
- );
- $unreachableBars[] = array(
- (string)$i, rand(1, 200), rand(1, 200)
- );
- }
- $tooltip = $this->translate('{title}: {value} of {sum} hosts are {label}');
- $this->view->chart = new GridChart();
- $this->view->chart->title = $this->translate('Host Group Chart');
- $this->view->chart->description = $this->translate('Contains host states of each service group.');
-
- $this->view->chart->alignTopLeft();
- $this->view->chart->setAxisLabel('', $this->translate('Hosts'))
- ->setXAxis(new StaticAxis())
- ->setAxisMin(null, 0);
- $this->view->chart->drawBars(
- array(
- 'label' => $this->translate('Up'),
- 'color' => '#44bb77',
- 'stack' => 'stack1',
- 'data' => $upBars,
- 'tooltip' => $tooltip
- ),
- array(
- 'label' => $this->translate('Down'),
- 'color' => '#ff5566',
- 'stack' => 'stack1',
- 'data' => $downBars,
- 'tooltip' => $tooltip
- ),
- array(
- 'label' => $this->translate('Unreachable'),
- 'color' => '#dd66ff',
- 'stack' => 'stack1',
- 'data' => $unreachableBars,
- 'tooltip' => $tooltip
- )
- );
- }
-
- private function drawServiceGroupPie($query)
- {
- $this->view->chart = new PieChart();
- $this->view->chart->alignTopLeft();
- $this->view->chart->drawPie(array(
- 'data' => array(
- (int) $query->services_ok,
- (int) $query->services_warning_unhandled,
- (int) $query->services_warning_handled,
- (int) $query->services_critical_unhandled,
- (int) $query->services_critical_handled,
- (int) $query->services_unknown_unhandled,
- (int) $query->services_unknown_handled,
- (int) $query->services_pending
- ),
- 'colors' => array('#44bb77', '#ff4444', '#ff0000', '#ffff00', '#ffff33', '#E066FF', '#f099FF', '#fefefe'),
- 'labels'=> array(
- $query->services_ok . ' Up Services',
- $query->services_warning_handled . $this->translate(' Warning Services (Handled)'),
- $query->services_warning_unhandled . $this->translate(' Warning Services (Unhandled)'),
- $query->services_critical_handled . $this->translate(' Down Services (Handled)'),
- $query->services_critical_unhandled . $this->translate(' Down Services (Unhandled)'),
- $query->services_unknown_handled . $this->translate(' Unreachable Services (Handled)'),
- $query->services_unknown_unhandled . $this->translate(' Unreachable Services (Unhandled)'),
- $query->services_pending . $this->translate(' Pending Services')
- )
- ));
- }
-
- private function drawHostGroupPie($query)
- {
- $this->view->chart = new PieChart();
- $this->view->chart->alignTopLeft();
- $this->view->chart->drawPie(array(
- 'data' => array(
- (int) $query->hosts_up,
- (int) $query->hosts_down_handled,
- (int) $query->hosts_down_unhandled,
- (int) $query->hosts_unreachable_handled,
- (int) $query->hosts_unreachable_unhandled,
- (int) $query->hosts_pending
- ),
- 'colors' => array(
- '#44bb77', // 'Ok'
- '#ff4444', // 'Warning'
- '#ff0000', // 'WarningHandled'
- '#E066FF',
- '#f099FF',
- '#fefefe'
- ),
- 'labels'=> array(
- (int) $query->hosts_up . $this->translate(' Up Hosts'),
- (int) $query->hosts_down_handled . $this->translate(' Down Hosts (Handled)'),
- (int) $query->hosts_down_unhandled . $this->translate(' Down Hosts (Unhandled)'),
- (int) $query->hosts_unreachable_handled . $this->translate(' Unreachable Hosts (Handled)'),
- (int) $query->hosts_unreachable_unhandled . $this->translate(' Unreachable Hosts (Unhandled)'),
- (int) $query->hosts_pending . $this->translate(' Pending Hosts')
- )
- ), array(
- 'data' => array(
- (int) $query->services_ok,
- (int) $query->services_warning_unhandled,
- (int) $query->services_warning_handled,
- (int) $query->services_critical_unhandled,
- (int) $query->services_critical_handled,
- (int) $query->services_unknown_unhandled,
- (int) $query->services_unknown_handled,
- (int) $query->services_pending
- ),
- 'colors' => array('#44bb77', '#ff4444', '#ff0000', '#ffff00', '#ffff33', '#E066FF', '#f099FF', '#fefefe'),
- 'labels'=> array(
- $query->services_ok . $this->translate(' Up Services'),
- $query->services_warning_handled . $this->translate(' Warning Services (Handled)'),
- $query->services_warning_unhandled . $this->translate(' Warning Services (Unhandled)'),
- $query->services_critical_handled . $this->translate(' Down Services (Handled)'),
- $query->services_critical_unhandled . $this->translate(' Down Services (Unhandled)'),
- $query->services_unknown_handled . $this->translate(' Unreachable Services (Handled)'),
- $query->services_unknown_unhandled . $this->translate(' Unreachable Services (Unhandled)'),
- $query->services_pending . $this->translate(' Pending Services')
- )
- ));
- }
-}
diff --git a/modules/monitoring/application/controllers/CommentController.php b/modules/monitoring/application/controllers/CommentController.php
index 122927531..4e085c5b9 100644
--- a/modules/monitoring/application/controllers/CommentController.php
+++ b/modules/monitoring/application/controllers/CommentController.php
@@ -37,6 +37,7 @@ class CommentController extends Controller
'type' => 'comment_type',
'persistent' => 'comment_is_persistent',
'expiration' => 'comment_expiration',
+ 'name' => 'comment_name',
'host_name',
'service_description',
'host_display_name',
@@ -51,7 +52,7 @@ class CommentController extends Controller
$this->getTabs()->add(
'comment',
array(
- 'icon' => 'comment',
+ 'icon' => 'comment-empty',
'label' => $this->translate('Comment'),
'title' => $this->translate('Display detailed information about a comment.'),
'url' =>'monitoring/comments/show'
@@ -73,6 +74,7 @@ class CommentController extends Controller
->populate(array(
'comment_id' => $this->comment->id,
'comment_is_service' => isset($this->comment->service_description),
+ 'comment_name' => $this->comment->name,
'redirect' => $listUrl
))
->handleRequest();
diff --git a/modules/monitoring/application/controllers/CommentsController.php b/modules/monitoring/application/controllers/CommentsController.php
index ac118c477..6dcf08ec4 100644
--- a/modules/monitoring/application/controllers/CommentsController.php
+++ b/modules/monitoring/application/controllers/CommentsController.php
@@ -46,6 +46,7 @@ class CommentsController extends Controller
'type' => 'comment_type',
'persistent' => 'comment_is_persistent',
'expiration' => 'comment_expiration',
+ 'name' => 'comment_name',
'host_name',
'service_description',
'host_display_name',
@@ -58,7 +59,7 @@ class CommentsController extends Controller
$this->getTabs()->add(
'comments',
array(
- 'icon' => 'comment',
+ 'icon' => 'comment-empty',
'label' => $this->translate('Comments') . sprintf(' (%d)', $query->count()),
'title' => $this->translate(
'Display detailed information about multiple comments.'
diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php
index 09aeb7d30..33ddaeacf 100644
--- a/modules/monitoring/application/controllers/ConfigController.php
+++ b/modules/monitoring/application/controllers/ConfigController.php
@@ -106,7 +106,7 @@ class ConfigController extends Controller
$form->setOnSuccess(function (BackendConfigForm $form) {
try {
- $form->add(array_filter($form->getValues()));
+ $form->add($form::transformEmptyValuesToNull($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
@@ -258,7 +258,7 @@ class ConfigController extends Controller
);
$form->setOnSuccess(function (TransportConfigForm $form) {
try {
- $form->add(array_filter($form->getValues()));
+ $form->add($form::transformEmptyValuesToNull($form->getValues()));
} catch (Exception $e) {
$form->error($e->getMessage());
return false;
diff --git a/modules/monitoring/application/controllers/DowntimeController.php b/modules/monitoring/application/controllers/DowntimeController.php
index 6e8a19809..e19ce38c0 100644
--- a/modules/monitoring/application/controllers/DowntimeController.php
+++ b/modules/monitoring/application/controllers/DowntimeController.php
@@ -44,6 +44,7 @@ class DowntimeController extends Controller
'is_fixed' => 'downtime_is_fixed',
'is_in_effect' => 'downtime_is_in_effect',
'entry_time' => 'downtime_entry_time',
+ 'name' => 'downtime_name',
'host_state',
'service_state',
'host_name',
@@ -91,6 +92,7 @@ class DowntimeController extends Controller
->populate(array(
'downtime_id' => $this->downtime->id,
'downtime_is_service' => $isService,
+ 'downtime_name' => $this->downtime->name,
'redirect' => Url::fromPath('monitoring/list/downtimes'),
))
->handleRequest();
diff --git a/modules/monitoring/application/controllers/DowntimesController.php b/modules/monitoring/application/controllers/DowntimesController.php
index fb15c98de..0b33aa339 100644
--- a/modules/monitoring/application/controllers/DowntimesController.php
+++ b/modules/monitoring/application/controllers/DowntimesController.php
@@ -51,6 +51,7 @@ class DowntimesController extends Controller
'is_fixed' => 'downtime_is_fixed',
'is_in_effect' => 'downtime_is_in_effect',
'entry_time' => 'downtime_entry_time',
+ 'name' => 'downtime_name',
'host_state',
'service_state',
'host_name',
diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php
index 8e493ed44..cfbff2169 100644
--- a/modules/monitoring/application/controllers/ListController.php
+++ b/modules/monitoring/application/controllers/ListController.php
@@ -229,6 +229,7 @@ class ListController extends Controller
'is_fixed' => 'downtime_is_fixed',
'is_in_effect' => 'downtime_is_in_effect',
'entry_time' => 'downtime_entry_time',
+ 'name' => 'downtime_name',
'host_state',
'service_state',
'host_name',
@@ -276,13 +277,13 @@ class ListController extends Controller
$this->setAutorefreshInterval(15);
$notifications = $this->backend->select()->from('notification', array(
- 'host_name',
- 'service_description',
- 'notification_output',
- 'notification_contact_name',
- 'notification_start_time',
- 'notification_state',
'host_display_name',
+ 'host_name',
+ 'notification_contact_name',
+ 'notification_output',
+ 'notification_state',
+ 'notification_timestamp',
+ 'service_description',
'service_display_name'
));
$this->applyRestriction('monitoring/filter/objects', $notifications);
@@ -291,7 +292,7 @@ class ListController extends Controller
$this->setupPaginationControl($notifications);
$this->setupLimitControl();
$this->setupSortControl(array(
- 'notification_start_time' => $this->translate('Notification Start')
+ 'notification_timestamp' => $this->translate('Notification Start')
), $notifications);
$this->view->notifications = $notifications;
@@ -422,6 +423,7 @@ class ListController extends Controller
'type' => 'comment_type',
'persistent' => 'comment_is_persistent',
'expiration' => 'comment_expiration',
+ 'name' => 'comment_name',
'host_name',
'service_description',
'host_display_name',
diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php
index bfd5167ff..2c7bc6039 100644
--- a/modules/monitoring/application/controllers/ShowController.php
+++ b/modules/monitoring/application/controllers/ShowController.php
@@ -29,7 +29,6 @@ class ShowController extends Controller
'contact_alias',
'contact_email',
'contact_pager',
- 'contact_object_id',
'contact_notify_service_timeperiod',
'contact_notify_service_recovery',
'contact_notify_service_warning',
@@ -61,13 +60,13 @@ class ShowController extends Controller
'service_description',
'notification_output',
'notification_contact_name',
- 'notification_start_time',
+ 'notification_timestamp',
'notification_state',
'host_display_name',
'service_display_name'
));
- $notifications->where('contact_object_id', $contact->contact_object_id);
+ $notifications->where('notification_contact_name', $contactName);
$this->applyRestriction('monitoring/filter/objects', $notifications);
$this->view->notifications = $notifications;
$this->setupLimitControl();
diff --git a/modules/monitoring/application/controllers/TimelineController.php b/modules/monitoring/application/controllers/TimelineController.php
index d97224564..c0aa3ff61 100644
--- a/modules/monitoring/application/controllers/TimelineController.php
+++ b/modules/monitoring/application/controllers/TimelineController.php
@@ -46,34 +46,33 @@ class TimelineController extends Controller
),
array(
'notify' => array(
+ 'class' => 'timeline-notification',
'detailUrl' => $detailUrl,
- 'label' => mt('monitoring', 'Notifications'),
- 'color' => '#3a71ea'
+ 'label' => mt('monitoring', 'Notifications')
),
'hard_state' => array(
+ 'class' => 'timeline-hard-state',
'detailUrl' => $detailUrl,
- 'label' => mt('monitoring', 'Hard state changes'),
- 'color' => '#ff7000'
+ 'label' => mt('monitoring', 'Hard state changes')
),
'comment' => array(
+ 'class' => 'timeline-comment',
'detailUrl' => $detailUrl,
- 'label' => mt('monitoring', 'Comments'),
- 'color' => '#79bdba'
+ 'label' => mt('monitoring', 'Comments')
),
'ack' => array(
- 'detailUrl' => $detailUrl,
- 'label' => mt('monitoring', 'Acknowledgements'),
- 'color' => '#a2721d'
+ 'class' => 'timeline-ack',
+ 'label' => mt('monitoring', 'Acknowledgements')
),
'dt_start' => array(
+ 'class' => 'timeline-downtime-start',
'detailUrl' => $detailUrl,
- 'label' => mt('monitoring', 'Started downtimes'),
- 'color' => '#8e8e8e'
+ 'label' => mt('monitoring', 'Started downtimes')
),
'dt_end' => array(
+ 'class' => 'timeline-downtime-end',
'detailUrl' => $detailUrl,
- 'label' => mt('monitoring', 'Ended downtimes'),
- 'color' => '#d5d6ad'
+ 'label' => mt('monitoring', 'Ended downtimes')
)
)
);
diff --git a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php
index cd5b866b7..180719ca7 100644
--- a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php
@@ -5,6 +5,7 @@ namespace Icinga\Module\Monitoring\Forms\Command\Object;
use DateTime;
use DateInterval;
+use Icinga\Application\Config;
use Icinga\Module\Monitoring\Command\Object\AcknowledgeProblemCommand;
use Icinga\Web\Notification;
@@ -40,6 +41,8 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
*/
public function createElements(array $formData = array())
{
+ $config = Config::module('monitoring');
+
$this->addElements(array(
array(
'textarea',
@@ -59,6 +62,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
'persistent',
array(
'label' => $this->translate('Persistent Comment'),
+ 'value' => (bool) $config->get('settings', 'acknowledge_persistent', false),
'description' => $this->translate(
'If you would like the comment to remain even when the acknowledgement is removed, check this'
. ' option.'
@@ -70,6 +74,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
'expire',
array(
'label' => $this->translate('Use Expire Time'),
+ 'value' => (bool) $config->get('settings', 'acknowledge_expire', false),
'description' => $this->translate(
'If the acknowledgement should expire, check this option.'
),
@@ -109,7 +114,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
'sticky',
array(
'label' => $this->translate('Sticky Acknowledgement'),
- 'value' => true,
+ 'value' => (bool) $config->get('settings', 'acknowledge_sticky', false),
'description' => $this->translate(
'If you want the acknowledgement to remain until the host or service recovers even if the host'
. ' or service changes state, check this option.'
@@ -121,7 +126,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm
'notify',
array(
'label' => $this->translate('Send Notification'),
- 'value' => true,
+ 'value' => (bool) $config->get('settings', 'acknowledge_notify', true),
'description' => $this->translate(
'If you do not want an acknowledgement notification to be sent out to the appropriate contacts,'
. ' uncheck this option.'
diff --git a/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php b/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php
index 4d6124e0c..3cff2cf7c 100644
--- a/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php
@@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Forms\Command\Object;
+use Icinga\Application\Config;
use Icinga\Module\Monitoring\Command\Object\AddCommentCommand;
use Icinga\Web\Notification;
@@ -53,7 +54,7 @@ class AddCommentCommandForm extends ObjectsCommandForm
'persistent',
array(
'label' => $this->translate('Persistent'),
- 'value' => true,
+ 'value' => (bool) Config::module('monitoring')->get('settings', 'comment_persistent', true),
'description' => $this->translate(
'If you uncheck this option, the comment will automatically be deleted the next time Icinga is'
. ' restarted.'
diff --git a/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php b/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php
index b7855294b..db0a619ac 100644
--- a/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php
@@ -39,7 +39,7 @@ class CheckNowCommandForm extends ObjectsCommandForm
),
'escape' => false,
'ignore' => true,
- 'label' => $this->getView()->icon('reschedule') . $this->translate('Check now'),
+ 'label' => $this->getView()->icon('arrows-cw') . $this->translate('Check now'),
'type' => 'submit',
'title' => $this->translate('Schedule the next active check to run immediately'),
'value' => $this->translate('Check now')
diff --git a/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php
index e526d60e7..3b1cd5927 100644
--- a/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php
@@ -20,42 +20,6 @@ class DeleteCommentCommandForm extends CommandForm
$this->setAttrib('class', 'inline');
}
- /**
- * {@inheritdoc}
- */
- public function createElements(array $formData = array())
- {
- $this->addElements(
- array(
- array(
- 'hidden',
- 'comment_id',
- array(
- 'required' => true,
- 'validators' => array('NotEmpty'),
- 'decorators' => array('ViewHelper')
- )
- ),
- array(
- 'hidden',
- 'comment_is_service',
- array(
- 'filters' => array('Boolean'),
- 'decorators' => array('ViewHelper')
- )
- ),
- array(
- 'hidden',
- 'redirect',
- array(
- 'decorators' => array('ViewHelper')
- )
- )
- )
- );
- return $this;
- }
-
/**
* {@inheritdoc}
*/
@@ -80,14 +44,59 @@ class DeleteCommentCommandForm extends CommandForm
return $this;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function createElements(array $formData = array())
+ {
+ $this->addElements(
+ array(
+ array(
+ 'hidden',
+ 'comment_id',
+ array(
+ 'required' => true,
+ 'validators' => array('NotEmpty'),
+ 'decorators' => array('ViewHelper')
+ )
+ ),
+ array(
+ 'hidden',
+ 'comment_is_service',
+ array(
+ 'filters' => array('Boolean'),
+ 'decorators' => array('ViewHelper')
+ )
+ ),
+ array(
+ 'hidden',
+ 'comment_name',
+ array(
+ 'decorators' => array('ViewHelper')
+ )
+ ),
+ array(
+ 'hidden',
+ 'redirect',
+ array(
+ 'decorators' => array('ViewHelper')
+ )
+ )
+ )
+ );
+ return $this;
+ }
+
/**
* {@inheritdoc}
*/
public function onSuccess()
{
$cmd = new DeleteCommentCommand();
- $cmd->setIsService($this->getElement('comment_is_service')->getValue())
- ->setCommentId($this->getElement('comment_id')->getValue());
+ $cmd
+ ->setCommentId($this->getElement('comment_id')->getValue())
+ ->setCommentName($this->getElement('comment_name')->getValue())
+ ->setIsService($this->getElement('comment_is_service')->getValue());
$this->getTransport($this->request)->send($cmd);
$redirect = $this->getElement('redirect')->getValue();
if (! empty($redirect)) {
diff --git a/modules/monitoring/application/forms/Command/Object/DeleteCommentsCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteCommentsCommandForm.php
index 2b5b9a79e..71886639e 100644
--- a/modules/monitoring/application/forms/Command/Object/DeleteCommentsCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/DeleteCommentsCommandForm.php
@@ -72,6 +72,7 @@ class DeleteCommentsCommandForm extends CommandForm
$cmd = new DeleteCommentCommand();
$cmd
->setCommentId($comment->id)
+ ->setCommentName($comment->name)
->setIsService(isset($comment->service_description));
$this->getTransport($this->request)->send($cmd);
}
diff --git a/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php
index 15c0e8ebd..be2109eec 100644
--- a/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php
@@ -68,6 +68,13 @@ class DeleteDowntimeCommandForm extends CommandForm
'filters' => array('Boolean')
)
),
+ array(
+ 'hidden',
+ 'downtime_name',
+ array(
+ 'decorators' => array('ViewHelper')
+ )
+ ),
array(
'hidden',
'redirect',
@@ -86,8 +93,10 @@ class DeleteDowntimeCommandForm extends CommandForm
public function onSuccess()
{
$cmd = new DeleteDowntimeCommand();
- $cmd->setDowntimeId($this->getElement('downtime_id')->getValue());
- $cmd->setIsService($this->getElement('downtime_is_service')->getValue());
+ $cmd
+ ->setDowntimeId($this->getElement('downtime_id')->getValue())
+ ->setDowntimeName($this->getElement('downtime_name')->getValue())
+ ->setIsService($this->getElement('downtime_is_service')->getValue());
$this->getTransport($this->request)->send($cmd);
$redirect = $this->getElement('redirect')->getValue();
diff --git a/modules/monitoring/application/forms/Command/Object/DeleteDowntimesCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteDowntimesCommandForm.php
index 52590d145..1e0399c88 100644
--- a/modules/monitoring/application/forms/Command/Object/DeleteDowntimesCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/DeleteDowntimesCommandForm.php
@@ -72,6 +72,7 @@ class DeleteDowntimesCommandForm extends CommandForm
$delDowntime = new DeleteDowntimeCommand();
$delDowntime
->setDowntimeId($downtime->id)
+ ->setDowntimeName($downtime->name)
->setIsService(isset($downtime->service_description));
$this->getTransport($this->request)->send($delDowntime);
}
diff --git a/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php b/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php
index 416e02e59..7d6672225 100644
--- a/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php
@@ -70,8 +70,8 @@ class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
'ignore' => true,
'label' => $this->getSubmitLabel(),
'title' => $this->translatePlural(
- 'Remove problem acknowledgement',
- 'Remove problem acknowledgements',
+ 'Remove acknowledgement',
+ 'Remove acknowledgements',
count($this->objects)
),
'type' => 'submit'
@@ -89,8 +89,8 @@ class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
$label = $this->getView()->icon('cancel');
if ($this->isLabelEnabled()) {
$label .= $this->translatePlural(
- 'Remove problem acknowledgement',
- 'Remove problem acknowledgements',
+ 'Remove acknowledgement',
+ 'Remove acknowledgements',
count($this->objects)
);
}
@@ -111,8 +111,8 @@ class RemoveAcknowledgementCommandForm extends ObjectsCommandForm
}
Notification::success(mtp(
'monitoring',
- 'Removing problem acknowledgement..',
- 'Removing problem acknowledgements..',
+ 'Removing acknowledgement..',
+ 'Removing acknowledgements..',
count($this->objects)
));
diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php
index b11d2d2d2..6bbd1a7f4 100644
--- a/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php
@@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Forms\Command\Object;
+use Icinga\Application\Config;
use Icinga\Module\Monitoring\Command\Object\ScheduleHostCheckCommand;
use Icinga\Web\Notification;
@@ -17,6 +18,8 @@ class ScheduleHostCheckCommandForm extends ScheduleServiceCheckCommandForm
*/
public function createElements(array $formData = array())
{
+ $config = Config::module('monitoring');
+
parent::createElements($formData);
$this->addElements(array(
array(
@@ -24,6 +27,7 @@ class ScheduleHostCheckCommandForm extends ScheduleServiceCheckCommandForm
'all_services',
array(
'label' => $this->translate('All Services'),
+ 'value' => (bool) $config->get('settings', 'hostcheck_all_services', false),
'description' => $this->translate(
'Schedule check for all services on the hosts and the hosts themselves.'
)
diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
index 003f3f0aa..53c951644 100644
--- a/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php
@@ -29,29 +29,26 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm
'description' => $this->translate(
'Schedule downtime for all services on the hosts and the hosts themselves.'
),
- 'label' => $this->translate('All Services'),
- 'value' => false
+ 'label' => $this->translate('All Services')
)
);
- if (! $this->getBackend()->isIcinga2()) {
- $this->addElement(
- 'select',
- 'child_hosts',
- array(
- 'description' => $this->translate(
- 'Define what should be done with the child hosts of the hosts.'
- ),
- 'label' => $this->translate('Child Hosts'),
- 'multiOptions' => array(
- 0 => $this->translate('Do nothing with child hosts'),
- 1 => $this->translate('Schedule triggered downtime for all child hosts'),
- 2 => $this->translate('Schedule non-triggered downtime for all child hosts')
- ),
- 'value' => 0
- )
- );
- }
+ $this->addElement(
+ 'select',
+ 'child_hosts',
+ array(
+ 'description' => $this->translate(
+ 'Define what should be done with the child hosts of the hosts.'
+ ),
+ 'label' => $this->translate('Child Hosts'),
+ 'multiOptions' => array(
+ 0 => $this->translate('Do nothing with child hosts'),
+ 1 => $this->translate('Schedule triggered downtime for all child hosts'),
+ 2 => $this->translate('Schedule non-triggered downtime for all child hosts')
+ ),
+ 'value' => 0
+ )
+ );
return $this;
}
diff --git a/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php b/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php
index 6bc691f26..ba7a049f6 100644
--- a/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php
+++ b/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php
@@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Forms\Command\Object;
+use Icinga\Application\Config;
use Icinga\Module\Monitoring\Command\Object\SendCustomNotificationCommand;
use Icinga\Web\Notification;
@@ -34,6 +35,8 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
*/
public function createElements(array $formData = array())
{
+ $config = Config::module('monitoring');
+
$this->addElements(array(
array(
'textarea',
@@ -53,25 +56,29 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
'forced',
array(
'label' => $this->translate('Forced'),
- 'value' => false,
+ 'value' => (bool) $config->get('settings', 'custom_notification_forced', false),
'description' => $this->translate(
'If you check this option, the notification is sent out regardless of time restrictions and'
. ' whether or not notifications are enabled.'
)
)
- ),
- array(
+ )
+ ));
+
+ if (! $this->getBackend()->isIcinga2()) {
+ $this->addElement(
'checkbox',
'broadcast',
array(
'label' => $this->translate('Broadcast'),
- 'value' => false,
+ 'value' => (bool) $config->get('settings', 'custom_notification_broadcast', false),
'description' => $this->translate(
'If you check this option, the notification is sent out to all normal and escalated contacts.'
)
)
- )
- ));
+ );
+ }
+
return $this;
}
@@ -87,8 +94,10 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
->setObject($object)
->setComment($this->getElement('comment')->getValue())
->setAuthor($this->request->getUser()->getUsername())
- ->setForced($this->getElement('forced')->isChecked())
- ->setBroadcast($this->getElement('broadcast')->isChecked());
+ ->setForced($this->getElement('forced')->isChecked());
+ if (($broadcast = $this->getElement('broadcast')) !== null) {
+ $notification->setBroadcast($broadcast->isChecked());
+ }
$this->getTransport($this->request)->send($notification);
}
Notification::success($this->translatePlural(
diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php
index 78cb049de..e7fdba67c 100644
--- a/modules/monitoring/application/forms/Config/BackendConfigForm.php
+++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php
@@ -147,12 +147,6 @@ class BackendConfigForm extends ConfigForm
}
$backendConfig->merge($data);
- foreach ($backendConfig->toArray() as $k => $v) {
- if ($v === null) {
- unset($backendConfig->$k);
- }
- }
-
$this->config->setSection($name, $backendConfig);
return $this;
}
diff --git a/modules/monitoring/application/forms/Config/Transport/ApiTransportForm.php b/modules/monitoring/application/forms/Config/Transport/ApiTransportForm.php
new file mode 100644
index 000000000..3a54ef2e9
--- /dev/null
+++ b/modules/monitoring/application/forms/Config/Transport/ApiTransportForm.php
@@ -0,0 +1,73 @@
+setName('form_config_command_transport_api');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createElements(array $formData = array())
+ {
+ $this->addElements(array(
+ array(
+ 'text',
+ 'host',
+ array(
+ 'required' => true,
+ 'label' => $this->translate('Host'),
+ 'description' => $this->translate(
+ 'Hostname or address of the remote Icinga instance'
+ )
+ )
+ ),
+ array(
+ 'number',
+ 'port',
+ array(
+ 'required' => true,
+ 'label' => $this->translate('Port'),
+ 'description' => $this->translate('SSH port to connect to on the remote Icinga instance'),
+ 'value' => 5665
+ )
+ ),
+ array(
+ 'text',
+ 'username',
+ array(
+ 'required' => true,
+ 'label' => $this->translate('API Username'),
+ 'description' => $this->translate(
+ 'User to log in as on the remote Icinga instance. Please note that key-based SSH login must be'
+ . ' possible for this user'
+ )
+ )
+ ),
+ array(
+ 'password',
+ 'password',
+ array(
+ 'required' => true,
+ 'label' => $this->translate('API Password'),
+ 'description' => $this->translate(
+ 'User to log in as on the remote Icinga instance. Please note that key-based SSH login must be'
+ . ' possible for this user'
+ )
+ )
+ )
+ ));
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/application/forms/Config/TransportConfigForm.php b/modules/monitoring/application/forms/Config/TransportConfigForm.php
index 4f14bfd5e..79ac1741b 100644
--- a/modules/monitoring/application/forms/Config/TransportConfigForm.php
+++ b/modules/monitoring/application/forms/Config/TransportConfigForm.php
@@ -7,8 +7,10 @@ use InvalidArgumentException;
use Icinga\Exception\IcingaException;
use Icinga\Exception\NotFoundError;
use Icinga\Forms\ConfigForm;
+use Icinga\Module\Monitoring\Command\Transport\ApiCommandTransport;
use Icinga\Module\Monitoring\Command\Transport\LocalCommandFile;
use Icinga\Module\Monitoring\Command\Transport\RemoteCommandFile;
+use Icinga\Module\Monitoring\Forms\Config\Transport\ApiTransportForm;
use Icinga\Module\Monitoring\Forms\Config\Transport\LocalTransportForm;
use Icinga\Module\Monitoring\Forms\Config\Transport\RemoteTransportForm;
@@ -68,7 +70,7 @@ class TransportConfigForm extends ConfigForm
*
* @param string $type The transport type for which to return a form
*
- * @return Form
+ * @return \Icinga\Web\Form
*
* @throws InvalidArgumentException In case the given transport type is invalid
*/
@@ -79,6 +81,8 @@ class TransportConfigForm extends ConfigForm
return new LocalTransportForm();
case RemoteCommandFile::TRANSPORT;
return new RemoteTransportForm();
+ case ApiCommandTransport::TRANSPORT:
+ return new ApiTransportForm();
default:
throw new InvalidArgumentException(
sprintf($this->translate('Invalid command transport type "%s" given'), $type)
@@ -163,12 +167,6 @@ class TransportConfigForm extends ConfigForm
}
$transportConfig->merge($data);
- foreach ($transportConfig->toArray() as $k => $v) {
- if ($v === null) {
- unset($transportConfig->$k);
- }
- }
-
$this->config->setSection($name, $transportConfig);
return $this;
}
@@ -223,7 +221,8 @@ class TransportConfigForm extends ConfigForm
$transportTypes = array(
LocalCommandFile::TRANSPORT => $this->translate('Local Command File'),
- RemoteCommandFile::TRANSPORT => $this->translate('Remote Command File')
+ RemoteCommandFile::TRANSPORT => $this->translate('Remote Command File'),
+ ApiCommandTransport::TRANSPORT => $this->translate('Icinga 2 API')
);
$transportType = isset($formData['transport']) ? $formData['transport'] : null;
diff --git a/modules/monitoring/application/forms/StatehistoryForm.php b/modules/monitoring/application/forms/StatehistoryForm.php
index 200830567..3a7c10df5 100644
--- a/modules/monitoring/application/forms/StatehistoryForm.php
+++ b/modules/monitoring/application/forms/StatehistoryForm.php
@@ -71,8 +71,7 @@ class StatehistoryForm extends Form
strtotime('midnight 8 months ago') => $this->translate('8 Months'),
strtotime('midnight 12 months ago') => $this->translate('1 Year'),
strtotime('midnight 24 months ago') => $this->translate('2 Years')
- ),
- 'class' => 'autosubmit'
+ )
)
);
$this->addElement(
@@ -83,8 +82,7 @@ class StatehistoryForm extends Form
'value' => $this->getRequest()->getParam('to', time()),
'multiOptions' => array(
time() => $this->translate('Today')
- ),
- 'class' => 'autosubmit'
+ )
)
);
@@ -98,8 +96,7 @@ class StatehistoryForm extends Form
'multiOptions' => array(
'services' => $this->translate('Services'),
'hosts' => $this->translate('Hosts')
- ),
- 'class' => 'autosubmit'
+ )
)
);
if ($objectType === 'services') {
@@ -118,8 +115,7 @@ class StatehistoryForm extends Form
'cnt_warning_hard' => $this->translate('Warning'),
'cnt_unknown_hard' => $this->translate('Unknown'),
'cnt_ok' => $this->translate('Ok')
- ),
- 'class' => 'autosubmit'
+ )
)
);
} else {
@@ -137,8 +133,7 @@ class StatehistoryForm extends Form
'cnt_up' => $this->translate('Up'),
'cnt_down_hard' => $this->translate('Down'),
'cnt_unreachable_hard' => $this->translate('Unreachable')
- ),
- 'class' => 'autosubmit'
+ )
)
);
}
diff --git a/modules/monitoring/application/locale/ar_SA/LC_MESSAGES/monitoring.mo b/modules/monitoring/application/locale/ar_SA/LC_MESSAGES/monitoring.mo
new file mode 100644
index 000000000..ceb13d3a4
Binary files /dev/null and b/modules/monitoring/application/locale/ar_SA/LC_MESSAGES/monitoring.mo differ
diff --git a/modules/monitoring/application/locale/ar_SA/LC_MESSAGES/monitoring.po b/modules/monitoring/application/locale/ar_SA/LC_MESSAGES/monitoring.po
new file mode 100644
index 000000000..15e202b76
--- /dev/null
+++ b/modules/monitoring/application/locale/ar_SA/LC_MESSAGES/monitoring.po
@@ -0,0 +1,4346 @@
+# Icinga Web 2 - Head for multiple monitoring backends.
+# Copyright (C) 2016 Icinga Development Team
+# This file is distributed under the same license as Monitoring Module.
+#
+# Munzir Taha , 2016.
+msgid ""
+msgstr ""
+"Project-Id-Version: Monitoring Module (2.3.2)\n"
+"Report-Msgid-Bugs-To: dev@icinga.org\n"
+"POT-Creation-Date: 2016-05-25 05:05+0300\n"
+"PO-Revision-Date: 2016-06-02 10:09+0300\n"
+"Last-Translator: Munzir Taha \n"
+"Language: ar_SA\n"
+"Language-Team: English \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:375
+msgid " Down Hosts (Handled)"
+msgstr "أجهزة مضيفة متوقفة (عولجت)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:376
+msgid " Down Hosts (Unhandled)"
+msgstr "أجهزة مضيفة متوقفة ( لم تعالج)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:343
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:397
+msgid " Down Services (Handled)"
+msgstr "خدمات متوقفة (عُولجت)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:344
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:398
+msgid " Down Services (Unhandled)"
+msgstr "خدمات متوقفة (لم تُعالج)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:379
+msgid " Pending Hosts"
+msgstr "أجهزة مضيفة معلقة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:347
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:401
+msgid " Pending Services"
+msgstr "خدمات معلقة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:377
+msgid " Unreachable Hosts (Handled)"
+msgstr "أجهزة مضيفة لا يمكن الوصول إليها (عُولجت)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:378
+msgid " Unreachable Hosts (Unhandled)"
+msgstr "أجهزة مضيفة لا يمكن الوصول إليها (لم تُعالج)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:345
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:399
+msgid " Unreachable Services (Handled)"
+msgstr "حدمات لا يمكن الوصول إليها (عولجت)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:346
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:400
+msgid " Unreachable Services (Unhandled)"
+msgstr "حدمات لا يمكن الوصول إليها (لم تُعالج)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:374
+msgid " Up Hosts"
+msgstr "أجهزة مضيفة قيد التشغيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:394
+msgid " Up Services"
+msgstr "خدمات قيد التشغيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:341
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:395
+msgid " Warning Services (Handled)"
+msgstr "خدمات تحذيرية (عولجت)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:342
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:396
+msgid " Warning Services (Unhandled)"
+msgstr "خدمات تحذيرية (لم تعالج)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:65
+#, php-format
+msgctxt "Last format parameter represents the time running"
+msgid "%1$s has been up and running with PID %2$d %3$s"
+msgstr "%1$s ما زالت قيد التشغيل ب PID %2$d %3$s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:35
+msgctxt "date.verbose"
+msgid "%A, %B %e, %Y"
+msgstr "%A, %B %e, %Y"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:75
+#, php-format
+msgid "%d Active"
+msgid_plural "%d Active"
+msgstr[0] "%d نشطة"
+msgstr[1] "%d نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:55
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:111
+#, php-format
+msgid "%d Disabled"
+msgid_plural "%d Disabled"
+msgstr[0] "%d متعطلة"
+msgstr[1] "%d متعطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:37
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:93
+#, php-format
+msgid "%d Passive"
+msgid_plural "%d Passive"
+msgstr[0] "%d سلبية"
+msgstr[1] "%d سلبية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:38
+#, php-format
+msgid "%d hosts down on %s"
+msgstr "%d أجهزة مضيفة متوقفة على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:16
+#, php-format
+msgid "%d hosts ok on %s"
+msgstr "%d أجهزة مضيفة سليمة على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:21
+#, php-format
+msgid "%d hosts unreachable on %s"
+msgstr "%d أجهزة مضيفة لا يمكن الوصول إليها على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:97
+#, php-format
+msgid "%d more ..."
+msgstr "%d المزيد ..."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:54
+#, php-format
+msgid "%d notifications have been sent for this issue."
+msgstr "%d من الإخطارات أرسلت بخصوص هذه المشكلة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:118
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:117
+#, php-format
+msgid "%d scheduled downtime"
+msgid_plural "%d scheduled downtimes"
+msgstr[0] "%d زمن توقف مجدول"
+msgstr[1] "%d من أزمنة التوقف المجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:26
+#, php-format
+msgid "%d services critical on %s"
+msgstr "%d من الخدمات الضرورية على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:48
+#, php-format
+msgid "%d services ok on %s"
+msgstr "%d من الخدمات سليمة على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:43
+#, php-format
+msgid "%d services unknown on %s"
+msgstr "%d من الخدمات مجهولة على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:32
+#, php-format
+msgid "%d services warning on %s"
+msgstr "%d من الخدمات التحذيرية على %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:136
+#, php-format
+msgid "%d unhandled hosts down"
+msgstr "%d أجهزة مضيفة لم تُعالج"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:27
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:27
+#, php-format
+msgid "%d unhandled problems"
+msgstr "%d مشاكل لم تُعالج"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:148
+#, php-format
+msgid "%d unhandled services critical"
+msgstr "%d من الخدمات غير المعالجة ضرورية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:46
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:44
+#, php-format
+msgid "%s acknowledgement"
+msgid_plural "%s acknowledgements"
+msgstr[0] "%s إشعار"
+msgstr[1] "%s من الإشعارات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:80
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:79
+#, php-format
+msgid "%s comment"
+msgid_plural "%s comments"
+msgstr[0] "%s تعليق"
+msgstr[1] "%s من التعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/not-running.phtml:7
+#, php-format
+msgid "%s is currently not up and running"
+msgstr "%s حاليا لا تعمل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/components/selectioninfo.phtml:12
+#, php-format
+msgctxt "Multi-selection count"
+msgid "%s row(s) selected"
+msgstr "%s من الصفوف تم اختيارها"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:19
+#, php-format
+msgid "%u Active"
+msgid_plural "%u Active"
+msgstr[0] "%u نشطة"
+msgstr[1] "%u نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/components/hostssummary.phtml:12
+#, php-format
+msgid "%u Host"
+msgid_plural "%u Hosts"
+msgstr[0] "%u مضيف"
+msgstr[1] "%u أجهزة مضيفة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/problem_hosts.phtml:11
+#, php-format
+msgid "%u Host DOWN"
+msgid_plural "%u Hosts DOWN"
+msgstr[0] "%u مضيف متوقف"
+msgstr[1] "%u أجهزة مضيفة متوقفة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:20
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:141
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:220
+#, php-format
+msgid "%u Host Disabled"
+msgid_plural "%u Hosts Disabled"
+msgstr[0] "%u مضيف معطل"
+msgstr[1] "%u من الأجهزة المضيفة معطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:50
+#, php-format
+msgid "%u Host Flapping"
+msgid_plural "%u Hosts Flapping"
+msgstr[0] "%u مضيف مذبذب"
+msgstr[1] "%u أجهزة مضيفة مذبذبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/ok_hosts.phtml:34
+#, php-format
+msgid "%u Host PENDING"
+msgid_plural "%u Hosts PENDING"
+msgstr[0] "%u مضيف معلق"
+msgstr[1] "%u أجهزة مضيفة معلقة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/problem_hosts.phtml:30
+#, php-format
+msgid "%u Host UNREACHABLE"
+msgid_plural "%u Hosts UNREACHABLE"
+msgstr[0] "%u مضيف لا يمكن الوصول إليه"
+msgstr[1] "%u من الأجهزة المضيفة لا يمكن الوصول إليها"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/ok_hosts.phtml:16
+#, php-format
+msgid "%u Host UP"
+msgid_plural "%u Hosts UP"
+msgstr[0] "%u مضيف سليم"
+msgstr[1] "%u أجهزة مضيفة سليمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml:13
+#, php-format
+msgid "%u Service"
+msgid_plural "%u Services"
+msgstr[0] "%u خدمة"
+msgstr[1] "%u من الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:75
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:175
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:254
+#, php-format
+msgid "%u Service Disabled"
+msgid_plural "%u Services Disabled"
+msgstr[0] "%u خدمة متعطلة"
+msgstr[1] "%u من الخدمات متعطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:105
+#, php-format
+msgid "%u Service Flapping"
+msgid_plural "%u Services Flapping"
+msgstr[0] "%u خدمة مذبذبة"
+msgstr[1] "%u من الخدمات مذبذبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:80
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:179
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:278
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:325
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:372
+#, php-format
+msgid "%u is not checked at all"
+msgid_plural "%u are not checked at all"
+msgstr[0] "%u لم يتم فحصها مطلقا"
+msgstr[1] "%u لم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:53
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:152
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:251
+#, php-format
+msgid "%u is passively checked"
+msgid_plural "%u are passively checked"
+msgstr[0] "%u تم فحصها سلبيا"
+msgstr[1] "%u تم فحصها سلبيا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hosts.phtml:62
+#, php-format
+msgid "%u unhandled service"
+msgid_plural "%u unhandled services"
+msgstr[0] "%u خدمة لم تُعالج"
+msgstr[1] "%u من الخدمات لم تُعالج"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/DataView/DataView.php:235
+msgid "(Case insensitive)"
+msgstr "(غير حساسة لحالة الأحرف)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:72
+msgid "1 Year"
+msgstr "سنة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:73
+msgid "2 Years"
+msgstr "سنتان"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:69
+msgid "3 Months"
+msgstr "3 أشهر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:103
+msgid "4 Hours"
+msgstr "4 ساعات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:70
+msgid "4 Months"
+msgstr "4 أشهر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:71
+msgid "8 Months"
+msgstr "8 أشهر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:448
+msgid "{title}: {value}m max. reaction time"
+msgstr "{title}: {value}m أقصى زمن رد فعل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:438
+msgid "{title}: {value}m min. reaction time"
+msgstr "{title}: {value}m أدنى زمن رد فعل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:289
+msgid "{title}: {value} of {sum} hosts are {label}"
+msgstr "{title}: {value} من {sum} أجهزة مضيفة {label}"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:240
+msgid "{title}: {value} of {sum} services are {label}"
+msgstr "{title}: {value} من {sum} خدمات {label}"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:129
+#, php-format
+msgid "A command transport with the name \"%s\" does already exist"
+msgstr "ناقل أمر باسم \"%s\" موجود مسبقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:46
+msgid ""
+"A comment, as entered by the author, associated with the scheduled downtime"
+msgstr "تعليق مدخل من قبل المؤلف له ارتباط بزمن التوقف المجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:77
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:212
+msgid "A downtime must not be in the past"
+msgstr "زمن التوقف لا يجب أن يكون في الماضي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:113
+#, php-format
+msgid "A monitoring backend with the name \"%s\" does already exist"
+msgstr " خلفية المراقبة المسماة \"%s\" موجودة مسبقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:49
+#, php-format
+msgid "A notification has been sent for this issue %s."
+msgstr "أُرسل إشعار بخصوص هذه المشكلة %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:67
+msgid "ACKNOWLEDGED"
+msgstr "معروف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:72
+msgid "ACKNOWLEDGEMENT REMOVED"
+msgstr "تمت إزالة إشعار المعرفة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:30
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:29
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:77
+msgid "Acknowledge"
+msgstr "يعرف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:118
+msgid "Acknowledge Host Problem"
+msgstr "تعرف على مشكلة مضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:175
+msgid "Acknowledge Host Problems"
+msgstr "تعرف على مشاكل الأجهزة المضيفة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:76
+msgid "Acknowledge Service Problem"
+msgstr "تعرف على مشكلة خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:178
+msgid "Acknowledge Service Problems"
+msgstr "تعرف على مشاكل خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:34
+msgid "Acknowledge problem"
+msgid_plural "Acknowledge problems"
+msgstr[0] "تعرف مشكلة"
+msgstr[1] "تعرف مشاكل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:85
+msgid ""
+"Acknowledge this problem, suppress all future notifications for it and tag "
+"it as being handled"
+msgstr ""
+"تعرف على هذه المشكلة، واخمد كل الإشعارات المستقبلية لها وضع علامة أنه تم"
+" معالجتها"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/statusicons.phtml:9
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml:9
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:15
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:16
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:12
+msgid "Acknowledged"
+msgstr "معروف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:335
+msgid "Acknowledged Problem Hosts"
+msgstr "مضيفون بمشاكل معروفة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:331
+msgid "Acknowledged Problem Services"
+msgstr "خدمات بمشاكل معروفة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:20
+msgid "Acknowledgement"
+msgstr "إشعار استلام"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:35
+#, php-format
+msgid ""
+"Acknowledgement remains until the %1$s recovers even if the %1$s changes "
+"state"
+msgstr "ستبقى الإشعارات حتى تتعافي %1$s حتى ولو غيرت %1$s حالتها"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:65
+msgid "Acknowledgements"
+msgstr "إشعارات استلام"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:302
+msgid "Acknowledgements Active For At Least Three Days"
+msgstr "الإشعارات النشطة لثلاثة أيام على الأقل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:157
+msgid "Acknowledging problem.."
+msgid_plural "Acknowledging problems.."
+msgstr[0] "اعتراف بمشكلة.."
+msgstr[1] "اعتراف بمشاكل.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/actions.phtml:41
+msgid "Actions"
+msgstr "أفعال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/statusicons.phtml:24
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml:24
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:29
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:25
+msgid "Active And Passive Checks Disabled"
+msgstr "تم تعطيل الفحوصات النشطة والسالبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:38
+msgid "Active Checks"
+msgstr "الفحوصات النشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/statusicons.phtml:22
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml:22
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:31
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:27
+msgid "Active Checks Disabled"
+msgstr "تم تعطيل الفحوصات النشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:54
+msgid "Active Endpoint"
+msgstr "نقطة نهاية نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:90
+msgid "Active Host Checks"
+msgstr "فحوصات المضيف النشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:99
+msgid "Active Service Checks"
+msgstr "فحوصات الخدمة نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:109
+msgid "Active checks"
+msgstr "فحوصات نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:145
+msgid "Actual end time"
+msgstr "زمن النهاية الفعلي "
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:140
+msgid "Actual start time"
+msgstr "زمن البدء الفعلي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:130
+msgid "Add Host Comment"
+msgstr "إضافة تعليق مضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:163
+msgid "Add Host Comments"
+msgstr "إضافة تعليقات مضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:88
+msgid "Add Service Comment"
+msgstr "إضافة تعليق خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:166
+msgid "Add Service Comments"
+msgstr "إضافة تعليقات خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/comments.phtml:14
+msgid "Add a new comment to this host"
+msgstr "إضافة تعليق جديد لهذا المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/comments.phtml:26
+msgid "Add a new comment to this service"
+msgstr "إضافة تعليق جديد لهذه الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/comments.phtml:7
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/comments.phtml:19
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:28
+msgid "Add comment"
+msgid_plural "Add comments"
+msgstr[0] "إضافة تعليق"
+msgstr[1] "إضافة تعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:62
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:61
+msgid "Add comments"
+msgstr "إضافة تعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:85
+msgid "Adding comment.."
+msgid_plural "Adding comments.."
+msgstr[0] "إضافة تعليق.."
+msgstr[1] "إضافة تعليقات.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:90
+msgid "Address"
+msgstr "عنوان"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:241
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:54
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:58
+msgid "Alert Summary"
+msgstr "ملخص التحذيرات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:11
+msgid "Alert summary"
+msgstr "ملخص التحذيرات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contactgroups.phtml:24
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:326
+msgid "Alias"
+msgstr "اسم مستعار"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:39
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:160
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:239
+msgid "All Hosts Enabled"
+msgstr "كل المضيفون نشطاء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:32
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php:26
+msgid "All Services"
+msgstr "كل الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:94
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:194
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:273
+msgid "All Services Enabled"
+msgstr "كل الخدمات مفعلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php:178
+msgid "All backends are disabled"
+msgstr "كل الخلفيات متعطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:16
+msgid "Allow acknowledging host and service problems"
+msgstr "السماح بالتعرف على مشاكل الخدمة والمضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:24
+msgid "Allow adding and deleting host and service comments"
+msgstr "السماح بإضافة وحذف تعليقات الخدمة والمضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:8
+msgid "Allow all commands"
+msgstr "السماح بكل الأوامر"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:28
+msgid "Allow commenting on hosts and services"
+msgstr "السماح بالتعليق على الخدمات والمضيفين"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:32
+msgid "Allow deleting host and service comments"
+msgstr "السماح بحذف تعليقات على المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:44
+msgid "Allow deleting host and service downtimes"
+msgstr "السماح بحذف أزمنة توقف المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:60
+msgid ""
+"Allow processing commands for toggling active checks on host and service "
+"objects"
+msgstr ""
+"السماح بمعالجة الأوامر لتبديل الفحوصات النشطة على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:72
+msgid ""
+"Allow processing commands for toggling event handlers on host and service "
+"objects"
+msgstr ""
+"السماح بمعالجة الأوامر لتبديل الفحوصات النشطة على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:52
+msgid ""
+"Allow processing commands for toggling features on an instance-wide basis"
+msgstr ""
+"السماح بمعالجة الأوامر لتبديل الفحوصات النشطة على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:56
+msgid ""
+"Allow processing commands for toggling features on host and service objects"
+msgstr "السماح بمعالجة الأوامر لتبديل المميزات على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:76
+msgid ""
+"Allow processing commands for toggling flap detection on host and service "
+"objects"
+msgstr "السماح بمعالجة الأوامر لتبديل فحص التقلب على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:68
+msgid ""
+"Allow processing commands for toggling notifications on host and service "
+"objects"
+msgstr "السماح بمعالجة الأوامر لتبديل التنبيهات على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:64
+msgid ""
+"Allow processing commands for toggling passive checks on host and service "
+"objects"
+msgstr ""
+"السماح بمعالجة الأوامر لتبديل الفحوصات السالبة على كائنات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:48
+msgid "Allow processing host and service check results"
+msgstr "السماح بمعالجة نتائج فحص المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:20
+msgid "Allow removing problem acknowledgements"
+msgstr "السماح بإزالة إشعارات المشكلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:36
+msgid "Allow scheduling and deleting host and service downtimes"
+msgstr "السماح بجدولة وحذف أزمنة توقف المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:12
+msgid "Allow scheduling host and service checks"
+msgstr "السماح بجدولة فحوصات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:40
+msgid "Allow scheduling host and service downtimes"
+msgstr "السماح بجدولة زمن توقف المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:80
+msgid "Allow sending custom notifications for hosts and services"
+msgstr "السماح بإرسال تنبيهات مخصصة للأجهزة المضيفة والخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:20
+msgid "Apply"
+msgstr "تطبيق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:39
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:42
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:249
+msgid "Author"
+msgstr "المؤلف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:33
+msgid "Average"
+msgstr "المتوسط"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:434
+msgid "Avg (min)"
+msgstr "المتوسط (الأدنى)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:74
+#, php-format
+msgid "Backend %s is not running"
+msgstr "الخلفية %s لا تعمل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/BackendPage.php:28
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:193
+msgid "Backend Name"
+msgstr "اسم الخلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/BackendPage.php:44
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:221
+msgid "Backend Type"
+msgstr "نوع الخلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:94
+msgid "Backends"
+msgstr "الخلفيات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:67
+msgid "Broadcast"
+msgstr "بث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:59
+msgid "COMMENT"
+msgstr "تعليق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:63
+msgid "COMMENT DELETED"
+msgstr "حذف التعليق"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Service.php:196
+msgid "CRITICAL"
+msgstr "ضروري"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:58
+msgctxt "icinga.state"
+msgid "CRITICAL"
+msgstr "ضروري"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Command/Transport/RemoteCommandFile.php:214
+msgid "Can't send external Icinga Command. Remote user is missing"
+msgstr "لا يمكن إرسال أمر \"إسنجا\" خارجي. مستخدم بعيد مفقود"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Command/Transport/RemoteCommandFile.php:219
+msgid ""
+"Can't send external Icinga Command. The private key for the remote user is "
+"missing"
+msgstr ""
+"لا يمكن إرسال أمر \"إسنجا\" خارجي. المفتاح الخاص بالمستخدم البعيد مفقود"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Controller.php:97
+#, php-format
+msgid ""
+"Cannot apply restriction %s using the filter %s. You can only use the "
+"following columns: %s"
+msgstr ""
+"لا يمكن تطبيق تقييد %s باستخدام المرشح %s. يمكنك استخدام الأعمدة التالية: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php:76
+#, php-format
+msgid ""
+"Cannot create command transport \"%s\". Invalid transport defined in \"%s\". "
+"Use one of \"%s\" or \"%s\"."
+msgstr ""
+"لا يمكن إنشاء ناقل أمر \"%s\". نقل غير صالح معرف في \"%s\". استخدم واحدا من \""
+"%s\" أو \"%s\"."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:350
+msgid ""
+"Cannot find the IDO schema. Please verify that the given database contains "
+"the schema and that the configured user has access to it."
+msgstr ""
+"تعذر العثور على مخطط IDO. الرجاء التأكد أن قاعدة البيانات المعطاة تحتوي على"
+" المخطط وأن المستخدم المعد له صلاحية عليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:158
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:160
+msgid "Check Execution"
+msgstr "فحص التنفيذ"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:113
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:140
+msgid "Check Performance"
+msgstr "فحص الأداء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checksource.phtml:4
+msgid "Check Source"
+msgstr "فحص المصدر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:51
+msgid "Check Time"
+msgstr "فحص الزمن"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checktimeperiod.phtml:4
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checktimeperiod.phtml:15
+msgid "Check Timeperiod"
+msgstr "فحص المدة الزمنية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:66
+msgid "Check attempts"
+msgstr "فحص المحاولات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/detail-content.phtml:32
+msgid "Check execution"
+msgstr "فحص التنفيذ"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:75
+msgid "Check execution time"
+msgstr "فحص زمن التنفيذ"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:82
+msgid "Check latency"
+msgstr "فحص التأخير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php:42
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php:45
+msgid "Check now"
+msgstr "الفحص الآن"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:12
+msgid "Check result is late"
+msgstr "فحص كون النتيجة متأخرة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php:78
+msgid ""
+"Check this to not to validate connectivity with the given Livestatus socket"
+msgstr "حدد هذا الخيار لعدم التحقق من صحة الاتصال مع مقبس Livestatus معين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:329
+msgid "Check this to not to validate the IDO schema of the chosen resource."
+msgstr "حدد هذا الخيار لعدم التحقق من صحة المخطط IDO للمورد الذي تم اختياره."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:185
+msgid "Check this to not to validate the configuration"
+msgstr "حدد هذا الخيار لعدم التحقق من الإعداد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:114
+msgid "Checks"
+msgstr "فحوصات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:45
+msgid "Child Hosts"
+msgstr "مضيفون تابعون"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/SecurityConfigForm.php:58
+msgid ""
+"Comma separated case insensitive list of protected custom variables. Use * "
+"as a placeholder for zero or more wildcard characters. Existance of those "
+"custom variables will be shown, but their values will be masked."
+msgstr ""
+"قائمة مفصولة بفواصل لمتغيرات مخصصة ومحمية غير حساسة لحالة الأحرف. "
+"استخدم * كعلامة نائبة عن أي عدد من المحارف. وسيظهر ما إذا كانت تلك "
+"المتغيرات المخصصة موجودة لكن قيمها ستحجب."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:163
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:165
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/command.phtml:12
+msgid "Command"
+msgstr "أمر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:177
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/LocalTransportForm.php:30
+msgid "Command File"
+msgstr "أمر ملف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/TransportPage.php:14
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:43
+msgctxt "setup.page.title"
+msgid "Command Transport"
+msgstr "ناقل الأمر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:62
+msgid "Command Transports"
+msgstr "نواقل الأمر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:240
+#, php-format
+msgid "Command transport \"%s\" not found"
+msgstr "ناقل الأمر \"%s\" غير موجود"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/CommandForm.php:65
+#, php-format
+msgid "Command transport \"%s\" not found."
+msgstr "ناقل الأمر \"%s\" غير موجود."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:189
+#, php-format
+msgid "Command transport \"%s\" successfully removed"
+msgstr "تم إزالة ناقل الأمر \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:229
+#, php-format
+msgid "Command transport \"%s\" successfully updated"
+msgstr "تم تحديث ناقل الأمر \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:98
+#, php-format
+msgid ""
+"Command transport configuration could not be written to: %s. An error "
+"occured:"
+msgstr "إعداد ناقل الأمر لا يمكن كتابته على: %s. حدث خطأ:"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:90
+#, php-format
+msgid "Command transport configuration has been successfully created: %s"
+msgstr "تم إنشاء إعداد ناقل الأمر: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:268
+msgid "Command transport successfully created"
+msgstr "تم إنشاء ناقل الأمر بنجاح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:163
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:70
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtimes/show.phtml:9
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:51
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comments/show.phtml:9
+msgid "Commands"
+msgstr "أوامر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:47
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:42
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:43
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:65
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:49
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentController.php:55
+msgid "Comment"
+msgstr "تعليق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:437
+msgid "Comment Timestamp"
+msgstr "زمن التعليق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:440
+msgid "Comment Type"
+msgstr "نوع التعليق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:12
+msgid "Comment detail information"
+msgstr "معلومات التعليق التفصيلية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentController.php:48
+msgid "Comment not found"
+msgstr "تعليق غير موجود"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:16
+msgid "Comment was caused by a downtime"
+msgstr "تعليق بسبب زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:6
+msgid "Comment was caused by a flapping host or service"
+msgstr "تعليق بسبب خدمة أو مضيف مذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:21
+msgid "Comment was caused by an acknowledgement"
+msgstr "تعليق بسبب إشعار"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:11
+msgid "Comment was created by an user"
+msgstr "تعليق منشأ من قبل مستخدم"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:200
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:59
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:58
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/comments.phtml:37
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/EventOverviewForm.php:64
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentsController.php:62
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:60
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:410
+msgid "Comments"
+msgstr "تعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php:196
+#, php-format
+msgid "Configuration for backend %s is disabled"
+msgstr "إعداد الخلفية %s معطل"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:98
+msgid ""
+"Configure how to protect your monitoring environment against prying eyes"
+msgstr "إعداد كيفية حماية بيئة المراقبة ضد أعين المتطفلين"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:93
+msgid "Configure how to retrieve monitoring information"
+msgstr "إعداد كيفية استعادة معلومات المراقبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentsController.php:95
+#, php-format
+msgid "Confirm removal of %d comments."
+msgstr "تأكيد إزالة %d من التعليقات."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimesController.php:99
+#, php-format
+msgid "Confirm removal of %d downtimes."
+msgstr "إعداد إزالة %d من أزمنة التوقف."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contactgroups.phtml:23
+msgid "Contact Group "
+msgstr "مجموعة الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:381
+msgid "Contact Groups"
+msgstr "مجموعات الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:6
+msgid "Contact details"
+msgstr "تفاصيل الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:397
+msgid "Contactgroup Alias"
+msgstr "اسم مجموعة الاتصال المستعار"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:396
+msgid "Contactgroup Name"
+msgstr "اسم مجموعة الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:196
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/contacts.phtml:35
+msgid "Contactgroups"
+msgstr "مجموعات الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:192
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/contacts.phtml:17
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:307
+msgid "Contacts"
+msgstr "جهات الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:292
+msgid "Contains host states of each service group."
+msgstr "يحتوي على حالات المضيف لكل مجموعة خدمة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:233
+msgid "Contains service states for each service group."
+msgstr "يحتوي حالات الخدمة لكل مجموعة خدمة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:47
+msgid "Could not find any valid SSH resources"
+msgstr "تعذر العثور على موارد SSH صالحة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:65
+msgid ""
+"Could not find any valid monitoring backend resources. Please configure a "
+"database resource first."
+msgstr ""
+"تعذر العثور على موارد مراقبة خلفية صالحة. الرجاء إعداد "
+"مورد لقاعدة البيانات أولا."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:254
+msgid "Create New Command Transport"
+msgstr "إنشاء ناقل أمر جديد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:93
+msgid "Create New Monitoring Backend"
+msgstr "إنشاء خلفية مراقبة جديدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:64
+msgid "Create a New Command Transport"
+msgstr "إنشاء ناقل أمر جديد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:9
+msgid "Create a New Monitoring Backend"
+msgstr "إنشاء خلفية مراقبة جديدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:70
+msgid "Create a new command transport"
+msgstr "إنشاء ناقل أمر جديد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:15
+msgid "Create a new monitoring backend"
+msgstr "إنشاء خلفية مراقبة جديدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:52
+msgid "Created"
+msgstr "أُنشيء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:41
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:117
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:257
+msgid "Critical"
+msgstr "ضروري"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:160
+msgid "Current Downtimes"
+msgstr "أزمنة التوقف الحالية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:174
+msgid "Current Host State"
+msgstr "حالة المضيفين الحالية"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:258
+msgid "Current Incidents"
+msgstr "الحوادث الحالية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:169
+msgid "Current Service State"
+msgstr "حالة الخدمة الحالية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:88
+msgid "Current State"
+msgstr "الحالة الحالية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/detail-content.phtml:43
+msgid "Custom Variables"
+msgstr "متغيرات مخصصة"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Host.php:185
+msgid "DOWN"
+msgstr "متوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:124
+msgctxt "icinga.state"
+msgid "DOWN"
+msgstr "متوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:83
+msgid "DOWNTIME DELETED"
+msgstr "حُذف زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:108
+msgid "DOWNTIME END"
+msgstr "نهاية زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:103
+msgid "DOWNTIME START"
+msgstr "بداية زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:105
+msgid "Database Name"
+msgstr "اسم قاعدة البيانات"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:84
+msgid "Database Resource"
+msgstr "مورد قاعدة بيانات"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:93
+msgid "Database Type"
+msgstr "نوع قاعدة البيانات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:42
+msgid "Date and time this downtime was entered"
+msgstr "تاريخ ووقت إدخال زمن التوقف هذا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:642
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:645
+msgid "Day"
+msgstr "يوم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:463
+msgid "Defect Chart"
+msgstr "رسم بياني للعيوب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:484
+msgid "Defects"
+msgstr "العيوب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:43
+msgid "Define what should be done with the child hosts of the hosts."
+msgstr "عرف ما يتحتم عمله مع المضيفين التابعين."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php:76
+msgid "Delete this comment"
+msgstr "احذف هذا التعليق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php:40
+msgid "Delete this downtime"
+msgstr "حذف زمن التوقف هذا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php:96
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteCommentsCommandForm.php:83
+msgid "Deleting comment.."
+msgid_plural "Deleting comments.."
+msgstr[0] "حذف تعليق.."
+msgstr[1] "حذف تعليقات.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php:97
+msgid "Deleting downtime."
+msgstr "حذف زمن التوقف."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteDowntimesCommandForm.php:83
+msgid "Deleting downtime.."
+msgid_plural "Deleting downtimes.."
+msgstr[0] "حذف زمن التوقف.."
+msgstr[1] "حذف أزمنة التوقف.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:10
+msgid "Details"
+msgstr "تفاصيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php:24
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HealthController.php:172
+msgid "Disable Notifications"
+msgstr "تعطيل التنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:185
+msgid "Disable This Backend"
+msgstr "تعطيل هذه الخلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:69
+msgid "Disable notifications for a specific time on a program-wide basis"
+msgstr "تعطيل التنبيهات لوقت محدد على أساس البرنامج بأكمله"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:71
+msgid "Disable temporarily"
+msgstr "تعطيل مؤقت"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:327
+msgid "Disabled Host Checks"
+msgstr "تعطيل فحوصات المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:319
+msgid "Disabled Host Notifications"
+msgstr "تنبيهات المضيف المعطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:323
+msgid "Disabled Service Checks"
+msgstr "فحوصات الخدمة المعطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:315
+msgid "Disabled Service Notifications"
+msgstr "تنبيهات الخدمة المعطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:130
+msgid "Disabling active checks.."
+msgstr "تعطيل الفحوصات النشطة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:222
+msgid "Disabling active host checks.."
+msgstr "تعطيل فحوصات المضيف النشطة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:226
+msgid "Disabling active service checks.."
+msgstr "تعطيل فحوصات الخدمة النشطة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:146
+msgid "Disabling event handler.."
+msgstr "تعطيل معالج الحدث.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:230
+msgid "Disabling event handlers.."
+msgstr "تعطيل معالجات الحدث.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:150
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:234
+msgid "Disabling flap detection.."
+msgstr "تعطيل فحص التذبذب.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php:61
+msgid "Disabling host and service notifications.."
+msgstr "تعطيل تنبيهات المضيف والخدمة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:142
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:238
+msgid "Disabling notifications.."
+msgstr "تعطيل التنبيهات.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:242
+msgid "Disabling obsessing over hosts.."
+msgstr "تعطيل التوجس على المضيفين.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:246
+msgid "Disabling obsessing over services.."
+msgstr "تعطيل التوجس على الخدمات.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:138
+msgid "Disabling obsessing.."
+msgstr "تعطيل التوجس.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:134
+msgid "Disabling passive checks.."
+msgstr "تعطيل الفحوصات السلبية.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:250
+msgid "Disabling passive host checks.."
+msgstr "تعطيل فحوصات المضيف السلبية.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:254
+msgid "Disabling passive service checks.."
+msgstr "تعطيل فحوصات الخدمة السلبية.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:258
+msgid "Disabling performance data.."
+msgstr "تعطيل بيانات الأداء.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentController.php:56
+msgid "Display detailed information about a comment."
+msgstr "عرض معلومات مفصلة عن تعليق."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimeController.php:66
+msgid "Display detailed information about a downtime."
+msgstr "عرض معلومات مفصلة عن توقف."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentsController.php:64
+msgid "Display detailed information about multiple comments."
+msgstr "عرض معلومات تفصيلية عن تعليقات متعددة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimesController.php:70
+msgid "Display detailed information about multiple downtimes."
+msgstr "عرض معلومات تفصيلية عن توقفات متعددة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Navigation/ActionForm.php:26
+msgid ""
+"Display this action only for objects matching this filter. Leave it blank if "
+"you want this action being displayed regardless of the object"
+msgstr ""
+"عرض هذا الفعل فقط للكائنات الموافقة لهذا المرشح. اتركه فارغا "
+"إذا كنت تريد لهذا الفعل أن يعرض بغض النظر عن الكائن"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:47
+msgid "Do nothing with child hosts"
+msgstr "لا تفعل شيئا بالمضيفين التابعين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:138
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:307
+msgid "Down"
+msgstr "متوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:15
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimeController.php:65
+msgid "Downtime"
+msgstr "زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimeController.php:57
+msgid "Downtime not found"
+msgstr "زمن التوقف غير موجود"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:204
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:96
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:95
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:41
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/EventOverviewForm.php:54
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimesController.php:69
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:212
+msgid "Downtimes"
+msgstr "أزمنة التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:306
+msgid "Downtimes Active For More Than Three Days"
+msgstr "أزمنة التوقف النشطة لأكثر من ثلاثة أيام"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:53
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:135
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:254
+msgid "Duration"
+msgstr "المدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:3
+msgctxt "Downtime status"
+msgid "ENDS"
+msgstr "نهايات"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:155
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:168
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:80
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:102
+#, php-format
+msgid "ERROR: %s"
+msgstr "خطأ: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:6
+msgctxt "Downtime status"
+msgid "EXPIRES"
+msgstr "انتهاء صلاحية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:210
+#, php-format
+msgid "Edit Command Transport %s"
+msgstr "تحرير ناقل الأمر %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:51
+#, php-format
+msgid "Edit Monitoring Backend %s"
+msgstr "تحرير خلفية المراقبة %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:90
+#, php-format
+msgid "Edit command transport %s"
+msgstr "تحرير ناقل الأمر %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:35
+#, php-format
+msgid "Edit monitoring backend %s"
+msgstr "تحرير خلفية المراقبة %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:24
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:21
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:42
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:327
+msgid "Email"
+msgstr "بريد إلكتروني"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:129
+msgid "Enabling active checks.."
+msgstr "تفعيل فحوصات نشطة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:221
+msgid "Enabling active host checks.."
+msgstr "تفعيل فحوصات مضيف نشطة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:225
+msgid "Enabling active service checks.."
+msgstr "تفعيل فحوصات الخدمة النشطة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:145
+msgid "Enabling event handler.."
+msgstr "تفعيل معالج حدث.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:229
+msgid "Enabling event handlers.."
+msgstr "تفعيل معالجات حدث.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:149
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:233
+msgid "Enabling flap detection.."
+msgstr "تفعيل كشف التذبذب.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:141
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:237
+msgid "Enabling notifications.."
+msgstr "تفعيل التنبيهات.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:241
+msgid "Enabling obsessing over hosts.."
+msgstr "تعطيل التوجس على المضيفين.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:245
+msgid "Enabling obsessing over services.."
+msgstr "تعطيل التوجس على الخدمات.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:137
+msgid "Enabling obsessing.."
+msgstr "تعطيل التوجس.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:133
+msgid "Enabling passive checks.."
+msgstr "تفعيل فحوصات سلبية.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:249
+msgid "Enabling passive host checks.."
+msgstr "تفعيل فحوصات مضيف سلبية.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:253
+msgid "Enabling passive service checks.."
+msgstr "تفعيل فحوصات الخدمة السلبية.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:257
+msgid "Enabling performance data.."
+msgstr "تفعيل بيانات الأداء.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:88
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:251
+msgid "End Time"
+msgstr "زمن الانتهاء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:75
+msgid "Ended downtimes"
+msgstr "أزمنة التوقف المنتهية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:159
+msgid ""
+"Enter here the duration of the downtime. The downtime will be automatically "
+"deleted after this time expired."
+msgstr ""
+"أدخل وقت التوقف هنا. سيتم حذف زمن التوقف تلقائيا "
+"بعد انقضاء هذا الوقت."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:90
+msgid ""
+"Enter the expire date and time for this acknowledgement here. Icinga will "
+"delete the acknowledgement after this time expired."
+msgstr ""
+"أدخل تاريخ الانتهاء ووقت هذا الإشعار هنا. \"إسنجا\" سيحذف "
+"هذا الإشعار بعد انتهاء هذا الوقت."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:43
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:248
+msgid "Entry Time"
+msgstr "زمن الدخول"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:216
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:336
+msgid "Event Grid"
+msgstr "شبكة الحدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:54
+msgid "Event Handler"
+msgstr "معالج الحدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:208
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:210
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:108
+msgid "Event Handlers"
+msgstr "معالجات الحدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:220
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:546
+msgid "Event Overview"
+msgstr "نظرة عامة على الحدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:116
+msgid "Execution time"
+msgstr "وقت التنفيذ"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:441
+msgid "Expiration"
+msgstr "انتهاء الصلاحية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:87
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php:43
+msgid "Expire Time"
+msgstr "وقت انتهاء الصلاحية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:57
+msgid "Expires"
+msgstr "انتهاء صلاحية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:27
+#, php-format
+msgid "Expires %s"
+msgstr "انتهاء صلاحية %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:87
+msgid "FLAPPING"
+msgstr "تذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:91
+msgid "FLAPPING STOPPED"
+msgstr "توقف التذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php:138
+msgid ""
+"Failed to send external Icinga command. No transport has been configured for "
+"this instance. Please contact your Icinga Web administrator."
+msgstr ""
+"فشل في إرسال أمر \"إسنجا\" الخارجي. لم يتم إعداد نقل "
+"لهذه الحالة. يرجى الاتصال بمدير الوب الخاص بإسنجا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:143
+#, php-format
+msgid "Failed to successfully validate the configuration: %s"
+msgstr "فشل التحقق من صحة الإعداد بنجاح: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:79
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:200
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:202
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/flags.phtml:2
+msgid "Feature Commands"
+msgstr "أوامر ميزة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Navigation/ActionForm.php:24
+msgid "Filter"
+msgstr "مرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:60
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:107
+msgid "Fixed"
+msgstr "ثابت"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:66
+msgid "Fixed downtimes have a static start and end time."
+msgstr "أزمنة التوقف الثابتة لها بداية ونهاية ثابتة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:8
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:10
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:58
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:117
+msgid "Flap Detection"
+msgstr "كشف التذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:5
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:19
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:15
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/EventOverviewForm.php:84
+msgid "Flapping"
+msgstr "التذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:60
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:108
+msgid "Flexible"
+msgstr "مرن"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:157
+msgid "Flexible Duration"
+msgstr "مدة مرنة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:63
+msgid ""
+"Flexible downtimes have a hard start and end time, but also an additional "
+"restriction on the duration in which the host or service may actually be "
+"down."
+msgstr ""
+"أزمنة التوقف المرنة لديها زمن بداية ونهاية صعب، ولكن أيضا لها تقييد إضافي "
+"على المدة التي يكون فيها المضيف أو الخدمة متوقفا."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:62
+msgid "Force Check"
+msgstr "فحص مفروض"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:55
+msgid "Forced"
+msgstr "مفروض"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:66
+msgid "From"
+msgstr "من"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:48
+msgid "Global Host Event Handler"
+msgstr "معالج حدث المضيف العالمي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:42
+msgid "Global Service Event Handler"
+msgstr "معالج حدث الخدمة العالمي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:31
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:130
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:229
+msgid "Handled"
+msgstr "مُعالج"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:55
+msgid "Hard state changes"
+msgstr "تغييرات حالة صعبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:325
+msgid "Healing Chart"
+msgstr "رسم الصحة البياني"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:89
+msgid "Hide the properties of monitored objects that match the filter"
+msgstr "إخفاء خصائص الكائنات المراقبة التي توافق المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:212
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:69
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:229
+msgid "History"
+msgstr "المحفوظات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:15
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:30
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:29
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:31
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml:20
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/notifications.phtml:53
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:139
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:246
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:438
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:97
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:185
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/DataView/DataView.php:275
+msgid "Host"
+msgstr "مضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:115
+msgid "Host Action"
+msgstr "فعل المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:176
+msgid "Host Address"
+msgstr "عنوان المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:61
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:121
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:148
+msgid "Host Checks"
+msgstr "فحوصات المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:25
+msgid "Host Group"
+msgstr "مجموعة المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:291
+msgid "Host Group Chart"
+msgstr "رسم بياني لمجموعة المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:534
+msgid "Host Group Name"
+msgstr "اسم مجموعة المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:501
+msgid "Host Groups"
+msgstr "مجموعات المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:132
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:268
+msgid "Host Problems"
+msgstr "مشاكل المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:35
+msgid "Host Problems:"
+msgstr "مشاكل المضيف:"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:173
+msgid "Host Severity"
+msgstr "خطورة المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:26
+msgid "Host States"
+msgstr "حالات المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:3
+msgid "Host and Service Checks"
+msgstr "فحوصات المضيف والخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/disable-notifications.phtml:10
+msgid "Host and service notifications are already disabled."
+msgstr "تنبيهات المضيف والخدمة تم تعطيلها مسبقا."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:33
+msgid "Host not found"
+msgstr "المضيف غير موجود"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:109
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:188
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml:16
+msgid "Hostgroups"
+msgstr "مجموعات المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:89
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:175
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:598
+msgid "Hostname"
+msgstr "اسم المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:141
+msgid "Hostname or address of the remote Icinga instance"
+msgstr "اسم المضيف وعنوان حالة \"إسنجا\" البعيدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:107
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:176
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:9
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:39
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:100
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:295
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:59
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:48
+msgid "Hosts"
+msgstr "المضيفون"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:639
+msgid "Hour"
+msgstr "ساعة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:137
+msgid "Hours"
+msgstr "ساعات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/service-header.phtml:30
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/host-header.phtml:29
+msgid "IPv4 address"
+msgstr "عنوان Ipv4"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/service-header.phtml:25
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/host-header.phtml:24
+msgid "IPv6 address"
+msgstr "عنوان IPv6"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:45
+msgid ""
+"Icinga Web 2 will protect your monitoring environment against prying eyes "
+"using the configuration specified below:"
+msgstr ""
+"واجهة وب إسنجا 2 ستحمي بيئة المراقبة الخاصة بك ضد أعين "
+"المتطفلين باستخدام الإعداد المحدد أدناه:"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:77
+#, php-format
+msgid ""
+"Icinga Web 2 will retrieve information from your monitoring environment "
+"using a backend called \"%s\" and the specified resource below:"
+msgstr ""
+"واجهة وب إسنجا 2 ستسترد المعلومات من بيئة المراقبة الخاصة بك "
+"باستخدام الخلفية المسماة \"%s\" والمورد المحدد أدناه:"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:76
+#, php-format
+msgid ""
+"Icinga Web 2 will use the named pipe located at \"%s\" to send commands to "
+"your monitoring instance."
+msgstr ""
+"واجهة وب إسنجا 2 ستستخدم الأنبوب المسمى الواقع على \"%s\" لإرسال أوامر "
+"إلى مثال المراقبة الخاصة بك."
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:49
+#, php-format
+msgid ""
+"Icinga Web 2 will use the named pipe located on a remote machine at \"%s\" "
+"to send commands to your monitoring instance by using the connection details "
+"listed below:"
+msgstr ""
+"واجهة وب إسنجا 2 ستستخدم \"الأنبوب المسمى\" الواقع على الجهاز البعيد \"%s\""
+" لإرسال أوامر "
+"إلى مثال المراقبة الخاصة بك باستخدام تفاصيل الاتصال المدونة أدناه:"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:74
+msgid "If the acknowledgement should expire, check this option."
+msgstr "إذا كان الإشعار ستنتهي صلاحيته فحدد هذا الخيار."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:58
+msgid ""
+"If you check this option, the notification is sent out regardless of time "
+"restrictions and whether or not notifications are enabled."
+msgstr ""
+"إذا قمت بتحديد هذا الخيار، فإن التنبيه سيرسل بغض النظر عن تقييدات "
+"الوقت وكون التنبيهات مفعلة أم لا."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:70
+msgid ""
+"If you check this option, the notification is sent out to all normal and "
+"escalated contacts."
+msgstr ""
+"إذا قمت بتحديد هذا الخيار، فإن التنبيه سيرسل لكل جهات "
+"الاتصال العادية والمصعّدة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:126
+msgid ""
+"If you do not want an acknowledgement notification to be sent out to the "
+"appropriate contacts, uncheck this option."
+msgstr ""
+"إذا كنت تريد لتنبيه الإشعار أن يرسل لجهة الاتصال المناسبة "
+"فقم بإلغاء هذا الخيار."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:101
+msgid ""
+"If you select the fixed option, the downtime will be in effect between the "
+"start and end times you specify whereas a flexible downtime starts when the "
+"host or service enters a problem state sometime between the start and end "
+"times you specified and lasts as long as the duration time you enter. The "
+"duration fields do not apply for fixed downtimes."
+msgstr ""
+"إذا قمت بتحديد الخيار الثابت، فإن زمن التوقف يكون ساري المفعول بين"
+"أزمنة البداية والنهاية التي تحددها في حين يبدأ التوقف المرن عندما يدخل"
+"مضيف أو خدمة إلى حالة مشكلة في وقت ما بين زمن البداية والنهاية "
+"الذين حددتهما ويستمر طيلة المدة الزمنية التي تدخلها. حقول الزمن "
+"لا تنطبق على أزمنة التوقف الثابتة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:64
+msgid ""
+"If you select this option, Icinga will force a check regardless of both what "
+"time the scheduled check occurs and whether or not checks are enabled."
+msgstr ""
+"إذا قمت بتحديد هذا الخيار، فإن إسنجا ستفرض اختبارا بغض النظر عن"
+"زمن حدوث الاختبار المجدول وعما إذا كانت الاختبارات مفعلة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:175
+msgid ""
+"If you still have any environments or views referring to this transport, you "
+"won't be able to send commands anymore after deletion."
+msgstr ""
+"إذا كان لديك أي بيئات أو عروض تشير إلى هذا النقل، فلن "
+"لن تكون قادرا على إرسال الأوامر مرة أخرى بعد الحذف."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:58
+msgid ""
+"If you uncheck this option, the comment will automatically be deleted the "
+"next time Icinga is restarted."
+msgstr ""
+"إذا قمت بإلغاء تحديد هذا الخيار، سيتم تلقائيا حذف التعليق"
+"في المرة القادمة التي سيعاد فيها تشغيل إسنجا."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:114
+msgid ""
+"If you want the acknowledgement to remain until the host or service recovers "
+"even if the host or service changes state, check this option."
+msgstr ""
+"ذا كنت ترغب في بقاء الإشعار حتى يتعافى المضيف أو الخدمة"
+"حتى إذا تغيرت حالة المضيف أو الخدمة، فاختر هذا الخيار."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:44
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:45
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:67
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:51
+msgid ""
+"If you work with other administrators, you may find it useful to share "
+"information about the the host or service that is having problems. Make sure "
+"you enter a brief description of what you are doing."
+msgstr ""
+"إذا كنت تعمل مع المسؤولين الآخرين، قد تجد أنه من المفيد تبادل "
+"المعلومات حول المضيف أو الخدمة التي تواجه مشاكل. تأكد "
+"من إدخال وصفا موجزا لما تقوم به."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:63
+msgid ""
+"If you would like the comment to remain even when the acknowledgement is "
+"removed, check this option."
+msgstr ""
+"إذا كنت ترغب في بقاء التعليق حتى عندما يُزال الإقرار "
+"فاختر هذا الخيار."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/statusicons.phtml:17
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml:17
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:25
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:21
+msgid "In Downtime"
+msgstr "في زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:151
+msgid "In effect"
+msgstr "ساري المفعول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:131
+msgid ""
+"Indicates the number of seconds that the scheduled downtime should last. "
+"This is usually only needed if this is a flexible downtime, which can start "
+"at a variable time, but lasts for the specified duration"
+msgstr ""
+"يشير إلى عدد الثواني التي يستمرها زمن التوقف المجدول. عادة "
+"ما تكون هناك حاجة إليها إذا كان هذا هو وقت التوقف المرن، "
+"الذي يمكن أن يبدأ في وقت متغير، ولكن يستمر للمدة المحددة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/command.phtml:7
+msgid "Instance"
+msgstr "حالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:203
+msgid "Instance Link"
+msgstr "رابط الحالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:84
+#, php-format
+msgid "Invalid command transport type \"%s\" given"
+msgstr "نوع ناقل الأمر المعطى \"%s\" غير صالح "
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Navigation/ActionForm.php:61
+#, php-format
+msgid "Invalid filter provided. You can only use the following columns: %s"
+msgstr "تم تزويد مرشح غير صالح. تستطيع استخدام الأعمدة التالية فقط: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:245
+msgid "Is In Effect"
+msgstr "ساري المفعول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checksource.phtml:11
+msgid "Is reachable"
+msgstr "يمكن الوصول إليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/WelcomePage.php:43
+msgid ""
+"It offers various status and reporting views with powerful filter "
+"capabilities that allow you to keep track of the most important events in "
+"your monitoring environment."
+msgstr ""
+"ويقدم الوضع عروض مختلفة للحالة والتقارير مع قدرات تصفية قوية "
+"تسمح لك بتتبع أهم الأحداث في بيئة المراقبة الخاصة بك."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:36
+msgid "Label"
+msgstr "عنوان"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:91
+msgid "Last Check"
+msgstr "آخر فحص"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:32
+msgid "Last External Command Check"
+msgstr "آخر فحص أمر خارجي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:177
+msgid "Last Host Check"
+msgstr "آخر فحص لمضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:36
+msgid "Last Log File Rotation"
+msgstr "آخر تدوير لملف السحل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:171
+msgid "Last Service Check"
+msgstr "آخر فحص لخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:92
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:172
+msgid "Last State Change"
+msgstr "آخر تغيير حالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:28
+msgid "Last Status Update"
+msgstr "آخر تحديث للحالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:7
+msgid "Last check"
+msgstr "آخر فحص"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:7
+msgid "Last update"
+msgstr "آخر تحديث"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:294
+msgid "Late Host Check Results"
+msgstr "آخر نتائج لفحص المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:298
+msgid "Late Service Check Results"
+msgstr "آخر نتائج لفحص الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:115
+msgid "Latency"
+msgstr "تأخير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:15
+msgid "Legend"
+msgstr "الدليل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notes.phtml:23
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notes.phtml:24
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/actions.phtml:17
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/actions.phtml:18
+msgid "Link opens in new window"
+msgstr "يفتح الرابط في نافذة جديدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hosts.phtml:75
+#, php-format
+msgid "List %s unhandled service problem on host %s"
+msgid_plural "List %s unhandled service problems on host %s"
+msgstr[0] "سرد مشكلة الخدمة غير المعالجة %s على المضيف %s"
+msgstr[1] "سرد مشاكل الخدمة غير المعالجة %s على المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:112
+#, php-format
+msgctxt "timeline.link.title"
+msgid "List %u %s registered %s"
+msgstr "سرد %u %s مسجلة %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:26
+#, php-format
+msgid "List %u actively checked host"
+msgid_plural "List %u actively checked hosts"
+msgstr[0] "سرد %u مضيف مفحوص بطريقة نشطة"
+msgstr[1] "سرد %u من المضيفين المفحوصين بطريقة نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:82
+#, php-format
+msgid "List %u actively checked service"
+msgid_plural "List %u actively checked services"
+msgstr[0] "سرد الخدمة %u المفحوصة بطريقة نشطة"
+msgstr[1] "سرد الخدمات %u المفحوصة بطريقة نشطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/components/hostssummary.phtml:17
+#, php-format
+msgid "List %u host"
+msgid_plural "List all %u hosts"
+msgstr[0] "سرد %u مضيف"
+msgstr[1] "سرد %u من المضيفين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:29
+#, php-format
+msgid "List %u host for which flap detection has been disabled"
+msgid_plural "List %u hosts for which flap detection has been disabled"
+msgstr[0] "سرد %u مضيف عطل فيه كشف التذبذب"
+msgstr[1] "سرد %u من المضيفين الذين عطل فيهم كشف التذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:150
+#, php-format
+msgid "List %u host for which notifications are suppressed"
+msgid_plural "List %u hosts for which notifications are suppressed"
+msgstr[0] "سرد %u مضيف حيث أُخمدت التنبيهات"
+msgstr[1] "سرد %u من المضيفين حيث أُخمدت التنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:59
+#, php-format
+msgid "List %u host that is currently flapping"
+msgid_plural "List %u hosts which are currently flapping"
+msgstr[0] "سرد %u مضيف يتذبذب حاليا"
+msgstr[1] "سرد %u مضيف يتذبذب حاليا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/problem_hosts.phtml:18
+#, php-format
+msgid "List %u host that is currently in state DOWN"
+msgid_plural "List %u hosts which are currently in state DOWN"
+msgstr[0] "سرد %u مضيف حاليا في حالة \"متوقف\""
+msgstr[1] "سرد %u من المضيفين حاليا في حالة \"متوقف\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/ok_hosts.phtml:41
+#, php-format
+msgid "List %u host that is currently in state PENDING"
+msgid_plural "List %u hosts which are currently in state PENDING"
+msgstr[0] "سرد %u مضيف حاليا في حالة \"معلق\""
+msgstr[1] "سرد %u من المضيفين حاليا في حالة \"معلق\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/problem_hosts.phtml:40
+#, php-format
+msgid "List %u host that is currently in state UNREACHABLE"
+msgid_plural "List %u hosts which are currently in state UNREACHABLE"
+msgstr[0] "سرد %u مضيف حاليا في حالة \"لا يمكن الوصول\""
+msgstr[1] "سرد %u من المضيفين حاليا في حالة \"لا يمكن الوصول\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/ok_hosts.phtml:23
+#, php-format
+msgid "List %u host that is currently in state UP"
+msgid_plural "List %u hosts which are currently in state UP"
+msgstr[0] "سرد %u مضيف حاليا في حالة \"سليم\""
+msgstr[1] "سرد %u من المضيفين حاليا في حالة \"سليمة\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:62
+#, php-format
+msgid "List %u host that is not being checked at all"
+msgid_plural "List %u hosts which are not being checked at all"
+msgstr[0] "سرد %u مضيف لم يتم فحصه مطلقا"
+msgstr[1] "سرد %u من المضيفين لم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:229
+#, php-format
+msgid "List %u host that is not processing any event handlers"
+msgid_plural "List %u hosts which are not processing any event handlers"
+msgstr[0] "سرد %u مضيف لا تقوم بمعالجة أي معالجات حدث"
+msgstr[1] "سرد %u من المضيفين لا تقوم بمعالجة أي معالجات حدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:44
+#, php-format
+msgid "List %u passively checked host"
+msgid_plural "List %u passively checked hosts"
+msgstr[0] "سرد %u مضيف مفحوص بطريقة سالبة"
+msgstr[1] "سرد %u من المضيفين المفحوصين بطريقة سالبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:100
+#, php-format
+msgid "List %u passively checked service"
+msgid_plural "List %u passively checked services"
+msgstr[0] "سرد %u خدمة مفحوصة بطريقة سالبة"
+msgstr[1] "سرد %u من الخدمات المفحوصة بطريقة سالبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml:20
+#, php-format
+msgid "List %u service"
+msgid_plural "List all %u services"
+msgstr[0] "سرد %u خدمة"
+msgstr[1] "سرد %u من الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:84
+#, php-format
+msgid "List %u service for which flap detection has been disabled"
+msgid_plural "List %u services for which flap detection has been disabled"
+msgstr[0] "سرد %u خدمة عطل فيه كشف التذبذب"
+msgstr[1] "سرد %u من الخدمات التي عطل فيها كشف التذبذب"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:184
+#, php-format
+msgid "List %u service for which notifications are suppressed"
+msgid_plural "List %u services for which notifications are suppressed"
+msgstr[0] "سرد %u خدمة حيث أُخمدت التنبيهات"
+msgstr[1] "سرد %u من الخدمات حيث أُخمدت التنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:114
+#, php-format
+msgid "List %u service that is currently flapping"
+msgid_plural "List %u services which are currently flapping"
+msgstr[0] "سرد %u خدمة مذبذبة حاليا"
+msgstr[1] "سرد %u من الخدمات مذبذبة حاليا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:20
+#, php-format
+msgid "List %u service that is currently in state CRITICAL"
+msgid_plural "List %u services which are currently in state CRITICAL"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"ضرورية\""
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"ضرورية\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:41
+#, php-format
+msgid "List %u service that is currently in state CRITICAL (Handled)"
+msgid_plural "List %u services which are currently in state CRITICAL (Handled)"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"ضرورية\" (مُعالجة)"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"ضرورية\" (مُعالجة)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:95
+#, php-format
+msgid ""
+"List %u service that is currently in state CRITICAL and not checked at all"
+msgid_plural ""
+"List %u services which are currently in state CRITICAL and not checked at all"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"ضرورية\" ولم يتم فحصها مطلقا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"ضرورية\" ولم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:68
+#, php-format
+msgid ""
+"List %u service that is currently in state CRITICAL and passively checked"
+msgid_plural ""
+"List %u services which are currently in state CRITICAL and passively checked"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"ضرورية\" وتم فحصها سلبيا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"ضرورية\" وتم فحصها سلبيا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:314
+#, php-format
+msgid "List %u service that is currently in state OK"
+msgid_plural "List %u services which are currently in state OK"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"سليمة\""
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"سليمة\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:340
+#, php-format
+msgid "List %u service that is currently in state OK and not checked at all"
+msgid_plural ""
+"List %u services which are currently in state OK and not checked at all"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"سليمة\" ولم يتم فحصها مطلقا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"سليمة\" ولم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:361
+#, php-format
+msgid "List %u service that is currently in state PENDING"
+msgid_plural "List %u services which are currently in state PENDING"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"معلقة\""
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"معلقة\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:387
+#, php-format
+msgid ""
+"List %u service that is currently in state PENDING and not checked at all"
+msgid_plural ""
+"List %u services which are currently in state PENDING and not checked at all"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"معلقة\" ولم يتم فحصها مطلقا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"معلقة\" ولم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:218
+#, php-format
+msgid "List %u service that is currently in state UNKNOWN"
+msgid_plural "List %u services which are currently in state UNKNOWN"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"مجهولة\""
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"مجهولة\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:239
+#, php-format
+msgid "List %u service that is currently in state UNKNOWN (Handled)"
+msgid_plural "List %u services which are currently in state UNKNOWN (Handled)"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"مجهولة\" (معالجة)"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"مجهولة\" (مُعالجة)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:293
+#, php-format
+msgid ""
+"List %u service that is currently in state UNKNOWN and not checked at all"
+msgid_plural ""
+"List %u services which are currently in state UNKNOWN and not checked at all"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"مجهولة\" ولم يتم فحصها مطلقا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"مجهولة\" ولم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:266
+#, php-format
+msgid ""
+"List %u service that is currently in state UNKNOWN and passively checked"
+msgid_plural ""
+"List %u services which are currently in state UNKNOWN and passively checked"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"مجهولة\" وتم فحصها سلبيا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"مجهولة\" وتم فحصها سلبيا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:119
+#, php-format
+msgid "List %u service that is currently in state WARNING"
+msgid_plural "List %u services which are currently in state WARNING"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"تحذير\""
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"تحذير\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:140
+#, php-format
+msgid "List %u service that is currently in state WARNING (Handled)"
+msgid_plural "List %u services which are currently in state WARNING (Handled)"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"تحذير\" (مُعالجة)"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"تحذير\" (مُعالجة)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:194
+#, php-format
+msgid ""
+"List %u service that is currently in state WARNING and not checked at all"
+msgid_plural ""
+"List %u services which are currently in state WARNING and not checked at all"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"تحذير\" ولم يتم فحصها مطلقا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"تحذير\" ولم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/parts/servicestatesummarybyhoststate.phtml:167
+#, php-format
+msgid ""
+"List %u service that is currently in state WARNING and passively checked"
+msgid_plural ""
+"List %u services which are currently in state WARNING and passively checked"
+msgstr[0] "سرد %u خدمة حاليا في حالة \"تحذير\" وتم فحصها سلبيا"
+msgstr[1] "سرد %u من الخدمات حاليا في حالة \"تحذير\" وتم فحصها سلبيا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:118
+#, php-format
+msgid "List %u service that is not being checked at all"
+msgid_plural "List %u services which are not being checked at all"
+msgstr[0] "سرد %u خدمة لم يتم فحصها مطلقا"
+msgstr[1] "سرد %u من الخدمات التي لم يتم فحصها مطلقا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:263
+#, php-format
+msgid "List %u service that is not processing any event handlers"
+msgid_plural "List %u services which are not processing any event handlers"
+msgstr[0] "سرد %u خدمة لا تقوم بمعالجة أي معالجات حدث"
+msgstr[1] "سرد %u من الخدمات التي لا تقوم بمعالجة أي معالجات حدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comments-header.phtml:23
+#, php-format
+msgid "List all %d comments"
+msgstr "سرد جميع التعليقات %d"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtimes-header.phtml:31
+#, php-format
+msgid "List all %d downtimes"
+msgstr "سرد جميع أزمنة التوقف %d"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml:32
+#, php-format
+msgid "List all %d hosts"
+msgstr "سرد جميع المضيفين %d"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/objects-header.phtml:36
+#, php-format
+msgid "List all %d services"
+msgstr "سرد جميع الخدمات %d"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:74
+#, php-format
+msgctxt "timeline.link.title"
+msgid "List all event records registered %s"
+msgstr "سرد جميع سجلات الأحداث المسجلة %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml:11
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:43
+#, php-format
+msgid "List all hosts in the group \"%s\""
+msgstr "سرد جميع المضيفين في مجموعة \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:43
+msgid "List all hosts, for which flap detection is enabled entirely"
+msgstr "سرد جميع المضيفين الذين فُعل لهم كشف التذبذب بصورة كاملة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:164
+msgid "List all hosts, for which notifications are enabled entirely"
+msgstr "سرد جميع المضيفين الذين فُعلت لهم التنبيهات بصورة كاملة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:243
+msgid "List all hosts, which are processing event handlers entirely"
+msgstr "سرد جميع المضيفين الذين يقومون بمعالجة معالجات الحدث بصورة كاملة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegrid.phtml:56
+#, php-format
+msgid "List all reported services on host %s"
+msgstr "سرد جميع الخدمات المذكورة على المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/servicegroups.phtml:11
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegroups.phtml:38
+#, php-format
+msgid "List all services in the group \"%s\""
+msgstr "سرد جميع الخدمات في مجموعة \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:141
+#, php-format
+msgid "List all services of all hosts in host group \"%s\""
+msgstr "سرد جميع الخدمات لكل المضيفين في مجموعة المضيف \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:209
+#, php-format
+msgid "List all services on host %s"
+msgstr "سرد جميع الخدمات على المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegrid.phtml:36
+#, php-format
+msgid "List all services with the name \"%s\" on all reported hosts"
+msgstr "سرد جميع الخدمات باسم \"%s\" على جميع المضيفين المذكورين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:98
+msgid "List all services, for which flap detection is enabled entirely"
+msgstr "سرد جميع الخدمات اللاتي فُعّل لها كشف التذبذب بصورة كاملة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:198
+msgid "List all services, for which notifications are enabled entirely"
+msgstr "سرد جميع الخدمات اللاتي فُعّلت لها التنبيهات بصورة كاملة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:277
+msgid "List all services, which are processing event handlers entirely"
+msgstr "سرد جميع الخدمات اللاتي تُعالج معالجات الحدث بصورة كاملة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:411
+msgid "List comments"
+msgstr "سرد التعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:382
+msgid "List contact groups"
+msgstr "سرد مجموعات جهة الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:308
+msgid "List contacts"
+msgstr "سرد جهات الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/contacts.phtml:29
+#, php-format
+msgid "List contacts in contact-group \"%s\""
+msgstr "سرد جهات الاتصال في مجموعة الاتصال \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:213
+msgid "List downtimes"
+msgstr "سرد أزمنة التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:547
+msgid "List event records"
+msgstr "سرد سجلات الحدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:502
+msgid "List host groups"
+msgstr "سرد مجموعات المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:49
+msgid "List hosts"
+msgstr "سرد المضيفين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:273
+msgid "List notifications"
+msgstr "سرد التنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:462
+msgid "List service groups"
+msgstr "سرد مجموعات الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:124
+msgid "List services"
+msgstr "سرد الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:119
+msgid "Livestatus Resource"
+msgstr "مورد Livestatus"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:183
+msgid "Load More"
+msgstr "تحميل أكثر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegrid.phtml:93
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegrid.phtml:114
+msgid "Load more"
+msgstr "تحميل أكثر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:95
+msgid "Local"
+msgstr "محلي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:225
+msgid "Local Command File"
+msgstr "ملف أمر محلي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:89
+msgid "Make use of the ssh identity resource"
+msgstr "استخدم مورد الهوية ssh"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:39
+msgid "Max"
+msgstr "أقصى"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:444
+msgid "Max (min)"
+msgstr "أقصى (أدنى)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:38
+msgid "Min"
+msgstr "أدنى"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:147
+msgid "Minutes"
+msgstr "دقائق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:21
+msgid "Monitoring Backend"
+msgstr "مراقبة الخلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/BackendPage.php:14
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:73
+msgctxt "setup.page.title"
+msgid "Monitoring Backend"
+msgstr "مراقبة الخلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:7
+msgid "Monitoring Backends"
+msgstr "مراقبة الخلفيات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:3
+msgid "Monitoring Features"
+msgstr "مراقبة المميزات"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:249
+msgid "Monitoring Health"
+msgstr "مراقبة الصحة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:21
+msgctxt "setup.page.title"
+msgid "Monitoring IDO Resource"
+msgstr "مراقبة مورد IDO"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php:14
+msgctxt "setup.page.title"
+msgid "Monitoring Livestatus Resource"
+msgstr "مراقبة مورد Livestatus"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/SecurityPage.php:14
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:42
+msgctxt "setup.page.title"
+msgid "Monitoring Security"
+msgstr "مراقبة الأمان"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:79
+#, php-format
+msgid "Monitoring backend \"%s\" not found"
+msgstr "مراقبة الخلفية \"%s\" غير موجود"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:149
+#, php-format
+msgid "Monitoring backend \"%s\" successfully removed"
+msgstr "تمت إزالة مراقبة الخلفية \"%s\" بنجاح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:68
+#, php-format
+msgid "Monitoring backend \"%s\" successfully updated"
+msgstr "تم تحديث مراقبة الخلفية \"%s\" بنجاح"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Navigation/Renderer/BackendAvailabilityNavigationItemRenderer.php:66
+#, php-format
+msgid "Monitoring backend %s is not running"
+msgstr "الخلفية %s لا تعمل"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:151
+#, php-format
+msgid ""
+"Monitoring backend configuration could not be written to: %s. An error "
+"occured:"
+msgstr "إعداد خلفية المراقبة لم يُتمكن من كتابته إلى: %s. حدث خطأ:"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:144
+#, php-format
+msgid "Monitoring backend configuration has been successfully written to: %s"
+msgstr "إعداد خلفية المراقبة تمت كتابته إلى: %s بنجاح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:116
+msgid "Monitoring backend successfully created"
+msgstr "تم إنشاء خلفية المراقبة بنجاح"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:76
+#, php-format
+msgid ""
+"Monitoring security configuration could not be written to: %s. An error "
+"occured:"
+msgstr "إعداد مراقبة الأمان لم يُتمكن من كتابته إلى: %s. حدث خطأ:"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:68
+#, php-format
+msgid "Monitoring security configuration has been successfully created: %s"
+msgstr "إعداد مراقبة الأمان تم إنشاؤه بنجاح: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:648
+msgid "Month"
+msgstr "شهر"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:313
+msgid "Muted"
+msgstr "صامت"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:21
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:39
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:45
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:51
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:57
+msgid "N/A"
+msgstr "غير متوفر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:49
+msgid "NOTIFICATION"
+msgstr "تنبيه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:20
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:325
+msgid "Name"
+msgstr "اسم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/SecurityConfigForm.php:31
+msgid "New security configuration has successfully been stored"
+msgstr "تم تخزين إعداد الأمان الجديد بنجاح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:22
+msgid "Next check"
+msgstr "الفحص التالي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:22
+msgid "Next update"
+msgstr "التحديث التالي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:155
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:48
+msgid "No"
+msgstr "لا"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php:176
+msgid "No backend has been configured"
+msgstr "لم يتمّ تهيئة أيّة خلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php:41
+#, php-format
+msgid "No command transports have been configured in \"%s\"."
+msgstr "لم يتمّ تهيئة أيّ أمر نواقل في: \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/comments.phtml:15
+msgid "No comments found matching the filter"
+msgstr "لا توجد تعليقات توافق المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php:189
+#, php-format
+msgid "No configuration for backend %s"
+msgstr "لا يوجد إعداد للخلفية %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contactgroups.phtml:16
+msgid "No contact groups found matching the filter"
+msgstr "لا توجد مجموعات توافق المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:14
+msgid "No contacts found matching the filter"
+msgstr "لا توجد جهات اتصال توافق المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/downtimes.phtml:19
+msgid "No downtimes found matching the filter."
+msgstr "لا يوجد أزمنة توقف توافق المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:31
+msgid "No historical events found matching the filter."
+msgstr "لا توجد أحداث تاريخية توافق المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:18
+msgid "No host groups found matching the filter."
+msgstr "لا توجد مجموعات مضيف توافق المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:18
+msgid "No hosts found matching the filter"
+msgstr "لا يوجد مضيفين يوافقون المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hosts.phtml:19
+msgid "No hosts found matching the filter."
+msgstr "لا يوجد مضيفين يوافقون المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:62
+msgid "No notification has been sent for this issue."
+msgstr "لم تُرسَل أي تنبيهات لهذه المشكلة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/notifications.phtml:18
+msgid "No notifications found matching the filter."
+msgstr "لا يوجد تنبيهات توافق المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:69
+msgid "No notifications have been sent for this contact"
+msgstr "لم تُرسَل أي تنبيهات لجهة الاتصال هذه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegroups.phtml:16
+msgid "No service groups found matching the filter."
+msgstr "لا توجد مجموعات خدمة توافق المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:20
+msgid "No services found matching the filter"
+msgstr "لا توجد خدمات توافق المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/services.phtml:20
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegrid.phtml:14
+msgid "No services found matching the filter."
+msgstr "لا توجد خدمات توافق المرشح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/eventgrid.phtml:77
+msgid "No state changes in the selected time period."
+msgstr "ليس هناك تغييرات حالة في الفترة الزمنية المحددة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:12
+msgid "No such contact"
+msgstr "جهة الاتصال غير موجودة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:198
+msgctxt "command transport instance association"
+msgid "None"
+msgstr "لا شيء"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:56
+msgctxt "monitoring.protected_customvars"
+msgid "None"
+msgstr "لا شيء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:57
+msgid "Not acknowledged"
+msgstr "غير معترف به"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checksource.phtml:13
+msgid "Not reachable"
+msgstr "لا يمكن الوصول إليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/notifications.phtml:68
+msgid "Not sent out to any contact"
+msgstr "لم يتم إرساله لأي جهة اتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notes.phtml:43
+msgid "Notes"
+msgstr "ملاحظات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:294
+msgid "Notification Start"
+msgstr "بداية التنبيه"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:224
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:129
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/monitoringfeatures.phtml:131
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:137
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:141
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/detail-content.phtml:24
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:138
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:143
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:2
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/EventOverviewForm.php:74
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:50
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:126
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:329
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:424
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:467
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:474
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:50
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:272
+msgid "Notifications"
+msgstr "تنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/statusicons.phtml:13
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml:13
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:22
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:18
+msgid "Notifications Disabled"
+msgstr "التنبيهات معطلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:15
+msgid "Notifications and Problems"
+msgstr "التنبيهات والمشاكل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:326
+msgid "Notifications and average reaction time per hour."
+msgstr "التنبيهات ومتوسط زمن رد الفعل في الساعة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:464
+msgid "Notifications and defects per hour"
+msgstr "التنبيهات والعيوب في الساعة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:58
+msgid "Notifications sent to this contact"
+msgstr "التنبيهات المرسلة لجهة الاتصال"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:78
+#, php-format
+msgid "Notifications will be re-enabled in %s "
+msgstr "سيعاد تفعيل التنبيهات في %s "
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/disable-notifications.phtml:13
+#, php-format
+msgid "Notifications will be re-enabled in %s ."
+msgstr "سيعاد تفعيل التنبيهات في %s ."
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Service.php:190
+msgid "OK"
+msgstr "سليم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:56
+msgctxt "icinga.state"
+msgid "OK"
+msgstr "سليم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:96
+msgid "Object type"
+msgstr "نوع الكائن"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:46
+msgid "Obsessing"
+msgstr "توجس"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:149
+msgid "Obsessing Over Hosts"
+msgstr "توجس على المضيفين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:158
+msgid "Obsessing Over Services"
+msgstr "توجس على الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:568
+msgid "Occurence"
+msgstr "حدوث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:120
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:243
+msgid "Ok"
+msgstr "سليم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:535
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:104
+msgid "One day"
+msgstr "يوم واحد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:537
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:106
+msgid "One month"
+msgstr "شهر واحد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:536
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:105
+msgid "One week"
+msgstr "أسبوع واحد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:538
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:107
+msgid "One year"
+msgstr "سنة واحدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:68
+msgid "Output"
+msgstr "مخرج"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:292
+msgid "Overdue"
+msgstr "متأخر"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:168
+msgid "Overview"
+msgstr "نظرة عامة"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Host.php:191
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Service.php:202
+msgid "PENDING"
+msgstr "معلق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:34
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:22
+msgid "Pager"
+msgstr "جهاز إخطار"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:328
+msgid "Pager Address / Number"
+msgstr "عنوان / رقم جهاز الإخطار"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:141
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:42
+msgid "Passive Checks"
+msgstr "اختبارات سلبية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:167
+msgid "Passive Host Checks"
+msgstr "فحوصات مضيف سلبية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:176
+msgid "Passive Service Checks"
+msgstr "فحوصات الخدمة السلبية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:136
+msgid "Passive checks"
+msgstr "فحوصات سلبية"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:113
+msgid "Password"
+msgstr "كلمة مرور"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:179
+msgid "Path to the Icinga command file on the remote Icinga instance"
+msgstr "مسار ملف أمر إسنجا على حالة إسنجا البعيدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/LocalTransportForm.php:32
+msgid "Path to the local Icinga command file"
+msgstr "مسار ملف أمر إسنجا المحلي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:88
+msgid "Per Host"
+msgstr "لكل مضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:77
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php:187
+msgid "Performance Data"
+msgstr "بيانات الأداء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/perfdata.phtml:2
+msgid "Performance data"
+msgstr "بيانات الأداء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:47
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:55
+msgid "Persistent"
+msgstr "دائم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:61
+msgid "Persistent Comment"
+msgstr "تعليق دائم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/BackendPage.php:16
+msgid ""
+"Please configure below how Icinga Web 2 should retrieve monitoring "
+"information."
+msgstr "الرجاء إعداد كيفية استعادة معلومات المراقبة من قبل إسنجا وب 2"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/TransportPage.php:16
+msgid ""
+"Please define below how you want to send commands to your monitoring "
+"instance."
+msgstr "الرجاء تعريف كيف تريد إرسال أوامر لحالة المراقبة خاصتك."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:23
+msgid ""
+"Please fill out the connection details below to access the IDO database of "
+"your monitoring environment."
+msgstr "الرجاء تعبئة تفاصيل الاتصال أدناه للوصول لقاعدة بيانات بيئة المراقبة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php:16
+msgid ""
+"Please fill out the connection details below to access the Livestatus socket "
+"interface for your monitoring environment."
+msgstr ""
+"الرجاء تعبئة تفاصيل الاتصال أدناه للوصول لواجهة مقبس Livestatus لبيئة"
+" المراقبة خاصتك."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/output.phtml:1
+msgid "Plugin Output"
+msgstr "مخرج التوصيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:150
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:101
+msgid "Port"
+msgstr "المنفذ"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/components/selectioninfo.phtml:3
+msgctxt "Multi-selection help"
+msgid ""
+"Press and hold the Ctrl key while clicking on rows to select multiple rows "
+"or press and hold the Shift key to select a range of rows"
+msgstr ""
+"اضغط باستمرار على مفتاح Ctrl أثناء الضغط على صفوف لاختيار صفوف متعددة "
+"أو الضغط باستمرار مع مفتاح Shift لاختيار مدى من الصفوف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:20
+msgid "Problem Handling"
+msgstr "معالجة المشكلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/detail-content.phtml:5
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:22
+msgid "Problem handling"
+msgstr "معالجة المشكلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:124
+msgid "Problems"
+msgstr "المشاكل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:14
+msgid "Process Info"
+msgstr "معلومات العملية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HealthController.php:33
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HealthController.php:55
+msgid "Process Information"
+msgstr "معلومات العملية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:166
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:168
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/command.phtml:21
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/command.phtml:33
+msgid "Process check result"
+msgstr "معالجة نتيجة الفحص"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:107
+msgid "Processing check result.."
+msgid_plural "Processing check results.."
+msgstr[0] "معالجة نتيجة الفحص.."
+msgstr[1] "معالجة نتائج الفحص.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:24
+msgid "Program Start Time"
+msgstr "زمن بداية البرنامج"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/info.phtml:18
+msgid "Program Version"
+msgstr "إصدار البرنامج"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/SecurityConfigForm.php:56
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/SecurityStep.php:53
+msgid "Protected Custom Variables"
+msgstr "متغيرات مخصصة محمية"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:264
+msgid "Recently Recovered Services"
+msgstr "خدمات تعافت مؤخرا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:95
+msgid "Remote"
+msgstr "بعيد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:226
+msgid "Remote Command File"
+msgstr "ملف أمر بعيد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:59
+msgid "Remote Host"
+msgstr "مضيف بعيد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:63
+msgid "Remote SSH Port"
+msgstr "منفذ SSH بعيد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/TransportStep.php:67
+msgid "Remote SSH User"
+msgstr "مستخدم SSH بعيد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteDowntimesCommandForm.php:63
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/DeleteCommentsCommandForm.php:63
+msgid "Remove"
+msgid_plural "Remove All"
+msgstr[0] "إزالة"
+msgstr[1] "إزالة الكل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comments/show.phtml:11
+#, php-format
+msgid "Remove %d comments"
+msgstr "إزالة %d من التعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:172
+#, php-format
+msgid "Remove Command Transport %s"
+msgstr "إزالة ناقل أمر %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ConfigController.php:139
+#, php-format
+msgid "Remove Monitoring Backend %s"
+msgstr "إزالة خلفية مراقبة %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtimes/show.phtml:11
+#, php-format
+msgid "Remove all %d scheduled downtimes"
+msgstr "إزالة كل أزمنة المجدولة %d"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/CommentsController.php:93
+msgid "Remove all Comments"
+msgstr "إزالة كل التعليقات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/DowntimesController.php:97
+msgid "Remove all Downtimes"
+msgstr "إزالة كل أزمنة التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comments/show.phtml:16
+msgid "Remove all selected comments"
+msgstr "إزالة كل التعليقات المحددة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtimes/show.phtml:16
+msgid "Remove all selected downtimes"
+msgstr "إزالة كل أزمنة التوقف المحددة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:107
+#, php-format
+msgid "Remove command transport %s"
+msgstr "إزالة ناقل الأمر %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:52
+#, php-format
+msgid "Remove monitoring backend %s"
+msgstr "إزالة خلفية المراقبة %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php:73
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php:92
+msgid "Remove problem acknowledgement"
+msgid_plural "Remove problem acknowledgements"
+msgstr[0] "إزالة إشعار مشكلة"
+msgstr[1] "إزالة إشعارات مشكلة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/RemoveAcknowledgementCommandForm.php:114
+msgid "Removing problem acknowledgement.."
+msgid_plural "Removing problem acknowledgements.."
+msgstr[0] "إزالة إشعار مشكلة.."
+msgstr[1] "إزالة إشعارات مشكلة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:540
+msgid "Report interval"
+msgstr "فترة التقرير"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:236
+msgid "Reporting"
+msgstr "التقارير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:188
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:190
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:34
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:48
+msgid "Reschedule"
+msgstr "إعادة الجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:142
+msgid "Reschedule Host Check"
+msgstr "إعادة جدولة فحص المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:187
+msgid "Reschedule Host Checks"
+msgstr "إعادة جدولة فحص المضيفين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:100
+msgid "Reschedule Service Check"
+msgstr "إعادة جدولة فحص الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:190
+msgid "Reschedule Service Checks"
+msgstr "إعادة جدولة فحوصات الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:236
+msgid "Resource"
+msgstr "مورد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:89
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:124
+msgid "Resource Name"
+msgstr "اسم المورد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:165
+#, php-format
+msgid "Resource configuration could not be udpated: %s. An error occured:"
+msgstr "إعداد المورد لا يُمكن تحديثه: %s. حدث خطأ:"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:160
+#, php-format
+msgid "Resource configuration has been successfully updated: %s"
+msgstr "إعداد المورد تم تحديثه بنجاح: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:85
+msgid "Restrict views to the Icinga objects that match the filter"
+msgstr "تقييد العروض بكائنات إسنجا التي توافق المرشح"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:60
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:86
+msgid "Runtime Variables"
+msgstr "متغيرات وقت التشغيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:77
+msgid "SCHEDULED DOWNTIME"
+msgstr "زمن توقف مجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:108
+msgid "SSH Identity"
+msgstr "هوية SSH"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:151
+msgid "SSH port to connect to on the remote Icinga instance"
+msgstr "منفذ SSH المُتصل به على حالة إسنجا البعيدة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:6
+msgctxt "Downtime status"
+msgid "STARTS"
+msgstr "يبدأ"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:40
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:42
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/SecurityConfigForm.php:20
+msgid "Save Changes"
+msgstr "حفظ التغييرات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:179
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:181
+msgid "Schedule Check"
+msgstr "فحص مجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:154
+msgid "Schedule Host Downtime"
+msgstr "زمن توقف مضيف مجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:199
+msgid "Schedule Host Downtimes"
+msgstr "أزمنة توقف مضيف مجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:112
+msgid "Schedule Service Downtime"
+msgstr "زمن توقف خدمة مجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:202
+msgid "Schedule Service Downtimes"
+msgstr "أزمنة توقف خدمة مجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:15
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:29
+msgid ""
+"Schedule a downtime to suppress all problem notifications within a specific "
+"period of time"
+msgstr "جدولة زمن توقف لإخماد كل تنبيهات المشكلة ضمن نطاق زمني محدد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:34
+msgid "Schedule check"
+msgid_plural "Schedule checks"
+msgstr[0] "جدولة فحص"
+msgstr[1] "جدولة فحوصات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php:28
+msgid "Schedule check for all services on the hosts and the hosts themselves."
+msgstr "جدولة فحص لكل خدمات المضيفين والمضيفين أنفسهم."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:7
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:21
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:47
+msgid "Schedule downtime"
+msgid_plural "Schedule downtimes"
+msgstr[0] "زمن توقف مجدول"
+msgstr[1] "أزمنة توقف مجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:30
+msgid ""
+"Schedule downtime for all services on the hosts and the hosts themselves."
+msgstr "جدولة فحص لكل خدمات المضيفين والمضيفين أنفسهم."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:100
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:99
+msgid "Schedule downtimes"
+msgstr "جدولة أزمنة توقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:49
+msgid "Schedule non-triggered downtime for all child hosts"
+msgstr "جدولة زمن توقف لا يمكن تشغيله لكل المضيفين التابعين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:42
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:56
+msgid "Schedule the next active check at a different time than the current one"
+msgstr "جدول الفحص التالي النشط في زمن مختلف عن الزمن الحالي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php:44
+msgid "Schedule the next active check to run immediately"
+msgstr "جدول الفحص التالي النشط ليعمل حالا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:48
+msgid "Schedule triggered downtime for all child hosts"
+msgstr "جدولة زمن توقف يمكن تشغيله لكل المضيفين التابعين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:72
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:100
+msgid "Scheduled"
+msgstr "مجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:253
+msgid "Scheduled End"
+msgstr "نهاية الجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:252
+msgid "Scheduled Start"
+msgstr "بداية الجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:127
+msgid "Scheduled end"
+msgstr "نهاية الجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:120
+msgid "Scheduled start"
+msgstr "بداية الجدولة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php:74
+msgid "Scheduling check.."
+msgid_plural "Scheduling checks.."
+msgstr[0] "جدولة الفحص.."
+msgstr[1] "جدولة الفحص.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php:51
+msgid "Scheduling host check.."
+msgid_plural "Scheduling host checks.."
+msgstr[0] "جدولة فحص المضيف.."
+msgstr[1] "جدولة فحص المضيفين.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:111
+msgid "Scheduling host downtime.."
+msgid_plural "Scheduling host downtimes.."
+msgstr[0] "جدولة زمن توقف المضيف.."
+msgstr[1] "جدولة أزمنة توقف المضيف.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:100
+msgid "Scheduling service check.."
+msgid_plural "Scheduling service checks.."
+msgstr[0] "جدولة فحص خدمة.."
+msgstr[1] "جدولة فحوصات خدمة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:223
+msgid "Scheduling service downtime.."
+msgid_plural "Scheduling service downtimes.."
+msgstr[0] "جدولة زمن توقف خدمة.."
+msgstr[1] "جدولة أزمنة توقف خدمة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:99
+msgid "Security"
+msgstr "أمان"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:223
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:178
+msgid "Send Custom Host Notification"
+msgstr "إرسال تنبيهات مضيف مخصصة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:136
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:226
+msgid "Send Custom Service Notification"
+msgstr "إرسال تنبيهات خدمة مخصصة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:123
+msgid "Send Notification"
+msgstr "إرسال تنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:18
+msgid "Send a custom notification to contacts responsible for this host"
+msgstr "إرسال تنبيه مخصص لجهات الاتصال المسئولة عن هذا المضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:33
+msgid "Send a custom notification to contacts responsible for this service"
+msgstr "إرسال تنبيه مخصص لجهات الاتصال المسئولة عن هذا الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:26
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:44
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:45
+#, php-format
+msgid "Send a mail to %s"
+msgstr "إرسال بريد إلى %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:29
+msgid "Send custom notification"
+msgid_plural "Send custom notifications"
+msgstr[0] "إرسال تنبيه مخصص"
+msgstr[1] "إرسال تنبيهات مخصصة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:10
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:25
+msgid "Send notification"
+msgstr "إرسال تنبيه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/hosts/show.phtml:144
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/services/show.phtml:146
+msgid "Send notifications"
+msgstr "إرسال تنبيهات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:95
+msgid "Sending custom notification.."
+msgid_plural "Sending custom notifications.."
+msgstr[0] "إرسال تنبيه مخصص.."
+msgstr[1] "إرسال تنبيهات مخصصة.."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/notifications.phtml:60
+#, php-format
+msgid "Sent to %s"
+msgstr "إرسال إلى %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:15
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:26
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:17
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:19
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:13
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml:3
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/service-header.phtml:48
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/notifications.phtml:44
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:247
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:439
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:199
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/DataView/DataView.php:278
+msgid "Service"
+msgstr "خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:116
+msgid "Service Action"
+msgstr "فعل خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:87
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:127
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:152
+msgid "Service Checks"
+msgstr "فحوصات الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:156
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:574
+msgid "Service Grid"
+msgstr "شبكة الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegroups.phtml:23
+msgid "Service Group"
+msgstr "مجموعة خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:232
+msgid "Service Group Chart"
+msgstr "مخطط مجموعة خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:487
+msgid "Service Group Name"
+msgstr "اسم مجموعة خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:461
+msgid "Service Groups"
+msgstr "مجموعات الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:170
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:599
+msgid "Service Name"
+msgstr "اسم الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:144
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:260
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/ok_hosts.phtml:78
+msgid "Service Problems"
+msgstr "مشاكل الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:20
+msgid "Service Problems:"
+msgstr "مشاكل الخدمة:"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:168
+msgid "Service Severity"
+msgstr "خطورة الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:28
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegroups.phtml:24
+msgid "Service States"
+msgstr "حالات الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:36
+msgid "Service not found"
+msgstr "الخدمة غير موجودة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:110
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:184
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/servicegroups.phtml:17
+msgid "Servicegroups"
+msgstr "مجموعات خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:108
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:180
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/tactical/components/hostservicechecks.phtml:10
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/contact.phtml:44
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:99
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:236
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:66
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:123
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:212
+msgid "Services"
+msgstr "الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:53
+msgid "Set the date and time when the check should be scheduled."
+msgstr "ضبط التاريخ والوقت الذي ينبغي جدولة الفحص فيه."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:89
+msgid "Set the end date and time for the downtime."
+msgstr "ضبط التاريخ والوقت لزمن التوقف."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php:44
+msgid "Set the expire time."
+msgstr "ضبط وقت انتهاء الصلاحية."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:79
+msgid "Set the start date and time for the downtime."
+msgstr "ضبط تاريخ البداية والوقت لزمن التوقف."
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:114
+msgctxt "setup.summary.btn.finish"
+msgid "Setup the monitoring module for Icinga Web 2"
+msgstr "ضبط وحدة المراقبة لـ إسنجا وب 2"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:87
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:486
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:533
+msgid "Severity"
+msgstr "الخطورة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/show-more.phtml:6
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:173
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/notifications.phtml:82
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hostgroups.phtml:270
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/comments.phtml:45
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegroups.phtml:166
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hosts.phtml:99
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/services.phtml:104
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/downtimes.phtml:48
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:73
+msgid "Show More"
+msgstr "عرض المزيد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:227
+#, php-format
+msgid "Show all event records of host %s"
+msgstr "عرض كل سجلات الحدث للمضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:223
+#, php-format
+msgid "Show all event records of service %s on host %s"
+msgstr "عرض كل سجلات الحدث للخدمة %s على المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TacticalController.php:20
+msgid ""
+"Show an overview of all hosts and services, their current states and "
+"monitoring feature utilisation"
+msgstr ""
+"عرض نظرة عامة عن كل الخدمات والمضيفين، وحالاتهم الحالية "
+"واستخدام ميزة المراقبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:12
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/contacts.phtml:11
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contactgroups.phtml:39
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/contacts.phtml:35
+#, php-format
+msgid "Show detailed information about %s"
+msgstr "عرض معلومات تفصيلية عن %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:137
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hosts.phtml:52
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/services.phtml:67
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Link.php:37
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:182
+#, php-format
+msgid "Show detailed information for host %s"
+msgstr "عرض معلومات تفصيلية عن المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:151
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/services.phtml:78
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/servicegrid.phtml:80
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Link.php:63
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php:195
+#, php-format
+msgid "Show detailed information for service %s on host %s"
+msgstr "عرض معلومات تفصيلية عن الخدمة %s على المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml:27
+#, php-format
+msgid "Show detailed information for this comment about host %s"
+msgstr "عرض معلومات تفصيلية لهذا التعليق عن المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml:13
+#, php-format
+msgid "Show detailed information for this comment about service %s on host %s"
+msgstr "عرض معلومات تفصيلية لهذا التعليق عن الخدمة %s على المضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:35
+#, php-format
+msgid "Show detailed information for this downtime scheduled for host %s"
+msgstr "عرض معلومات تفصيلية عن زمن التوقف المجدول هذا للمضيف %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:22
+#, php-format
+msgid ""
+"Show detailed information for this downtime scheduled for service %s on host "
+"%s"
+msgstr ""
+"عرض معلومات تفصيلية عن زمن التوقف المجدول هذا للخدمة %s على المضيف"
+"%s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HealthController.php:30
+msgid ""
+"Show information about the current monitoring instance's process and it's "
+"performance as well as available features"
+msgstr ""
+"أظهر معلومات عن عملية حالة المراقبة الحالية "
+"وأدائها فضلا عن الميزات المتوفرة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:51
+msgid ""
+"Show recent alerts and visualize notifications and problems based on their "
+"amount and chronological distribution"
+msgstr ""
+"عرض التنبيهات الأخيرة وتصور الإنذارات والمشاكل على أساس كميتها وتوزيعها الزمني"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:255
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:127
+msgid "Show resource configuration"
+msgstr "عرض إعداد المورد"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HealthController.php:41
+msgid "Show statistics about the monitored objects"
+msgstr "عرض إحصائيات عن الكائنات المراقبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:61
+#, php-format
+msgid "Show summarized information for %u hosts"
+msgstr "عرض معلومات مختصرة عن مضيفين %u"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:68
+#, php-format
+msgid "Show summarized information for %u services"
+msgstr "عرض معلومات مختصرة عن خدمات %u"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:336
+msgid "Show the Event Grid"
+msgstr "عرض شبكة الحدث"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:574
+msgid "Show the Service Grid"
+msgstr "عرض شبكة الخدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:254
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:126
+#, php-format
+msgid "Show the configuration of the %s resource"
+msgstr "عرض إعداد المورد %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:24
+msgid "Show the number of historical event records grouped by time and type"
+msgstr "عرض عدد سجلات الأحداث التاريخية والتي تم تجميعها حسب الوقت والنوع"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php:76
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:184
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:327
+msgid "Skip Validation"
+msgstr "تخطي التحقق"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:128
+msgid "Socket"
+msgstr "مقبس"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/service-header.phtml:13
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/service-header.phtml:42
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/object/host-header.phtml:12
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/hosts.phtml:38
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/list/services.phtml:51
+msgctxt "Soft state"
+msgid "Soft"
+msgstr "ناعم"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:111
+msgctxt "setup.welcome.btn.next"
+msgid "Start"
+msgstr "بداية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:78
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:250
+msgid "Start Time"
+msgstr "زمن البداية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:70
+msgid "Started downtimes"
+msgstr "بداية أزمنة التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:114
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:134
+msgid "State"
+msgstr "حالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/EventOverviewForm.php:44
+msgid "State Changes"
+msgstr "تغييرات الحالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HealthController.php:43
+msgid "Stats"
+msgstr "إحصائيات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:53
+msgid "Status"
+msgstr "الحالة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:111
+msgid "Sticky Acknowledgement"
+msgstr "إشعار مثبت"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:31
+msgid "Submit Passive Check Result"
+msgid_plural "Submit Passive Check Results"
+msgstr[0] "تسليم نتيجة الفحص السلبي"
+msgstr[1] "تسليم نتائج الفحص السلبي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostController.php:166
+msgid "Submit Passive Host Check Result"
+msgstr "تسليم نتيجة فحص المضيف السلبي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/HostsController.php:211
+msgid "Submit Passive Host Check Results"
+msgstr "تسليم نتائج فحص المضيف السلبي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServiceController.php:124
+msgid "Submit Passive Service Check Result"
+msgstr "تسليم نتيجة فحص الخدمة السلبي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ServicesController.php:214
+msgid "Submit Passive Service Check Results"
+msgstr "تسليم نتائج فحص الخدمة السلبي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/command.phtml:17
+#, php-format
+msgid "Submit a one time or so called passive result for the %s check"
+msgstr "تسليم لمرة واحدة أو ما يسمى بالنتيجة السلبية للفحص %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:248
+msgid "System"
+msgstr "نظام"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:172
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TacticalController.php:23
+msgid "Tactical Overview"
+msgstr "نظرة عامة تكتيكية"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:192
+msgid ""
+"The Zend database adapter for MySQL is required to access a MySQL database."
+msgstr "مطلوب محول قاعدة بيانات زند لـ MySQL للوصول إلى قاعدة بيانات MySQL."
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:212
+msgid ""
+"The Zend database adapter for PostgreSQL is required to access a PostgreSQL "
+"database."
+msgstr ""
+"مطلوب محول قاعدة بيانات زند لـ PostgreSQL للوصول إلى قاعدة بيانات PostgreSQL."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:102
+msgid "The configuration has been successfully validated."
+msgstr "تم التحقق من الإعداد بنجاح."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/BackendPage.php:46
+msgid "The data source used for retrieving monitoring information"
+msgstr "مصدر البيانات المستخدم لاسترجاع معلومات المراقبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:143
+msgid "The date/time the scheduled downtime actually ended"
+msgstr "تاريخ ووقت انتهاء زمن التوقف المجدول الفعلي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:123
+msgid ""
+"The date/time the scheduled downtime is supposed to end. If this is a "
+"flexible (non-fixed) downtime, this refers to the last possible time that "
+"the downtime can start"
+msgstr ""
+"التاريخ/الوقت الذي يفترض انتهاء زمن التوقف المجدول فيه. إذا كان "
+"زمنا مرنا (غير ثابت)، فإنه يشير إلى آخر وقت من الممكن أن يبدأ "
+"فيه زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:116
+msgid ""
+"The date/time the scheduled downtime is supposed to start. If this is a "
+"flexible (non-fixed) downtime, this refers to the earliest possible time "
+"that the downtime can start"
+msgstr ""
+"التاريخ/الوقت الذي يفترض ابتداء زمن التوقف فيه. إذا كان زمنا "
+"مرنا (غير ثابت)، فإنه يشير إلى أول وقت من الممكن أن يبدأ "
+"فيه زمن التوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php:69
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:204
+msgid "The end time must be greater than the start time"
+msgstr "زمن النهاية يجب أن يكون أكبر من زمن البداية"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/DataView/DataView.php:448
+#, php-format
+msgid "The filter column \"%s\" is not allowed here."
+msgstr "لا يُسمح هنا بعمود المرشح \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:66
+msgid "The given resource name is already in use."
+msgstr "اسم المورد المعطى مستخدم سابقا."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/BackendPage.php:29
+msgid "The identifier of this backend"
+msgstr "رقم التعريف لهذه الخلفية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/notifications.phtml:57
+#, php-format
+msgid "The last one was sent %s."
+msgstr "تم إرسال آخر %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:205
+msgid ""
+"The name of the Icinga instance this transport should exclusively transfer "
+"commands to."
+msgstr "اسم حالة \"إسنجا\" التي يتحتم على هذا النقل حصريا نقل الأوامر إليها."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:38
+msgid "The name of the person who scheduled this downtime"
+msgstr "اسم الشخص الذي جدول زمن التوقف هذا"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:219
+msgid ""
+"The name of this command transport that is used to differentiate it from "
+"others"
+msgstr "اسم ناقل الأمر هذا الذي يستخدم للتفرقة بينه وبين الآخرين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:195
+msgid ""
+"The name of this monitoring backend that is used to differentiate it from "
+"others"
+msgstr "اسم خلفية المراقبة هذه التي تستخدم للتفرقة بينها وبين الآخرين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:79
+msgid ""
+"The performance data of this check result. Leave empty if this check result "
+"has no performance data"
+msgstr ""
+"بيانات الأداء لنتيجة الفحص هذه. دعها فارغة إذا لم يكن لنتيجة الفحص هذه "
+"بيانات أداء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:69
+msgid "The plugin output of this check result"
+msgstr "مخرج التوصيل لنتيجة الفحص هذه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:237
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:109
+msgid "The resource to use"
+msgstr "المورد المراد استخدامه"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/DataView/DataView.php:357
+#, php-format
+msgid "The sort column \"%s\" is not allowed in \"%s\"."
+msgstr "عمود الفرز \"%s\" لا يُسمح به في \"%s\"."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:54
+msgid "The state this check result should report"
+msgstr "حالة نتيجة الفحص التي يجب أن تكون في التقرير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:223
+msgid "The type of data source used for retrieving monitoring information"
+msgstr "نوع مصدر البيانات المستخدم لاسترجاع معلومات المراقبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:381
+msgid ""
+"There is currently more than one icinga instance writing to the IDO. You'll "
+"see all objects from all instances without any differentation. If this is "
+"not desired, consider setting up a separate IDO for each instance."
+msgstr ""
+"يوجد حاليا أكثر من حالة icinga تقوم بالكتابة على IDO. سترى "
+"كل الكائنات من جميع الحالات دون أي اختلاف. إن لم يكن هذا "
+"هو المطلوب، فانظر في إنشاء IDO منفصلة لكل حالة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/BackendConfigForm.php:375
+msgid ""
+"There is currently no icinga instance writing to the IDO. Make sure that a "
+"icinga instance is configured and able to write to the IDO."
+msgstr ""
+"لا يوجد حاليا أي حالة إسنجا تقوم بالكتابة على IDO. تأكد من "
+"أن حالة إسنجا تم إعدادها وقادرة على الكتابة على IDO."
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php:91
+#, php-format
+msgid "There is no \"%s\" monitoring backend"
+msgstr "لا يوحد خلفية مراقبة \"%s\""
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:22
+msgid ""
+"This command is used to acknowledge host or service problems. When a problem "
+"is acknowledged, future notifications about problems are temporarily "
+"disabled until the host or service recovers."
+msgstr ""
+"يستخدم هذا الأمر للإشعار بمشاكل المضيف أو الخدمة. عندما يتم الإشعار "
+"بمشكلة، فإن الإخطارات المستقبلية حول المشاكل سيتم تعطيلها مؤقتا "
+"حتى يتعافى المضيف أو الخدمة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:19
+msgid "This command is used to add host or service comments."
+msgstr "يستخدم هذا الأمر لإضافة تعليقات على المضيف أو الخدمة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php:26
+msgid ""
+"This command is used to disable host and service notifications for a "
+"specific time."
+msgstr "يستخدم هذا الأمر لتعطيل التنبيهات على المضيف والخدمة لوقت محدد."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:33
+msgid ""
+"This command is used to schedule host and service downtimes. During the "
+"specified downtime, Icinga will not send notifications out about the hosts "
+"and services. When the scheduled downtime expires, Icinga will send out "
+"notifications for the hosts and services as it normally would. Scheduled "
+"downtimes are preserved across program shutdowns and restarts."
+msgstr ""
+"يستخدم هذا الأمر لجدولة أزمنة التوقف للمضيف والخدمة. خلال فترة التوقف "
+"المحددة لن يرسل إسنجا أي إخطارات عن المضيفين والخدمات. عند انتهاء"
+"صلاحية زمن التوقف المجدول، ستقوم إسنجا بإرسال إخطارات للمضيفين "
+"والخدمات كالمعتاد. يتم الاحتفاظ بأزمنة التوقف المجدول خلال إغلاق "
+"البرنامج وإعادة تشغيله."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php:23
+msgid ""
+"This command is used to schedule the next check of hosts or services. Icinga "
+"will re-queue the hosts or services to be checked at the time you specify."
+msgstr ""
+"يستخدم هذا الأمر لجدولة الفحص التالي للمضيفين والخدمات. ستقوم إسنجا "
+"بإعادة قائمة الانتظار للمضيفين والخدمات لتُفحص في الوقت الذي تحدده."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:20
+msgid ""
+"This command is used to send custom notifications about hosts or services."
+msgstr "يستخدم هذا الأمر لإرسال تنبيهات مخصصة حول المضيفين والخدمات."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:20
+msgid "This command is used to submit passive host or service check results."
+msgstr "يستخدم هذا الأمر لتسليم نتائج فحص المضيف أو الخدمة السلبي."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:63
+msgid "This comment does not expire."
+msgstr "هذا التعليق لا تنتهي صلاحيته."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml:41
+#, php-format
+msgid "This comment expires on %s at %s"
+msgstr "هذا التعليق تنتهي صلاحيته في %s في %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:60
+#, php-format
+msgid "This comment expires on %s at %s."
+msgstr "هذا التعليق تنتهي صلاحيته في %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:47
+msgid "This downtime is flexible"
+msgstr "زمن التوقف هذا مرن"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:51
+msgid "This downtime is in effect"
+msgstr "زمن التوقف هذا ساري المفعول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:106
+#, php-format
+msgid ""
+"This fixed host downtime has been scheduled to start on %s at %s and to end "
+"on %s at %s."
+msgstr ""
+"زمن توقف المضيف الثابت هذا تمت جدولته ليبدأ في %s في %s "
+"وينتهي في %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:96
+#, php-format
+msgid ""
+"This fixed host downtime was started on %s at %s and expires on %s at %s."
+msgstr ""
+"زمن توقف المضيف الثابت هذا بدأ في %s في %s "
+"وينتهي في %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:105
+#, php-format
+msgid ""
+"This fixed service downtime has been scheduled to start on %s at %s and to "
+"end on %s at %s."
+msgstr ""
+"زمن توقف الخدمة الثابت هذه تمت جدولته ليبدأ في %s في %s "
+"وينتهي في %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:95
+#, php-format
+msgid ""
+"This fixed service downtime was started on %s at %s and expires on %s at %s."
+msgstr "زمن توقف الخدمة الثابت هذا بدأ في %s في %s وينتهي في %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:85
+#, php-format
+msgid ""
+"This flexible host downtime has been scheduled to start between %s - %s and "
+"to last for %s."
+msgstr ""
+"زمن توقف المضيف المرن هذا تمت جدولته ليبدأ بين %s - %s "
+"ويستمر إلى %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:74
+#, php-format
+msgid ""
+"This flexible host downtime was started on %s at %s and lasts for %s until "
+"%s at %s."
+msgstr ""
+"زمن توقف المضيف المرن هذا بدأ في s في %s ويستمر حتى %s "
+"إلى %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:84
+#, php-format
+msgid ""
+"This flexible service downtime has been scheduled to start between %s - %s "
+"and to last for %s."
+msgstr ""
+"زمن توقف الخدمة المرن هذا تمت جدولته ليبدأ بين %s - %s "
+"ويستمر إلى %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:73
+#, php-format
+msgid ""
+"This flexible service downtime was started on %s at %s and lasts for %s "
+"until %s at %s."
+msgstr ""
+"زمن توقف الخدمة المرن هذا بدأ في s في %s ويستمر حتى %s "
+"إلى %s في %s."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/WelcomePage.php:33
+msgid "This is the core module for Icinga Web 2."
+msgstr "هذه هي الوحدة الأساسية في إسنجا وب 2."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/event-history.phtml:54
+msgid "This notification was not sent out to any contact."
+msgstr "لم يتم إرسال هذا التنبيه لأي جهة اتصال."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:22
+msgid "Time to Reaction (Ack, Recover)"
+msgstr "وقت رد الفعل (إشعار، استرداد)"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:109
+msgid "TimeLine interval"
+msgstr "فترة الجدول الزمني"
+
+#: /usr/share/icingaweb2/modules/monitoring/configuration.php:228
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:25
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/TimelineController.php:29
+msgid "Timeline"
+msgstr "الجدول الزمني"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:82
+msgid "To"
+msgstr "إلى"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:183
+msgid ""
+"To access the IDO stored in a MySQL database the PDO-MySQL module for PHP is "
+"required."
+msgstr ""
+"للوصول إلى الـ IDO المخزنة في قاعدة بيانات \"ماي سيكول\" فإن وحدة PDO-MySQL"
+" للـ PHP "
+"مطلوبة."
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:203
+msgid ""
+"To access the IDO stored in a PostgreSQL database the PDO-PostgreSQL module "
+"for PHP is required."
+msgstr ""
+"للوصول إلى الـ IDO المخزنة في قاعدة بيانات PostgreSQL فإن وحدة PDO-PostgreSQL "
+"للـ PHP مطلوبة."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/SecurityPage.php:16
+msgid ""
+"To protect your monitoring environment against prying eyes please fill out "
+"the settings below."
+msgstr ""
+"لحماية بيئة المراقبة الخاصة بك ضد أعين المتطفلين الرجاء تعبئة "
+"الإعدادات أدناه."
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:85
+msgid "Today"
+msgstr "اليوم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:56
+msgid "Top 5 Recent Alerts"
+msgstr "آخر أعلى 5 إنذارات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:68
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:94
+msgid "Total"
+msgstr "الكلي"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:535
+msgid "Total Hosts"
+msgstr "إجمالي المضيفين"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:488
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ListController.php:536
+msgid "Total Services"
+msgstr "إجمالي الخدمات"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:76
+msgid "Transport"
+msgstr "النقل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:217
+msgid "Transport Name"
+msgstr "اسم النقل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/TransportConfigForm.php:241
+msgid "Transport Type"
+msgstr "نوع النقل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:29
+msgid "Trend"
+msgstr "اتجاه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:39
+msgid "Trend for the last 24h"
+msgstr "الاتجاه في آخر 24 ساعة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:99
+msgid "Type"
+msgstr "نوع"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:39
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/config/index.phtml:94
+#, php-format
+msgid "Type: %s"
+msgstr "نوع: %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Service.php:199
+msgid "UNKNOWN"
+msgstr "مجهول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:59
+msgctxt "icinga.state"
+msgid "UNKNOWN"
+msgstr "مجهول"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Host.php:188
+msgid "UNREACHABLE"
+msgstr "لا يمكن الوصول إليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:128
+msgctxt "icinga.state"
+msgid "UNREACHABLE"
+msgstr "لا يمكن الوصول للوجهة"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Host.php:182
+msgid "UP"
+msgstr "قيد التشغيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:123
+msgctxt "icinga.state"
+msgid "UP"
+msgstr "قيد التشغيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/service/statusicons.phtml:5
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml:5
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/HostFlags.php:13
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/ServiceFlags.php:9
+msgid "Unhandled"
+msgstr "غير مُعالج"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/health/stats.phtml:14
+msgid "Unhandled Problems:"
+msgstr "مشاكل غير معالجة:"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:119
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:264
+msgid "Unknown"
+msgstr "مجهول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:139
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:314
+msgid "Unreachable"
+msgstr "لا يمكن الوصول إليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:137
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:300
+msgid "Up"
+msgstr "قيد التشغيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php:72
+msgid "Use Expire Time"
+msgstr "استخدام وقت انتهاء الصلاحية"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:88
+msgid "Use SSH Identity"
+msgstr "استخدام هوية SSH"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:40
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:43
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:163
+msgid "User"
+msgstr "مستخدم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-description.phtml:10
+msgid "User Comment"
+msgstr "تعليق مستخدم"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Config/Transport/RemoteTransportForm.php:165
+msgid ""
+"User to log in as on the remote Icinga instance. Please note that key-based "
+"SSH login must be possible for this user"
+msgstr ""
+"المستخدم الذي يمكن الدخول بواسطته لحالة إسنجا البعيدة. يرجى ملاحظة أن "
+"دخول SSH المبني على المفاتيح يجب أن يكون متاحا لهذا المستخدم"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/BackendStep.php:109
+msgid "Username"
+msgstr "اسم المستخدم"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:124
+msgid "Validate Configuration"
+msgstr "التحقق من الإعداد"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:125
+msgid "Validation In Progress"
+msgstr "جار التحقق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/IdoResourcePage.php:131
+msgid "Validation Log"
+msgstr "سجل التحقق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:37
+msgid "Value"
+msgstr "قيمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:623
+msgid "Value for interval not valid"
+msgstr "قيمة الفترة ليست صالحة"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/Service.php:193
+msgid "WARNING"
+msgstr "تحذير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php:57
+msgctxt "icinga.state"
+msgid "WARNING"
+msgstr "تحذير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/helpers/Perfdata.php:40
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/StatehistoryForm.php:118
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/ChartController.php:250
+msgid "Warning"
+msgstr "تحذير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Setup/WelcomePage.php:21
+msgid "Welcome to the configuration of the monitoring module for Icinga Web 2!"
+msgstr "مرحبا بك في إعداد وحدة المراقبة لـ إسنجا وب 2!"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:155
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/comment/show.phtml:48
+msgid "Yes"
+msgstr "نعم"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:189
+msgid "Zend database adapter for MySQL"
+msgstr "محول زند لقاعدة بيانات ماي سيكول"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:209
+msgid "Zend database adapter for PostgreSQL"
+msgstr "محول زند لقاعدة بيانات بوستجرى إس كيو إل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml:22
+msgid "acknowledged"
+msgstr "معترف به"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:60
+#, php-format
+msgctxt "timeline.link.title.datetime.twice"
+msgid "between %s and %s"
+msgstr "بين %s و%s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:42
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml:34
+msgid "by"
+msgstr "بواسطة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:80
+msgid "changed"
+msgstr "غُيِّر"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/comments.phtml:51
+msgid "commented"
+msgstr "عُلِّق"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:79
+msgid "created"
+msgstr "أُنشيء"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:84
+msgid "disable"
+msgstr "تعطيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:194
+msgid "down"
+msgstr "متوقف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php:85
+msgid "enable"
+msgstr "تفعيل"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:60
+#, php-format
+msgctxt "Last format parameter represents the end time"
+msgid "ends %s"
+msgstr "انتهاء %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:28
+#, php-format
+msgid "expected %s"
+msgstr "متوقع %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:54
+#, php-format
+msgctxt "Last format parameter represents the downtime expire time"
+msgid "expires %s"
+msgstr "تنتهي صلاحيته %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:69
+msgid "hard state"
+msgstr "حالة صعبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/downtime/show.phtml:138
+msgid "he date/time the scheduled downtime was actually started"
+msgstr "التاريخ والوقت الذي ابتدأ فيه فعليا زمن التوقف المجدول"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml:29
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/MonitoredObject.php:735
+msgid "host"
+msgstr "مضيف"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:48
+#, php-format
+msgctxt "timeline.link.title.month.and.year"
+msgid "in %s"
+msgstr "في %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:54
+#, php-format
+msgctxt "timeline.link.title.year"
+msgid "in %s"
+msgstr "في %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:37
+msgid "in the last hour"
+msgstr "في الساعة الأخيرة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:41
+#, php-format
+msgctxt "timeline.link.title.week.and.year"
+msgid "in week %s of %s"
+msgstr "في الاسبوع %s من %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checksource.phtml:9
+msgid "is not reachable"
+msgstr "لا يمكن الوصول إليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checksource.phtml:9
+msgid "is reachable"
+msgstr "يمكن الوصول إليه"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/alertsummary/index.phtml:35
+msgid "notifications per hour"
+msgstr "التنبيهات في الساعة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/timeline/index.phtml:35
+#, php-format
+msgctxt "timeline.link.title.time"
+msgid "on %s"
+msgstr "في %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:65
+#, php-format
+msgctxt "Last format parameter represents the time scheduled"
+msgid "scheduled %s"
+msgstr "مجدول في %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/downtime.phtml:70
+#, php-format
+msgctxt "Last format parameter represents the time scheduled"
+msgid "scheduled flexible %s"
+msgstr "مجدول بصورة مرنة في %s"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/Object/MonitoredObject.php:738
+msgid "service"
+msgstr "خدمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml:69
+msgid "soft state"
+msgstr "حالة ناعمة"
+
+#: /usr/share/icingaweb2/modules/monitoring/library/Monitoring/MonitoringWizard.php:53
+msgctxt "setup.summary.subject"
+msgid "the monitoring module"
+msgstr "وحدة المراقبة"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:192
+msgid "unchanged"
+msgstr "دون تغيير"
+
+#: /usr/share/icingaweb2/modules/monitoring/application/controllers/AlertsummaryController.php:196
+msgid "up"
+msgstr "قيد التشغيل"
+
+
diff --git a/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.mo b/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.mo
index 3560dc336..8a508762f 100644
Binary files a/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.mo and b/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.mo differ
diff --git a/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.po b/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.po
index 79a04cf40..adfad0abe 100644
--- a/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.po
+++ b/modules/monitoring/application/locale/de_DE/LC_MESSAGES/monitoring.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: Monitoring Module (2.1.2)\n"
"Report-Msgid-Bugs-To: dev@icinga.org\n"
"POT-Creation-Date: 2016-02-29 14:40+0000\n"
-"PO-Revision-Date: 2016-04-26 12:08+0200\n"
+"PO-Revision-Date: 2016-12-07 17:02+0100\n"
"Last-Translator: Thomas Gelf \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language-Team: \n"
-"X-Generator: Poedit 1.8.7.1\n"
+"X-Generator: Poedit 1.8.11\n"
#: /vagrant/modules/monitoring/application/controllers/ChartController.php:375
msgid " Down Hosts (Handled)"
@@ -1816,7 +1816,16 @@ msgstr ""
"Backend mit dem Namen “%s” und die weiter unten spezifizierte Ressourcen "
"abrufen:"
-#: /vagrant/modules/monitoring/library/Monitoring/TransportStep.php:76
+#: /vagrant/modules/monitoring/library/Monitoring/TransportStep.php:87
+msgid ""
+"Icinga Web 2 will use the Icinga 2 API to send commands to your monitoring "
+"instance by using the connection details listed below:"
+msgstr ""
+"Icinga Web 2 wird die Icinga 2 API verwenden, um Kommandos an Ihre "
+"Monitoringinstanz zu senden. Dazu werden die folgenden "
+"Verbindungseinstellungen verwendet:"
+
+#: /vagrant/modules/monitoring/library/Monitoring/TransportStep.php:49
#, php-format
msgid ""
"Icinga Web 2 will use the named pipe located at \"%s\" to send commands to "
@@ -1919,8 +1928,8 @@ msgstr ""
#: /vagrant/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:45
msgid ""
"If you work with other administrators, you may find it useful to share "
-"information about the the host or service that is having problems. Make sure "
-"you enter a brief description of what you are doing."
+"information about the host or service that is having problems. Make sure you "
+"enter a brief description of what you are doing."
msgstr ""
"Wenn Sie mit anderen Administratoren zusammenarbeiten, werden Sie es "
"nützlich finden, Informationen zu Hosts oder Services mit Problemen "
diff --git a/modules/monitoring/application/locale/it_IT/LC_MESSAGES/monitoring.po b/modules/monitoring/application/locale/it_IT/LC_MESSAGES/monitoring.po
index ec0f3e5f6..8f752efba 100644
--- a/modules/monitoring/application/locale/it_IT/LC_MESSAGES/monitoring.po
+++ b/modules/monitoring/application/locale/it_IT/LC_MESSAGES/monitoring.po
@@ -1872,7 +1872,7 @@ msgstr ""
#: /usr/share/icingaweb2/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php:45
msgid ""
"If you work with other administrators, you may find it useful to share "
-"information about the the host or service that is having problems. Make sure "
+"information about the host or service that is having problems. Make sure "
"you enter a brief description of what you are doing."
msgstr ""
"Se lavori con altri amministratori potresti trovare utile condividere le "
diff --git a/modules/monitoring/application/locale/pt_BR/LC_MESSAGES/monitoring.po b/modules/monitoring/application/locale/pt_BR/LC_MESSAGES/monitoring.po
index 9edbc328c..2f6b97aa4 100644
--- a/modules/monitoring/application/locale/pt_BR/LC_MESSAGES/monitoring.po
+++ b/modules/monitoring/application/locale/pt_BR/LC_MESSAGES/monitoring.po
@@ -1553,7 +1553,7 @@ msgstr ""
#: /usr/local/icingaweb/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php:73
msgid ""
"If you work with other administrators, you may find it useful to share "
-"information about the the host or service that is having problems. Make sure "
+"information about the host or service that is having problems. Make sure "
"you enter a brief description of what you are doing."
msgstr ""
"Se você trabalha com outros administradores, você pode achar isso útil para "
diff --git a/modules/monitoring/application/locale/ru_RU/LC_MESSAGES/monitoring.po b/modules/monitoring/application/locale/ru_RU/LC_MESSAGES/monitoring.po
index bcaf5fb6d..655f0adce 100644
--- a/modules/monitoring/application/locale/ru_RU/LC_MESSAGES/monitoring.po
+++ b/modules/monitoring/application/locale/ru_RU/LC_MESSAGES/monitoring.po
@@ -1819,7 +1819,7 @@ msgstr ""
#: /vagrant/modules/monitoring/application/forms/Command/Object/SendCustomNotificationCommandForm.php:45
msgid ""
"If you work with other administrators, you may find it useful to share "
-"information about the the host or service that is having problems. Make sure "
+"information about the host or service that is having problems. Make sure "
"you enter a brief description of what you are doing."
msgstr ""
diff --git a/modules/monitoring/application/views/helpers/HostFlags.php b/modules/monitoring/application/views/helpers/HostFlags.php
index a4c5bc7d2..81d8ebcdf 100644
--- a/modules/monitoring/application/views/helpers/HostFlags.php
+++ b/modules/monitoring/application/views/helpers/HostFlags.php
@@ -1,9 +1,6 @@
view->icon('eye-off', $this->view->translate('Active Checks Disabled'));
}
}
- return $icons;
+ return implode(' ', $icons);
}
}
diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php
index 06443b8f1..6b9113830 100644
--- a/modules/monitoring/application/views/helpers/Perfdata.php
+++ b/modules/monitoring/application/views/helpers/Perfdata.php
@@ -81,7 +81,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
$data []= sprintf(
'%s ',
$text,
- StringHelper::ellipsisCenter($text, 24)
+ $text
);
}
}
diff --git a/modules/monitoring/application/views/helpers/PluginOutput.php b/modules/monitoring/application/views/helpers/PluginOutput.php
index ba3013a3a..92500e4e2 100644
--- a/modules/monitoring/application/views/helpers/PluginOutput.php
+++ b/modules/monitoring/application/views/helpers/PluginOutput.php
@@ -1,10 +1,25 @@
fixLinks($output);
- // Help browsers to break words in plugin output
$output = trim($output);
- // Add space after comma where missing
- $output = preg_replace('/,[^\s]/', ', ', $output);
- // Add zero width space after ')', ']', ':', '.', '_' and '-' if not surrounded by whitespaces
- $output = preg_replace('/([^\s])([\\)\\]:._-])([^\s])/', '$1$2$3', $output);
- // Add zero width space before '(' and '[' if not surrounded by whitespaces
- $output = preg_replace('/([^\s])([([])([^\s])/', '$1$2$3', $output);
-
+ // Add space after comma where missing, to help browsers to break words in plugin output
+ $output = preg_replace('/,(?=[^\s])/', ', ', $output);
if (! $raw) {
if ($isHtml) {
+ $output = $this->processHtml($output);
$output = '' . $output . '
';
} else {
$output = '' . $output . '
';
@@ -70,32 +92,68 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
return $output;
}
- protected function fixLinks($html)
+ /**
+ * Replace classic Icinga CGI links with Icinga Web 2 links and color state information, if any
+ *
+ * @param string $html
+ *
+ * @return string
+ */
+ protected function processHtml($html)
{
-
- $ret = array();
- $dom = new DOMDocument;
- $dom->loadXML('' . $html . '
', LIBXML_NOERROR | LIBXML_NOWARNING);
- $dom->preserveWhiteSpace = false;
- $links = $dom->getElementsByTagName('a');
- foreach ($links as $tag)
- {
- $href = $tag->getAttribute('href');
- if (preg_match('~^/cgi\-bin/status\.cgi\?(.+)$~', $href, $m)) {
- parse_str($m[1], $params);
- if (isset($params['host'])) {
- $tag->setAttribute('href', $this->view->baseUrl(
- '/monitoring/host/show?host=' . urlencode($params['host']
- )));
+ $pattern = '/[([](OK|WARNING|CRITICAL|UNKNOWN)[)\]]/';
+ $doc = new DOMDocument();
+ $doc->loadXML('' . $html . '
', LIBXML_NOERROR | LIBXML_NOWARNING);
+ $dom = new RecursiveIteratorIterator(new DomNodeIterator($doc), RecursiveIteratorIterator::SELF_FIRST);
+ $nodesToRemove = array();
+ foreach ($dom as $node) {
+ /** @var \DOMNode $node */
+ if ($node->nodeType === XML_TEXT_NODE) {
+ $start = 0;
+ while (preg_match($pattern, $node->nodeValue, $match, PREG_OFFSET_CAPTURE, $start)) {
+ $offsetLeft = $match[0][1];
+ $matchLength = strlen($match[0][0]);
+ $leftLength = $offsetLeft - $start;
+ if ($leftLength) {
+ $text = new DOMText(substr($node->nodeValue, $start, $leftLength));
+ $node->parentNode->insertBefore($text, $node);
+ }
+ $span = $doc->createElement('span', $match[0][0]);
+ $span->setAttribute('class', 'state-' . strtolower($match[1][0]));
+ $node->parentNode->insertBefore($span, $node);
+ $start = $offsetLeft + $matchLength;
+ }
+ if ($start) {
+ $nodesToRemove[] = $node;
+ }
+ } elseif ($node->nodeType === XML_ELEMENT_NODE) {
+ /** @var \DOMElement $node */
+ if ($node->tagName === 'a'
+ && preg_match('~^/cgi\-bin/status\.cgi\?(.+)$~', $node->getAttribute('href'), $match)
+ ) {
+ parse_str($match[1], $params);
+ if (isset($params['host'])) {
+ $node->setAttribute(
+ 'href',
+ $this->view->baseUrl('/monitoring/host/show?host=' . urlencode($params['host']))
+ );
+ }
}
- } else {
- // ignoring
}
- //$ret[$tag->getAttribute('href')] = $tag->childNodes->item(0)->nodeValue;
}
- return substr($dom->saveHTML(), 5, -7);
+ foreach ($nodesToRemove as $node) {
+ /** @var \DOMNode $node */
+ $node->parentNode->removeChild($node);
+ }
+
+ return substr($doc->saveHTML(), 5, -7);
}
+ /**
+ * Initialize and return self::$purifier
+ *
+ * @return HTMLPurifier
+ */
protected function getPurifier()
{
if (self::$purifier === null) {
@@ -105,7 +163,8 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.EscapeNonASCIICharacters', true);
- $config->set('HTML.Allowed', 'p,br,b,a[href],i,table,tr,td[colspan],div,*[class]');
+ $config->set('HTML.Allowed', 'p,br,b,a[href|target],i,table,tr,th[colspan],td[colspan],div,*[class]');
+ $config->set('Attr.AllowedFrameTargets', array('_blank'));
// This avoids permission problems:
// $config->set('Core.DefinitionCache', null);
$config->set('Cache.DefinitionImpl', null);
diff --git a/modules/monitoring/application/views/helpers/ServiceFlags.php b/modules/monitoring/application/views/helpers/ServiceFlags.php
index e9bfd70ba..47a351c4c 100644
--- a/modules/monitoring/application/views/helpers/ServiceFlags.php
+++ b/modules/monitoring/application/views/helpers/ServiceFlags.php
@@ -3,30 +3,31 @@
class Zend_View_Helper_ServiceFlags extends Zend_View_Helper_Abstract
{
- public function serviceFlags($service) {
+ public function serviceFlags($service)
+ {
$icons = array();
- if (!$service->service_handled && $service->service_state > 0) {
+ if (! $service->service_handled && $service->service_state > 0) {
$icons[] = $this->view->icon('attention-alt', $this->view->translate('Unhandled'));
}
- if ($service->service_acknowledged && !$service->service_in_downtime) {
+ if ($service->service_acknowledged) {
$icons[] = $this->view->icon('ok', $this->view->translate('Acknowledged'));
}
if ($service->service_is_flapping) {
$icons[] = $this->view->icon('flapping', $this->view->translate('Flapping'));
}
- if (!$service->service_notifications_enabled) {
+ if (! $service->service_notifications_enabled) {
$icons[] = $this->view->icon('bell-off-empty', $this->view->translate('Notifications Disabled'));
}
if ($service->service_in_downtime) {
$icons[] = $this->view->icon('plug', $this->view->translate('In Downtime'));
}
- if (!$service->service_active_checks_enabled) {
- if (!$service->service_passive_checks_enabled) {
+ if (! $service->service_active_checks_enabled) {
+ if (! $service->service_passive_checks_enabled) {
$icons[] = $this->view->icon('eye-off', $this->view->translate('Active And Passive Checks Disabled'));
} else {
- $icons[] = $this->view->icon('eye-off', $this->view->translate('Active Checks Disabled'));
+ $icons[] = $this->view->icon('eye-off', $this->view->translate('Active Checks Disabled'));
}
}
- return $icons;
+ return implode(' ', $icons);
}
-}
\ No newline at end of file
+}
diff --git a/modules/monitoring/application/views/scripts/chart/hostgroup.phtml b/modules/monitoring/application/views/scripts/chart/hostgroup.phtml
deleted file mode 100644
index 22a8a8c05..000000000
--- a/modules/monitoring/application/views/scripts/chart/hostgroup.phtml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-compact) { ?>
-
- = $chart->render(); ?>
- = isset($chart2) ? $chart2->render() : ''; ?>
-
-
- = $chart->render(); ?>
-
diff --git a/modules/monitoring/application/views/scripts/chart/servicegroup.phtml b/modules/monitoring/application/views/scripts/chart/servicegroup.phtml
deleted file mode 100644
index f24efe5ba..000000000
--- a/modules/monitoring/application/views/scripts/chart/servicegroup.phtml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-compact) { ?>
-
- = $chart->render(); ?>
-
-
- = $chart->render(); ?>
-
diff --git a/modules/monitoring/application/views/scripts/chart/test.phtml b/modules/monitoring/application/views/scripts/chart/test.phtml
deleted file mode 100644
index 214f44d33..000000000
--- a/modules/monitoring/application/views/scripts/chart/test.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- = $svg->render() ?>
-
-
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/config/index.phtml b/modules/monitoring/application/views/scripts/config/index.phtml
index 091aaf70f..79a8ccd3c 100644
--- a/modules/monitoring/application/views/scripts/config/index.phtml
+++ b/modules/monitoring/application/views/scripts/config/index.phtml
@@ -92,7 +92,7 @@
); ?>
(= sprintf(
$this->translate('Type: %s'),
- $config->host !== null ? $this->translate('Remote') : $this->translate('Local')
+ ucfirst($config->get('transport', 'local'))
) ?>)
diff --git a/modules/monitoring/application/views/scripts/host/show.phtml b/modules/monitoring/application/views/scripts/host/show.phtml
index badf7ffcf..72f5af4a8 100644
--- a/modules/monitoring/application/views/scripts/host/show.phtml
+++ b/modules/monitoring/application/views/scripts/host/show.phtml
@@ -1,15 +1,14 @@
-
-
+
compact): ?>
= $this->tabs ?>
= $this->render('partials/object/host-header.phtml') ?>
- stats = $object->stats;
$this->baseFilter = Filter::where('host', $object->host_name);
echo $this->render('list/components/servicesummary.phtml');
- ?>
+?>
+ = $this->render('partials/object/quick-actions.phtml') ?>
-
= $this->render('partials/object/detail-content.phtml') ?>
diff --git a/modules/monitoring/application/views/scripts/hosts/show.phtml b/modules/monitoring/application/views/scripts/hosts/show.phtml
index 683680663..48c4b5254 100644
--- a/modules/monitoring/application/views/scripts/hosts/show.phtml
+++ b/modules/monitoring/application/views/scripts/hosts/show.phtml
@@ -31,8 +31,8 @@
$acknowledgeLink,
null,
array(
- 'icon' => 'ok',
- 'class' => 'action-link'
+ 'class' => 'action-link',
+ 'icon' => 'check'
)
) ?>
@@ -63,8 +63,8 @@
$addCommentLink,
null,
array(
- 'icon' => 'comment',
- 'class' => 'action-link'
+ 'class' => 'action-link',
+ 'icon' => 'comment-empty'
)
) ?>
@@ -145,8 +145,8 @@
$sendCustomNotificationLink,
null,
array(
- 'icon' => 'bell-alt',
- 'class' => 'action-link'
+ 'class' => 'action-link',
+ 'icon' => 'bell'
)
) ?>
@@ -167,8 +167,8 @@
$processCheckResultAllLink,
null,
array(
- 'icon' => 'reply',
- 'class' => 'action-link'
+ 'class' => 'action-link',
+ 'icon' => 'edit'
)
) ?>
@@ -189,8 +189,8 @@
$rescheduleAllLink,
null,
array(
- 'icon' => 'reschedule',
- 'class' => 'action-link'
+ 'class' => 'action-link',
+ 'icon' => 'calendar-empty'
)
) ?>
diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml
index 6de773435..da00fccc6 100644
--- a/modules/monitoring/application/views/scripts/list/hosts.phtml
+++ b/modules/monitoring/application/views/scripts/list/hosts.phtml
@@ -4,8 +4,6 @@ use Icinga\Module\Monitoring\Object\Host;
if (! $this->compact): ?>
= $this->tabs ?>
- = $this->render('list/components/hostssummary.phtml') ?>
- = $this->render('list/components/selectioninfo.phtml') ?>
= $this->paginator ?>
= $this->limiter ?>
@@ -82,7 +80,7 @@ if (! $this->compact): ?>
)
) ?>)
- = implode(' ', $this->hostFlags($host)) ?>
+ = $this->hostFlags($host) ?>
= $this->pluginOutput($this->ellipsis($host->host_output, 10000), true) ?>
@@ -107,3 +105,10 @@ if (! $this->compact): ?>
+compact): ?>
+
+
+ = $this->render('list/components/hostssummary.phtml') ?>
+ = $this->render('list/components/selectioninfo.phtml') ?>
+
+
diff --git a/modules/monitoring/application/views/scripts/list/notifications.phtml b/modules/monitoring/application/views/scripts/list/notifications.phtml
index 8316665d1..dc34a8c88 100644
--- a/modules/monitoring/application/views/scripts/list/notifications.phtml
+++ b/modules/monitoring/application/views/scripts/list/notifications.phtml
@@ -35,7 +35,7 @@ if (! $this->compact): ?>
= $stateLabel ?>
- = $this->timeAgo($notification->notification_start_time, $this->compact) ?>
+ = $this->timeAgo($notification->notification_timestamp, $this->compact) ?>
diff --git a/modules/monitoring/application/views/scripts/list/servicegrid.phtml b/modules/monitoring/application/views/scripts/list/servicegrid.phtml
index 2d50a067d..845cac745 100644
--- a/modules/monitoring/application/views/scripts/list/servicegrid.phtml
+++ b/modules/monitoring/application/views/scripts/list/servicegrid.phtml
@@ -81,7 +81,7 @@ $hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . '
$service->service_display_name,
$service->host_display_name
),
- 'class' => 'bg-color-' . Service::getStateText($service->service_state) . ($service->service_handled ? ' handled' : ''),
+ 'class' => 'service-grid-link state-' . Service::getStateText($service->service_state) . ($service->service_handled ? ' handled' : ''),
'title' => $service->service_output
)
) ?>
diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml
index d8fd5d4b5..c9f1e855b 100644
--- a/modules/monitoring/application/views/scripts/list/services.phtml
+++ b/modules/monitoring/application/views/scripts/list/services.phtml
@@ -5,8 +5,6 @@ use Icinga\Module\Monitoring\Object\Service;
if (! $this->compact): ?>
= $this->tabs ?>
- = $this->render('list/components/servicesummary.phtml') ?>
- = $this->render('list/components/selectioninfo.phtml') ?>
= $this->paginator ?>
= $this->limiter ?>
@@ -82,7 +80,7 @@ if (! $this->compact): ?>
'class' => 'rowaction'
)
) ?>
- = implode(' ', $this->serviceFlags($service)) ?>
+ = $this->serviceFlags($service) ?>
@@ -112,3 +110,10 @@ if (! $this->compact): ?>
+compact): ?>
+
+
+ = $this->render('list/components/servicesummary.phtml') ?>
+ = $this->render('list/components/selectioninfo.phtml') ?>
+
+
diff --git a/modules/monitoring/application/views/scripts/partials/command/object-command-form.phtml b/modules/monitoring/application/views/scripts/partials/command/object-command-form.phtml
index 34e31f897..1359e5f36 100644
--- a/modules/monitoring/application/views/scripts/partials/command/object-command-form.phtml
+++ b/modules/monitoring/application/views/scripts/partials/command/object-command-form.phtml
@@ -1,21 +1,17 @@
-
- compact): ?>
- = $this->tabs; ?>
-
- getType() === $object::TYPE_HOST): ?>
- = $this->render('partials/object/host-header.phtml'); ?>
- compact): ?>
+ = $this->tabs ?>
+
+getType() === $object::TYPE_HOST) {
+ echo $this->render('partials/object/host-header.phtml');
$this->baseFilter = Filter::where('host', $object->host_name);
$this->stats = $object->stats;
echo $this->render('list/components/servicesummary.phtml');
- ?>
-
- = $this->render('partials/object/service-header.phtml'); ?>
-
-
+} else {
+ echo $this->render('partials/object/service-header.phtml');
+} ?>
- = $form; ?>
+ = $form ?>
diff --git a/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml b/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml
index dbb8829fe..8d241eed0 100644
--- a/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml
+++ b/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml
@@ -1,19 +1,15 @@
-
- compact): ?>
- = $tabs; ?>
-
-
-
- = $this->render('list/components/servicesummary.phtml'); ?>
- = $this->render('partials/service/objects-header.phtml'); ?>
-
+compact): ?>
+ = $tabs ?>
+
+
+ = $this->render('list/components/servicesummary.phtml') ?>
+ = $this->render('partials/service/objects-header.phtml') ?>
+
= $this->render('list/components/hostssummary.phtml') ?>
- = $this->render('partials/host/objects-header.phtml'); ?>
-
+ = $this->render('partials/host/objects-header.phtml') ?>
+
-
-
- = $form; ?>
+ = $form ?>
diff --git a/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml b/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml
index 6d27a14a4..2ed932916 100644
--- a/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml
+++ b/modules/monitoring/application/views/scripts/partials/comment/comment-detail.phtml
@@ -43,19 +43,28 @@
$this->formatTime($comment->expiration)
)) : '' ?>
setAttrib('class', $deleteButton->getAttrib('class') . ' remove-action');
$deleteButton->populate(
array(
'comment_id' => $comment->id,
- 'comment_is_service' => isset($comment->service_description)
+ 'comment_is_service' => isset($comment->service_description),
+ 'comment_name' => $comment->name
)
);
+ $deleteButton->getElement('btn_submit')
+ ->setAttrib('aria-label', $this->translate('Delete comment'))
+ ->setAttrib('id', $buttonId)
+ ->setAttrib('aria-describedby', $buttonId . ' ' . $textId);
echo $deleteButton;
} ?>
-
diff --git a/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml b/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml
index 96130db7a..bfe88a761 100644
--- a/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml
+++ b/modules/monitoring/application/views/scripts/partials/downtime/downtime-header.phtml
@@ -53,20 +53,28 @@
setAttrib('class', $deleteButton->getAttrib('class') . ' remove-action');
$deleteButton->populate(
array(
- 'downtime_id' => $downtime->id,
- 'downtime_is_service' => isset($downtime->service_description)
+ 'downtime_id' => $downtime->id,
+ 'downtime_is_service' => isset($downtime->service_description),
+ 'downtime_name' => $downtime->name
)
);
+ $deleteButton->getElement('btn_submit')
+ ->setAttrib('aria-label', $this->translate('Delete downtime'))
+ ->setAttrib('id', $buttonId)
+ ->setAttrib('aria-describedby', $buttonId . ' ' . $textId);
echo $deleteButton;
} ?>
-
diff --git a/modules/monitoring/application/views/scripts/partials/event-history.phtml b/modules/monitoring/application/views/scripts/partials/event-history.phtml
index 67236bd6a..0d9c64870 100644
--- a/modules/monitoring/application/views/scripts/partials/event-history.phtml
+++ b/modules/monitoring/application/views/scripts/partials/event-history.phtml
@@ -40,12 +40,14 @@ $lastDate = null;
peekAhead() as $event):
$icon = '';
$iconCssClass = '';
+ $iconTitle = null;
$isService = isset($event->service_description);
$msg = $event->output;
$stateName = 'no-state';
switch ($event->type) {
case 'notify':
- $icon = 'bell-alt';
+ $icon = 'bell';
+ $iconTitle = $this->translate('Notification', 'tooltip');
$label = $this->translate('NOTIFICATION');
$msg = $msg ? preg_replace_callback(
'/^\[([^\]]+)\]/',
@@ -55,56 +57,73 @@ $lastDate = null;
$stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
break;
case 'comment':
- $icon = 'comment';
+ $icon = 'comment-empty';
+ $iconTitle = $this->translate('Comment', 'tooltip');
$label = $this->translate('COMMENT');
break;
case 'comment_deleted':
$icon = 'cancel';
+ $iconTitle = $this->translate('Comment removed', 'tooltip');
$label = $this->translate('COMMENT DELETED');
break;
case 'ack':
$icon = 'ok';
+ $iconTitle = $this->translate('Acknowledged', 'tooltip');
$label = $this->translate('ACKNOWLEDGED');
break;
case 'ack_deleted':
$icon = 'ok';
$iconCssClass = 'icon-strikethrough';
+ $iconTitle = $this->translate('Acknowledgement removed', 'tooltip');
$label = $this->translate('ACKNOWLEDGEMENT REMOVED');
break;
case 'dt_comment':
- // TODO(el): Does not appear in history
$icon = 'plug';
+ $iconTitle = $this->translate('Downtime scheduled', 'tooltip');
$label = $this->translate('SCHEDULED DOWNTIME');
break;
case 'dt_comment_deleted':
- // TODO(el): Does not appear in history
$icon = 'plug';
$iconCssClass = 'icon-strikethrough';
+ $iconTitle = $this->translate('Downtime removed', 'tooltip');
$label = $this->translate('DOWNTIME DELETED');
break;
case 'flapping':
- // TODO(el): Icon
+ $icon = 'flapping';
+ $iconTitle = $this->translate('Flapping started', 'tooltip');
$label = $this->translate('FLAPPING');
break;
case 'flapping_deleted':
- // TODO(el): Icon
+ $icon = 'flapping';
+ $iconCssClass = 'icon-strikethrough';
+ $iconTitle = $this->translate('Flapping stopped', 'tooltip');
$label = $this->translate('FLAPPING STOPPED');
break;
case 'hard_state':
+ if ((int) $event->state === 0) {
+ $icon = 'thumbs-up';
+ } else {
+ $icon = 'warning-empty';
+ }
+ $iconTitle = $this->translate('Hard state', 'tooltip');
$label = $isService ? Service::getStateText($event->state, true) : Host::getStateText($event->state, true);
$stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
break;
case 'soft_state':
+ $icon = 'spinner';
+ $iconTitle = $this->translate('Soft state', 'tooltip');
$label = $isService ? Service::getStateText($event->state, true) : Host::getStateText($event->state, true);
$stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state);
break;
case 'dt_start':
$icon = 'plug';
+ $iconTitle = $this->translate('Downtime started', 'tooltip');
$label = $this->translate('DOWNTIME START');
break;
case 'dt_end':
$icon = 'plug';
$iconCssClass = 'icon-strikethrough';
+ $iconTitle = $this->translate('Downtime ended', 'tooltip');
$label = $this->translate('DOWNTIME END');
break;
} ?>
@@ -157,7 +176,7 @@ $lastDate = null;
icon($icon, null, $iconCssClass ? array('class' => $iconCssClass) : array());
+ echo $this->icon($icon, $iconTitle, $iconCssClass ? array('class' => $iconCssClass) : array());
} ?>= $this->nl2br($this->createTicketLinks($this->escapeComment($msg)))
// TODO(ak): this allows only a[href] in messages, but plugin output allows more
?>
diff --git a/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml b/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml
index 731ba1cf8..48141e2fd 100644
--- a/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml
+++ b/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml
@@ -20,7 +20,7 @@ if (! ($hostCount = count($objects))): return; endif ?>
$host->host_name,
$host->host_display_name
) ?>
- = implode(' ', $this->hostFlags($host)) ?>
+ = $this->hostFlags($host) ?>
diff --git a/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml b/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml
deleted file mode 100644
index 4421c301f..000000000
--- a/modules/monitoring/application/views/scripts/partials/host/statusicons.phtml
+++ /dev/null
@@ -1,28 +0,0 @@
-object->host_handled && $this->object->host_state > 0) {
- $icons[] = $this->icon('attention-alt', $this->translate('Unhandled'));
-}
-
-if ($this->object->host_acknowledged && !$this->object->host_in_downtime) {
- $icons[] = $this->icon('ok', $this->translate('Acknowledged'));
-}
-
-if (! $this->object->host_notifications_enabled) {
- $icons[] = $this->icon('bell-off-empty', $this->translate('Notifications Disabled'));
-}
-
-if ($this->object->host_in_downtime) {
- $icons[] = $this->icon('plug', $this->translate('In Downtime'));
-}
-
-if (! $this->object->host_active_checks_enabled) {
- if ($this->object->host_passive_checks_enabled) {
- $icons[] = $this->icon('eye-off', $this->translate('Active Checks Disabled'));
- } else {
- $icons[] = $this->icon('eye-off', $this->translate('Active And Passive Checks Disabled'));
- }
-}
-
-?>= implode("\n", $icons); ?>
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/partials/object/host-header.phtml b/modules/monitoring/application/views/scripts/partials/object/host-header.phtml
index 8bc7b6c64..3bfb35030 100644
--- a/modules/monitoring/application/views/scripts/partials/object/host-header.phtml
+++ b/modules/monitoring/application/views/scripts/partials/object/host-header.phtml
@@ -19,7 +19,12 @@ use Icinga\Module\Monitoring\Object\Host;
host_display_name !== $object->host_name): ?>
(= $this->escape($object->host_name) ?>)
- = $this->render('partials/host/statusicons.phtml') ?>
+ host_alias !== $object->host_display_name && $object->host_alias !== $object->host_name): ?>
+
+ = $this->escape($this->translate('Alias', 'host') . ': ' . $object->host_alias) ?>
+
+
+ = $this->hostFlags($object) ?>
host_address6 && $object->host_address6 !== $object->host_name): ?>