From d7467da439f41dc126e09df8b124bc5ff5147078 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 6 Aug 2020 13:53:11 +0000 Subject: [PATCH 001/587] Introduced EMAIL_REQUIRED config option. --- WEB-INF/config.php.dist | 4 ++++ WEB-INF/lib/ttRegistrator.class.php | 2 +- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/register.tpl | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 9583d59b3..d2772ffdf 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -50,6 +50,10 @@ define('DSN', 'mysqli://root:no@localhost/dbname?charset=utf8mb4'); define('MULTIORG_MODE', true); +// EMAIL_REQUIRED defines whether an email is required for new registrations. +define('EMAIL_REQUIRED', false); + + // Directory name. // If you install time tracker into a sub-directory of your site reflect this in the DIR_NAME parameter. // For example, for http://localhost/timetracker/ define DIR_NAME as 'timetracker'. diff --git a/WEB-INF/lib/ttRegistrator.class.php b/WEB-INF/lib/ttRegistrator.class.php index 936bb4ffd..09de79a4b 100644 --- a/WEB-INF/lib/ttRegistrator.class.php +++ b/WEB-INF/lib/ttRegistrator.class.php @@ -84,7 +84,7 @@ function validate() { $this->err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); if ($this->password1 !== $this->password2) $this->err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); - if (!ttValidEmail($this->email, true)) + if (!ttValidEmail($this->email, !isTrue('EMAIL_REQUIRED'))) $this->err->add($i18n->get('error.field'), $i18n->get('label.email')); if (!ttUserHelper::canAdd()) $this->err->add($i18n->get('error.user_count')); diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index e157c623b..f17ed2542 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - + From 829b3196939bd06792da5d57f73d49dd98c3a240 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 8 Aug 2020 14:44:35 +0000 Subject: [PATCH 002/587] Cosmetic presentation fix for attachment display on projects.php. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/projects.tpl | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index f17ed2542..19f2f036f 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5270 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5271 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/register.tpl b/WEB-INF/templates/register.tpl index d751c9bfa..cdf343f2d 100644 --- a/WEB-INF/templates/register.tpl +++ b/WEB-INF/templates/register.tpl @@ -33,7 +33,7 @@ {$forms.groupForm.password2.control}
{$i18n.label.email}:{$i18n.label.email}{if isTrue('EMAIL_REQUIRED')} (*){/if}: {$forms.groupForm.manager_email.control}
- - {if $show_files && $project.has_files} + {if $show_files} + {if $project.has_files} + {else} + + {/if} {/if} {/foreach} From 1b1312986ef577890693952a04c098be6e190560 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 8 Aug 2020 16:44:40 +0000 Subject: [PATCH 003/587] Improved error reporting for recent registrations. --- WEB-INF/lib/ttRegistrator.class.php | 1 + WEB-INF/resources/ca.lang.php | 1 + WEB-INF/resources/cs.lang.php | 1 + WEB-INF/resources/da.lang.php | 1 + WEB-INF/resources/de.lang.php | 2 ++ WEB-INF/resources/en.lang.php | 1 + WEB-INF/resources/es.lang.php | 1 + WEB-INF/resources/et.lang.php | 2 ++ WEB-INF/resources/fa.lang.php | 1 + WEB-INF/resources/fi.lang.php | 1 + WEB-INF/resources/fr.lang.php | 1 + WEB-INF/resources/gr.lang.php | 1 + WEB-INF/resources/he.lang.php | 1 + WEB-INF/resources/hu.lang.php | 1 + WEB-INF/resources/it.lang.php | 1 + WEB-INF/resources/ja.lang.php | 1 + WEB-INF/resources/ko.lang.php | 1 + WEB-INF/resources/nl.lang.php | 2 ++ WEB-INF/resources/no.lang.php | 1 + WEB-INF/resources/pl.lang.php | 1 + WEB-INF/resources/pt-br.lang.php | 1 + WEB-INF/resources/pt.lang.php | 1 + WEB-INF/resources/ro.lang.php | 1 + WEB-INF/resources/ru.lang.php | 1 + WEB-INF/resources/sk.lang.php | 1 + WEB-INF/resources/sl.lang.php | 1 + WEB-INF/resources/sr.lang.php | 1 + WEB-INF/resources/sv.lang.php | 1 + WEB-INF/resources/tr.lang.php | 1 + WEB-INF/resources/zh-cn.lang.php | 1 + WEB-INF/resources/zh-tw.lang.php | 1 + WEB-INF/templates/footer.tpl | 2 +- 32 files changed, 35 insertions(+), 1 deletion(-) diff --git a/WEB-INF/lib/ttRegistrator.class.php b/WEB-INF/lib/ttRegistrator.class.php index 09de79a4b..aadd7d14f 100644 --- a/WEB-INF/lib/ttRegistrator.class.php +++ b/WEB-INF/lib/ttRegistrator.class.php @@ -100,6 +100,7 @@ function register() { // Protection from too many recent bot registrations from user IP. if (!$this->created_by_id) { // No problems for logged in user (site admin). if ($this->registeredRecently()) { + $this->err->add($i18n->get('error.registered_recently')); $this->err->add($i18n->get('error.access_denied')); return false; } diff --git a/WEB-INF/resources/ca.lang.php b/WEB-INF/resources/ca.lang.php index 30efec063..c16f214a3 100644 --- a/WEB-INF/resources/ca.lang.php +++ b/WEB-INF/resources/ca.lang.php @@ -82,6 +82,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Error de la base de dades.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Dada "{0}" incorrecta.', 'error.empty' => 'L\\\'Arxiu "{0}" està buit.', diff --git a/WEB-INF/resources/cs.lang.php b/WEB-INF/resources/cs.lang.php index 707b3dcbe..14a319bf3 100644 --- a/WEB-INF/resources/cs.lang.php +++ b/WEB-INF/resources/cs.lang.php @@ -84,6 +84,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Chyba databáze.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Nesprávná "{0}" data.', 'error.empty' => 'Pole "{0}" je prázdné.', diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 9b061118f..29534c54a 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -77,6 +77,7 @@ 'error.sys' => 'System fejl.', 'error.db' => 'Database fejl.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Forkert "{0}" data.', 'error.empty' => 'Felt "{0}" er tom.', diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index a66723626..b76f05cfd 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -75,6 +75,8 @@ 'error.access_denied' => 'Zugriff verweigert.', 'error.sys' => 'Systemfehler.', 'error.db' => 'Datenbankfehler.', +// TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', 'error.feature_disabled' => 'Funktion ist deaktiviert.', 'error.field' => 'Ungültige "{0}" Daten.', 'error.empty' => 'Feld "{0}" ist leer.', diff --git a/WEB-INF/resources/en.lang.php b/WEB-INF/resources/en.lang.php index 4b17bc464..45e5868d2 100644 --- a/WEB-INF/resources/en.lang.php +++ b/WEB-INF/resources/en.lang.php @@ -72,6 +72,7 @@ 'error.access_denied' => 'Access denied.', 'error.sys' => 'System error.', 'error.db' => 'Database error.', +'error.registered_recently' => 'Registered recently.', 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Incorrect "{0}" data.', 'error.empty' => 'Field "{0}" is empty.', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index 0bd854328..8ffb5fa3d 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -81,6 +81,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Error de la base de datos.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Dato "{0}" incorrecto.', 'error.empty' => 'El archivo "{0}" esta vacío.', diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index 0b4603566..80766f902 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -76,6 +76,8 @@ 'error.access_denied' => 'Puudub ligipääs.', 'error.sys' => 'Rakenduse viga.', 'error.db' => 'Andmebaasi viga.', +// TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', 'error.feature_disabled' => 'Rakenduse funktsionaalsus on välja lülitatud.', 'error.field' => 'Välja "{0}" andmed ei vasta nõutele.', 'error.empty' => 'Väli "{0}" on tühi.', diff --git a/WEB-INF/resources/fa.lang.php b/WEB-INF/resources/fa.lang.php index ef7591192..3fedc3e22 100644 --- a/WEB-INF/resources/fa.lang.php +++ b/WEB-INF/resources/fa.lang.php @@ -81,6 +81,7 @@ 'error.sys' => 'خطا در سیستم.', 'error.db' => 'خطا در پایگاه داده.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'داده اشتباه در "{0}".', 'error.empty' => 'فیلد "{0}" خالیست.', diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index 2d91252ef..9a2c841c6 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -79,6 +79,7 @@ 'error.sys' => 'Järjestelmävirhe.', 'error.db' => 'Tietokantavirhe.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Virheellinen "{0}" tieto.', 'error.empty' => 'Kenttä "{0}" on tyhjä.', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index a4452a4e2..c3656c231 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -77,6 +77,7 @@ 'error.sys' => 'Erreur système.', 'error.db' => 'Erreur de base de données.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Donnée "{0}" incorrecte.', 'error.empty' => 'Le champ "{0}" est vide.', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index d2d036ddf..23ec5b88f 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -76,6 +76,7 @@ 'error.sys' => 'Σφάλμα συστήματος.', 'error.db' => 'Σφάλμα βάσης δεδομένων.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Λανθασμένο "{0}" δεδομένο.', 'error.empty' => 'Το πεδίο "{0}" είναι κενό.', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index 3f0cf5d66..8dd36fdf4 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -83,6 +83,7 @@ 'error.sys' => 'שגיאת מערכת', 'error.db' => 'שגיאה של בסיס הנתונים', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'נתון "{0}" שגוי', 'error.empty' => 'השדה "{0}" ריק', diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index 82f1ff081..e450a4d3f 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -84,6 +84,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Adatbázis hiba.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Hibás "{0}" mező tartalma.', 'error.empty' => 'A "{0}" mező üres.', diff --git a/WEB-INF/resources/it.lang.php b/WEB-INF/resources/it.lang.php index 15407a6b9..e48125e5f 100644 --- a/WEB-INF/resources/it.lang.php +++ b/WEB-INF/resources/it.lang.php @@ -78,6 +78,7 @@ 'error.sys' => 'Errore di sistema.', 'error.db' => 'Errore database.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Dato "{0}" errato.', 'error.empty' => 'Il campo "{0}" è vuoto.', diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index b116fb35b..511ac3037 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -82,6 +82,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'データベースのエラー。', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => '不正確な"{0}"データ。', 'error.empty' => '"{0}"のフィールドが空白です。', diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index 6b17d47d2..17e83f372 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -82,6 +82,7 @@ // 'error.sys' => 'System error.', 'error.db' => '데이터베이스 오류.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => '부정확한 "{0}" 의 데이터.', 'error.empty' => '"{0}" 의 필드가 비어있습니다.', diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 5881139e3..12890db33 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -71,6 +71,8 @@ 'error.access_denied' => 'Toegang geweigerd.', 'error.sys' => 'Systeem fout.', 'error.db' => 'Database fout.', +// TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', 'error.feature_disabled' => 'Functie is uitgeschakeld.', 'error.field' => 'Incorrecte gegevens: "{0}".', 'error.empty' => 'Veld "{0}" is leeg.', diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index 3677fdda5..8cbb1c5bd 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -83,6 +83,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Databasefeil.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Feil "{0}" data.', 'error.empty' => 'Feltet "{0}" er tomt.', diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index dff252c93..09a3e3517 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -80,6 +80,7 @@ 'error.sys' => 'Błąd systemu.', 'error.db' => 'Błąd bazy danych.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Niepoprawne dane: "{0}".', 'error.empty' => 'Pole "{0}" jest puste.', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index db5e0f17c..6949d3bef 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -77,6 +77,7 @@ 'error.sys' => 'Erro no sistema.', 'error.db' => 'Erro no banco de dados.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Dados incorretos "{0}".', 'error.empty' => 'Campo "{0}" está vazio.', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index b88fb9f18..5232c5822 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -83,6 +83,7 @@ // 'error.access_denied' => 'Access denied.', // 'error.sys' => 'System error.', // 'error.db' => 'Database error.', +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', // 'error.field' => 'Incorrect "{0}" data.', // 'error.empty' => 'Field "{0}" is empty.', diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index c569adb7e..1a0586ea2 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -85,6 +85,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Eroare baza de date.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', // 'error.field' => 'Incorrect "{0}" data.', 'error.empty' => 'Campul "{0}" este gol.', diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index 5302c225b..4c4b7ff8f 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -71,6 +71,7 @@ 'error.access_denied' => 'Доступ запрещён.', 'error.sys' => 'Системная ошибка.', 'error.db' => 'Ошибка базы данных.', +'error.registered_recently' => 'Недавняя регистрация.', 'error.feature_disabled' => 'Функция отключена.', 'error.field' => 'Некорректные данные в поле "{0}".', 'error.empty' => 'Пустое поле "{0}".', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index 53c5ee3dc..26d91c217 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -81,6 +81,7 @@ 'error.sys' => 'Systémová chyba.', 'error.db' => 'Databázová chyba.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Nesprávne "{0}" údaje.', 'error.empty' => 'Pole "{0}" je prázdne.', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index a3d350ca6..b69c4ba0a 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -81,6 +81,7 @@ // 'error.access_denied' => 'Access denied.', // 'error.sys' => 'System error.', // 'error.db' => 'Database error.', +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', // 'error.field' => 'Incorrect "{0}" data.', // 'error.empty' => 'Field "{0}" is empty.', diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index fe385a67c..e6dbaeb5b 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -77,6 +77,7 @@ 'error.sys' => 'Greška u sistemu.', 'error.db' => 'Greška u bazi podataka.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Pogrešan "{0}" podatak.', 'error.empty' => 'Polje "{0}" je prazno.', diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index 221c39d4a..7c1d468dd 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -77,6 +77,7 @@ 'error.sys' => 'Systemfel.', 'error.db' => 'Databasfel.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => '"{0}" innehåller ett felaktigt värde.', 'error.empty' => '"{0}" kan inte vara tomt.', diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index 0f0537325..c3ffd03f4 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -85,6 +85,7 @@ // 'error.sys' => 'System error.', 'error.db' => 'Veritabanı hatası.', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => 'Hatalı veri "{0}".', 'error.empty' => 'Alan "{0}" boştur.', diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index 29422cc5f..ddc48aff3 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -77,6 +77,7 @@ 'error.sys' => '系统错误。', 'error.db' => '数据库错误。', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => '不正确的"{0}"数据。', 'error.empty' => '栏目"{0}"为空。', diff --git a/WEB-INF/resources/zh-tw.lang.php b/WEB-INF/resources/zh-tw.lang.php index d4720b341..ca657fef9 100644 --- a/WEB-INF/resources/zh-tw.lang.php +++ b/WEB-INF/resources/zh-tw.lang.php @@ -80,6 +80,7 @@ // 'error.sys' => 'System error.', 'error.db' => '資料庫錯誤。', // TODO: translate the following. +// 'error.registered_recently' => 'Registered recently.', // 'error.feature_disabled' => 'Feature is disabled.', 'error.field' => '不正確的"{0}"資料。', 'error.empty' => '欄目"{0}"為空。', diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 19f2f036f..1a46a4552 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5271 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5272 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/projects.tpl b/WEB-INF/templates/projects.tpl index 7e6317310..345b7ef47 100644 --- a/WEB-INF/templates/projects.tpl +++ b/WEB-INF/templates/projects.tpl @@ -97,8 +97,12 @@
{$project.name|escape} {$project.description|escape}{$i18n.label.files} 
- - + - + {if $show_users} - + {/if} {if $show_tasks} @@ -32,7 +32,7 @@ - + {/if}
Anuko Time Tracker 1.19.23.5272 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5273 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From 5d7378e5ee0e6b4090e53e50ffcea74f9a2a6c9e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 17 Aug 2020 21:46:13 +0000 Subject: [PATCH 004/587] Removed non-editable sender field from mail.tpl to simplify it. --- WEB-INF/config.php.dist | 2 +- WEB-INF/templates/mail.tpl | 4 ---- invoice_send.php | 10 ---------- report_send.php | 10 ---------- 4 files changed, 1 insertion(+), 25 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index d2772ffdf..89cbd3965 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -95,7 +95,7 @@ define('HELP_LINK', 'https://www.anuko.com/time-tracker/user-guide/index.htm'); // Default sender for mail. // -define('SENDER', '"Anuko Time Tracker" '); +define('SENDER', 'Anuko Time Tracker '); // MAIL_MODE - mail sending mode. Can be 'mail' or 'smtp'. diff --git a/WEB-INF/templates/mail.tpl b/WEB-INF/templates/mail.tpl index c57399f1f..13e2be598 100644 --- a/WEB-INF/templates/mail.tpl +++ b/WEB-INF/templates/mail.tpl @@ -6,10 +6,6 @@
- - - - diff --git a/invoice_send.php b/invoice_send.php index e94e8050f..c69edbd9d 100644 --- a/invoice_send.php +++ b/invoice_send.php @@ -101,16 +101,6 @@ } } // isPost -$smarty->assign('sender', SENDER); -if (function_exists('imap_mime_header_decode')) { - // Decode sender in case it is encoded. PHP IMAP extension must be installed for us to get here. - $elements = imap_mime_header_decode(SENDER); - if (count($elements) > 1) { - // Reassign sender. - $smarty->assign('sender', $elements[count($elements) - 2]->text); - } -} - $smarty->assign('title', $i18n->get('title.send_invoice')); $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.mailForm.'.($cl_receiver?'comment':'receiver').'.focus()"'); diff --git a/report_send.php b/report_send.php index 526457bf4..e837f3e50 100644 --- a/report_send.php +++ b/report_send.php @@ -95,16 +95,6 @@ } } -$smarty->assign('sender', SENDER); -if (function_exists('imap_mime_header_decode')) { - $elements = imap_mime_header_decode(SENDER); - if (count($elements) > 1) { - // Reassign sender. - $new = $elements[count($elements) - 2]->text; - $smarty->assign('sender', $elements[count($elements) - 2]->text); - } -} - $smarty->assign('title', $i18n->get('title.send_report')); $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.mailForm.'.($cl_receiver?'comment':'receiver').'.focus()"'); From eb8e81c3bf667dea03e9c3a1131af13245a65910 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 17 Aug 2020 22:00:11 +0000 Subject: [PATCH 005/587] Removed no longer used string from translation files. --- WEB-INF/resources/ca.lang.php | 1 - WEB-INF/resources/cs.lang.php | 1 - WEB-INF/resources/da.lang.php | 1 - WEB-INF/resources/de.lang.php | 1 - WEB-INF/resources/en.lang.php | 1 - WEB-INF/resources/es.lang.php | 1 - WEB-INF/resources/et.lang.php | 1 - WEB-INF/resources/fa.lang.php | 1 - WEB-INF/resources/fi.lang.php | 1 - WEB-INF/resources/fr.lang.php | 1 - WEB-INF/resources/gr.lang.php | 1 - WEB-INF/resources/he.lang.php | 1 - WEB-INF/resources/hu.lang.php | 1 - WEB-INF/resources/it.lang.php | 1 - WEB-INF/resources/ja.lang.php | 1 - WEB-INF/resources/ko.lang.php | 1 - WEB-INF/resources/nl.lang.php | 1 - WEB-INF/resources/no.lang.php | 1 - WEB-INF/resources/pl.lang.php | 1 - WEB-INF/resources/pt-br.lang.php | 1 - WEB-INF/resources/pt.lang.php | 1 - WEB-INF/resources/ro.lang.php | 1 - WEB-INF/resources/ru.lang.php | 1 - WEB-INF/resources/sk.lang.php | 1 - WEB-INF/resources/sl.lang.php | 1 - WEB-INF/resources/sr.lang.php | 1 - WEB-INF/resources/sv.lang.php | 1 - WEB-INF/resources/tr.lang.php | 1 - WEB-INF/resources/zh-cn.lang.php | 1 - WEB-INF/resources/zh-tw.lang.php | 1 - WEB-INF/templates/footer.tpl | 2 +- 31 files changed, 1 insertion(+), 31 deletions(-) diff --git a/WEB-INF/resources/ca.lang.php b/WEB-INF/resources/ca.lang.php index c16f214a3..c6195cccc 100644 --- a/WEB-INF/resources/ca.lang.php +++ b/WEB-INF/resources/ca.lang.php @@ -645,7 +645,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'De', 'form.mail.to' => 'Per a', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/cs.lang.php b/WEB-INF/resources/cs.lang.php index 14a319bf3..daefafebf 100644 --- a/WEB-INF/resources/cs.lang.php +++ b/WEB-INF/resources/cs.lang.php @@ -658,7 +658,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Od', 'form.mail.to' => 'Komu', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 29534c54a..23c5df739 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -622,7 +622,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Fra', 'form.mail.to' => 'Til', 'form.mail.report_subject' => 'Tidsregistrerings Rapport', 'form.mail.footer' => 'Anuko Time Tracker er et simpelt, let at bruge, open source
tidsregistrerings system. Besøg www.anuko.com for mere information.', diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index b76f05cfd..482f42bcb 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -600,7 +600,6 @@ 'form.group_delete.hint' => 'Sind Sie sicher, dass Sie die gesamte Gruppe löschen möchten?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Von', 'form.mail.to' => 'An', 'form.mail.report_subject' => 'Time Tracker Bericht', 'form.mail.footer' => 'Anuko Time Tracker ist ein einfaches, leicht zu bedienendes, Open-Source
Zeitverwaltungs-System. Besuchen Sie www.anuko.com für weitere Informationen.', diff --git a/WEB-INF/resources/en.lang.php b/WEB-INF/resources/en.lang.php index 45e5868d2..5003f5b16 100644 --- a/WEB-INF/resources/en.lang.php +++ b/WEB-INF/resources/en.lang.php @@ -583,7 +583,6 @@ 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'From', 'form.mail.to' => 'To', 'form.mail.report_subject' => 'Time Tracker Report', 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
time tracking system. Visit www.anuko.com for more information.', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index 8ffb5fa3d..0136a9db0 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -659,7 +659,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'De', 'form.mail.to' => 'Para', // TODO: translate form.mail.report_subject. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index 80766f902..433ed64d3 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -630,7 +630,6 @@ 'form.group_delete.hint' => 'Oled kindel, et soovid kogu gruppi kustutada?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Kellelt', 'form.mail.to' => 'Kellele', 'form.mail.report_subject' => 'Time Tracker raport', 'form.mail.footer' => 'Anuko Time Tracker on lihtne, lihtsalt kasutatav ja avatud lähtekoodiga
ajaarvestussüsteem. Lisainfo saamiseks külastage www.anuko.com lehekülge.', diff --git a/WEB-INF/resources/fa.lang.php b/WEB-INF/resources/fa.lang.php index 3fedc3e22..3b767ea8d 100644 --- a/WEB-INF/resources/fa.lang.php +++ b/WEB-INF/resources/fa.lang.php @@ -644,7 +644,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'از', 'form.mail.to' => 'به', 'form.mail.report_subject' => 'گزارش تایم شیت', // TODO: translate form.mail.footer. diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index 9a2c841c6..f895b34b2 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -627,7 +627,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Lähettäjä', 'form.mail.to' => 'Vastaanottaja', 'form.mail.report_subject' => 'Time Tracker -raportti', 'form.mail.footer' => 'Anuko Time Tracker on yksinkertainen ja helppokäyttöinen vapaan koodin tuntiseurantaohjelmisto. Lisätietoja sivulla www.anuko.com.', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index c3656c231..06b0550be 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -618,7 +618,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'De', 'form.mail.to' => 'À', 'form.mail.report_subject' => 'Rapport Time Tracker', 'form.mail.footer' => 'Anuko Time Tracker est un système de gestion du temps, open source, simple et facile à utiliser. Visitez www.anuko.com pour plus d\\\'informations.', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index 23ec5b88f..dc921299e 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -610,7 +610,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Από', 'form.mail.to' => 'Προς', 'form.mail.report_subject' => 'Time Tracker αναφορά', 'form.mail.footer' => 'Το Anuko Time Tracker είναι ένα απλό, εύχρηστο, ανοικτού κώδικα σύστημα παρακολούθησης χρόνου. Επισκεφθείτε τη διεύθυνση www.anuko.com για περισσότερες πληροφορίες.', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index 8dd36fdf4..f082be589 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -646,7 +646,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'מאת', 'form.mail.to' => 'אל', 'form.mail.report_subject' => 'דוח Time Tracker', 'form.mail.footer' => 'Anuko Time Tracker הינה מערכת פשוטה, קלה לשימוש וחינמית לניהול זמן. בקר באתר www.anuko.com לפרטים נוספים.', diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index e450a4d3f..02b1ef081 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -650,7 +650,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Feladó', 'form.mail.to' => 'Címzett', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/it.lang.php b/WEB-INF/resources/it.lang.php index e48125e5f..f4c30d7cc 100644 --- a/WEB-INF/resources/it.lang.php +++ b/WEB-INF/resources/it.lang.php @@ -625,7 +625,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Da', 'form.mail.to' => 'A', 'form.mail.report_subject' => 'Rapporto Time Tracker', 'form.mail.footer' => 'Anuko Time Tracker è un sistema semplice e open source
per registrare i tempi di lavoro. Visita www.anuko.com per maggiori informazioni.', diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index 511ac3037..0808b0bd2 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -653,7 +653,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'から', 'form.mail.to' => 'まで', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index 17e83f372..b92b05304 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -651,7 +651,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => '부터', 'form.mail.to' => '까지', // TODO: is this correct? The meaning is that we send an email TO this person. // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 12890db33..35955b252 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -587,7 +587,6 @@ 'form.group_delete.hint' => 'Bent u er zeker van dat u de hele groep wilt verwijderen?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Van', 'form.mail.to' => 'Aan', 'form.mail.report_subject' => 'Time Tracker rapport', 'form.mail.footer' => 'Anuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem. Bezoek www.anuko.com voor meer informatie.', diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index 8cbb1c5bd..dc6ffa1f6 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -650,7 +650,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Fra', 'form.mail.to' => 'Til', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index 09a3e3517..1c3c51dcd 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -630,7 +630,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Od', 'form.mail.to' => 'Do', 'form.mail.report_subject' => 'Raport Time Tracker', 'form.mail.footer' => 'Anuko Time Tracker jest prostym, łatwym w użyciu, otwartoźródłowym
systemem śledzenia czasu. Odwiedź www.anuko.com, aby uzyskać więcej informacji.', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index 6949d3bef..bcf76ad7f 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -625,7 +625,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'De', 'form.mail.to' => 'Para', 'form.mail.report_subject' => 'Relatório do Time Tracker', 'form.mail.footer' => 'Anuko Time Tracker é um sistema, simples, de fácil uso, de código aberto,
de rastreamento do tempo. Visite www.anuko.com para mais informações.', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index 5232c5822..f607279b4 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -632,7 +632,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'De', 'form.mail.to' => 'Para', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index 1a0586ea2..3014652df 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -653,7 +653,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'De la', 'form.mail.to' => 'Catre', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index 4c4b7ff8f..8d11e2bcd 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -564,7 +564,6 @@ 'form.group_delete.hint' => 'Вы уверены, что хотите удалить всю группу?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'От', 'form.mail.to' => 'Кому', 'form.mail.report_subject' => 'Time Tracker отчёт', 'form.mail.footer' => 'Anuko Time Tracker - это открытая (open source), простая и лёгкая в использовании система трекинга рабочего времени. Подробности на сайте www.anuko.com.', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index 26d91c217..e6f76e279 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -635,7 +635,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Od', 'form.mail.to' => 'Komu', 'form.mail.report_subject' => 'Time Tracker zostava', 'form.mail.footer' => 'Anuko Time Tracker je jednoduchý a ľahko použiteľný systém na sledovanie času s otvoreným zdrojovým kódom.
Navštívte www.anuko.com pre viac informácií.', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index b69c4ba0a..ce46d71a5 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -626,7 +626,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Od', 'form.mail.to' => 'Za', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index e6dbaeb5b..be48065bc 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -628,7 +628,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Forma mejla. Pogledajte primer na https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Od', 'form.mail.to' => 'Za', 'form.mail.report_subject' => 'Evidencija vremena', 'form.mail.footer' => 'Anuko Time Tracker je jednostavan i lak za korišćenje za praćenje
radnog vremena. Posetite www.anuko.com za više informacija.', diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index 7c1d468dd..de3b37b04 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -627,7 +627,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Från', 'form.mail.to' => 'Till', 'form.mail.report_subject' => 'Tidsrapport', 'form.mail.footer' => 'Anuko Time Tracker är en lättanvänd applikation byggd med öppen källkod för att enkelt spåra och hålla koll på arbetstider. Besök www.anuko.com för mer information.', diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index c3ffd03f4..cb7e4ab91 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -666,7 +666,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => 'Kimden', 'form.mail.to' => 'Kime', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index ddc48aff3..cc186b6bf 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -637,7 +637,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => '从', 'form.mail.to' => '到', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/resources/zh-tw.lang.php b/WEB-INF/resources/zh-tw.lang.php index ca657fef9..bd10eecc4 100644 --- a/WEB-INF/resources/zh-tw.lang.php +++ b/WEB-INF/resources/zh-tw.lang.php @@ -643,7 +643,6 @@ // 'form.group_delete.hint' => 'Are you sure you want to delete the entire group?', // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. -'form.mail.from' => '從', 'form.mail.to' => '到', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 1a46a4552..ccba687b6 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
{$i18n.form.mail.from} (*):{$sender}
{$i18n.form.mail.to} (*): {$forms.mailForm.receiver.control}
- - + {if $show_projects} diff --git a/WEB-INF/templates/login.db2.tpl b/WEB-INF/templates/login.db2.tpl index 4ab3ad2c0..9b0b02679 100644 --- a/WEB-INF/templates/login.db2.tpl +++ b/WEB-INF/templates/login.db2.tpl @@ -13,7 +13,7 @@ - + diff --git a/WEB-INF/templates/login.ldap2.tpl b/WEB-INF/templates/login.ldap2.tpl index 7fd32ed2e..26201ce1a 100644 --- a/WEB-INF/templates/login.ldap2.tpl +++ b/WEB-INF/templates/login.ldap2.tpl @@ -16,7 +16,7 @@ - + diff --git a/WEB-INF/templates/password_change2.tpl b/WEB-INF/templates/password_change2.tpl index 703c46aaa..62a70ceab 100644 --- a/WEB-INF/templates/password_change2.tpl +++ b/WEB-INF/templates/password_change2.tpl @@ -1,6 +1,6 @@ {$forms.newPasswordForm.open}
{$i18n.form.change_password.tip}
-
+
Anuko Time Tracker 1.19.23.5273 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5274 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From 16b64e409b21e48d3ede0bf903ff3b6fa0fafc64 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 19 Aug 2020 20:38:34 +0000 Subject: [PATCH 006/587] Removed no longer used enablePlugin() function. --- WEB-INF/lib/ttUser.class.php | 28 ---------------------------- WEB-INF/templates/footer.tpl | 2 +- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/WEB-INF/lib/ttUser.class.php b/WEB-INF/lib/ttUser.class.php index 331633e11..c1b771a2d 100644 --- a/WEB-INF/lib/ttUser.class.php +++ b/WEB-INF/lib/ttUser.class.php @@ -778,34 +778,6 @@ function markUserDeleted($user_id) { return true; } - // enablePlugin either enables or disables a specific plugin for group. - function enablePlugin($plugin, $enable = true) - { - if (!$this->can('manage_advanced_settings')) - return false; // Note: enablePlugin is currently only used on week_view.php. - // So, it's not really a plugin we are enabling, but rather week view display options. - // Therefore, a check for manage_advanced_settings, not manage_features. - - $plugin_array = explode(',', $this->plugins); - if ($enable && !in_array($plugin, $plugin_array)) - $plugin_array[] = $plugin; // Add plugin to array. - - if (!$enable && in_array($plugin, $plugin_array)) { - $key = array_search($plugin, $plugin_array); - if ($key !== false) - unset($plugin_array[$key]); // Remove plugin from array. - } - - $plugins = implode(',', $plugin_array); - if ($plugins != $this->plugins) { - if (!$this->updateGroup(array('plugins' => $plugins))) - return false; - $this->plugins = $plugins; - } - - return true; - } - // isUserValid determines if a user is valid for on behalf work. function isUserValid($user_id) { if ($user_id == $this->id) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index ccba687b6..2290a8307 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - + {if $show_projects} @@ -31,6 +31,6 @@ - +
Anuko Time Tracker 1.19.23.5274 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5275 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From 7ac1f44518da55cf0baaa11c880aeb1189283faf Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 20 Aug 2020 21:01:12 +0000 Subject: [PATCH 007/587] Initial attempt to include custom fields in group by options in reports for user testing, with some known remaining issues. --- WEB-INF/lib/ttReportHelper.class.php | 297 +++++++++++++++------------ WEB-INF/templates/footer.tpl | 2 +- reports.php | 4 +- 3 files changed, 162 insertions(+), 141 deletions(-) diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index 72c99df85..6229b5e9b 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -281,7 +281,7 @@ static function getItems($options) { foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; $checkbox_field_name = 'show_'.$field_name; - if ($options[$checkbox_field_name]) { + if ($options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { if ($userField['type'] == CustomFields::TYPE_TEXT) { $ecfTableName = 'ecf'.$userField['id']; array_push($fields, "$ecfTableName.value as $field_name"); @@ -306,7 +306,7 @@ static function getItems($options) { foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; $checkbox_field_name = 'show_'.$field_name; - if ($options[$checkbox_field_name]) { + if ($options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { if ($timeField['type'] == CustomFields::TYPE_TEXT) { $cflTable = 'cfl'.$timeField['id']; array_push($fields, "$cflTable.value as $field_name"); @@ -382,7 +382,7 @@ static function getItems($options) { $field_name = 'user_field_'.$userField['id']; $checkbox_field_name = 'show_'.$field_name; $entity_type = CustomFields::ENTITY_USER; - if ($options[$field_name] || $options[$checkbox_field_name]) { + if ($options[$field_name] || $options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { $ecfTable = 'ecf'.$userField['id']; if ($userField['type'] == CustomFields::TYPE_TEXT) { // Add one join for each text field. @@ -411,7 +411,7 @@ static function getItems($options) { foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; $checkbox_field_name = 'show_'.$field_name; - if ($options[$field_name] || $options[$checkbox_field_name]) { + if ($options[$field_name] || $options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { $cflTable = 'cfl'.$timeField['id']; if ($timeField['type'] == CustomFields::TYPE_TEXT) { // Add one join for each text field. @@ -469,7 +469,7 @@ static function getItems($options) { foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; $checkbox_field_name = 'show_'.$field_name; - if ($options[$checkbox_field_name]) { + if ($options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { if ($userField['type'] == CustomFields::TYPE_TEXT) { $ecfTableName = 'ecf'.$userField['id']; array_push($fields, "$ecfTableName.value as $field_name"); @@ -493,7 +493,7 @@ static function getItems($options) { foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; $checkbox_field_name = 'show_'.$field_name; - if ($options[$checkbox_field_name]) { + if ($options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { array_push($fields, "null as $field_name"); // null for each time custom field. } } @@ -537,13 +537,13 @@ static function getItems($options) { // Prepare sql query part for left joins. $left_joins = null; - // Left joins for custom fields. + // Left joins for user custom fields. if ($custom_fields && $custom_fields->userFields) { foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; $checkbox_field_name = 'show_'.$field_name; $entity_type = CustomFields::ENTITY_USER; - if ($options[$field_name] || $options[$checkbox_field_name]) { + if ($options[$field_name] || $options[$checkbox_field_name] || ttReportHelper::groupingBy($field_name, $options)) { $ecfTable = 'ecf'.$userField['id']; if ($userField['type'] == CustomFields::TYPE_TEXT) { // Add one join for each text field. @@ -670,13 +670,14 @@ static function getSubtotals($options) { $mdb2 = getConnection(); $concat_part = ttReportHelper::makeConcatPart($options); + $group_by_fields_part = ttReportHelper::makeGroupByFieldsPart($options); $work_unit_part = ttReportHelper::makeWorkUnitPart($options); $join_part = ttReportHelper::makeJoinPart($options); $cost_part = ttReportHelper::makeCostPart($options); $where = ttReportHelper::getWhere($options); $group_by_part = ttReportHelper::makeGroupByPart($options); - $parts = "$concat_part, sum(time_to_sec(l.duration)) as time, null as expenses".$work_unit_part.$cost_part; + $parts = $concat_part.$group_by_fields_part.", sum(time_to_sec(l.duration)) as time, null as expenses".$work_unit_part.$cost_part; $sql = "select $parts from tt_log l $join_part $where $group_by_part"; // By now we have sql for time items. @@ -1641,67 +1642,33 @@ static function makeGroupByKey($options, $row) { return $group_by_key; } + // makeSingleDropdownGroupByPart is a helper function for makeGroupByPart. + // It prepates a group by part corresponding to a single dropdown control. + static function makeSingleDropdownGroupByPart($dropdown_value, $options) { + if ($dropdown_value == null || $dropdown_value == 'no_grouping') + return null; + if ('date' == $dropdown_value) + return (', l.date'); + if ('user' == $dropdown_value) + return (', u.name'); + if ('client' == $dropdown_value) + return (', c.name'); + if ('project' == $dropdown_value) + return (', p.name'); + if ('task' == $dropdown_value) + return (', t.name'); + if (ttReportHelper::groupingBy($dropdown_value, $options)) + return (", $dropdown_value"); + } + // makeGroupByPart builds a combined group by part for sql query for time items using group_by1, // group_by2, and group_by3 values passed in $options. static function makeGroupByPart($options) { if (!ttReportHelper::grouping($options)) return null; - $group_by1 = $options['group_by1']; - $group_by2 = $options['group_by2']; - $group_by3 = $options['group_by3']; - - // TODO: redo this using the if instead so that we can include custom fields properly. - switch ($group_by1) { - case 'date': - $group_by_parts .= ', l.date'; - break; - case 'user': - $group_by_parts .= ', u.name'; - break; - case 'client': - $group_by_parts .= ', c.name'; - break; - case 'project': - $group_by_parts .= ', p.name'; - break; - case 'task': - $group_by_parts .= ', t.name'; - break; - } - switch ($group_by2) { - case 'date': - $group_by_parts .= ', l.date'; - break; - case 'user': - $group_by_parts .= ', u.name'; - break; - case 'client': - $group_by_parts .= ', c.name'; - break; - case 'project': - $group_by_parts .= ', p.name'; - break; - case 'task': - $group_by_parts .= ', t.name'; - break; - } - switch ($group_by3) { - case 'date': - $group_by_parts .= ', l.date'; - break; - case 'user': - $group_by_parts .= ', u.name'; - break; - case 'client': - $group_by_parts .= ', c.name'; - break; - case 'project': - $group_by_parts .= ', p.name'; - break; - case 'task': - $group_by_parts .= ', t.name'; - break; - } + $group_by_parts .= ttReportHelper::makeSingleDropdownGroupByPart($options['group_by1'], $options); + $group_by_parts .= ttReportHelper::makeSingleDropdownGroupByPart($options['group_by2'], $options); + $group_by_parts .= ttReportHelper::makeSingleDropdownGroupByPart($options['group_by3'], $options); // Remove garbage from the beginning. $group_by_parts = ltrim($group_by_parts, ', '); $group_by_part = "group by $group_by_parts"; @@ -1769,80 +1736,136 @@ static function makeGroupByExpensesPart($options) { return $group_by_part; } - // makeConcatPart builds a concatenation part for getSubtotals query (for time items). - static function makeConcatPart($options) { - $group_by1 = $options['group_by1']; - $group_by2 = $options['group_by2']; - $group_by3 = $options['group_by3']; + // makeSingleDropdownConcatPart is a helper function for makeConcatPart. + // It make a concatenation part for getSubtotals query for time items + // corresponding to a single dropdown control. + static function makeSingleDropdownConcatPart($dropdown_value, $options) { + if ($dropdown_value == null || $dropdown_value == 'no_grouping') + return null; + if ('date' == $dropdown_value) + return (", ' - ', l.date"); + if ('user' == $dropdown_value) + return (", ' - ', u.name"); + if ('client' == $dropdown_value) + return (", ' - ', coalesce(c.name, 'Null')"); + if ('project' == $dropdown_value) + return (", ' - ', coalesce(p.name, 'Null')"); + if ('task' == $dropdown_value) + return (", ' - ', coalesce(t.name, 'Null')"); + if (ttReportHelper::groupingBy($dropdown_value, $options)) { + return ttReportHelper::makeSingleDropdownConcatCustomFieldPart($dropdown_value); + } + } - switch ($group_by1) { - case 'date': - $what_to_concat .= ", ' - ', l.date"; - break; - case 'user': - $what_to_concat .= ", ' - ', u.name"; - $fields_part .= ', u.name as user'; - break; - case 'client': - $what_to_concat .= ", ' - ', coalesce(c.name, 'Null')"; - $fields_part .= ', c.name as client'; - break; - case 'project': - $what_to_concat .= ", ' - ', coalesce(p.name, 'Null')"; - $fields_part .= ', p.name as project'; - break; - case 'task': - $what_to_concat .= ", ' - ', coalesce(t.name, 'Null')"; - $fields_part .= ', t.name as task'; - break; + // makeSingleDropdownConcatCustomFieldPart is a helper function for makeSingleDropdownConcatPart. + // It prepares the part when a custom field is selected. + static function makeSingleDropdownConcatCustomFieldPart($dropdown_value) { + global $custom_fields; + + // Iterate through time custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($dropdown_value == $field_name) { + if ($userField['type'] == CustomFields::TYPE_TEXT) { + return (", ' - ', coalesce(ecf".$userField['id'].".value, 'Null')"); + } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", ' - ', coalesce(cfo".$userField['id'].".value, 'Null')"); + } + } + } } - switch ($group_by2) { - case 'date': - $what_to_concat .= ", ' - ', l.date"; - break; - case 'user': - $what_to_concat .= ", ' - ', u.name"; - $fields_part .= ', u.name as user'; - break; - case 'client': - $what_to_concat .= ", ' - ', coalesce(c.name, 'Null')"; - $fields_part .= ', c.name as client'; - break; - case 'project': - $what_to_concat .= ", ' - ', coalesce(p.name, 'Null')"; - $fields_part .= ', p.name as project'; - break; - case 'task': - $what_to_concat .= ", ' - ', coalesce(t.name, 'Null')"; - $fields_part .= ', t.name as task'; - break; + // Iterate through time custom fields. + if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $field_name = 'time_field_'.$timeField['id']; + if ($dropdown_value == $field_name) { + if ($timeField['type'] == CustomFields::TYPE_TEXT) { + return (", ' - ', coalesce(cfl".$timeField['id'].".value, 'Null')"); + } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", ' - ', coalesce(cfo".$timeField['id'].".value, 'Null')"); + } + } + } } - switch ($group_by3) { - case 'date': - $what_to_concat .= ", ' - ', l.date"; - break; - case 'user': - $what_to_concat .= ", ' - ', u.name"; - $fields_part .= ', u.name as user'; - break; - case 'client': - $what_to_concat .= ", ' - ', coalesce(c.name, 'Null')"; - $fields_part .= ', c.name as client'; - break; - case 'project': - $what_to_concat .= ", ' - ', coalesce(p.name, 'Null')"; - $fields_part .= ', p.name as project'; - break; - case 'task': - $what_to_concat .= ", ' - ', coalesce(t.name, 'Null')"; - $fields_part .= ', t.name as task'; - break; + return null; + } + + // makeSingleDropdownGroupByFieldPart is a helper function for makeGroupByFieldsPart. + // It make a fields part for getSubtotals query for time items + // corresponding to a single group by dropdown control. + static function makeSingleDropdownGroupByFieldPart($dropdown_value, $options) { + if ($dropdown_value == null || $dropdown_value == 'no_grouping') + return null; + if ('user' == $dropdown_value) + return (', u.name as user'); + if ('client' == $dropdown_value) + return (', c.name as client'); + if ('project' == $dropdown_value) + return (', p.name as project'); + if ('task' == $dropdown_value) + return (', t.name as task'); + if (ttReportHelper::groupingBy($dropdown_value, $options)) { + return ttReportHelper::makeSingleDropdownGroupByCustomFieldPart($dropdown_value); } - // Remove garbage from both ends. - $what_to_concat = trim($what_to_concat, "', -"); - $concat_part = "concat($what_to_concat) as group_field"; - $concat_part = trim($concat_part, ' -'); - return "$concat_part $fields_part"; + } + + // makeSingleDropdownGroupByCustomFieldPart is a helper function for makeGroupByFieldsPart. + // It prepares the part when a custom field is selected. + static function makeSingleDropdownGroupByCustomFieldPart($dropdown_value) { + global $custom_fields; + + // Iterate through time custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($dropdown_value == $field_name) { + if ($userField['type'] == CustomFields::TYPE_TEXT) { + return (", ecf".$userField['id'].".value as $field_name"); + } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", cfo".$userField['id'].".value as $field_name"); + } + } + } + } + // Iterate through time custom fields. + if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $field_name = 'time_field_'.$timeField['id']; + if ($dropdown_value == $field_name) { + if ($timeField['type'] == CustomFields::TYPE_TEXT) { + return (", cfl".$timeField['id'].".value as $field_name"); + } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", cfo".$timeField['id'].".value as $field_name"); + } + } + } + } + return null; + } + + // makeGroupByFieldsPart builds a list of fields for sql query for time items using group_by1, + // group_by2, and group_by3 values passed in $options. + static function makeGroupByFieldsPart($options) { + if (!ttReportHelper::grouping($options)) return null; + + $group_by_fields_parts .= ttReportHelper::makeSingleDropdownGroupByFieldPart($options['group_by1'], $options); + $group_by_fields_parts .= ttReportHelper::makeSingleDropdownGroupByFieldPart($options['group_by2'], $options); + $group_by_fields_parts .= ttReportHelper::makeSingleDropdownGroupByFieldPart($options['group_by3'], $options); + return $group_by_fields_parts; + } + + // makeConcatPart builds a concatenation part for getSubtotals query (for time items). + static function makeConcatPart($options) { + if (!ttReportHelper::grouping($options)) return null; + + $concat_part .= ttReportHelper::makeSingleDropdownConcatPart($options['group_by1'], $options); + $concat_part .= ttReportHelper::makeSingleDropdownConcatPart($options['group_by2'], $options); + $concat_part .= ttReportHelper::makeSingleDropdownConcatPart($options['group_by3'], $options); + // Remove garbage from the beginning. + $concat_part = trim($concat_part, "', -"); + $concat_part = "concat($concat_part) as group_field"; + return $concat_part; } // makeConcatPart builds a concatenation part for getSubtotals query (for expense items). @@ -2006,7 +2029,7 @@ static function makeJoinPart($options) { foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; $field_value = $options[$field_name]; - if ($field_value) { + if ($field_value || ttReportHelper::groupingBy($field_name, $options)) { $cflTable = 'cfl'.$timeField['id']; if ($timeField['type'] == CustomFields::TYPE_TEXT) { // Add one join for each text field. @@ -2026,7 +2049,7 @@ static function makeJoinPart($options) { $field_name = 'user_field_'.$userField['id']; $field_value = $options[$field_name]; $entity_type = CustomFields::ENTITY_USER; - if ($field_value) { + if ($field_value || ttReportHelper::groupingBy($field_name, $options)) { // We need to add left joins when input is not null. $ecfTable = 'ecf'.$userField['id']; if ($userField['type'] == CustomFields::TYPE_TEXT) { diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 2290a8307..a0bfa83b9 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} - + - + diff --git a/expense_edit.php b/expense_edit.php index f736f2132..092f33c11 100644 --- a/expense_edit.php +++ b/expense_edit.php @@ -1,30 +1,6 @@ addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$active_clients, 'datakeys'=>array('id', 'name'), @@ -98,7 +73,6 @@ $project_list = $user->getAssignedProjects(); $form->addInput(array('type'=>'combobox', 'name'=>'project', - 'style'=>'width: 250px;', 'value'=>$cl_project, 'data'=>$project_list, 'datakeys'=>array('id','name'), @@ -107,7 +81,7 @@ // Dropdown for clients if the clients plugin is enabled. if ($user->isPluginEnabled('cl')) { $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. + // We need an array of assigned project ids to do some trimming. foreach($project_list as $project) $projects_assigned_to_user[] = $project['id']; @@ -124,7 +98,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$client_list, 'datakeys'=>array('id', 'name'), @@ -137,15 +110,14 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'recalculateCost();', 'name'=>'predefined_expense', - 'style'=>'width: 250px;', 'value'=>$cl_predefined_expense, 'data'=>$predefined_expenses, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); + $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','value'=>$cl_quantity)); } -$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','style'=>'width: 250px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_item_name)); -$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); +$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','value'=>$cl_item_name)); +$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','value'=>$cl_cost)); if ($user->can('manage_invoices') && $user->isPluginEnabled('ps')) $form->addInput(array('type'=>'checkbox','name'=>'paid','value'=>$cl_paid)); $form->addInput(array('type'=>'datefield','name'=>'date','maxlength'=>'20','value'=>$cl_date)); @@ -239,5 +211,5 @@ $smarty->assign('project_list', $project_list); $smarty->assign('task_list', $task_list); $smarty->assign('title', $i18n->get('title.edit_expense')); -$smarty->assign('content_page_name', 'expense_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'expense_edit2.tpl'); +$smarty->display('index2.tpl'); diff --git a/expense_edit1.php b/expense_edit1.php new file mode 100644 index 000000000..d8b452d56 --- /dev/null +++ b/expense_edit1.php @@ -0,0 +1,243 @@ +isPluginEnabled('ex')) { + header('Location: feature_disabled.php'); + exit(); +} +$cl_id = (int)$request->getParameter('id'); +// Get the expense item we are editing. +$expense_item = ttExpenseHelper::getItem($cl_id); +if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { + // Prohibit editing not ours, approved, or invoiced items. + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +$item_date = new DateAndTime(DB_DATEFORMAT, $expense_item['date']); +$confirm_save = $user->getConfigOption('confirm_save'); +$trackingMode = $user->getTrackingMode(); +$show_project = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; + +// Initialize variables. +$cl_date = $cl_client = $cl_project = $cl_item_name = $cl_cost = null; +if ($request->isPost()) { + $cl_date = trim($request->getParameter('date')); + $cl_client = $request->getParameter('client'); + $cl_project = $request->getParameter('project'); + $cl_item_name = trim($request->getParameter('item_name')); + $cl_cost = trim($request->getParameter('cost')); + if ($user->isPluginEnabled('ps')) + $cl_paid = $request->getParameter('paid'); +} else { + $cl_date = $item_date->toString($user->getDateFormat()); + $cl_client = $expense_item['client_id']; + $cl_project = $expense_item['project_id']; + $cl_item_name = $expense_item['name']; + $cl_cost = $expense_item['cost']; + $cl_paid = $expense_item['paid']; +} + +// Initialize elements of 'expenseItemForm'. +$form = new Form('expenseItemForm'); + +// Dropdown for clients in MODE_TIME. Use all active clients. +if (MODE_TIME == $trackingMode && $user->isPluginEnabled('cl')) { + $active_clients = ttGroupHelper::getActiveClients(true); + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillProjectDropdown(this.value);', + 'name'=>'client', + 'style'=>'width: 250px;', + 'value'=>$cl_client, + 'data'=>$active_clients, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + // Note: in other modes the client list is filtered to relevant clients only. See below. +} + +if ($show_project) { + // Dropdown for projects assigned to user. + $project_list = $user->getAssignedProjects(); + $form->addInput(array('type'=>'combobox', + 'name'=>'project', + 'style'=>'width: 250px;', + 'value'=>$cl_project, + 'data'=>$project_list, + 'datakeys'=>array('id','name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + + // Dropdown for clients if the clients plugin is enabled. + if ($user->isPluginEnabled('cl')) { + $active_clients = ttGroupHelper::getActiveClients(true); + // We need an array of assigned project ids to do some trimming. + foreach($project_list as $project) + $projects_assigned_to_user[] = $project['id']; + + // Build a client list out of active clients. Use only clients that are relevant to user. + // Also trim their associated project list to only assigned projects (to user). + foreach($active_clients as $client) { + $projects_assigned_to_client = explode(',', $client['projects']); + $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); + if ($intersection) { + $client['projects'] = implode(',', $intersection); + $client_list[] = $client; + } + } + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillProjectDropdown(this.value);', + 'name'=>'client', + 'style'=>'width: 250px;', + 'value'=>$cl_client, + 'data'=>$client_list, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + } +} +// If predefined expenses are configured, add controls to select an expense and quantity. +$predefined_expenses = ttGroupHelper::getPredefinedExpenses(); +if ($predefined_expenses) { + $form->addInput(array('type'=>'combobox', + 'onchange'=>'recalculateCost();', + 'name'=>'predefined_expense', + 'style'=>'width: 250px;', + 'value'=>$cl_predefined_expense, + 'data'=>$predefined_expenses, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); +} +$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','style'=>'width: 250px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_item_name)); +$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); +if ($user->can('manage_invoices') && $user->isPluginEnabled('ps')) + $form->addInput(array('type'=>'checkbox','name'=>'paid','value'=>$cl_paid)); +$form->addInput(array('type'=>'datefield','name'=>'date','maxlength'=>'20','value'=>$cl_date)); +// Hidden control for record id. +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); +$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_save or btn_copy click. +$on_click_action = 'browser_today.value=get_date();'; +$form->addInput(array('type'=>'submit','name'=>'btn_copy','onclick'=>$on_click_action,'value'=>$i18n->get('button.copy'))); +if ($confirm_save) $on_click_action .= 'return(confirmSave());'; +$form->addInput(array('type'=>'submit','name'=>'btn_save','onclick'=>$on_click_action,'value'=>$i18n->get('button.save'))); +$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); + +if ($request->isPost()) { + // Validate user input. + if ($user->isPluginEnabled('cl') && $user->isOptionEnabled('client_required') && !$cl_client) + $err->add($i18n->get('error.client')); + if ($show_project && !$cl_project) + $err->add($i18n->get('error.project')); + if (!ttValidString($cl_item_name)) $err->add($i18n->get('error.field'), $i18n->get('label.item')); + if (!ttValidFloat($cl_cost)) $err->add($i18n->get('error.field'), $i18n->get('label.cost')); + if (!ttValidDate($cl_date)) $err->add($i18n->get('error.field'), $i18n->get('label.date')); + + // This is a new date for the expense item. + $new_date = new DateAndTime($user->getDateFormat(), $cl_date); + + // Prohibit creating entries in future. + if (!$user->isOptionEnabled('future_entries')) { + $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); + if ($new_date->after($browser_today)) + $err->add($i18n->get('error.future_date')); + } + if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); + // Finished validating user input. + + // Save record. + if ($request->getParameter('btn_save')) { + // We need to: + // 1) Prohibit updating locked entries (that are in locked range). + // 2) Prohibit saving unlocked entries into locked range. + + // Now, step by step. + // 1) Prohibit saving locked entries in any form. + if ($user->isDateLocked($item_date)) + $err->add($i18n->get('error.range_locked')); + + // 2) Prohibit saving unlocked entries into locked range. + if ($err->no() && $user->isDateLocked($new_date)) + $err->add($i18n->get('error.range_locked')); + + // Now, an update. + if ($err->no()) { + if (ttExpenseHelper::update(array('id'=>$cl_id,'date'=>$new_date->toString(DB_DATEFORMAT), + 'client_id'=>$cl_client,'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'paid'=>$cl_paid))) { + header('Location: expenses.php?date='.$new_date->toString(DB_DATEFORMAT)); + exit(); + } + } + } + + // Save as new record. + if ($request->getParameter('btn_copy')) { + // We need to prohibit saving into locked interval. + if ($user->isDateLocked($new_date)) + $err->add($i18n->get('error.range_locked')); + + // Now, a new insert. + if ($err->no()) { + if (ttExpenseHelper::insert(array('date'=>$new_date->toString(DB_DATEFORMAT),'client_id'=>$cl_client, + 'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'status'=>1))) { + header('Location: expenses.php?date='.$new_date->toString(DB_DATEFORMAT)); + exit(); + } else + $err->add($i18n->get('error.db')); + } + } + + if ($request->getParameter('btn_delete')) { + header("Location: expense_delete.php?id=$cl_id"); + exit(); + } +} // isPost + +if ($confirm_save) { + $smarty->assign('confirm_save', true); + $smarty->assign('entry_date', $cl_date); +} +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('show_project', $show_project); +$smarty->assign('predefined_expenses', $predefined_expenses); +$smarty->assign('client_list', $client_list); +$smarty->assign('project_list', $project_list); +$smarty->assign('task_list', $task_list); +$smarty->assign('title', $i18n->get('title.edit_expense')); +$smarty->assign('content_page_name', 'expense_edit.tpl'); +$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index e6fc238e5..a6bea1735 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5363"); +define("APP_VERSION", "1.19.23.5364"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 2a3c243eb57e2a41f319be331e001a23a2828372 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 21:59:57 +0000 Subject: [PATCH 109/587] Fixed calendar icon presentation for empty DIR_NAME condition. --- WEB-INF/lib/form/DateField.class.php | 2 +- initialize.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WEB-INF/lib/form/DateField.class.php b/WEB-INF/lib/form/DateField.class.php index f3513c480..5eb217bac 100644 --- a/WEB-INF/lib/form/DateField.class.php +++ b/WEB-INF/lib/form/DateField.class.php @@ -406,7 +406,7 @@ function adjustiFrame(pickerDiv, iFrameDiv) { $html .= " value=\"".htmlspecialchars($this->getValue())."\""; $html .= ">"; - if (defined('DIR_NAME')) + if (defined('DIR_NAME') && !empty(DIR_NAME)) $app_root = '/'.DIR_NAME; $html .= " name."');\">\n"; diff --git a/initialize.php b/initialize.php index a6bea1735..e1b70c7b2 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5364"); +define("APP_VERSION", "1.19.23.5365"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From b13c5b01c6bc514bd075df969eb4f054523a75b3 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 22:29:05 +0000 Subject: [PATCH 110/587] Rolling back a previous commit, something is wrong. --- WEB-INF/lib/form/DateField.class.php | 2 +- initialize.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WEB-INF/lib/form/DateField.class.php b/WEB-INF/lib/form/DateField.class.php index 5eb217bac..f3513c480 100644 --- a/WEB-INF/lib/form/DateField.class.php +++ b/WEB-INF/lib/form/DateField.class.php @@ -406,7 +406,7 @@ function adjustiFrame(pickerDiv, iFrameDiv) { $html .= " value=\"".htmlspecialchars($this->getValue())."\""; $html .= ">"; - if (defined('DIR_NAME') && !empty(DIR_NAME)) + if (defined('DIR_NAME')) $app_root = '/'.DIR_NAME; $html .= " name."');\">\n"; diff --git a/initialize.php b/initialize.php index e1b70c7b2..f138dff08 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5365"); +define("APP_VERSION", "1.19.23.5366"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 9398c60f4f9b9b13bcc0617e9de38bb9599680df Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 14 Nov 2020 13:37:57 +0000 Subject: [PATCH 111/587] Fixed path to calendar icon for some DIR_NAME situations. --- WEB-INF/lib/form/DateField.class.php | 5 +++-- initialize.php | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/WEB-INF/lib/form/DateField.class.php b/WEB-INF/lib/form/DateField.class.php index f3513c480..8ff06af5f 100644 --- a/WEB-INF/lib/form/DateField.class.php +++ b/WEB-INF/lib/form/DateField.class.php @@ -406,8 +406,9 @@ function adjustiFrame(pickerDiv, iFrameDiv) { $html .= " value=\"".htmlspecialchars($this->getValue())."\""; $html .= ">"; - if (defined('DIR_NAME')) - $app_root = '/'.DIR_NAME; + $dir_name = trim(constant('DIR_NAME'), '/'); + if (!empty($dir_name)) + $app_root = '/'.$dir_name; $html .= " name."');\">\n"; } diff --git a/initialize.php b/initialize.php index f138dff08..be4ad934b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5366"); +define("APP_VERSION", "1.19.23.5367"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From a9d1256cd4d7a5158ec1c499fd1df02e6f5303f9 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 14 Nov 2020 13:49:39 +0000 Subject: [PATCH 112/587] Disabled logging a warning when DIR_NAME is not defined. --- WEB-INF/lib/form/DateField.class.php | 2 +- initialize.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WEB-INF/lib/form/DateField.class.php b/WEB-INF/lib/form/DateField.class.php index 8ff06af5f..01c14f2e6 100644 --- a/WEB-INF/lib/form/DateField.class.php +++ b/WEB-INF/lib/form/DateField.class.php @@ -406,7 +406,7 @@ function adjustiFrame(pickerDiv, iFrameDiv) { $html .= " value=\"".htmlspecialchars($this->getValue())."\""; $html .= ">"; - $dir_name = trim(constant('DIR_NAME'), '/'); + $dir_name = trim(@constant('DIR_NAME'), '/'); if (!empty($dir_name)) $app_root = '/'.$dir_name; diff --git a/initialize.php b/initialize.php index be4ad934b..4405f89db 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5367"); +define("APP_VERSION", "1.19.23.5368"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 61e9d2d2e88bef94f8392f7a6b2a3ae9085e9c45 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 13:27:44 +0000 Subject: [PATCH 113/587] Removed redundant forward slash in password reset URL. --- WEB-INF/config.php.dist | 1 - password_reset.php | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 4db71fad4..4a0fff710 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -60,7 +60,6 @@ define('EMAIL_REQUIRED', false); // // define('DIR_NAME', 'timetracker'); // -define('DIR_NAME', ''); // WEEKEND_START_DAY diff --git a/password_reset.php b/password_reset.php index ba3547132..0ef5e32a5 100644 --- a/password_reset.php +++ b/password_reset.php @@ -105,10 +105,12 @@ $http = 'http'; $cl_subject = $user_i18n->get('form.reset_password.email_subject'); - if (defined('DIR_NAME')) - $pass_edit_url = $http.'://'.$_SERVER['HTTP_HOST'].'/'.DIR_NAME.'/password_change.php?ref='.$temp_ref; - else - $pass_edit_url = $http.'://'.$_SERVER['HTTP_HOST'].'/password_change.php?ref='.$temp_ref; + + $dir_name = trim(@constant('DIR_NAME'), '/'); + if (!empty($dir_name)) + $app_root = '/'.$dir_name; + + $pass_edit_url = $http.'://'.$_SERVER['HTTP_HOST'].$app_root.'/password_change.php?ref='.$temp_ref; $mailer->setMailMode(MAIL_MODE); if ($mailer->send($cl_subject, sprintf($user_i18n->get('form.reset_password.email_body'), $_SERVER['REMOTE_ADDR'], $pass_edit_url))) From 926a2de4528984fd0091209e367e4ecfa16c364d Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 13:40:12 +0000 Subject: [PATCH 114/587] Cosmetic. --- WEB-INF/config.php.dist | 28 ++-------------------------- password_reset.php | 28 ++-------------------------- 2 files changed, 4 insertions(+), 52 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 4a0fff710..7b6eabbd2 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -1,30 +1,6 @@ Date: Tue, 24 Nov 2020 14:04:27 +0000 Subject: [PATCH 115/587] Removed unnecessary assignments from JavaScript. --- WEB-INF/templates/user_add2.tpl | 2 -- WEB-INF/templates/user_edit2.tpl | 2 -- initialize.php | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index 370fb08f3..d125f2feb 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -43,7 +43,6 @@ function handleClientControl() { if (selectedRoleId == roles[i][0]) { var isClient = roles[i][1]; if (isClient == 1) { - clientControl.style.visibility = "visible"; clientBlock.style.display = ""; nonClientBlock.style.display = "none"; projectsControl.style.display = "none"; @@ -56,7 +55,6 @@ function handleClientControl() { } } else { clientControl.value = ""; - clientControl.style.visibility = "hidden"; clientBlock.style.display = "none"; nonClientBlock.style.display = ""; projectsControl.style.display = ""; diff --git a/WEB-INF/templates/user_edit2.tpl b/WEB-INF/templates/user_edit2.tpl index 6339b9734..5cec542f2 100644 --- a/WEB-INF/templates/user_edit2.tpl +++ b/WEB-INF/templates/user_edit2.tpl @@ -65,7 +65,6 @@ function handleClientControl() { if (selectedRoleId == roles[i][0]) { var isClient = roles[i][1]; if (isClient == 1) { - clientControl.style.visibility = "visible"; clientBlock.style.display = ""; nonClientBlock.style.display = "none"; projectsControl.style.display = "none"; @@ -78,7 +77,6 @@ function handleClientControl() { } } else { clientControl.value = ""; - clientControl.style.visibility = "hidden"; clientBlock.style.display = "none"; nonClientBlock.style.display = ""; projectsControl.style.display = ""; diff --git a/initialize.php b/initialize.php index 4405f89db..66bcaa4dd 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5368"); +define("APP_VERSION", "1.19.23.5369"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From bc2c67dbd3e354d9d441aa349f3a7cd5af31e307 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 14:24:00 +0000 Subject: [PATCH 116/587] Renamed a function for clarity. --- WEB-INF/templates/user_add2.tpl | 6 +++--- WEB-INF/templates/user_edit2.tpl | 6 +++--- initialize.php | 2 +- user_add.php | 4 ++-- user_edit.php | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index d125f2feb..6adc5f7cd 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -29,9 +29,9 @@ function setDefaultRate(element) { } } -// handleClientControl - controls visibility of the client dropdown depending on the selected user role, -// also hides and unselects projects when "Client" user role is selected. -function handleClientControl() { +// handleClientRole - manages visibility and content of controls related to client role, +// also hides and unselects projects when client role is selected. +function handleClientRole() { var selectedRoleId = document.getElementById("role").value; var clientControl = document.getElementById("client"); var clientBlock = document.getElementById("client_block"); diff --git a/WEB-INF/templates/user_edit2.tpl b/WEB-INF/templates/user_edit2.tpl index 5cec542f2..ecc0a838e 100644 --- a/WEB-INF/templates/user_edit2.tpl +++ b/WEB-INF/templates/user_edit2.tpl @@ -51,9 +51,9 @@ function setRate(element) { } } -// handleClientControl - controls visibility of the client dropdown depending on the selected user role, -// also hides and unselects projects when "Client" user role is selected. -function handleClientControl() { +// handleClientRole - manages visibility and content of controls related to client role, +// also hides and unselects projects when client role is selected. +function handleClientRole() { var selectedRoleId = document.getElementById("role").value; var clientControl = document.getElementById("client"); var clientBlock = document.getElementById("client_block"); diff --git a/initialize.php b/initialize.php index 66bcaa4dd..76635a4a5 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5369"); +define("APP_VERSION", "1.19.23.5370"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_add.php b/user_add.php index 327ee8702..e87fed752 100644 --- a/user_add.php +++ b/user_add.php @@ -82,7 +82,7 @@ $form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); $active_roles = ttTeamHelper::getActiveRolesForUser(); -$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles,'datakeys'=>array('id', 'name'))); +$form->addInput(array('type'=>'combobox','onchange'=>'handleClientRole()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles,'datakeys'=>array('id', 'name'))); if ($user->isPluginEnabled('cl')) $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -211,7 +211,7 @@ function render(&$table, $value, $row, $column, $selected = false) { $smarty->assign('auth_external', $auth->isPasswordExternal()); $smarty->assign('active_roles', $active_roles); $smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); +$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientRole();"'); $smarty->assign('show_quota', $show_quota); $smarty->assign('show_projects', $show_projects); $smarty->assign('title', $i18n->get('title.add_user')); diff --git a/user_edit.php b/user_edit.php index 493cb8d4d..17c8292e3 100644 --- a/user_edit.php +++ b/user_edit.php @@ -118,7 +118,7 @@ $form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); $active_roles = ttTeamHelper::getActiveRolesForUser(); -$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles, 'datakeys'=>array('id', 'name'))); +$form->addInput(array('type'=>'combobox','onchange'=>'handleClientRole()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles, 'datakeys'=>array('id', 'name'))); if ($user->isPluginEnabled('cl')) $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -274,7 +274,7 @@ function render(&$table, $value, $row, $column, $selected = false) { $smarty->assign('active_roles', $active_roles); $smarty->assign('can_swap', $can_swap); $smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); +$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientRole();"'); $smarty->assign('show_quota', $show_quota); $smarty->assign('show_projects', $show_projects); $smarty->assign('user_id', $user_id); From 016dd166540c7f8754b588cad9e01f55357595b2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 14:30:20 +0000 Subject: [PATCH 117/587] Made access_denied.php page mobile friendly. --- access_denied.php | 2 +- initialize.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/access_denied.php b/access_denied.php index 72a28d192..7d804f550 100644 --- a/access_denied.php +++ b/access_denied.php @@ -33,4 +33,4 @@ $smarty->assign('title', $i18n->get('label.error')); $smarty->assign('content_page_name', 'access_denied.tpl'); -$smarty->display('index.tpl'); +$smarty->display('index2.tpl'); diff --git a/initialize.php b/initialize.php index 76635a4a5..c26d92d08 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5370"); +define("APP_VERSION", "1.19.23.5371"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 32c1ced1ae5cf2df327ad896df0a4d1aa6c98860 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 14:55:33 +0000 Subject: [PATCH 118/587] Made swap_roles.php page mobile-friendly. --- WEB-INF/templates/swap_roles2.tpl | 11 ++++++++++ access_denied.php | 28 ++----------------------- initialize.php | 2 +- swap_roles.php | 34 +++++-------------------------- 4 files changed, 19 insertions(+), 56 deletions(-) create mode 100644 WEB-INF/templates/swap_roles2.tpl diff --git a/WEB-INF/templates/swap_roles2.tpl b/WEB-INF/templates/swap_roles2.tpl new file mode 100644 index 000000000..804b07a4d --- /dev/null +++ b/WEB-INF/templates/swap_roles2.tpl @@ -0,0 +1,11 @@ +
{$i18n.form.swap.hint}
+{$forms.swapForm.open} +
Anuko Time Tracker 1.19.23.5275 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5276 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/reports.php b/reports.php index 253652b94..94b837cc1 100644 --- a/reports.php +++ b/reports.php @@ -357,8 +357,6 @@ if (MODE_PROJECTS_AND_TASKS == $trackingMode) $group_by_options['task'] = $i18n->get('form.reports.group_by_task'); // If we have time custom fields - add group by options for them. -/* - * This is unfinished work in progress. if ($custom_fields && $custom_fields->timeFields) { foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; @@ -371,7 +369,7 @@ $field_name = 'user_field_'.$userField['id']; $group_by_options[$field_name] = $userField['label']; } -}*/ +} $group_by_options_size = sizeof($group_by_options); $form->addInput(array('type'=>'combobox','onchange'=>'handleCheckboxes();','name'=>'group_by1','data'=>$group_by_options)); if ($group_by_options_size > 2) $form->addInput(array('type'=>'combobox','onchange'=>'handleCheckboxes();','name'=>'group_by2','data'=>$group_by_options)); From a33fc4c1ebcc8bf8ded9c7d0583f7a8269d7b5b7 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 23 Aug 2020 17:27:54 +0000 Subject: [PATCH 008/587] Fixed reports for expenses when grouped by various custom fields. --- WEB-INF/lib/ttReportHelper.class.php | 284 +++++++++++++++------------ WEB-INF/templates/footer.tpl | 2 +- 2 files changed, 156 insertions(+), 130 deletions(-) diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index 6229b5e9b..655b32ab3 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -685,12 +685,14 @@ static function getSubtotals($options) { if ($options['show_cost'] && $user->isPluginEnabled('ex')) { // if ex(penses) plugin is enabled $concat_part = ttReportHelper::makeConcatExpensesPart($options); + $group_by_fields_part = ttReportHelper::makeGroupByFieldsExpensesPart($options); $join_part = ttReportHelper::makeJoinExpensesPart($options); $where = ttReportHelper::getExpenseWhere($options); $group_by_expenses_part = ttReportHelper::makeGroupByExpensesPart($options); - $sql_for_expenses = "select $concat_part, null as time"; - if ($options['show_work_units']) $sql_for_expenses .= ", null as units"; - $sql_for_expenses .= ", sum(ei.cost) as cost, sum(ei.cost) as expenses from tt_expense_items ei $join_part $where $group_by_expenses_part"; + $parts = $concat_part.$group_by_fields_part.", null as time"; + if ($options['show_work_units']) $parts .= ", null as units"; + $parts .= ", sum(ei.cost) as cost, sum(ei.cost) as expenses"; + $sql_for_expenses = "select $parts from tt_expense_items ei $join_part $where $group_by_expenses_part"; // Create a combined query. $fields = ttReportHelper::makeCombinedSelectPart($options); @@ -1675,64 +1677,34 @@ static function makeGroupByPart($options) { return $group_by_part; } + // makeSingleDropdownGroupByExpensesPart is a helper function for makeGroupByExpensesPart. + // It prepates a group by part corresponding to a single dropdown control. + static function makeSingleDropdownGroupByExpensesPart($dropdown_value, $options) { + if ($dropdown_value == null || $dropdown_value == 'no_grouping') + return null; + if ('date' == $dropdown_value) + return (', ei.date'); + if ('user' == $dropdown_value) + return (', u.name'); + if ('client' == $dropdown_value) + return (', c.name'); + if ('project' == $dropdown_value) + return (', p.name'); + if (ttReportHelper::groupingBy($dropdown_value, $options)) + return (", $dropdown_value"); + } + // makeGroupByExpensesPart builds a combined group by part for sql query for expense items using // group_by1, group_by2, and group_by3 values passed in $options. static function makeGroupByExpensesPart($options) { - $no_grouping = ($options['group_by1'] == null || $options['group_by1'] == 'no_grouping') && - ($options['group_by2'] == null || $options['group_by2'] == 'no_grouping') && - ($options['group_by3'] == null || $options['group_by3'] == 'no_grouping'); - if ($no_grouping) return null; - - $group_by1 = $options['group_by1']; - $group_by2 = $options['group_by2']; - $group_by3 = $options['group_by3']; + if (!ttReportHelper::grouping($options)) return null; - switch ($group_by1) { - case 'date': - $group_by_parts .= ', ei.date'; - break; - case 'user': - $group_by_parts .= ', u.name'; - break; - case 'client': - $group_by_parts .= ', c.name'; - break; - case 'project': - $group_by_parts .= ', p.name'; - break; - } - switch ($group_by2) { - case 'date': - $group_by_parts .= ', ei.date'; - break; - case 'user': - $group_by_parts .= ', u.name'; - break; - case 'client': - $group_by_parts .= ', c.name'; - break; - case 'project': - $group_by_parts .= ', p.name'; - break; - } - switch ($group_by3) { - case 'date': - $group_by_parts .= ', ei.date'; - break; - case 'user': - $group_by_parts .= ', u.name'; - break; - case 'client': - $group_by_parts .= ', c.name'; - break; - case 'project': - $group_by_parts .= ', p.name'; - break; - } + $group_by_parts .= ttReportHelper::makeSingleDropdownGroupByExpensesPart($options['group_by1'], $options); + $group_by_parts .= ttReportHelper::makeSingleDropdownGroupByExpensesPart($options['group_by2'], $options); + $group_by_parts .= ttReportHelper::makeSingleDropdownGroupByExpensesPart($options['group_by3'], $options); // Remove garbage from the beginning. $group_by_parts = ltrim($group_by_parts, ', '); - if ($group_by_parts) - $group_by_part = "group by $group_by_parts"; + $group_by_part = "group by $group_by_parts"; return $group_by_part; } @@ -1762,7 +1734,7 @@ static function makeSingleDropdownConcatPart($dropdown_value, $options) { static function makeSingleDropdownConcatCustomFieldPart($dropdown_value) { global $custom_fields; - // Iterate through time custom fields. + // Iterate through user custom fields. if ($custom_fields && $custom_fields->userFields) { foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; @@ -1791,6 +1763,40 @@ static function makeSingleDropdownConcatCustomFieldPart($dropdown_value) { return null; } + // makeSingleDropdownConcatCustomFieldExpensesPart is a helper function for makeSingleDropdownConcatExpensesPart. + // It prepares the part when a custom field is selected. + static function makeSingleDropdownConcatCustomFieldExpensesPart($dropdown_value) { + global $custom_fields; + + // Iterate through user custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($dropdown_value == $field_name) { + if ($userField['type'] == CustomFields::TYPE_TEXT) { + return (", ' - ', coalesce(ecf".$userField['id'].".value, 'Null')"); + } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", ' - ', coalesce(cfo".$userField['id'].".value, 'Null')"); + } + } + } + } + // Iterate through time custom fields. + if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $field_name = 'time_field_'.$timeField['id']; + if ($dropdown_value == $field_name) { + if ($timeField['type'] == CustomFields::TYPE_TEXT) { + return (", ' - ', 'Null'"); + } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", ' - ', 'Null'"); + } + } + } + } + return null; + } + // makeSingleDropdownGroupByFieldPart is a helper function for makeGroupByFieldsPart. // It make a fields part for getSubtotals query for time items // corresponding to a single group by dropdown control. @@ -1815,7 +1821,7 @@ static function makeSingleDropdownGroupByFieldPart($dropdown_value, $options) { static function makeSingleDropdownGroupByCustomFieldPart($dropdown_value) { global $custom_fields; - // Iterate through time custom fields. + // Iterate through user custom fields. if ($custom_fields && $custom_fields->userFields) { foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; @@ -1844,6 +1850,36 @@ static function makeSingleDropdownGroupByCustomFieldPart($dropdown_value) { return null; } + // makeSingleDropdownGroupByCustomFieldExpensesPart is a helper function for makeGroupByFieldsPart. + // It prepares the part when a custom field is selected. + static function makeSingleDropdownGroupByCustomFieldExpensesPart($dropdown_value) { + global $custom_fields; + + // Iterate through user custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($dropdown_value == $field_name) { + if ($userField['type'] == CustomFields::TYPE_TEXT) { + return (", ecf".$userField['id'].".value as $field_name"); + } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { + return (", cfo".$userField['id'].".value as $field_name"); + } + } + } + } + // Iterate through time custom fields. + if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $field_name = 'time_field_'.$timeField['id']; + if ($dropdown_value == $field_name) { + return (", null as $field_name"); + } + } + } + return null; + } + // makeGroupByFieldsPart builds a list of fields for sql query for time items using group_by1, // group_by2, and group_by3 values passed in $options. static function makeGroupByFieldsPart($options) { @@ -1855,6 +1891,17 @@ static function makeGroupByFieldsPart($options) { return $group_by_fields_parts; } + // makeGroupByFieldsExpensesPart builds a list of fields for sql query for expense items using group_by1, + // group_by2, and group_by3 values passed in $options. + static function makeGroupByFieldsExpensesPart($options) { + if (!ttReportHelper::grouping($options)) return null; + + $group_by_fields_parts .= ttReportHelper::makeSingleDropdownGroupByFieldExpensesPart($options['group_by1'], $options); + $group_by_fields_parts .= ttReportHelper::makeSingleDropdownGroupByFieldExpensesPart($options['group_by2'], $options); + $group_by_fields_parts .= ttReportHelper::makeSingleDropdownGroupByFieldExpensesPart($options['group_by3'], $options); + return $group_by_fields_parts; + } + // makeConcatPart builds a concatenation part for getSubtotals query (for time items). static function makeConcatPart($options) { if (!ttReportHelper::grouping($options)) return null; @@ -1863,85 +1910,64 @@ static function makeConcatPart($options) { $concat_part .= ttReportHelper::makeSingleDropdownConcatPart($options['group_by2'], $options); $concat_part .= ttReportHelper::makeSingleDropdownConcatPart($options['group_by3'], $options); // Remove garbage from the beginning. - $concat_part = trim($concat_part, "', -"); + if (ttStartsWith($concat_part, ", ' - ', ")) + $concat_part = substr($concat_part, 9); $concat_part = "concat($concat_part) as group_field"; return $concat_part; } + // makeSingleDropdownConcatExpensesPart is a helper function for makeConcatExpensesPart. + // It make a concatenation part for getSubtotals query for expense items + // corresponding to a single dropdown control. + static function makeSingleDropdownConcatExpensesPart($dropdown_value, $options) { + if ($dropdown_value == null || $dropdown_value == 'no_grouping') + return null; + if ('date' == $dropdown_value) + return (", ' - ', ei.date"); + if ('user' == $dropdown_value) + return (", ' - ', u.name"); + if ('client' == $dropdown_value) + return (", ' - ', coalesce(c.name, 'Null')"); + if ('project' == $dropdown_value) + return (", ' - ', coalesce(p.name, 'Null')"); + if ('task' == $dropdown_value) + return (", ' - ', 'Null'"); + if (ttReportHelper::groupingBy($dropdown_value, $options)) { + return ttReportHelper::makeSingleDropdownConcatCustomFieldExpensesPart($dropdown_value); + } + } + // makeConcatPart builds a concatenation part for getSubtotals query (for expense items). static function makeConcatExpensesPart($options) { - $group_by1 = $options['group_by1']; - $group_by2 = $options['group_by2']; - $group_by3 = $options['group_by3']; + if (!ttReportHelper::grouping($options)) return null; - switch ($group_by1) { - case 'date': - $what_to_concat .= ", ' - ', ei.date"; - break; - case 'user': - $what_to_concat .= ", ' - ', u.name"; - $fields_part .= ', u.name as user'; - break; - case 'client': - $what_to_concat .= ", ' - ', coalesce(c.name, 'Null')"; - $fields_part .= ', c.name as client'; - break; - case 'project': - $what_to_concat .= ", ' - ', coalesce(p.name, 'Null')"; - $fields_part .= ', p.name as project'; - break; - case 'task': - $what_to_concat .= ", ' - ', 'Null'"; - $fields_part .= ', null as task'; - break; - } - switch ($group_by2) { - case 'date': - $what_to_concat .= ", ' - ', ei.date"; - break; - case 'user': - $what_to_concat .= ", ' - ', u.name"; - $fields_part .= ', u.name as user'; - break; - case 'client': - $what_to_concat .= ", ' - ', coalesce(c.name, 'Null')"; - $fields_part .= ', c.name as client'; - break; - case 'project': - $what_to_concat .= ", ' - ', coalesce(p.name, 'Null')"; - $fields_part .= ', p.name as project'; - break; - case 'task': - $what_to_concat .= ", ' - ', 'Null'"; - $fields_part .= ', null as task'; - break; - } - switch ($group_by3) { - case 'date': - $what_to_concat .= ", ' - ', ei.date"; - break; - case 'user': - $what_to_concat .= ", ' - ', u.name"; - $fields_part .= ', u.name as user'; - break; - case 'client': - $what_to_concat .= ", ' - ', coalesce(c.name, 'Null')"; - $fields_part .= ', c.name as client'; - break; - case 'project': - $what_to_concat .= ", ' - ', coalesce(p.name, 'Null')"; - $fields_part .= ', p.name as project'; - break; - case 'task': - $what_to_concat .= ", ' - ', 'Null'"; - $fields_part .= ', null as task'; - break; - } + $concat_part .= ttReportHelper::makeSingleDropdownConcatExpensesPart($options['group_by1'], $options); + $concat_part .= ttReportHelper::makeSingleDropdownConcatExpensesPart($options['group_by2'], $options); + $concat_part .= ttReportHelper::makeSingleDropdownConcatExpensesPart($options['group_by3'], $options); // Remove garbage from the beginning. - if ($what_to_concat) - $what_to_concat = substr($what_to_concat, 8); - $concat_part = "concat($what_to_concat) as group_field"; - return "$concat_part $fields_part"; + if (ttStartsWith($concat_part, ", ' - ', ")) + $concat_part = substr($concat_part, 9); + $concat_part = "concat($concat_part) as group_field"; + return $concat_part; + } + + // makeSingleDropdownGroupByFieldExpensesPart is a helper function for makeGroupByFieldsExpensesPart. + // It make a fields part for getSubtotals query for expense items + // corresponding to a single group by dropdown control. + static function makeSingleDropdownGroupByFieldExpensesPart($dropdown_value, $options) { + if ($dropdown_value == null || $dropdown_value == 'no_grouping') + return null; + if ('user' == $dropdown_value) + return (', u.name as user'); + if ('client' == $dropdown_value) + return (', c.name as client'); + if ('project' == $dropdown_value) + return (', p.name as project'); + if ('task' == $dropdown_value) + return (', null as task'); + if (ttReportHelper::groupingBy($dropdown_value, $options)) { + return ttReportHelper::makeSingleDropdownGroupByCustomFieldExpensesPart($dropdown_value); + } } // makeCombinedSelectPart builds a list of fields for a combined select on a union for getSubtotals. @@ -2137,7 +2163,7 @@ static function makeJoinExpensesPart($options) { $field_name = 'user_field_'.$userField['id']; $field_value = $options[$field_name]; $entity_type = CustomFields::ENTITY_USER; - if ($field_value) { + if ($field_value || ttReportHelper::groupingBy($field_name, $options)) { // We need to add left joins when input is not null. $ecfTable = 'ecf'.$userField['id']; if ($userField['type'] == CustomFields::TYPE_TEXT) { diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index a0bfa83b9..2f7b9a148 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} {if $show_start} - {/if} {if $show_duration} diff --git a/expense_delete.php b/expense_delete.php index 788fb59fa..7ecd2c6d3 100644 --- a/expense_delete.php +++ b/expense_delete.php @@ -1,30 +1,6 @@ assign('expense_item', $expense_item); $smarty->assign('show_project', $show_project); $smarty->assign('title', $i18n->get('title.delete_expense')); -$smarty->assign('content_page_name', 'expense_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'expense_delete2.tpl'); +$smarty->display('index2.tpl'); diff --git a/expense_delete1.php b/expense_delete1.php new file mode 100644 index 000000000..788fb59fa --- /dev/null +++ b/expense_delete1.php @@ -0,0 +1,88 @@ +isPluginEnabled('ex')) { + header('Location: feature_disabled.php'); + exit(); +} +$cl_id = (int)$request->getParameter('id'); +// Get the expense item we are deleting. +$expense_item = ttExpenseHelper::getItem($cl_id); +if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { + // Prohibit deleting not ours, approved, or invoiced items. + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +if ($request->isPost()) { + if ($request->getParameter('delete_button')) { // Delete button pressed. + + // Determine if it is okay to delete the record. + $item_date = new DateAndTime(DB_DATEFORMAT, $expense_item['date']); + if ($user->isDateLocked($item_date)) + $err->add($i18n->get('error.range_locked')); + + if ($err->no()) { + // Mark the record as deleted. + if (ttExpenseHelper::markDeleted($cl_id)) { + header('Location: expenses.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } + } + if ($request->getParameter('cancel_button')) { // Cancel button pressed. + header('Location: expenses.php'); + exit(); + } +} // isPost + +$form = new Form('expenseItemForm'); +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); +$form->addInput(array('type'=>'submit','name'=>'delete_button','value'=>$i18n->get('label.delete'))); +$form->addInput(array('type'=>'submit','name'=>'cancel_button','value'=>$i18n->get('button.cancel'))); + +$show_project = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); + +$smarty->assign('forms', array($form->getName() => $form->toArray())); +$smarty->assign('expense_item', $expense_item); +$smarty->assign('show_project', $show_project); +$smarty->assign('title', $i18n->get('title.delete_expense')); +$smarty->assign('content_page_name', 'expense_delete.tpl'); +$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index 6fb811b4d..e6fc238e5 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5362"); +define("APP_VERSION", "1.19.23.5363"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From d9d5c3b7106cdefa4d56826658308f15a233a5b2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 21:47:35 +0000 Subject: [PATCH 108/587] Made expense_edit.php mobile-friendly. --- WEB-INF/templates/expense_edit2.tpl | 186 +++++++++++++++++++++ WEB-INF/templates/expenses2.tpl | 4 +- expense_edit.php | 44 +---- expense_edit1.php | 243 ++++++++++++++++++++++++++++ initialize.php | 2 +- 5 files changed, 440 insertions(+), 39 deletions(-) create mode 100644 WEB-INF/templates/expense_edit2.tpl create mode 100644 expense_edit1.php diff --git a/WEB-INF/templates/expense_edit2.tpl b/WEB-INF/templates/expense_edit2.tpl new file mode 100644 index 000000000..3cea79482 --- /dev/null +++ b/WEB-INF/templates/expense_edit2.tpl @@ -0,0 +1,186 @@ + + +{$forms.expenseItemForm.open} +
Anuko Time Tracker 1.19.23.5276 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5277 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From 5e8379fccfbc3a20fb6653b64278000f59638f89 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 23 Aug 2020 23:37:29 +0000 Subject: [PATCH 009/587] Fixed totals only reports when grouping by time custom fields to eliminate multiple rows. --- WEB-INF/lib/ttReportHelper.class.php | 6 +++--- WEB-INF/templates/footer.tpl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index 655b32ab3..0a1f4b803 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -701,7 +701,7 @@ static function getSubtotals($options) { $combined .= ", sum(cost) as cost, sum(expenses) as expenses from (($sql) union all ($sql_for_expenses)) t group by $fields"; $sql = $combined; } - +//die($sql); // Execute query. $res = $mdb2->query($sql); if (is_a($res, 'PEAR_Error')) die($res->getMessage()); @@ -2059,11 +2059,11 @@ static function makeJoinPart($options) { $cflTable = 'cfl'.$timeField['id']; if ($timeField['type'] == CustomFields::TYPE_TEXT) { // Add one join for each text field. - $left_joins .= " left join tt_custom_field_log $cflTable on ($cflTable.log_id = l.id and $cflTable.status = 1)"; + $left_joins .= " left join tt_custom_field_log $cflTable on ($cflTable.log_id = l.id and $cflTable.status = 1 and $cflTable.field_id = ".$timeField['id'].")"; } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { $cfoTable = 'cfo'.$timeField['id']; // Add two joins for each dropdown field. - $left_joins .= " left join tt_custom_field_log $cflTable on ($cflTable.log_id = l.id and $cflTable.status = 1)"; + $left_joins .= " left join tt_custom_field_log $cflTable on ($cflTable.log_id = l.id and $cflTable.status = 1 and $cflTable.field_id = ".$timeField['id'].")"; $left_joins .= " left join tt_custom_field_options $cfoTable on ($cfoTable.field_id = $cflTable.field_id and $cfoTable.id = $cflTable.option_id)"; } } diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 2f7b9a148..1e95b9a39 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} - + + + - + + {if $custom_fields && $custom_fields->userFields} {foreach $custom_fields->userFields as $userField} diff --git a/initialize.php b/initialize.php index 32ba423e9..c50180255 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5351"); +define("APP_VERSION", "1.19.23.5352"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From c1be12e38a181c77447056040d1cfdda6a2dc7bb Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 7 Nov 2020 15:54:26 +0000 Subject: [PATCH 097/587] Made user_edit.php mobile friendly. --- WEB-INF/templates/user_add2.tpl | 23 ++- WEB-INF/templates/user_edit2.tpl | 202 ++++++++++++++++++++ initialize.php | 2 +- user_edit.php | 39 +--- user_edit1.php | 308 +++++++++++++++++++++++++++++++ 5 files changed, 529 insertions(+), 45 deletions(-) create mode 100644 WEB-INF/templates/user_edit2.tpl create mode 100644 user_edit1.php diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index b1ae40d1b..370fb08f3 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -68,7 +68,6 @@ function handleClientControl() { {$forms.userForm.open} -{$forms.projectForm.open}
Anuko Time Tracker 1.19.23.5277 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5278 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From ffb49a46ad93331209e9286ba38ebe8cbf5bff63 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 27 Aug 2020 13:04:10 +0000 Subject: [PATCH 010/587] Fixed headers in totals only reports when grouping by custom fields. --- WEB-INF/lib/ttReportHelper.class.php | 50 +++++++++++++++++++++++----- WEB-INF/templates/footer.tpl | 2 +- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index 0a1f4b803..c48cfb265 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -2199,12 +2199,47 @@ static function groupingBy($what, $options) { return $grouping; } - // makeGroupByHeader builds a column header for a totals-only report using group_by1, - // group_by2, and group_by3 values passed in $options. - static function makeGroupByHeader($options) { + // makeGroupByHeaderdPart is a helper function for makeGroupByHeader. + // It obtains a part of the header associated with a single group by dropdown. + static function makeGroupByHeaderPart($dropdown_value) { global $i18n; global $custom_fields; + // First, try to get a label from a translation file, which is the most likely scenario + // such as grouping by date, user, project, or task. + $key = 'label.'.$dropdown_value; + $part = $i18n->get($key); + if ($part) return $part; + + // If label is not found in translation file, we may be grouping by a custom field. + // Obtain custom field label if so. + + // Process time custom fields. + if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $field_name = 'time_field_'.$timeField['id']; + if ($dropdown_value == $field_name) { + return $timeField['label']; + } + } + } + // Process user custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($dropdown_value == $field_name) { + return $userField['label']; + } + } + } + + // Return null if nothing is found. + return null; + } + + // makeGroupByHeader builds a column header for a totals-only report using group_by1, + // group_by2, and group_by3 values passed in $options. + static function makeGroupByHeader($options) { $no_grouping = ($options['group_by1'] == null || $options['group_by1'] == 'no_grouping') && ($options['group_by2'] == null || $options['group_by2'] == 'no_grouping') && ($options['group_by3'] == null || $options['group_by3'] == 'no_grouping'); @@ -2213,20 +2248,17 @@ static function makeGroupByHeader($options) { if ($options['group_by1'] != null && $options['group_by1'] != 'no_grouping') { // We have group_by1. $group_by1 = $options['group_by1']; - $key = 'label.'.$group_by1; - $group_by_header .= ' - '.$i18n->get($key); + $group_by_header .= ' - '.ttReportHelper::makeGroupByHeaderPart($group_by1); } if ($options['group_by2'] != null && $options['group_by2'] != 'no_grouping') { // We have group_by2. $group_by2 = $options['group_by2']; - $key = 'label.'.$group_by2; - $group_by_header .= ' - '.$i18n->get($key); + $group_by_header .= ' - '.ttReportHelper::makeGroupByHeaderPart($group_by2); } if ($options['group_by3'] != null && $options['group_by3'] != 'no_grouping') { // We have group_by3. $group_by3 = $options['group_by3']; - $key = 'label.'.$group_by3; - $group_by_header .= ' - '.$i18n->get($key); + $group_by_header .= ' - '.ttReportHelper::makeGroupByHeaderPart($group_by3); } $group_by_header = ltrim($group_by_header, ' -'); return $group_by_header; diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 1e95b9a39..e50ec2e1e 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {if $work_item.can_edit} - + {else} {/if} {if $work_item.can_delete} - + {else} {/if} @@ -92,8 +92,8 @@ - - + + {/foreach}
Anuko Time Tracker 1.19.23.5278 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5279 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From 265283090e39161683fb68690ce30b27a0475bf8 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 27 Aug 2020 14:24:49 +0000 Subject: [PATCH 011/587] Cosmetic improvment in comment. --- WEB-INF/lib/ttReportHelper.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index c48cfb265..e090af6f4 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -665,6 +665,9 @@ static function getFromSession() { // getSubtotals calculates report items subtotals when a report is grouped by. // Without expenses, it's a simple select with group by. // With expenses, it becomes a select with group by from a combined set of records obtained with "union all". + // getSubtotals uses helper functions such as makeConcatPart and others to get parts to assemble an sql query from. + // Query may become quite complex depending on $options, whether custom fields are used, etc. + // This is the reason for having individual functions for parts (to keep getSubtotals easier to manage). static function getSubtotals($options) { global $user; $mdb2 = getConnection(); @@ -701,7 +704,7 @@ static function getSubtotals($options) { $combined .= ", sum(cost) as cost, sum(expenses) as expenses from (($sql) union all ($sql_for_expenses)) t group by $fields"; $sql = $combined; } -//die($sql); + // Execute query. $res = $mdb2->query($sql); if (is_a($res, 'PEAR_Error')) die($res->getMessage()); From 369d91a563b2d0812c2f8271be8a26024607100e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 31 Aug 2020 22:49:10 +0000 Subject: [PATCH 012/587] Cosmetic link fix. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 70fd57398..f3b7987ef 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Anuko [Time Tracker](https://www.anuko.com/time-tracker/index.htm) is a simple, easy to use, open source, web-based time tracking application written in PHP. It allows you to track the time that employees or colleagues spend working on projects and tasks. It needs a web server such as Apache, IIS, etc. to run on, and a database to keep the data in, such as MySQL. ## Free Hosting -[Anuko](https://www.anuko.com) provides [free hosting](https://www.anuko.com/time_tracker/free_hosting/index.htm) of Time Tracker to individuals and small groups up to 5 users. To start using Time Tracker immediately, create a group at https://timetracker.anuko.com +[Anuko](https://www.anuko.com) provides [free hosting](https://www.anuko.com/time-tracker/free-hosting/index.htm) of Time Tracker to individuals and small groups up to 5 users. To start using Time Tracker immediately, create a group at https://timetracker.anuko.com ## Resources * Project home page: https://www.anuko.com/time-tracker/index.htm From dcd9548e4ac0b5b307a3427361d7508a2119a3d2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 3 Sep 2020 18:20:53 +0000 Subject: [PATCH 013/587] Refactored password_reset.php for consistency of success and error messages display. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/password_reset.tpl | 6 ------ password_reset.php | 16 +++++++++------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index e50ec2e1e..bb92ff430 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - - + + {/foreach}
Anuko Time Tracker 1.19.23.5279 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5280 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/password_reset.tpl b/WEB-INF/templates/password_reset.tpl index 93c5d49db..a8dadf957 100644 --- a/WEB-INF/templates/password_reset.tpl +++ b/WEB-INF/templates/password_reset.tpl @@ -2,11 +2,6 @@
-{if $result_message} - - -
{$result_message}
-{else} @@ -20,7 +15,6 @@
{$i18n.label.login}:{$forms.resetPasswordForm.btn_submit.control}
-{/if}
diff --git a/password_reset.php b/password_reset.php index bbb54adb5..8e3badbc4 100644 --- a/password_reset.php +++ b/password_reset.php @@ -88,10 +88,10 @@ if ($receiver) { import('mail.Mailer'); - $sender = new Mailer(); - $sender->setCharSet(CHARSET); - $sender->setSender(SENDER); - $sender->setReceiver("$receiver"); + $mailer = new Mailer(); + $mailer->setCharSet(CHARSET); + $mailer->setSender(SENDER); + $mailer->setReceiver("$receiver"); if ((!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] !== 'off')) || ($_SERVER['SERVER_PORT'] == 443)) $secure_connection = true; if($secure_connection) @@ -105,9 +105,11 @@ else $pass_edit_url = $http.'://'.$_SERVER['HTTP_HOST'].'/password_change.php?ref='.$temp_ref; - $sender->setMailMode(MAIL_MODE); - $res = $sender->send($cl_subject, sprintf($user_i18n->get('form.reset_password.email_body'), $_SERVER['REMOTE_ADDR'], $pass_edit_url)); - $smarty->assign('result_message', $res ? $i18n->get('form.reset_password.message') : $i18n->get('error.mail_send')); + $mailer->setMailMode(MAIL_MODE); + if ($mailer->send($cl_subject, sprintf($user_i18n->get('form.reset_password.email_body'), $_SERVER['REMOTE_ADDR'], $pass_edit_url))) + $msg->add($i18n->get('form.reset_password.message')); + else + $err->add($i18n->get('error.mail_send')); } } } // isPost From b5170d623c7f174639586e9ed3f4dd6b6323dac4 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 7 Sep 2020 16:29:57 +0000 Subject: [PATCH 014/587] Introduced a configurable php session cookie name. --- WEB-INF/config.php.dist | 8 +++++++- WEB-INF/templates/footer.tpl | 2 +- initialize.php | 9 ++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 89cbd3965..89ec98a1a 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -71,9 +71,15 @@ define('DIR_NAME', ''); define('WEEKEND_START_DAY', 6); +// SESSION_COOKIE_NAME +// +// PHP session cookie name. +// define('SESSION_COOKIE_NAME', 'tt_PHPSESSID'); + + // PHPSESSID_TTL // -// Lifetime in seconds for tt_PHPSESSID cookie. Time to live is extended by this value +// Lifetime in seconds for session cookie. Time to live is extended by this value // with each visit to the site so that users don't have to re-login. // define('PHPSESSID_TTL', 86400); // diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index bb92ff430..1604f7e48 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} {if $u.group_id != $user->group_id || $u.rank < $user->rank || ($u.rank == $user->rank && $u.id == $user->id)} - - {if $u.id != $user->id}{else}{/if} + + {if $u.id != $user->id}{else}{/if} {else} @@ -76,8 +76,8 @@ {/if} {if $u.group_id != $user->group_id || $u.rank < $user->rank} - - + + {else} diff --git a/WEB-INF/templates/week.tpl b/WEB-INF/templates/week.tpl index 9d3ef0bf2..92ce31d92 100644 --- a/WEB-INF/templates/week.tpl +++ b/WEB-INF/templates/week.tpl @@ -149,23 +149,23 @@ function fillDropdowns() { {if $show_files} {if $record.has_files} - + {else} - + {/if} {/if} diff --git a/WEB-INF/templates/work/admin_work.tpl b/WEB-INF/templates/work/admin_work.tpl index 929b4d619..13f37e911 100644 --- a/WEB-INF/templates/work/admin_work.tpl +++ b/WEB-INF/templates/work/admin_work.tpl @@ -22,8 +22,8 @@ - - + + {/foreach}
Anuko Time Tracker 1.19.23.5280 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5281 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/initialize.php b/initialize.php index a1393f6e6..b4f8e2aa4 100644 --- a/initialize.php +++ b/initialize.php @@ -90,16 +90,19 @@ ini_set('session.gc_probability', 1); } +// "tt_" prefix is to avoid sharing session with other PHP apps that do not name session. +if (!defined('SESSION_COOKIE_NAME')) define('SESSION_COOKIE_NAME', 'tt_PHPSESSID'); + // Set session cookie lifetime. session_set_cookie_params($phpsessid_ttl); -if (isset($_COOKIE['tt_PHPSESSID'])) { +if (isset($_COOKIE[SESSION_COOKIE_NAME])) { // Extend PHP session cookie lifetime by PHPSESSID_TTL (if defined, otherwise 24 hours) // so that users don't have to re-login during this period from now. - setcookie('tt_PHPSESSID', $_COOKIE['tt_PHPSESSID'], time() + $phpsessid_ttl, '/'); + setcookie(SESSION_COOKIE_NAME, $_COOKIE[SESSION_COOKIE_NAME], time() + $phpsessid_ttl, '/'); } // Start or resume PHP session. -session_name('tt_PHPSESSID'); // "tt_" prefix is to avoid sharing session with other PHP apps that do not name session. +session_name(SESSION_COOKIE_NAME); @session_start(); // Authorization. From 47c8e993fe8947e44c61aff455881f2b400ce705 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 7 Sep 2020 17:05:38 +0000 Subject: [PATCH 015/587] Introduced a configurable login cookie name. --- WEB-INF/config.php.dist | 8 +++++++- WEB-INF/lib/Auth.class.php | 2 +- WEB-INF/templates/footer.tpl | 2 +- initialize.php | 1 + login.php | 4 ++-- mobile/login.php | 4 ++-- mobile/user_delete.php | 6 +++--- mobile/user_edit.php | 8 ++++---- password_change.php | 2 +- register.php | 2 +- user_delete.php | 6 +++--- user_edit.php | 8 ++++---- 12 files changed, 30 insertions(+), 23 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 89ec98a1a..4db71fad4 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -73,7 +73,7 @@ define('WEEKEND_START_DAY', 6); // SESSION_COOKIE_NAME // -// PHP session cookie name. +// PHP session cookie name. // define('SESSION_COOKIE_NAME', 'tt_PHPSESSID'); @@ -93,6 +93,12 @@ define('WEEKEND_START_DAY', 6); // define('PHP_SESSION_PATH', '/tmp/timetracker'); // Directory must exist and be writable. +// LOGIN_COOKIE_NAME +// +// Cookie name for user login to remember it between browser sessions. +// define('LOGIN_COOKIE_NAME', 'tt_login'); + + // Forum and help links from the main menu. // define('FORUM_LINK', 'https://www.anuko.com/forum/viewforum.php?f=4'); diff --git a/WEB-INF/lib/Auth.class.php b/WEB-INF/lib/Auth.class.php index ecb48340b..ccf2d915d 100644 --- a/WEB-INF/lib/Auth.class.php +++ b/WEB-INF/lib/Auth.class.php @@ -32,7 +32,7 @@ class Auth { function isAuthenticated() { if (isset($_SESSION['authenticated'])) { // This check does not work properly because we are not getting here. Need to improve. -// if (!isset($_COOKIE['tt_login'])) { +// if (!isset($_COOKIE[LOGIN_COOKIE_NAME])) { // die ("Your browser's cookie functionality is turned off. Please turn it on."); // } diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 1604f7e48..46628ad7b 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- + {else} - + {/if} {/if} - - + + {/foreach}
Anuko Time Tracker 1.19.23.5281 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5282 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/initialize.php b/initialize.php index b4f8e2aa4..4c526a13b 100644 --- a/initialize.php +++ b/initialize.php @@ -92,6 +92,7 @@ // "tt_" prefix is to avoid sharing session with other PHP apps that do not name session. if (!defined('SESSION_COOKIE_NAME')) define('SESSION_COOKIE_NAME', 'tt_PHPSESSID'); +if (!defined('LOGIN_COOKIE_NAME')) define('LOGIN_COOKIE_NAME', 'tt_login'); // Set session cookie lifetime. session_set_cookie_params($phpsessid_ttl); diff --git a/login.php b/login.php index 8185203a3..705692045 100644 --- a/login.php +++ b/login.php @@ -32,7 +32,7 @@ import('ttUser'); $cl_login = $request->getParameter('login'); -if ($cl_login == null && $request->isGet()) $cl_login = @$_COOKIE['tt_login']; +if ($cl_login == null && $request->isGet()) $cl_login = @$_COOKIE[LOGIN_COOKIE_NAME]; $cl_password = $request->getParameter('password'); $form = new Form('loginForm'); @@ -58,7 +58,7 @@ $_SESSION['date'] = $current_user_date; // Remember user login in a cookie. - setcookie('tt_login', $cl_login, time() + COOKIE_EXPIRE, '/'); + setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); $user = new ttUser(null, $auth->getUserId()); // Redirect, depending on user role. diff --git a/mobile/login.php b/mobile/login.php index a432e5b60..fb574767a 100644 --- a/mobile/login.php +++ b/mobile/login.php @@ -34,7 +34,7 @@ if ($request->isPost()) { $cl_login = $request->getParameter('login'); } else { - $cl_login = @$_COOKIE['tt_login']; + $cl_login = @$_COOKIE[LOGIN_COOKIE_NAME]; } $cl_password = $request->getParameter('password'); @@ -63,7 +63,7 @@ $_SESSION['date'] = $current_user_date; // Remember user login in a cookie. - setcookie('tt_login', $cl_login, time() + COOKIE_EXPIRE, '/'); + setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); $user = new ttUser(null, $auth->getUserId()); // Redirect, depending on user role. diff --git a/mobile/user_delete.php b/mobile/user_delete.php index e44483ecc..132f73022 100644 --- a/mobile/user_delete.php +++ b/mobile/user_delete.php @@ -61,9 +61,9 @@ } // If we deleted our own account, do housekeeping and logout. if ($user->id == $user_id) { - // Remove tt_login cookie that stores login name. - unset($_COOKIE['tt_login']); - setcookie('tt_login', NULL, -1); + // Remove LOGIN_COOKIE_NAME cookie that stores login name. + unset($_COOKIE[LOGIN_COOKIE_NAME]); + setcookie(LOGIN_COOKIE_NAME, NULL, -1); $auth->doLogout(); header('Location: login.php'); diff --git a/mobile/user_edit.php b/mobile/user_edit.php index 411586bda..58de5e8ab 100644 --- a/mobile/user_edit.php +++ b/mobile/user_edit.php @@ -195,7 +195,7 @@ function render(&$table, $value, $row, $column, $selected = false) { // If our own login changed, set new one in cookie to remember it. if (($user_id == $user->id) && ($user->login != $cl_login)) { - setcookie('tt_login', $cl_login, time() + COOKIE_EXPIRE, '/'); + setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); } // In case the name of the "on behalf" user has changed - set it in session. @@ -205,9 +205,9 @@ function render(&$table, $value, $row, $column, $selected = false) { // If we deactivated our own account, do housekeeping and logout. if ($user->id == $user_id && !is_null($cl_status) && $cl_status == INACTIVE) { - // Remove tt_login cookie that stores login name. - unset($_COOKIE['tt_login']); - setcookie('tt_login', NULL, -1); + // Remove LOGIN_COOKIE_NAME cookie that stores login name. + unset($_COOKIE[LOGIN_COOKIE_NAME]); + setcookie(LOGIN_COOKIE_NAME, NULL, -1); $auth->doLogout(); header('Location: login.php'); diff --git a/password_change.php b/password_change.php index cefc30e5f..5fea82629 100644 --- a/password_change.php +++ b/password_change.php @@ -83,7 +83,7 @@ ttUserHelper::setPassword($user_id, $cl_password1); if ($auth->doLogin($user->login, $cl_password1)) { - setcookie('tt_login', $user->login, time() + COOKIE_EXPIRE, '/'); + setcookie(LOGIN_COOKIE_NAME, $user->login, time() + COOKIE_EXPIRE, '/'); // Redirect, depending on user role. if ($user->can('administer_site')) { header('Location: admin_groups.php'); diff --git a/register.php b/register.php index 0c0374b33..47f3b406e 100644 --- a/register.php +++ b/register.php @@ -106,7 +106,7 @@ if ($err->no()) { // Registration successful. if ($auth->doLogin($cl_manager_login, $cl_password1)) { - setcookie('tt_login', $cl_manager_login, time() + COOKIE_EXPIRE, '/'); + setcookie(LOGIN_COOKIE_NAME, $cl_manager_login, time() + COOKIE_EXPIRE, '/'); header('Location: time.php'); } else { header('Location: login.php'); diff --git a/user_delete.php b/user_delete.php index 38d4f5424..24f84010f 100644 --- a/user_delete.php +++ b/user_delete.php @@ -61,9 +61,9 @@ } // If we deleted our own account, do housekeeping and logout. if ($user->id == $user_id) { - // Remove tt_login cookie that stores login name. - unset($_COOKIE['tt_login']); - setcookie('tt_login', NULL, -1); + // Remove LOGIN_COOKIE_NAME cookie that stores login name. + unset($_COOKIE[LOGIN_COOKIE_NAME]); + setcookie(LOGIN_COOKIE_NAME, NULL, -1); $auth->doLogout(); header('Location: login.php'); diff --git a/user_edit.php b/user_edit.php index 195e87a34..d74ae2785 100644 --- a/user_edit.php +++ b/user_edit.php @@ -256,7 +256,7 @@ function render(&$table, $value, $row, $column, $selected = false) { if ($result) { // If our own login changed, set new one in cookie to remember it. if (($user_id == $user->id) && ($user->login != $cl_login)) { - setcookie('tt_login', $cl_login, time() + COOKIE_EXPIRE, '/'); + setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); } // In case the name of the "on behalf" user has changed - set it in session. @@ -266,9 +266,9 @@ function render(&$table, $value, $row, $column, $selected = false) { // If we deactivated our own account, do housekeeping and logout. if ($user->id == $user_id && !is_null($cl_status) && $cl_status == INACTIVE) { - // Remove tt_login cookie that stores login name. - unset($_COOKIE['tt_login']); - setcookie('tt_login', NULL, -1); + // Remove LOGIN_COOKIE_NAME cookie that stores login name. + unset($_COOKIE[LOGIN_COOKIE_NAME]); + setcookie(LOGIN_COOKIE_NAME, NULL, -1); $auth->doLogout(); header('Location: login.php'); From c5fa0dcd085fc5d8cc669dcedd892c3d405c3523 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 7 Sep 2020 20:06:05 +0000 Subject: [PATCH 016/587] Fixed double-encoding of special characters on tme_delete pages. --- WEB-INF/templates/footer.tpl | 2 +- mobile/time_delete.php | 3 --- time_delete.php | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 46628ad7b..c59aa67dd 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- + {else} - + {/if} {/if} diff --git a/WEB-INF/templates/timesheets.tpl b/WEB-INF/templates/timesheets.tpl index 237eb98be..318702a71 100644 --- a/WEB-INF/templates/timesheets.tpl +++ b/WEB-INF/templates/timesheets.tpl @@ -40,13 +40,13 @@ {/if} {if $show_files} {if $timesheet.has_files} - + {else} - + {/if} {/if} - - + + {/foreach}
Anuko Time Tracker 1.19.23.5282 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5283 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/mobile/time_delete.php b/mobile/time_delete.php index c8e692534..e80c5c733 100644 --- a/mobile/time_delete.php +++ b/mobile/time_delete.php @@ -49,9 +49,6 @@ $trackingMode = $user->getTrackingMode(); $showProject = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; -// Escape comment for presentation. -$time_rec['comment'] = htmlspecialchars($time_rec['comment']); - if ($request->isPost()) { if ($request->getParameter('delete_button')) { // Delete button pressed. diff --git a/time_delete.php b/time_delete.php index c953bb95e..9cbed727e 100644 --- a/time_delete.php +++ b/time_delete.php @@ -53,9 +53,6 @@ $showStart = TYPE_START_FINISH == $recordType || TYPE_ALL == $recordType; $showDuration = TYPE_DURATION == $recordType || TYPE_ALL == $recordType; -// Escape comment for presentation. -$time_rec['comment'] = htmlspecialchars($time_rec['comment']); - if ($request->isPost()) { if ($request->getParameter('delete_button')) { // Delete button pressed. From 437760730a94f54222ad2f3e64f5151e1ba20a1c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 7 Sep 2020 21:47:48 +0000 Subject: [PATCH 017/587] Removed no longer needed files. --- WEB-INF/templates/table_test.tpl | 12 ---- table_test.php | 118 ------------------------------- 2 files changed, 130 deletions(-) delete mode 100644 WEB-INF/templates/table_test.tpl delete mode 100644 table_test.php diff --git a/WEB-INF/templates/table_test.tpl b/WEB-INF/templates/table_test.tpl deleted file mode 100644 index cf7e4b2ba..000000000 --- a/WEB-INF/templates/table_test.tpl +++ /dev/null @@ -1,12 +0,0 @@ -{$forms.weekTimeForm.open} - - - - -
{$forms.weekTimeForm.week_durations.control}
- - - - -
{$forms.weekTimeForm.btn_submit.control}
-{$forms.weekTimeForm.close} diff --git a/table_test.php b/table_test.php deleted file mode 100644 index 7cd5cda35..000000000 --- a/table_test.php +++ /dev/null @@ -1,118 +0,0 @@ - 'something goes here too', // Row ideentifier. - 'label' => 'This is a label for row 0', - 'day_0' => array('id' => '0_0', 'duration' => '00:00'), - 'day_1' => array('id' => '0_1', 'duration' => '01:00'), - 'day_2' => array('id' => '0_2', 'duration' => '02:00'), - 'day_3' => array('id' => '0_3', 'duration' => null), - 'day_4' => array('id' => '0_4', 'duration' => '04:00') - ), - array( // Row 1. - 'label' => 'This is a label for row 1', - 'day_0' => array('id' => '1_0', 'duration' => '00:30'), - 'day_1' => array('id' => '1_1', 'duration' => '01:30'), - 'day_2' => array('id' => '1_2', 'duration' => '02:30'), - ) -); - -$totals = array( - 'label' => 'Total:', - 'day_0' => '00:30', - 'day_1' => '02:30', - 'day_2' => '04:30', - 'day_3' => null, - 'day_4' => '04:00', - 'day_5' => null, - 'day_6' => null -); - -// Define rendering class for a label field to the left of durations. -class LabelCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200,'valign'=>'middle')); - $this->setValue(htmlspecialchars($value)); - return $this->toString(); - } -} - -// Define rendering class for a single cell for time entry in week view table. -class TimeCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - $field_name = $table->getValueAt($row,$column)['id']; // Our text field names (and ids) are like x_y (row_column). - $field = new TextField($field_name); - $field->setFormName($table->getFormName()); - $field->setSize(2); - $field->setValue($table->getValueAt($row,$column)['duration']); - $this->setValue($field->getHtml()); - return $this->toString(); - } -} - -// Elements of weekTimeForm. -$form = new Form('weekTimeForm'); - -// Create week_durations table. -$table = new Table('week_durations'); -// $table->setIAScript('markModified'); // TODO: write a script to mark table or particular cells as modified. -$table->setTableOptions(array('width'=>'100%','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); -$table->setData($durations_with_labels); -// Add columns to table. -$table->addColumn(new TableColumn('label', '', new LabelCellRenderer(), $totals['label'])); -$table->addColumn(new TableColumn('day_0', 'day 0', new TimeCellRenderer(), $totals['day_0'])); -$table->addColumn(new TableColumn('day_1', 'day 1', new TimeCellRenderer(), $totals['day_1'])); -$table->addColumn(new TableColumn('day_2', 'day 2', new TimeCellRenderer(), $totals['day_2'])); -$table->addColumn(new TableColumn('day_3', 'day 3', new TimeCellRenderer(), $totals['day_3'])); -$table->addColumn(new TableColumn('day_4', 'day 4', new TimeCellRenderer(), $totals['day_4'])); -$table->addColumn(new TableColumn('day_5', 'day 5', new TimeCellRenderer())); -$table->addColumn(new TableColumn('day_6', 'day 6', new TimeCellRenderer())); -$table->setInteractive(false); -$form->addInputElement($table); - -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.submit'))); - -// Submit. -if ($request->isPost()) { - if ($request->getParameter('btn_submit')) { - } -} - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('title', $i18n->get('title.time')); -$smarty->assign('content_page_name', 'table_test.tpl'); -$smarty->display('index.tpl'); From 80a4772c2f46c88432215e83fdf11fc77084f694 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 14 Sep 2020 16:08:23 +0000 Subject: [PATCH 018/587] Cosmetic maintenance improvement. --- WEB-INF/lib/ttOrgHelper.class.php | 20 +++++++++++++++++++- WEB-INF/templates/footer.tpl | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/WEB-INF/lib/ttOrgHelper.class.php b/WEB-INF/lib/ttOrgHelper.class.php index ffb39beb4..81169032a 100644 --- a/WEB-INF/lib/ttOrgHelper.class.php +++ b/WEB-INF/lib/ttOrgHelper.class.php @@ -68,10 +68,28 @@ static function getInactiveOrgs() { $inactive_orgs = array(); $mdb2 = getConnection(); + // Construct $org_sizes_part (if we have to). + $sql = "show tables like 'org_sizes'"; + $res = $mdb2->query($sql); + if (!is_a($res, 'PEAR_Error') && $res->fetchRow()) { + // org_sizes table exist. + $sql = "select org_id from org_sizes order by org_id"; + $res = $mdb2->query($sql); + if (!is_a($res, 'PEAR_Error')) { + while ($val = $res->fetchRow()) { + $orgs_to_ignore[] = $val['org_id']; + } + $comma_separated = implode(',', $orgs_to_ignore); + if ($comma_separated) { + $org_sizes_part = " and org_id not in ($comma_separated)"; + } + } + } + // Determine inactive organizations by querying the database for max access timestamp for its users. $cutoff_timestamp = $mdb2->quote(date('Y-m-d', strtotime('-1 year'))); $sql = "select org_id from". - " (select max(accessed) as last_access, org_id from tt_users where org_id > 0 group by org_id order by last_access, org_id) as t". + " (select max(accessed) as last_access, org_id from tt_users where org_id > 0".$org_sizes_part." group by org_id order by last_access, org_id) as t". " where last_access is null or last_access < $cutoff_timestamp limit 50"; // Max 50 orgs at a time for now... $res = $mdb2->query($sql); if (!is_a($res, 'PEAR_Error')) { diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index c59aa67dd..a7126d9e5 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- diff --git a/mobile/time.php b/mobile/time.php index 1cda7fb63..0bdfcfaa4 100644 --- a/mobile/time.php +++ b/mobile/time.php @@ -392,6 +392,7 @@ $smarty->assign('next_date', $next_date); $smarty->assign('prev_date', $prev_date); $smarty->assign('day_total', ttTimeHelper::getTimeForDay($cl_date)); +$smarty->assign('week_total', ttTimeHelper::getTimeForWeek($selected_date)); $smarty->assign('time_records', ttTimeHelper::getRecords($cl_date)); $smarty->assign('show_client', $showClient); $smarty->assign('show_billable', $showBillable); From 699d0753f8a1315bf03ee061ec1e15612a65cabf Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 17 Sep 2020 17:02:13 +0000 Subject: [PATCH 020/587] Added a display option controlling whether to show custom fields in the list of records for each day. --- WEB-INF/templates/display_options.tpl | 3 +++ WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/time.tpl | 12 ++++++++++++ display_options.php | 4 ++++ time.php | 7 +++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/WEB-INF/templates/display_options.tpl b/WEB-INF/templates/display_options.tpl index f41bd6f58..025b7d984 100644 --- a/WEB-INF/templates/display_options.tpl +++ b/WEB-INF/templates/display_options.tpl @@ -11,6 +11,9 @@ + + + diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 1a38b304f..3c8cdf7fd 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5283 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5284 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From dbaa1e2d8b7a838da612fb8aa060c09c688969f3 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 14 Sep 2020 19:21:29 +0000 Subject: [PATCH 019/587] Added week total on mobile time.php. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/mobile/time.tpl | 4 ++++ mobile/time.php | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index a7126d9e5..1a38b304f 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- + + + +
Anuko Time Tracker 1.19.23.5284 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5285 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/mobile/time.tpl b/WEB-INF/templates/mobile/time.tpl index 5be118c69..3c9d4276c 100644 --- a/WEB-INF/templates/mobile/time.tpl +++ b/WEB-INF/templates/mobile/time.tpl @@ -35,6 +35,10 @@ {$i18n.label.day_total}: {$day_total}
{$i18n.label.week_total}:{$week_total}
{/if}
{$forms.displayOptionsForm.time_not_complete_days.control} {$i18n.label.what_is_it}
{$forms.displayOptionsForm.record_custom_fields.control} {$i18n.label.what_is_it}
 
{$i18n.title.reports}
- {/if} + {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + + {/foreach} + {/if} {if $show_project} {/if} @@ -139,6 +144,13 @@ {if $show_client} {/if} + {* record custom fileds *} + {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + {assign var="control_name" value='time_field_'|cat:$timeField['id']} + + {/foreach} + {/if} {if $show_project} {/if} diff --git a/display_options.php b/display_options.php index a4d3deacb..8df3ba2b2 100644 --- a/display_options.php +++ b/display_options.php @@ -42,11 +42,13 @@ if ($request->isPost()) { $cl_time_note_on_separate_row = $request->getParameter('time_note_on_separate_row'); $cl_time_not_complete_days = $request->getParameter('time_not_complete_days'); + $cl_record_custom_fields = $request->getParameter('record_custom_fields'); $cl_report_note_on_separate_row = $request->getParameter('report_note_on_separate_row'); $cl_custom_css = trim($request->getParameter('custom_css')); } else { $cl_time_note_on_separate_row = $config->getDefinedValue('time_note_on_separate_row'); $cl_time_not_complete_days = $config->getDefinedValue('time_not_complete_days'); + $cl_record_custom_fields = $config->getDefinedValue('record_custom_fields'); $cl_report_note_on_separate_row = $config->getDefinedValue('report_note_on_separate_row'); $cl_custom_css = $user->getCustomCss(); } @@ -63,6 +65,7 @@ // $form->addInput(array('type'=>'checkbox','name'=>'time_note','value'=>$cl_time_note)); $form->addInput(array('type'=>'checkbox','name'=>'time_note_on_separate_row','value'=>$cl_time_note_on_separate_row)); $form->addInput(array('type'=>'checkbox','name'=>'time_not_complete_days','value'=>$cl_time_not_complete_days)); +$form->addInput(array('type'=>'checkbox','name'=>'record_custom_fields','value'=>$cl_record_custom_fields)); // TODO: consider adding other fields (timesheet, work_units, invoice, approved, cost, paid)? // Reports. @@ -81,6 +84,7 @@ // Update config. $config->setDefinedValue('time_note_on_separate_row', $cl_time_note_on_separate_row); $config->setDefinedValue('time_not_complete_days', $cl_time_not_complete_days); + $config->setDefinedValue('record_custom_fields', $cl_record_custom_fields); $config->setDefinedValue('report_note_on_separate_row', $cl_report_note_on_separate_row); if ($user->updateGroup(array( 'config' => $config->getConfig(), diff --git a/time.php b/time.php index e375e8425..b249f05b7 100644 --- a/time.php +++ b/time.php @@ -79,6 +79,7 @@ $showStart = TYPE_START_FINISH == $recordType || TYPE_ALL == $recordType; $showDuration = TYPE_DURATION == $recordType || TYPE_ALL == $recordType; $showFiles = $user->isPluginEnabled('at'); +$showRecordCustomFields = $user->isOptionEnabled('record_custom_fields'); // Initialize and store date in session. $cl_date = $request->getParameter('date', @$_SESSION['date']); @@ -102,6 +103,11 @@ // Determine column span for note field. $colspan = 0; if ($showClient) $colspan++; + if ($showRecordCustomFields && $custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $colspan++; + } + } if ($showProject) $colspan++; if ($showTask) $colspan++; if ($showStart) $colspan++; @@ -477,6 +483,7 @@ $smarty->assign('week_total', $week_total); $smarty->assign('day_total', ttTimeHelper::getTimeForDay($cl_date)); $smarty->assign('time_records', $timeRecords); +$smarty->assign('show_record_custom_fields', $showRecordCustomFields); $smarty->assign('show_navigation', $user->isPluginEnabled('wv') && !$user->isOptionEnabled('week_menu')); $smarty->assign('show_client', $showClient); $smarty->assign('show_billable', $showBillable); From dc3f6787167d402b56748ed9369efab5a0650adb Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 17 Sep 2020 19:03:28 +0000 Subject: [PATCH 021/587] Fixed column span for reports with show note on separate row option. --- WEB-INF/templates/footer.tpl | 2 +- report.php | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 3c8cdf7fd..21b8924ca 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5285 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5286 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/time.tpl b/WEB-INF/templates/time.tpl index d0121d0ee..be0299a48 100644 --- a/WEB-INF/templates/time.tpl +++ b/WEB-INF/templates/time.tpl @@ -114,6 +114,11 @@ {if $show_client} {$i18n.label.client}{$timeField['label']|escape}{$i18n.label.project}{$record.client|escape}{$record.$control_name|escape}{$record.project|escape}
- - - + + {/foreach}
Anuko Time Tracker 1.19.23.5286 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5287 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/report.php b/report.php index da035fca7..539a897c7 100644 --- a/report.php +++ b/report.php @@ -286,11 +286,23 @@ $totals = ttReportHelper::getTotals($options); // Determine column span for note field. -$colspan = 1; +$colspan = 0; if ($user->can('view_reports') || $user->can('view_all_reports') || $user->isClient()) $colspan++; +if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $checkbox_control_name = 'show_user_field_'.$userField['id']; + if ($bean->getAttribute($checkbox_control_name)) $colspan++; + } +} if ($bean->getAttribute('chclient')) $colspan++; if ($bean->getAttribute('chproject')) $colspan++; if ($bean->getAttribute('chtask')) $colspan++; +if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $checkbox_control_name = 'show_time_field_'.$timeField['id']; + if ($bean->getAttribute($checkbox_control_name)) $colspan++; + } +} if ($bean->getAttribute('chstart')) $colspan++; if ($bean->getAttribute('chfinish')) $colspan++; if ($bean->getAttribute('chduration')) $colspan++; From 0e59ca83782ca8de51829b1ec4081976a639d43b Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 24 Sep 2020 13:01:03 +0000 Subject: [PATCH 022/587] Introduced label.menu in translation files. --- WEB-INF/resources/ca.lang.php | 2 +- WEB-INF/resources/cs.lang.php | 2 +- WEB-INF/resources/da.lang.php | 3 ++- WEB-INF/resources/de.lang.php | 4 ++-- WEB-INF/resources/en.lang.php | 2 +- WEB-INF/resources/es.lang.php | 2 +- WEB-INF/resources/et.lang.php | 3 ++- WEB-INF/resources/fa.lang.php | 3 ++- WEB-INF/resources/fi.lang.php | 3 ++- WEB-INF/resources/fr.lang.php | 3 ++- WEB-INF/resources/gr.lang.php | 3 ++- WEB-INF/resources/he.lang.php | 3 ++- WEB-INF/resources/hu.lang.php | 2 +- WEB-INF/resources/it.lang.php | 3 ++- WEB-INF/resources/ja.lang.php | 2 +- WEB-INF/resources/ko.lang.php | 2 +- WEB-INF/resources/nl.lang.php | 3 ++- WEB-INF/resources/no.lang.php | 2 +- WEB-INF/resources/pl.lang.php | 3 ++- WEB-INF/resources/pt-br.lang.php | 3 ++- WEB-INF/resources/pt.lang.php | 2 +- WEB-INF/resources/ro.lang.php | 2 +- WEB-INF/resources/ru.lang.php | 2 +- WEB-INF/resources/sk.lang.php | 3 ++- WEB-INF/resources/sl.lang.php | 2 +- WEB-INF/resources/sr.lang.php | 3 ++- WEB-INF/resources/sv.lang.php | 3 ++- WEB-INF/resources/tr.lang.php | 2 +- WEB-INF/resources/zh-cn.lang.php | 3 ++- WEB-INF/resources/zh-tw.lang.php | 2 +- WEB-INF/templates/footer.tpl | 2 +- 31 files changed, 47 insertions(+), 32 deletions(-) diff --git a/WEB-INF/resources/ca.lang.php b/WEB-INF/resources/ca.lang.php index c6195cccc..de6e0df96 100644 --- a/WEB-INF/resources/ca.lang.php +++ b/WEB-INF/resources/ca.lang.php @@ -157,6 +157,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => 'Moneda', @@ -704,7 +705,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/cs.lang.php b/WEB-INF/resources/cs.lang.php index daefafebf..92411b33b 100644 --- a/WEB-INF/resources/cs.lang.php +++ b/WEB-INF/resources/cs.lang.php @@ -159,6 +159,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => 'Měna', @@ -717,7 +718,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 23c5df739..3ab49c39e 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -152,6 +152,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Team navn', // TODO: replace "team" with "group". 'label.address' => 'Adresse', 'label.currency' => 'Valuta', @@ -679,7 +681,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index 482f42bcb..7db6f93bb 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -149,6 +149,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Gruppenname', 'label.address' => 'Adresse', 'label.currency' => 'Währung', @@ -655,8 +657,6 @@ // 'form.timesheet_view.disapprove_body' => "Your timesheet %s was not approved.

%s", // Display Options form. See example at https://timetracker.anuko.com/display_options.php. -// TODO: translate the following. -// 'form.display_options.menu' => 'Menu', 'form.display_options.note_on_separate_row' => 'Beschreibung in separater Zeile', // TODO: translate the following. // 'form.display_options.not_complete_days' => 'Not complete days', diff --git a/WEB-INF/resources/en.lang.php b/WEB-INF/resources/en.lang.php index 5003f5b16..b052ec602 100644 --- a/WEB-INF/resources/en.lang.php +++ b/WEB-INF/resources/en.lang.php @@ -145,6 +145,7 @@ 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +'label.menu' => 'Menu', 'label.group_name' => 'Group name', 'label.address' => 'Address', 'label.currency' => 'Currency', @@ -635,7 +636,6 @@ 'form.timesheet_view.disapprove_body' => "Your timesheet %s was not approved.

%s", // Display Options form. See example at https://timetracker.anuko.com/display_options.php. -'form.display_options.menu' => 'Menu', 'form.display_options.note_on_separate_row' => 'Note on separate row', 'form.display_options.not_complete_days' => 'Not complete days', 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index 0136a9db0..0c1d2c6b9 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -156,6 +156,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', 'label.address' => 'Dirección', 'label.currency' => 'Moneda', @@ -719,7 +720,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index 433ed64d3..b6b442441 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -164,6 +164,8 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Grupi nimi', 'label.address' => 'Aadress', 'label.currency' => 'Valuuta', @@ -687,7 +689,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/fa.lang.php b/WEB-INF/resources/fa.lang.php index 3b767ea8d..35fb9feff 100644 --- a/WEB-INF/resources/fa.lang.php +++ b/WEB-INF/resources/fa.lang.php @@ -160,6 +160,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'نام تیم', // TODO: replace "team" with "group". 'label.address' => 'آدرس', 'label.currency' => 'واحد پول', @@ -703,7 +705,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index f895b34b2..753dcf8ce 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -154,6 +154,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Tiimin nimi', // TODO: replace "team" with "group". 'label.address' => 'Osoite', 'label.currency' => 'Valuutta', @@ -685,7 +687,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index 06b0550be..ca00e9471 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -152,6 +152,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Nom équipe', // TODO: replace "team" with "group". 'label.address' => 'Adresse', 'label.currency' => 'Devise', @@ -675,7 +677,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index dc921299e..ba630f269 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -148,6 +148,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Όνομα ομάδας', 'label.address' => 'Διεύθυνση', 'label.currency' => 'Νόμισμα', @@ -668,7 +670,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index f082be589..296e82b1b 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -168,6 +168,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'שם הצוות', // TODO: replace "team" with "group". 'label.address' => 'כתובת', 'label.currency' => 'מטבע', @@ -704,7 +706,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index 02b1ef081..6328f330f 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -160,6 +160,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => 'Pénznem', @@ -709,7 +710,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/it.lang.php b/WEB-INF/resources/it.lang.php index f4c30d7cc..e3bc6a31d 100644 --- a/WEB-INF/resources/it.lang.php +++ b/WEB-INF/resources/it.lang.php @@ -152,6 +152,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Nome del gruppo', 'label.address' => 'Indirizzo', 'label.currency' => 'Moneta', @@ -682,7 +684,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index 0808b0bd2..26d222ebd 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -163,6 +163,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => '通貨', @@ -712,7 +713,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index b92b05304..fbfd6794b 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -162,6 +162,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => '화폐', @@ -710,7 +711,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 35955b252..7ce3b19c0 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -151,6 +151,8 @@ 'button.disapprove' => 'Afkeuren', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Groepsnaam', 'label.address' => 'Adres', 'label.currency' => 'Munteenheid', @@ -639,7 +641,6 @@ 'form.timesheet_view.disapprove_body' => "Jouw tijdenoverzicht %s is afgekeurd.

%s", // Display Options form. See example at https://timetracker.anuko.com/display_options.php. -'form.display_options.menu' => 'Menu', 'form.display_options.note_on_separate_row' => 'Notitie in aparte kolom', // TODO: translate the following. // 'form.display_options.not_complete_days' => 'Not complete days', diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index dc6ffa1f6..81aff4489 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -162,6 +162,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => 'Valuta', @@ -709,7 +710,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index 1c3c51dcd..2000584e9 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -156,6 +156,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Nazwa zespołu', // TODO: replace "team" with "group". 'label.address' => 'Adres', 'label.currency' => 'Waluta', @@ -688,7 +690,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index bcf76ad7f..61afec796 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -153,6 +153,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Nome da equipe', // TODO: replace "team" with "group". 'label.address' => 'Endereço', 'label.currency' => 'Moeda', @@ -683,7 +685,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index f607279b4..b4aa0cc02 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -155,6 +155,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', // 'label.currency' => 'Currency', @@ -691,7 +692,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index 3014652df..419b26467 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -162,6 +162,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => 'Moneda', @@ -712,7 +713,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index 8d11e2bcd..49ee3edeb 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -136,6 +136,7 @@ 'button.disapprove' => 'Не одобрить', // Labels for controls on forms. Labels in this section are used on multiple forms. +'label.menu' => 'Меню', 'label.group_name' => 'Название группы', 'label.address' => 'Адрес', 'label.currency' => 'Валюта', @@ -616,7 +617,6 @@ 'form.timesheet_view.disapprove_body' => "Ваш табель %s не одобрен.

%s", // Display Options form. See example at https://timetracker.anuko.com/display_options.php. -'form.display_options.menu' => 'Меню', 'form.display_options.note_on_separate_row' => 'Комментарий в отдельном ряду', 'form.display_options.not_complete_days' => 'Незавершенные дни', 'form.display_options.custom_css' => 'Пользовательская CSS', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index e6f76e279..eceb1e521 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -158,6 +158,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Názov tímu', // TODO: replace "team" with "group". 'label.address' => 'Adresa', 'label.currency' => 'Mena', @@ -693,7 +695,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index ce46d71a5..8ee642e54 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -152,6 +152,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', // 'label.currency' => 'Currency', @@ -685,7 +686,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index be48065bc..8bc2e7223 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -153,6 +153,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Naziv tim-a', // TODO: replace "team" with "group". 'label.address' => 'Adresa', 'label.currency' => 'Valuta', @@ -686,7 +688,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index de3b37b04..dd3981f36 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -152,6 +152,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => 'Namn på grupp', 'label.address' => 'Adress', 'label.currency' => 'Valuta', @@ -684,7 +686,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index cb7e4ab91..9475ad0d2 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -166,6 +166,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => 'Para birimi', @@ -725,7 +726,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index cc186b6bf..ed76b599a 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -154,6 +154,8 @@ // 'button.disapprove' => 'Disapprove', // Labels for controls on forms. Labels in this section are used on multiple forms. +// TODO: translate the following. +// 'label.menu' => 'Menu', 'label.group_name' => '团队名称', // TODO: replace "team" with "group". // TODO: translate the following. // 'label.address' => 'Address', @@ -696,7 +698,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/resources/zh-tw.lang.php b/WEB-INF/resources/zh-tw.lang.php index bd10eecc4..913c12cf1 100644 --- a/WEB-INF/resources/zh-tw.lang.php +++ b/WEB-INF/resources/zh-tw.lang.php @@ -159,6 +159,7 @@ // Labels for controls on forms. Labels in this section are used on multiple forms. // TODO: translate the following. +// 'label.menu' => 'Menu', // 'label.group_name' => 'Group name', // 'label.address' => 'Address', 'label.currency' => '貨幣', @@ -702,7 +703,6 @@ // Display Options form. See example at https://timetracker.anuko.com/display_options.php. // TODO: translate the following. -// 'form.display_options.menu' => 'Menu', // 'form.display_options.note_on_separate_row' => 'Note on separate row', // 'form.display_options.not_complete_days' => 'Not complete days', // 'form.display_options.custom_css' => 'Custom CSS', diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 21b8924ca..bf3ff0991 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - - + + {/foreach}
Anuko Time Tracker 1.19.23.5287 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5288 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} From b482d50d4e04e6a5e5e65b6e7142db1f084c9dce Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 24 Sep 2020 15:25:32 +0000 Subject: [PATCH 023/587] Starting work on improving presentation on mobile screens. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 7 ++ WEB-INF/templates/header2.tpl | 191 ++++++++++++++++++++++++++++++++++ WEB-INF/templates/index2.tpl | 5 + rtl.css | 14 ++- 5 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 WEB-INF/templates/footer2.tpl create mode 100644 WEB-INF/templates/header2.tpl create mode 100644 WEB-INF/templates/index2.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index bf3ff0991..4e07aa67a 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - - + + {/foreach} {/if} @@ -60,8 +60,8 @@ - - + + {/foreach}
Anuko Time Tracker 1.19.23.5288 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5289 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl new file mode 100644 index 000000000..9d3b69616 --- /dev/null +++ b/WEB-INF/templates/footer2.tpl @@ -0,0 +1,7 @@ + {* page-content *} + + + + + + diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl new file mode 100644 index 000000000..d887e22a6 --- /dev/null +++ b/WEB-INF/templates/header2.tpl @@ -0,0 +1,191 @@ + + + + + + + + +{if $i18n.language.rtl} + +{/if} +{if $user->getCustomCss()} + +{/if} + Time Tracker{if $title} - {$title}{/if} + + + + + + + + + +{* top menu for small screens *} + +{* end of top menu for small screens *} + +{* top menu for large screens *} +{if $authenticated} + {if $user->can('administer_site')} + {* top menu for admin *} + + {* end of top menu for admin *} + + {* sub menu for admin *} +
+ + + + + {if isTrue('WORK_SERVER_ADMINISTRATION')} + + {/if} + +
{$i18n.menu.groups}{$i18n.menu.options}{$i18n.label.work}
+
+ {* end of sub menu for admin *} + {else} + {* top menu for authorized user *} +
+ + + + {if $user->exists() && $user->can('manage_own_settings')} + + {/if} + {if $user->can('manage_basic_settings')} + + {/if} + {if $user->can('manage_features')} + + {/if} + + + +
{$i18n.menu.logout}{$i18n.menu.profile}{$i18n.menu.group}{$i18n.menu.plugins}{$i18n.menu.forum}{$i18n.menu.help}
+
+ {* end of top menu for authorized user *} + + {* sub menu for authorized user *} +
+ + + {if $user->exists() && ($user->can('track_own_time') || $user->can('track_time'))} + + {if $user->isPluginEnabled('wv') && $user->isOptionEnabled('week_menu')} + + {/if} + {/if} + {if $user->exists() && $user->isPluginEnabled('ex') && ($user->can('track_own_expenses') || $user->can('track_expenses'))} + + {/if} + {if $user->exists() && ($user->can('view_own_reports') || $user->can('view_reports') || $user->can('view_all_reports') || $user->can('view_client_reports'))} + + {/if} + {if $user->exists() && $user->isPluginEnabled('ts') && ($user->can('track_own_time') || $user->can('track_time'))} + + {/if} + {if $user->exists() && $user->isPluginEnabled('iv') && ($user->can('manage_invoices') || $user->can('view_client_invoices'))} + + {/if} + {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && + ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() || + $user->isPluginEnabled('cl'))} + + {/if} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + + {/if} + {if ($smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} + + {/if} + {if $user->can('view_users') || $user->can('manage_users')} + + {/if} + {if $user->isPluginEnabled('cl') && ($user->can('view_own_clients') || $user->can('manage_clients'))} + + {/if} + {if $user->isPluginEnabled('wk') && ($user->can('update_work') || $user->can('bid_on_work') || $user->can('manage_work')) && $user->exists()} + + {/if} + {if $user->can('export_data')} + + {/if} + +
{$i18n.menu.time}{$i18n.menu.week}{$i18n.menu.expenses}{$i18n.menu.reports}{$i18n.menu.timesheets}{$i18n.title.invoices}{$i18n.menu.charts}{$i18n.menu.projects}{$i18n.menu.tasks}{$i18n.menu.users}{$i18n.menu.clients}{$i18n.title.work}{$i18n.menu.export}
+
+ {* end of sub menu for authorized user *} + {/if} +{else} + {* top menu for non authorized user *} +
+ + + + {if isTrue('MULTIORG_MODE') && $smarty.const.AUTH_MODULE == 'db'} + + {/if} + + + +
{$i18n.menu.login}{$i18n.menu.register}{$i18n.menu.forum}{$i18n.menu.help}
+
+{/if} +{* end of top menu for large screens *} + +{* page title and user details *} +{if $title} +
{$title}{if $timestring}: {$timestring}{/if}
+ {if $authenticated} +
{$user->getUserPartForHeader()}
{* No need to escape as it is done in the class. *} + {/if} +{/if} +{* end of page title and user details *} + +{* output errors *} +{if $err->yes()} +
+ {foreach $err->getErrors() as $error} +{$error.message}
{* No need to escape as they are not coming from user and may contain a link. *} + {/foreach} +
+{/if} +{* end of output errors *} + +{* output messages *} +{if $msg->yes()} +
+ {foreach $msg->getErrors() as $message} +{$message.message}
{* No need to escape. *} + {/foreach} +
+{/if} +{* end of output messages *} + +
\ No newline at end of file diff --git a/WEB-INF/templates/index2.tpl b/WEB-INF/templates/index2.tpl new file mode 100644 index 000000000..410a7616a --- /dev/null +++ b/WEB-INF/templates/index2.tpl @@ -0,0 +1,5 @@ +{include file="header2.tpl"} + +{if $content_page_name}{include file="$content_page_name"}{/if} + +{include file="footer2.tpl"} diff --git a/rtl.css b/rtl.css index ede511c8e..5688a2823 100644 --- a/rtl.css +++ b/rtl.css @@ -2,4 +2,16 @@ html { direction: rtl; -} \ No newline at end of file +} + +.large-screen-label { + text-align: left; +} + +.small-screen-label { + text-align: right; +} + +.td-with-input { + text-align: right; +} From bb8dacfd02940c68b9529a78787e52132b25714a Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 24 Sep 2020 16:16:07 +0000 Subject: [PATCH 024/587] Some initial work on mobile styles. --- WEB-INF/templates/header2.tpl | 4 +- WEB-INF/templates/site_map.tpl | 90 +++++++ default2.css | 428 +++++++++++++++++++++++++++++++++ login.php | 11 +- site_map.php | 41 ++++ 5 files changed, 570 insertions(+), 4 deletions(-) create mode 100644 WEB-INF/templates/site_map.tpl create mode 100644 default2.css create mode 100644 site_map.php diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl index d887e22a6..4af0ef8af 100644 --- a/WEB-INF/templates/header2.tpl +++ b/WEB-INF/templates/header2.tpl @@ -5,7 +5,7 @@ - + {if $i18n.language.rtl} {/if} @@ -27,7 +27,7 @@ {if $user->custom_logo} Time Tracker {else} - Anuko Time Tracker + Anuko Time Tracker {/if}
diff --git a/WEB-INF/templates/site_map.tpl b/WEB-INF/templates/site_map.tpl new file mode 100644 index 000000000..695a99093 --- /dev/null +++ b/WEB-INF/templates/site_map.tpl @@ -0,0 +1,90 @@ +{if $authenticated} + {if $user->can('administer_site')} + {* sub menu for admin *} +

+ {$i18n.menu.groups}
+ {$i18n.menu.options}
+ {if isTrue('WORK_SERVER_ADMINISTRATION')} + {$i18n.label.work}
+ {/if} +

+ {* end of sub menu for admin *} + {* main menu for admin *} +

+ {$i18n.menu.logout}
+ {$i18n.menu.forum}
+ {$i18n.menu.help}
+

+ {* end of main menu for admin *} + {else} + {* sub menu for authorized user *} +

+ {if $user->exists() && ($user->can('track_own_time') || $user->can('track_time'))} + {$i18n.menu.time}
+ {if $user->isPluginEnabled('wv') && $user->isOptionEnabled('week_menu')} + {$i18n.menu.week}
+ {/if} + {/if} + {if $user->exists() && $user->isPluginEnabled('ex') && ($user->can('track_own_expenses') || $user->can('track_expenses'))} + {$i18n.menu.expenses}
+ {/if} + {if $user->exists() && ($user->can('view_own_reports') || $user->can('view_reports') || $user->can('view_all_reports') || $user->can('view_client_reports'))} + {$i18n.menu.reports}
+ {/if} + {if $user->exists() && $user->isPluginEnabled('ts') && ($user->can('track_own_time') || $user->can('track_time'))} + {$i18n.menu.timesheets}
+ {/if} + {if $user->exists() && $user->isPluginEnabled('iv') && ($user->can('manage_invoices') || $user->can('view_client_invoices'))} + {$i18n.title.invoices}
+ {/if} + {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && + ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() || + $user->isPluginEnabled('cl'))} + {$i18n.menu.charts}
+ {/if} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + {$i18n.menu.projects}
+ {/if} + {if ($smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} + {$i18n.menu.tasks}
+ {/if} + {if $user->can('view_users') || $user->can('manage_users')} + {$i18n.menu.users}
+ {/if} + {if $user->isPluginEnabled('cl') && ($user->can('view_own_clients') || $user->can('manage_clients'))} + {$i18n.menu.clients}
+ {/if} + {if $user->can('export_data')} + {$i18n.menu.export}
+ {/if} +

+ {* end of sub menu for authorized user *} + {* main menu for authorized user *} +

+ {$i18n.menu.logout}
+ {if $user->exists() && $user->can('manage_own_settings')} + {$i18n.menu.profile}
+ {/if} + {if $user->can('manage_basic_settings')} + {$i18n.menu.group}
+ {/if} + {if $user->can('manage_features')} + {$i18n.menu.plugins}
+ {/if} + {$i18n.menu.forum}
+ {$i18n.menu.help}
+

+ {* end of main menu for authorized user *} + {/if} +{else} + {* main menu for non authorized user *} +

+ {$i18n.menu.login}
+ {if isTrue('MULTIORG_MODE') && $smarty.const.AUTH_MODULE == 'db'} + {$i18n.menu.register}
+ {/if} + {$i18n.menu.forum}
+ {$i18n.menu.help}
+

+ {* end of main menu for non authorized user *} +{/if} diff --git a/default2.css b/default2.css new file mode 100644 index 000000000..a5536914e --- /dev/null +++ b/default2.css @@ -0,0 +1,428 @@ +body { + margin: 0px; + font-size: 10pt; + font-family: Verdana, sans-serif; + background-color: white; +} + +div.logo { + padding: .5rem; + text-align: center; + background-color: #a6ccf7; +} + +div.top-menu-large-screen { + background-color: black; + display: block; +} + +.top-submenu-large-screen { + background-color: #d9d9d9; + display: block; +} + +div.top-menu-small-screen { + background-color: black; + display: none; +} + +div.top-menu-small-screen a { + font-size: 1rem; + font-weight: bold; + color: white; + margin: .1rem .2rem .1rem .2rem; +} + +div.top-menu-large-screen a { + font-size: 1rem; + font-weight: bold; + color: white; + margin: .1rem .2rem .1rem .2rem; +} + +.top-menu-table { + margin-left: auto; + margin-right: auto; +} + +.top-submenu-table { + margin-left: auto; + margin-right: auto; +} + +.top-submenu-large-screen a { + font-size: 1rem; + color: #444444; + margin: .1rem .2rem .1rem .2rem; +} + +div.page-title { + font-size: 12pt; + font-weight: bold; + color: silver; + text-align: center; + padding: .25rem; + border-bottom: 1px solid lightgray; + margin-bottom: .2rem; +} + +div.user-details { + text-align: center; + padding: .2rem; +} + +.page-errors { + margin-top: .5rem; + text-align: center; + color: red; +} + +.page-content { + text-align: center; +} + +.form-control-separator { + height: .5rem; +} + +div#LoginAboutText { + padding: 1rem; + margin-left:auto; + margin-right:auto; +} + +#ldapDefaultDomain { + color: #777777; +} + +div.page-hint { + margin-top: 1rem; +} + +.centered-table { + margin-top: .5rem; + margin-left: auto; + margin-right: auto; + display: inline-block; +} + +.large-screen-label { + text-align: right; + vertical-align: middle; + display: table-cell; +} + +.small-screen-label { + text-align: left; + display: none; +} + +.small-screen-form-control-separator { + height: .25rem; + display: none; +} + +.page-content input { + border-radius: 4px; + border: 1px solid #c9c9c9; + padding: .4rem; +} + +.td-with-input { + text-align: left; +} + +.page-content input:focus { + background-color: yellow; + border: 1px solid black; + outline: none; +} + + +@media screen and (max-width: 600px) { + + .large-screen-label { + display: none; + } + + .small-screen-label { + display: block; + } + + .small-screen-form-control-separator { + display: block; + } +} + + + + + + +.contribute-msg { + text-align: center; + padding: .2rem; + background-color: #eeeeee; +} + +.version-and-copyright { + text-align: center; + padding: .5rem; +} + + +@media screen and (max-width: 1170px) { + div.top-menu-small-screen { + display: block; + } + + div.top-menu-large-screen { + display: none; + } + + div.top-submenu-large-screen { + display: none; + } +} + + + + + + + + + + +a { color: blue; text-decoration: none; } + +a:visited { text-decoration: none; } + +a:hover { text-decoration: underline; } + +html { + overflow-y: scroll; +} + +table { font-size: 10pt; font-family: Verdana, sans-serif; } + +input, button, select, textarea { + font-size: 10pt; + font-family: Verdana, sans-serif; + margin: 2px 2px 2px 2px; + padding: 2px 5px 2px 5px; +} + +input[type=checkbox], label { + vertical-align: middle; +} + +.pageTitle { + font-size: 12pt; + font-weight: bold; + color: silver; +} + +.systemMenu { + font-size: 1rem; + font-weight: bold; + color: white; + background-color: black; + margin: .1rem .2rem .1rem .2rem; +} + +.mainMenu { + font-size: 1rem; + color: #444444; + margin: .1rem .2rem .1rem .2rem; +} + +.onBehalf { + font-weight: bold; +} + +/* calendar styles */ +.calendarHeader { + padding: 5px; + font-size: 8pt; + color: #333333; + background-color: #d9d9d9; +} + +.calendarDay { + padding: 5px; + border: 1px solid silver; + font-size: 8pt; + color: #333333; + background-color: #ffffff; +} + +.calendarDaySelected { + padding: 5px; + border: 1px solid silver; + font-size: 8pt; + color: #666666; + background-color: #a6ccf7; +} + +.calendarDayWeekend { + padding: 5px; + border: 1px solid silver; + font-size: 8pt; + color: #666666; + background-color: #f7f7f7; +} + +.calendarDayHoliday { + padding: 5px; + border: 1px solid silver; + font-size: 8pt; + color: #666666; + background-color: #f7f7f7; +} + +.calendarDayHeader { + padding: 5px; + border: 1px solid white; + font-size: 8pt; + color: #333333; +} + +.calendarDayHeaderWeekend { + padding: 5px; + border: 1px solid white; + font-size: 8pt; + color: #999999; +} + +.calendarLinkWeekend { + color: #999999; +} + +.calendarLinkHoliday { + color: #999999; +} + +.calendarLinkRecordsExist { + color: #ff0000; +} + +.calendarLinkNonCompleteDay { + color: #800080; +} +/* end of calendar styles */ + +.tableHeader { + font-weight: bold; + text-align: left; +} + +.tableHeaderCentered { + font-weight: bold; + text-align: center; +} + +.rowReportItem { + background-color: #f5f5f5; +} + +.rowReportItemAlt { + background-color: #ffffff; +} + +.rowReportSubtotal { + background-color: #e0e0e0; +} + +.cellLeftAligned { + text-align: left; + vertical-align: top; +} + +.cellRightAligned { + text-align: right; + vertical-align: top; +} + +.cellLeftAlignedSubtotal { + font-weight: bold; + vertical-align: top; +} + +.cellRightAlignedSubtotal { + font-weight: bold; + text-align: right; + vertical-align: top; +} + +.midAligned { + text-align: center; +} + +.sectionHeader { + font-weight: bold; + border-bottom: 1px solid lightgray; +} + +.sectionHeaderNoBorder { + font-weight: bold; +} + +.error { + color: red; +} + +.info_message { + color: #0000c0; +} + +.divider { + background-color: #efefef; +} + +div.table-divider { height: 30px; } + +.uncompleted-entry { + display: inline-block; + height: 8px; + width: 8px; + border: 1px solid rgba(0, 0, 0, .1); + border-radius: 50%; + background-color: rgba(0, 0, 0, .1); +} +.uncompleted-entry.active { background-color: red; } + +.table_icon { + height: 16px; + width: 16px; +} + +/* Mobile styles */ +.mobile-table { + border: 0; + width: 100%; + border-spacing: 0; +} + +.mobile-textarea { + width: 100%; + resize: vertical; + height: 5em; +} + +.mobile-input { + width: 100%; +} + +.mobile-table-details { + width: 100%; + table-layout: fixed; + overflow-wrap: break-word; + word-wrap: break-word; + border-spacing: 1px; + border: 0; +} + +.mobile-table-details td { + padding: 3px; +} diff --git a/login.php b/login.php index 705692045..ac506fccc 100644 --- a/login.php +++ b/login.php @@ -85,6 +85,13 @@ $smarty->assign('show_hint', $show_hint); $smarty->assign('onload', 'onLoad="document.loginForm.'.(!$cl_login?'login':'password').'.focus()"'); $smarty->assign('title', $i18n->get('title.login')); -$smarty->assign('content_page_name', 'login.tpl'); +if (defined('DEBUG_MOBILE')) + $smarty->assign('content_page_name', 'login2.tpl'); +else { + $smarty->assign('content_page_name', 'login.tpl'); +} $smarty->assign('about_text', $i18n->get('form.login.about')); -$smarty->display('index.tpl'); +if (defined('DEBUG_MOBILE')) + $smarty->display('index2.tpl'); +else + $smarty->display('index.tpl'); diff --git a/site_map.php b/site_map.php new file mode 100644 index 000000000..05c6172a8 --- /dev/null +++ b/site_map.php @@ -0,0 +1,41 @@ +isAuthenticated(); // This call assigns 'authenticated' to smarty. + +// $smarty->assign('title', $i18n->get('form.label.menu')); +$smarty->assign('content_page_name', 'site_map.tpl'); +$smarty->display('index2.tpl'); From 8f2cfae8517bd8b18594950175b8c00f1c096574 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 24 Sep 2020 16:49:14 +0000 Subject: [PATCH 025/587] Added mobile-friendly login templates. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/login.db2.tpl | 20 ++++++++++++++++++++ WEB-INF/templates/login.ldap2.tpl | 23 +++++++++++++++++++++++ WEB-INF/templates/login2.tpl | 14 ++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 WEB-INF/templates/login.db2.tpl create mode 100644 WEB-INF/templates/login.ldap2.tpl create mode 100644 WEB-INF/templates/login2.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 4e07aa67a..eef858b3b 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {if $show_files} {if $project.has_files} - + {else} {/if} diff --git a/WEB-INF/templates/report.tpl b/WEB-INF/templates/report.tpl index 822083df1..f7ef4ff2e 100644 --- a/WEB-INF/templates/report.tpl +++ b/WEB-INF/templates/report.tpl @@ -164,8 +164,8 @@ {if $bean->getAttribute('chinvoice')}{/if} {if $bean->getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')} - {if 1 == $item.type}{/if} - {if 2 == $item.type}{/if} + {if 1 == $item.type}{/if} + {if 2 == $item.type}{/if} {/if} {if $use_checkboxes} {if 1 == $item.type}{/if} diff --git a/WEB-INF/templates/roles.tpl b/WEB-INF/templates/roles.tpl index d1d60b849..227392489 100644 --- a/WEB-INF/templates/roles.tpl +++ b/WEB-INF/templates/roles.tpl @@ -22,8 +22,8 @@ - - + + {/foreach} {/if} @@ -52,8 +52,8 @@ - - + + {/foreach}
Anuko Time Tracker 1.19.23.5289 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5290 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 9d3b69616..274ed2567 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/login.db2.tpl b/WEB-INF/templates/login.db2.tpl new file mode 100644 index 000000000..97e0c1886 --- /dev/null +++ b/WEB-INF/templates/login.db2.tpl @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + +
{$i18n.label.login}:
{$i18n.label.login}:{$forms.loginForm.login.control}
{$i18n.label.password}:
{$i18n.label.password}:{$forms.loginForm.password.control}
{$i18n.form.login.forgot_password}
{$forms.loginForm.btn_login.control}
diff --git a/WEB-INF/templates/login.ldap2.tpl b/WEB-INF/templates/login.ldap2.tpl new file mode 100644 index 000000000..74d0eda44 --- /dev/null +++ b/WEB-INF/templates/login.ldap2.tpl @@ -0,0 +1,23 @@ +{if $show_hint} +
{$i18n.label.ldap_hint}
+{/if} + + + + + + + + + + + + + + + + + + + +
{$i18n.label.login}:
{$i18n.label.login}:{$forms.loginForm.login.control}@{$Auth_ldap_params.default_domain}
{$i18n.label.password}:
{$i18n.label.password}:{$forms.loginForm.password.control}
{$i18n.form.login.forgot_password}
{$forms.loginForm.btn_login.control}
diff --git a/WEB-INF/templates/login2.tpl b/WEB-INF/templates/login2.tpl new file mode 100644 index 000000000..fa4237dbf --- /dev/null +++ b/WEB-INF/templates/login2.tpl @@ -0,0 +1,14 @@ + + +{$forms.loginForm.open} +{include file="login.`$smarty.const.AUTH_MODULE`2.tpl"} +{$forms.loginForm.close} + +{if !empty($about_text)} +
{$about_text}
+{/if} From 9b66da374af45d3e62b8af2df4db29bbc5c97a24 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 24 Sep 2020 18:15:26 +0000 Subject: [PATCH 026/587] Some style fixes for mobile login pages. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/login.db2.tpl | 4 ++-- WEB-INF/templates/login.ldap2.tpl | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index eef858b3b..d607961ff 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - - + + {/foreach} {/if} diff --git a/WEB-INF/templates/predefined_expenses.tpl b/WEB-INF/templates/predefined_expenses.tpl index e115b58db..d35fac0b4 100644 --- a/WEB-INF/templates/predefined_expenses.tpl +++ b/WEB-INF/templates/predefined_expenses.tpl @@ -14,8 +14,8 @@ - - + + {/foreach} {/if} diff --git a/WEB-INF/templates/projects.tpl b/WEB-INF/templates/projects.tpl index 345b7ef47..19bbe2373 100644 --- a/WEB-INF/templates/projects.tpl +++ b/WEB-INF/templates/projects.tpl @@ -26,13 +26,13 @@ {if $show_files} {if $project.has_files} - + {else} - + {/if} {/if} - - + + {/foreach} {/if} @@ -64,13 +64,13 @@ {if $show_files} {if $project.has_files} - + {else} - + {/if} {/if} - - + + {/foreach}
Anuko Time Tracker 1.19.23.5290 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5291 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 274ed2567..3a472507f 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/login.db2.tpl b/WEB-INF/templates/login.db2.tpl index 97e0c1886..71eb170c8 100644 --- a/WEB-INF/templates/login.db2.tpl +++ b/WEB-INF/templates/login.db2.tpl @@ -1,11 +1,11 @@ - + - + diff --git a/WEB-INF/templates/login.ldap2.tpl b/WEB-INF/templates/login.ldap2.tpl index 74d0eda44..e51abec12 100644 --- a/WEB-INF/templates/login.ldap2.tpl +++ b/WEB-INF/templates/login.ldap2.tpl @@ -2,13 +2,13 @@
{$i18n.label.ldap_hint}
{/if}
{$i18n.label.login}:
{$i18n.label.login}:
{$i18n.label.login}: {$forms.loginForm.login.control}
{$i18n.label.password}:
{$i18n.label.password}:
{$i18n.label.password}: {$forms.loginForm.password.control}
- + - + From 6eca4003aeffeb54a318a0f022a591bb177ddc4b Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 24 Sep 2020 19:22:28 +0000 Subject: [PATCH 027/587] Some progress with making registration page mobile-friendly. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/register2.tpl | 56 +++++++++++++++++++++++++++++++++ default2.css | 28 +++++++---------- register.php | 11 +++++-- 5 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 WEB-INF/templates/register2.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index d607961ff..e7c1cdde1 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
{$i18n.label.login}:
{$i18n.label.login}:
{$i18n.label.login}: {$forms.loginForm.login.control}@{$Auth_ldap_params.default_domain}
{$i18n.label.password}:
{$i18n.label.password}:
{$i18n.label.password}: {$forms.loginForm.password.control}
- {/if} {if !$user->isClient()} - + {/if} {/foreach} diff --git a/WEB-INF/templates/mobile/time.tpl b/WEB-INF/templates/mobile/time.tpl index 3c9d4276c..6b8bca0c6 100644 --- a/WEB-INF/templates/mobile/time.tpl +++ b/WEB-INF/templates/mobile/time.tpl @@ -25,8 +25,8 @@ {/if} - - + + {/foreach}
Anuko Time Tracker 1.19.23.5291 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5292 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 3a472507f..c3797a337 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/register2.tpl b/WEB-INF/templates/register2.tpl new file mode 100644 index 000000000..d91ec66ea --- /dev/null +++ b/WEB-INF/templates/register2.tpl @@ -0,0 +1,56 @@ +{$forms.groupForm.open} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$i18n.label.group_name} (*):
{$i18n.label.group_name} (*):{$forms.groupForm.group_name.control} {$i18n.label.what_is_it}
{$i18n.label.currency}:
{$i18n.label.currency}:{$forms.groupForm.currency.control}
{$i18n.label.language}:
{$i18n.label.language}:{$forms.groupForm.lang.control}
{$i18n.label.manager_name} (*):
{$i18n.label.manager_name} (*):{$forms.groupForm.manager_name.control}
{$i18n.label.manager_login} (*):
{$i18n.label.manager_login} (*):{$forms.groupForm.manager_login.control}
{$i18n.label.password} (*):
{$i18n.label.password} (*):{$forms.groupForm.password1.control}
{$i18n.label.confirm_password} (*):
{$i18n.label.confirm_password} (*):{$forms.groupForm.password2.control}
{$i18n.label.email}{if isTrue('EMAIL_REQUIRED')} (*){/if}:
{$i18n.label.email}{if isTrue('EMAIL_REQUIRED')} (*){/if}:{$forms.groupForm.manager_email.control}
{$i18n.label.required_fields}
{$forms.groupForm.btn_submit.control}
+{$forms.groupForm.close} diff --git a/default2.css b/default2.css index a5536914e..b24fa06c2 100644 --- a/default2.css +++ b/default2.css @@ -138,6 +138,17 @@ div.page-hint { outline: none; } +.contribute-msg { + text-align: center; + margin-top: 2rem; + padding: .2rem; + background-color: #eeeeee; +} + +.version-and-copyright { + text-align: center; + padding: .5rem; +} @media screen and (max-width: 600px) { @@ -154,23 +165,6 @@ div.page-hint { } } - - - - - -.contribute-msg { - text-align: center; - padding: .2rem; - background-color: #eeeeee; -} - -.version-and-copyright { - text-align: center; - padding: .5rem; -} - - @media screen and (max-width: 1170px) { div.top-menu-small-screen { display: block; diff --git a/register.php b/register.php index 47f3b406e..28c6d8bf5 100644 --- a/register.php +++ b/register.php @@ -118,5 +118,12 @@ $smarty->assign('title', $i18n->get('title.add_group')); $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.groupForm.group_name.focus()"'); -$smarty->assign('content_page_name', 'register.tpl'); -$smarty->display('index.tpl'); +if (defined('DEBUG_MOBILE')) + $smarty->assign('content_page_name', 'register2.tpl'); +else { + $smarty->assign('content_page_name', 'register.tpl'); +} +if (defined('DEBUG_MOBILE')) + $smarty->display('index2.tpl'); +else + $smarty->display('index.tpl'); From 2f756f715ce0e2249b895feccca838b17f095224 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 25 Sep 2020 12:32:51 +0000 Subject: [PATCH 028/587] Some style fixes for registration page. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/register2.tpl | 41 +++++++++++++++++--------------- default2.css | 26 +++++++++++++++++--- img/icon-question-mark.png | Bin 0 -> 1119 bytes 5 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 img/icon-question-mark.png diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index e7c1cdde1..4e66e0f70 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {if $can_edit} - - + + {/if} {/foreach} diff --git a/WEB-INF/templates/expenses.tpl b/WEB-INF/templates/expenses.tpl index 1e9476c3d..3c5867279 100644 --- a/WEB-INF/templates/expenses.tpl +++ b/WEB-INF/templates/expenses.tpl @@ -207,23 +207,23 @@ function recalculateCost() { {if $show_files} {if $item.has_files} - + {else} - + {/if} {/if} diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 713d34116..a4d2075af 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5292 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5293 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index c3797a337..23ce92f69 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/register2.tpl b/WEB-INF/templates/register2.tpl index d91ec66ea..5584fde39 100644 --- a/WEB-INF/templates/register2.tpl +++ b/WEB-INF/templates/register2.tpl @@ -1,50 +1,53 @@ {$forms.groupForm.open} - + - - + + - + - + - + - + + - - + - + - + - + - + - + - + - + - + - + @@ -53,4 +56,4 @@
{$i18n.label.group_name} (*):
{$i18n.label.group_name} (*):{$forms.groupForm.group_name.control} {$i18n.label.what_is_it}{$forms.groupForm.group_name.control} + {$i18n.label.what_is_it} + {$i18n.label.what_is_it} +
{$i18n.label.currency}:
{$i18n.label.currency}: {$forms.groupForm.currency.control}
{$i18n.label.language}:
{$i18n.label.language}: {$forms.groupForm.lang.control}
{$i18n.label.manager_name} (*):
{$i18n.label.manager_name} (*): {$forms.groupForm.manager_name.control}
{$i18n.label.manager_login} (*):
{$i18n.label.manager_login} (*): {$forms.groupForm.manager_login.control}
{$i18n.label.password} (*):
{$i18n.label.password} (*): {$forms.groupForm.password1.control}
{$i18n.label.confirm_password} (*):
{$i18n.label.confirm_password} (*): {$forms.groupForm.password2.control}
{$i18n.label.email}{if isTrue('EMAIL_REQUIRED')} (*){/if}:
{$i18n.label.email}{if isTrue('EMAIL_REQUIRED')} (*){/if}: {$forms.groupForm.manager_email.control}
{$i18n.label.required_fields}
{$forms.groupForm.btn_submit.control}
-{$forms.groupForm.close} +{$forms.groupForm.close} \ No newline at end of file diff --git a/default2.css b/default2.css index b24fa06c2..f4a3a8e07 100644 --- a/default2.css +++ b/default2.css @@ -150,18 +150,38 @@ div.page-hint { padding: .5rem; } +.centered-table td img { + vertical-align: middle; +} + +.what-is-it-img { + display: none; +} + +.what-is-it-text { + display: inline-block; +} + @media screen and (max-width: 600px) { .large-screen-label { - display: none; + display: none; } .small-screen-label { - display: block; + display: block; } .small-screen-form-control-separator { - display: block; + display: block; + } + + .what-is-it-img { + display: inline-block; + } + + .what-is-it-text { + display: none; } } diff --git a/img/icon-question-mark.png b/img/icon-question-mark.png new file mode 100644 index 0000000000000000000000000000000000000000..a6225d27106d55648816f78920581bc7587b0f44 GIT binary patch literal 1119 zcmaJ=OK1~87~ZBfN^P|uRa+sB+X{lsKJqk6V@p=Z^G-QmTqG&-PrWg_gX-yo1Stu&ygZE)CK{R%& zxjf1X1DtGVl<4?SCC$WWg6QolnW8)n5s=`Rsz=GiTenG|Dp7JcC@_MVfCV)*Wx=7T z!JIrbE=LryZ#U>IahO1ZNCYKqLbth6lw9KF@YylbBv^7m<5BW=Qh6Z*5{3mqkYc!X>lmu0wMm}6M5{E;}CrHpb}KDitV-=bszA(Nx&VzEdS z{gh#i(QG6Vp&1|T^Lep{*DmWwEO~XitH!`XTeegasfG?5Mo}^*QIy1){w_f?S7>#6 zxlOoXbV)R6mSUWeYL0^Ne^*Ug@wQPG{>k^B#CEQ1LOKg=W73lG;6}TgP$rkKpok1B zXBZQ;E@lb_GVFq3g2YgeVu2vas_s~p5Q4y^bsLGg4AXp+#2l2WDqJ!d_Qk{DU^2wV zS++kGVIsSBCH#IL8|34Do~>bdL!Q*2j%rxt4>nX6>xe-!abzA^>LI8kEkgrKMRRKX zT>N$Uma$6xTmp5mG){(gM*G*OYbLB8=eQzVd|8n`)Un#Zy&oh}DSLVzHin#WvrEN>sO%%N9o(_CUKKbG4^ekR2H=KEJsq)0t+kC41wH@o+ z_TXrX8Iy)bo(@caJFay*=Qg=7&(EHG)O2p4y8a&ZcJthxi))X&hz2*YaFWf9&F(Kd OPd?p0$X||+9Qg(7pK7T9 literal 0 HcmV?d00001 From 1d94570d421f7098a997136d7119ed4d82171cd2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 25 Sep 2020 13:00:12 +0000 Subject: [PATCH 029/587] Style fixes for login pages. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/login.db2.tpl | 8 ++++---- WEB-INF/templates/login.ldap2.tpl | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 4e66e0f70..713d34116 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- - - + + {/foreach}
Anuko Time Tracker 1.19.23.5293 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5294 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 23ce92f69..40e7f2547 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/login.db2.tpl b/WEB-INF/templates/login.db2.tpl index 71eb170c8..4ab3ad2c0 100644 --- a/WEB-INF/templates/login.db2.tpl +++ b/WEB-INF/templates/login.db2.tpl @@ -1,13 +1,13 @@ - + - + - + - + diff --git a/WEB-INF/templates/login.ldap2.tpl b/WEB-INF/templates/login.ldap2.tpl index e51abec12..7fd32ed2e 100644 --- a/WEB-INF/templates/login.ldap2.tpl +++ b/WEB-INF/templates/login.ldap2.tpl @@ -2,15 +2,15 @@
{$i18n.label.ldap_hint}
{/if}
{$i18n.label.login}:
{$i18n.label.login}: {$forms.loginForm.login.control}
{$i18n.label.password}:
{$i18n.label.password}: {$forms.loginForm.password.control}
- + - + - + - + From 01da94bbc817e3ebeb3eff697dab5ea1ce74224f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 25 Sep 2020 13:41:04 +0000 Subject: [PATCH 030/587] Renamed 3 icon files. --- WEB-INF/templates/admin_groups.tpl | 4 ++-- WEB-INF/templates/cf_custom_fields.tpl | 4 ++-- WEB-INF/templates/cf_dropdown_options.tpl | 4 ++-- WEB-INF/templates/clients.tpl | 8 ++++---- WEB-INF/templates/entity_files.tpl | 4 ++-- WEB-INF/templates/expenses.tpl | 8 ++++---- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/groups.tpl | 4 ++-- WEB-INF/templates/invoices.tpl | 2 +- WEB-INF/templates/mobile/time.tpl | 4 ++-- WEB-INF/templates/notifications.tpl | 4 ++-- WEB-INF/templates/predefined_expenses.tpl | 4 ++-- WEB-INF/templates/projects.tpl | 18 +++++++++--------- WEB-INF/templates/report.tpl | 4 ++-- WEB-INF/templates/roles.tpl | 8 ++++---- WEB-INF/templates/tasks.tpl | 8 ++++---- WEB-INF/templates/templates.tpl | 8 ++++---- WEB-INF/templates/time.tpl | 8 ++++---- WEB-INF/templates/timesheets.tpl | 16 ++++++++-------- WEB-INF/templates/users.tpl | 8 ++++---- WEB-INF/templates/week.tpl | 8 ++++---- WEB-INF/templates/work/admin_work.tpl | 8 ++++---- WEB-INF/templates/work/work.tpl | 8 ++++---- img/{icon_delete.png => icon-delete.png} | Bin img/{icon_edit.png => icon-edit.png} | Bin img/{icon_file.png => icon-file.png} | Bin img/{icon_files.png => icon-files.png} | Bin 28 files changed, 78 insertions(+), 78 deletions(-) rename img/{icon_delete.png => icon-delete.png} (100%) rename img/{icon_edit.png => icon-edit.png} (100%) rename img/{icon_file.png => icon-file.png} (100%) rename img/{icon_files.png => icon-files.png} (100%) diff --git a/WEB-INF/templates/admin_groups.tpl b/WEB-INF/templates/admin_groups.tpl index 9f2ecb6f4..af98c12fd 100644 --- a/WEB-INF/templates/admin_groups.tpl +++ b/WEB-INF/templates/admin_groups.tpl @@ -22,8 +22,8 @@ - - + + {/foreach} {/if} diff --git a/WEB-INF/templates/cf_custom_fields.tpl b/WEB-INF/templates/cf_custom_fields.tpl index e056c606b..6636d79e1 100644 --- a/WEB-INF/templates/cf_custom_fields.tpl +++ b/WEB-INF/templates/cf_custom_fields.tpl @@ -30,8 +30,8 @@ {/if} - - + + {/foreach} {/if} diff --git a/WEB-INF/templates/cf_dropdown_options.tpl b/WEB-INF/templates/cf_dropdown_options.tpl index d694a1ebc..92b2d4dac 100644 --- a/WEB-INF/templates/cf_dropdown_options.tpl +++ b/WEB-INF/templates/cf_dropdown_options.tpl @@ -16,8 +16,8 @@ {foreach $options as $key=>$val} - - + + {/foreach} {/if} diff --git a/WEB-INF/templates/clients.tpl b/WEB-INF/templates/clients.tpl index cba3256c3..07b835c87 100644 --- a/WEB-INF/templates/clients.tpl +++ b/WEB-INF/templates/clients.tpl @@ -20,8 +20,8 @@ - - + + {/foreach}
{$i18n.label.login}:
{$i18n.label.login}: {$forms.loginForm.login.control}@{$Auth_ldap_params.default_domain}
{$i18n.label.password}:
{$i18n.label.password}: {$forms.loginForm.password.control}
{$group.name|escape} {$group.date} {$group.lang}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$i18n.label.type_dropdown} {$i18n.label.configure}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$val|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$client.name|escape} {$client.address|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
@@ -43,8 +43,8 @@
{$client.name|escape} {$client.address|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/entity_files.tpl b/WEB-INF/templates/entity_files.tpl index fe5dc5445..ab9564852 100644 --- a/WEB-INF/templates/entity_files.tpl +++ b/WEB-INF/templates/entity_files.tpl @@ -16,8 +16,8 @@
{$file.name|escape} {$file.description|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$item.cost}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files} {if $item.approved || $item.invoice_id}   {else} - {$i18n.label.edit} + {$i18n.label.edit} {/if} {if $item.approved || $item.invoice_id}   {else} - {$i18n.label.delete} + {$i18n.label.delete} {/if}
- - - + + {/foreach}
Anuko Time Tracker 1.19.23.5294 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5295 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 40e7f2547..e7b8069a4 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/groups.tpl b/WEB-INF/templates/groups.tpl index 7b2a24017..636a252b0 100644 --- a/WEB-INF/templates/groups.tpl +++ b/WEB-INF/templates/groups.tpl @@ -22,8 +22,8 @@
{$subgroup.name|escape} {$subgroup.description|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/invoices.tpl b/WEB-INF/templates/invoices.tpl index af632ef58..e27eb3991 100644 --- a/WEB-INF/templates/invoices.tpl +++ b/WEB-INF/templates/invoices.tpl @@ -43,7 +43,7 @@
{if $invoice.paid}{$i18n.label.yes}{else}{$i18n.label.no}{/if}{$i18n.label.delete}{$i18n.label.delete}
{$record.project|escape}{if ($record.duration == '0:00' && $record.start <> '')}{/if}{$record.duration}{if ($record.duration == '0:00' && $record.start <> '')}{/if}{if $record.approved || $record.timesheet_id || $record.invoice_id} {else}{$i18n.label.edit}{/if}{if $record.approved || $record.timesheet_id || $record.invoice_id} {else}{$i18n.label.delete}{/if}{if $record.approved || $record.timesheet_id || $record.invoice_id} {else}{$i18n.label.edit}{/if}{if $record.approved || $record.timesheet_id || $record.invoice_id} {else}{$i18n.label.delete}{/if}
diff --git a/WEB-INF/templates/notifications.tpl b/WEB-INF/templates/notifications.tpl index 3cd3347b7..d54579027 100644 --- a/WEB-INF/templates/notifications.tpl +++ b/WEB-INF/templates/notifications.tpl @@ -19,8 +19,8 @@
{$notification['cron_spec']|escape} {$notification['email']|escape} {$notification['report_condition']|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$predefined_expense['name']|escape} {$predefined_expense['cost']|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$project.description|escape}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$project.description|escape}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
@@ -99,7 +99,7 @@
{$project.description|escape}{$i18n.label.files}{$i18n.label.files} {$item.invoice|escape}{$item.timesheet_name|escape}{if $item.has_files}{$i18n.label.files}{/if}{if $item.has_files}{$i18n.label.files}{/if}{if $item.has_files}{$i18n.label.files}{/if}{if $item.has_files}{$i18n.label.files}{/if}{$role.name|escape} {$role.rank} {$role.description|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$role.name|escape} {$role.rank} {$role.description|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/tasks.tpl b/WEB-INF/templates/tasks.tpl index 646899ddf..591820199 100644 --- a/WEB-INF/templates/tasks.tpl +++ b/WEB-INF/templates/tasks.tpl @@ -32,8 +32,8 @@
{$task.name|escape} {$task.description|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
{$task.name|escape} {$task.description|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/templates.tpl b/WEB-INF/templates/templates.tpl index fa3faac63..282387830 100644 --- a/WEB-INF/templates/templates.tpl +++ b/WEB-INF/templates/templates.tpl @@ -16,8 +16,8 @@
{$template['name']|escape} {$template['description']|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
@@ -37,8 +37,8 @@

{$template['name']|escape} {$template['description']|escape}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/time.tpl b/WEB-INF/templates/time.tpl index be0299a48..69d214127 100644 --- a/WEB-INF/templates/time.tpl +++ b/WEB-INF/templates/time.tpl @@ -167,16 +167,16 @@ {/if} {if $show_files} {if $record.has_files} -
{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files} {if $record.approved || $record.timesheet_id || $record.invoice_id}   {else} - {$i18n.label.edit} + {$i18n.label.edit} {if ($record.duration == '0:00' && $record.start <> '')} @@ -189,7 +189,7 @@ {if $record.approved || $record.timesheet_id || $record.invoice_id}   {else} - {$i18n.label.delete} + {$i18n.label.delete} {/if}
{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
@@ -86,13 +86,13 @@ {/if} {if $show_files} {if $timesheet.has_files} -
{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/users.tpl b/WEB-INF/templates/users.tpl index d7d3e3aa7..c3f6861ea 100644 --- a/WEB-INF/templates/users.tpl +++ b/WEB-INF/templates/users.tpl @@ -35,8 +35,8 @@
{$u.quota_percent}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete} {$u.quota_percent}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete} {if $record.comment}{$record.comment|escape}{else} {/if}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files}{$i18n.label.files} {if $record.approved || $record.timesheet_id || $record.invoice_id}   {else} - {$i18n.label.edit} + {$i18n.label.edit} {/if} {if $record.approved || $record.timesheet_id || $record.invoice_id}   {else} - {$i18n.label.delete} + {$i18n.label.delete} {/if}
{$work_item.description|escape} {$work_item.group_name|escape} ({$work_item.site_id}.{$work_item.group_id}) {$work_item.amount_with_currency}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
@@ -48,8 +48,8 @@
{$offer.description|escape} {$offer.group_name|escape} ({$offer.site_id}.{$offer.group_id}) {$offer.amount_with_currency}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/WEB-INF/templates/work/work.tpl b/WEB-INF/templates/work/work.tpl index 76d953065..67235b64f 100644 --- a/WEB-INF/templates/work/work.tpl +++ b/WEB-INF/templates/work/work.tpl @@ -25,12 +25,12 @@
{if $work_item.num_offers}{$work_item.num_offers}{/if} {$work_item.amount_with_currency}{$i18n.label.edit}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.delete}{$offer.description|escape} {$offer.status_label} {$offer.amount_with_currency}{$i18n.label.edit}{$i18n.label.delete}{$i18n.label.edit}{$i18n.label.delete}
diff --git a/img/icon_delete.png b/img/icon-delete.png similarity index 100% rename from img/icon_delete.png rename to img/icon-delete.png diff --git a/img/icon_edit.png b/img/icon-edit.png similarity index 100% rename from img/icon_edit.png rename to img/icon-edit.png diff --git a/img/icon_file.png b/img/icon-file.png similarity index 100% rename from img/icon_file.png rename to img/icon-file.png diff --git a/img/icon_files.png b/img/icon-files.png similarity index 100% rename from img/icon_files.png rename to img/icon-files.png From 98027b33bac363af92bf89aefd0121a4ef24232b Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 25 Sep 2020 16:20:35 +0000 Subject: [PATCH 031/587] Starting to get rid of styles from php code. --- WEB-INF/lib/form/Form.class.php | 2 + WEB-INF/lib/form/FormElement.class.php | 30 +- WEB-INF/lib/form/PasswordField.class.php | 2 + WEB-INF/lib/form/TextField.class.php | 2 + WEB-INF/templates/header2.tpl | 2 +- default.css | 214 +++++++++++ default2.css | 442 ----------------------- login.php | 4 +- 8 files changed, 238 insertions(+), 460 deletions(-) delete mode 100644 default2.css diff --git a/WEB-INF/lib/form/Form.class.php b/WEB-INF/lib/form/Form.class.php index 1f77414b1..1bbf2253e 100644 --- a/WEB-INF/lib/form/Form.class.php +++ b/WEB-INF/lib/form/Form.class.php @@ -53,12 +53,14 @@ function addInput($params) { case 'text': import('form.TextField'); $el = new TextField($params['name']); + if (isset($params['class'])) $el->setCssClass($params['class']); if (isset($params['maxlength'])) $el->setMaxLength($params['maxlength']); break; case 'password': import('form.PasswordField'); $el = new PasswordField($params['name']); + if (isset($params['class'])) $el->setCssClass($params['class']); if (isset($params['maxlength'])) $el->setMaxLength($params['maxlength']); break; diff --git a/WEB-INF/lib/form/FormElement.class.php b/WEB-INF/lib/form/FormElement.class.php index 0443e6c9a..096084ef4 100644 --- a/WEB-INF/lib/form/FormElement.class.php +++ b/WEB-INF/lib/form/FormElement.class.php @@ -28,27 +28,27 @@ // FromElement is the base class for controls on forms. class FormElement { - var $id = ''; // Control id. - var $name; // Control name. - var $form_name = ''; // Form name the control is in. - var $value = ''; // Value of the control. - var $size = ''; // Control size. - var $max_length = ''; // Max length of text in control. - var $on_change = ''; // What happens when value of control changes. - var $on_click = ''; // What happens when the control is clicked. - var $label = ''; // Optional label for control. - var $style = ''; // Control style. - var $enabled = true; // Whether the control is enabled. - var $class = 'FormElement'; // PHP class name for the element. - var $cssClass = null; // CSS class name for the element. + var $id = ''; // control id + var $name; // control name + var $form_name = ''; // form name the control is in + var $value = ''; // value of the control + var $size = ''; // control size + var $max_length = ''; // max length of text in control + var $on_change = ''; // what happens when value of control changes + var $on_click = ''; // what happens when the control is clicked + var $label = ''; // optional label for control + var $style = ''; // control style + var $enabled = true; // whether the control is enabled + var $class = 'FormElement'; // php class name for the control + var $css_class = null; // css class name for the control function __construct() { } function getName() { return $this->name; } function getClass() { return $this->class; } - function getCssClass() { return $this->cssClass; } - function setCssClass($cssClass) { $this->cssClass = $cssClass; } + function getCssClass() { return $this->css_class; } + function setCssClass($css_class) { $this->css_class = $css_class; } function setFormName($name) { $this->form_name = $name; } function getFormName() { return $this->form_name; } diff --git a/WEB-INF/lib/form/PasswordField.class.php b/WEB-INF/lib/form/PasswordField.class.php index 747a6ac45..579be5edb 100644 --- a/WEB-INF/lib/form/PasswordField.class.php +++ b/WEB-INF/lib/form/PasswordField.class.php @@ -33,6 +33,7 @@ class PasswordField extends FormElement { function __construct($name) { $this->class = 'PasswordField'; + $this->css_class = 'password-field'; $this->name = $name; } @@ -40,6 +41,7 @@ function getHtml() { if ($this->id == '') $this->id = $this->name; $html = "\n\tcss_class\""; $html.= ' id="'.$this->id.'"'; $html.= ' name="'.$this->name.'"'; diff --git a/WEB-INF/lib/form/TextField.class.php b/WEB-INF/lib/form/TextField.class.php index 6b745a2af..fdfb76837 100644 --- a/WEB-INF/lib/form/TextField.class.php +++ b/WEB-INF/lib/form/TextField.class.php @@ -35,6 +35,7 @@ class TextField extends FormElement { function __construct($name) { $this->class = 'TextField'; + $this->css_class = 'text-field'; $this->name = $name; } @@ -43,6 +44,7 @@ function setTitle($title) { $this->title = $title; } function getHtml() { if (empty($this->id)) $this->id = $this->name; $html = "\n\tcss_class\""; $html .= " id=\"$this->id\" name=\"$this->name\""; if (!empty($this->size)) $html .= " size=\"$this->size\""; if (!empty($this->style)) $html .= " style=\"$this->style\""; diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl index 4af0ef8af..9aba06219 100644 --- a/WEB-INF/templates/header2.tpl +++ b/WEB-INF/templates/header2.tpl @@ -5,7 +5,7 @@ - + {if $i18n.language.rtl} {/if} diff --git a/default.css b/default.css index 3b4921acf..d6b8f6571 100644 --- a/default.css +++ b/default.css @@ -27,6 +27,220 @@ // +----------------------------------------------------------------------+ */ +body { + margin: 0px; + font-size: 10pt; + font-family: Verdana, sans-serif; + background-color: white; +} + +div.logo { + padding: .5rem; + text-align: center; + background-color: #a6ccf7; +} + +div.top-menu-large-screen { + background-color: black; + display: block; +} + +.top-submenu-large-screen { + background-color: #d9d9d9; + display: block; +} + +div.top-menu-small-screen { + background-color: black; + display: none; +} + +div.top-menu-small-screen a { + font-size: 1rem; + font-weight: bold; + color: white; + margin: .1rem .2rem .1rem .2rem; +} + +div.top-menu-large-screen a { + font-size: 1rem; + font-weight: bold; + color: white; + margin: .1rem .2rem .1rem .2rem; +} + +.top-menu-table { + margin-left: auto; + margin-right: auto; +} + +.top-submenu-table { + margin-left: auto; + margin-right: auto; +} + +.top-submenu-large-screen a { + font-size: 1rem; + color: #444444; + margin: .1rem .2rem .1rem .2rem; +} + +div.page-title { + font-size: 12pt; + font-weight: bold; + color: silver; + text-align: center; + padding: .25rem; + border-bottom: 1px solid lightgray; + margin-bottom: .2rem; +} + +div.user-details { + text-align: center; + padding: .2rem; +} + +.page-errors { + margin-top: .5rem; + text-align: center; + color: red; +} + +.page-content { + text-align: center; +} + +.form-control-separator { + height: .5rem; +} + +div#LoginAboutText { + padding: 1rem; + margin-left:auto; + margin-right:auto; +} + +#ldapDefaultDomain { + color: #777777; +} + +div.page-hint { + margin-top: 1rem; +} + +.centered-table { + margin-top: .5rem; + margin-left: auto; + margin-right: auto; + display: inline-block; +} + +.large-screen-label { + text-align: right; + vertical-align: middle; + display: table-cell; +} + +.small-screen-label { + text-align: left; + display: none; +} + +.small-screen-form-control-separator { + height: .25rem; + display: none; +} + +.page-content input { + border-radius: 4px; + border: 1px solid #c9c9c9; + padding: .4rem; +} + +.td-with-input { + text-align: left; +} + +.page-content input:focus { + background-color: yellow; + border: 1px solid black; + outline: none; +} + +.contribute-msg { + text-align: center; + margin-top: 2rem; + padding: .2rem; + background-color: #eeeeee; +} + +.version-and-copyright { + text-align: center; + padding: .5rem; +} + +.centered-table td img { + vertical-align: middle; +} + +.what-is-it-img { + display: none; +} + +.what-is-it-text { + display: inline-block; +} + +input.text-field { + width: 220px; +} + +input.password-field { + width: 220px; +} + +@media screen and (max-width: 600px) { + + .large-screen-label { + display: none; + } + + .small-screen-label { + display: block; + } + + .small-screen-form-control-separator { + display: block; + } + + .what-is-it-img { + display: inline-block; + } + + .what-is-it-text { + display: none; + } +} + +@media screen and (max-width: 1170px) { + div.top-menu-small-screen { + display: block; + } + + div.top-menu-large-screen { + display: none; + } + + div.top-submenu-large-screen { + display: none; + } +} + + + + + +/* TODO: below are legacy styles. Review as work on mobile-friendly pages continues. */ a { color: blue; text-decoration: none; } a:visited { text-decoration: none; } diff --git a/default2.css b/default2.css deleted file mode 100644 index f4a3a8e07..000000000 --- a/default2.css +++ /dev/null @@ -1,442 +0,0 @@ -body { - margin: 0px; - font-size: 10pt; - font-family: Verdana, sans-serif; - background-color: white; -} - -div.logo { - padding: .5rem; - text-align: center; - background-color: #a6ccf7; -} - -div.top-menu-large-screen { - background-color: black; - display: block; -} - -.top-submenu-large-screen { - background-color: #d9d9d9; - display: block; -} - -div.top-menu-small-screen { - background-color: black; - display: none; -} - -div.top-menu-small-screen a { - font-size: 1rem; - font-weight: bold; - color: white; - margin: .1rem .2rem .1rem .2rem; -} - -div.top-menu-large-screen a { - font-size: 1rem; - font-weight: bold; - color: white; - margin: .1rem .2rem .1rem .2rem; -} - -.top-menu-table { - margin-left: auto; - margin-right: auto; -} - -.top-submenu-table { - margin-left: auto; - margin-right: auto; -} - -.top-submenu-large-screen a { - font-size: 1rem; - color: #444444; - margin: .1rem .2rem .1rem .2rem; -} - -div.page-title { - font-size: 12pt; - font-weight: bold; - color: silver; - text-align: center; - padding: .25rem; - border-bottom: 1px solid lightgray; - margin-bottom: .2rem; -} - -div.user-details { - text-align: center; - padding: .2rem; -} - -.page-errors { - margin-top: .5rem; - text-align: center; - color: red; -} - -.page-content { - text-align: center; -} - -.form-control-separator { - height: .5rem; -} - -div#LoginAboutText { - padding: 1rem; - margin-left:auto; - margin-right:auto; -} - -#ldapDefaultDomain { - color: #777777; -} - -div.page-hint { - margin-top: 1rem; -} - -.centered-table { - margin-top: .5rem; - margin-left: auto; - margin-right: auto; - display: inline-block; -} - -.large-screen-label { - text-align: right; - vertical-align: middle; - display: table-cell; -} - -.small-screen-label { - text-align: left; - display: none; -} - -.small-screen-form-control-separator { - height: .25rem; - display: none; -} - -.page-content input { - border-radius: 4px; - border: 1px solid #c9c9c9; - padding: .4rem; -} - -.td-with-input { - text-align: left; -} - -.page-content input:focus { - background-color: yellow; - border: 1px solid black; - outline: none; -} - -.contribute-msg { - text-align: center; - margin-top: 2rem; - padding: .2rem; - background-color: #eeeeee; -} - -.version-and-copyright { - text-align: center; - padding: .5rem; -} - -.centered-table td img { - vertical-align: middle; -} - -.what-is-it-img { - display: none; -} - -.what-is-it-text { - display: inline-block; -} - -@media screen and (max-width: 600px) { - - .large-screen-label { - display: none; - } - - .small-screen-label { - display: block; - } - - .small-screen-form-control-separator { - display: block; - } - - .what-is-it-img { - display: inline-block; - } - - .what-is-it-text { - display: none; - } -} - -@media screen and (max-width: 1170px) { - div.top-menu-small-screen { - display: block; - } - - div.top-menu-large-screen { - display: none; - } - - div.top-submenu-large-screen { - display: none; - } -} - - - - - - - - - - -a { color: blue; text-decoration: none; } - -a:visited { text-decoration: none; } - -a:hover { text-decoration: underline; } - -html { - overflow-y: scroll; -} - -table { font-size: 10pt; font-family: Verdana, sans-serif; } - -input, button, select, textarea { - font-size: 10pt; - font-family: Verdana, sans-serif; - margin: 2px 2px 2px 2px; - padding: 2px 5px 2px 5px; -} - -input[type=checkbox], label { - vertical-align: middle; -} - -.pageTitle { - font-size: 12pt; - font-weight: bold; - color: silver; -} - -.systemMenu { - font-size: 1rem; - font-weight: bold; - color: white; - background-color: black; - margin: .1rem .2rem .1rem .2rem; -} - -.mainMenu { - font-size: 1rem; - color: #444444; - margin: .1rem .2rem .1rem .2rem; -} - -.onBehalf { - font-weight: bold; -} - -/* calendar styles */ -.calendarHeader { - padding: 5px; - font-size: 8pt; - color: #333333; - background-color: #d9d9d9; -} - -.calendarDay { - padding: 5px; - border: 1px solid silver; - font-size: 8pt; - color: #333333; - background-color: #ffffff; -} - -.calendarDaySelected { - padding: 5px; - border: 1px solid silver; - font-size: 8pt; - color: #666666; - background-color: #a6ccf7; -} - -.calendarDayWeekend { - padding: 5px; - border: 1px solid silver; - font-size: 8pt; - color: #666666; - background-color: #f7f7f7; -} - -.calendarDayHoliday { - padding: 5px; - border: 1px solid silver; - font-size: 8pt; - color: #666666; - background-color: #f7f7f7; -} - -.calendarDayHeader { - padding: 5px; - border: 1px solid white; - font-size: 8pt; - color: #333333; -} - -.calendarDayHeaderWeekend { - padding: 5px; - border: 1px solid white; - font-size: 8pt; - color: #999999; -} - -.calendarLinkWeekend { - color: #999999; -} - -.calendarLinkHoliday { - color: #999999; -} - -.calendarLinkRecordsExist { - color: #ff0000; -} - -.calendarLinkNonCompleteDay { - color: #800080; -} -/* end of calendar styles */ - -.tableHeader { - font-weight: bold; - text-align: left; -} - -.tableHeaderCentered { - font-weight: bold; - text-align: center; -} - -.rowReportItem { - background-color: #f5f5f5; -} - -.rowReportItemAlt { - background-color: #ffffff; -} - -.rowReportSubtotal { - background-color: #e0e0e0; -} - -.cellLeftAligned { - text-align: left; - vertical-align: top; -} - -.cellRightAligned { - text-align: right; - vertical-align: top; -} - -.cellLeftAlignedSubtotal { - font-weight: bold; - vertical-align: top; -} - -.cellRightAlignedSubtotal { - font-weight: bold; - text-align: right; - vertical-align: top; -} - -.midAligned { - text-align: center; -} - -.sectionHeader { - font-weight: bold; - border-bottom: 1px solid lightgray; -} - -.sectionHeaderNoBorder { - font-weight: bold; -} - -.error { - color: red; -} - -.info_message { - color: #0000c0; -} - -.divider { - background-color: #efefef; -} - -div.table-divider { height: 30px; } - -.uncompleted-entry { - display: inline-block; - height: 8px; - width: 8px; - border: 1px solid rgba(0, 0, 0, .1); - border-radius: 50%; - background-color: rgba(0, 0, 0, .1); -} -.uncompleted-entry.active { background-color: red; } - -.table_icon { - height: 16px; - width: 16px; -} - -/* Mobile styles */ -.mobile-table { - border: 0; - width: 100%; - border-spacing: 0; -} - -.mobile-textarea { - width: 100%; - resize: vertical; - height: 5em; -} - -.mobile-input { - width: 100%; -} - -.mobile-table-details { - width: 100%; - table-layout: fixed; - overflow-wrap: break-word; - word-wrap: break-word; - border-spacing: 1px; - border: 0; -} - -.mobile-table-details td { - padding: 3px; -} diff --git a/login.php b/login.php index ac506fccc..9230f6383 100644 --- a/login.php +++ b/login.php @@ -36,8 +36,8 @@ $cl_password = $request->getParameter('password'); $form = new Form('loginForm'); -$form->addInput(array('type'=>'text','size'=>'25','maxlength'=>'100','name'=>'login','style'=>'width: 220px;','value'=>$cl_login)); -$form->addInput(array('type'=>'password','size'=>'25','maxlength'=>'50','name'=>'password','style'=>'width: 220px;','value'=>$cl_password)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); +$form->addInput(array('type'=>'password','maxlength'=>'50','name'=>'password','value'=>$cl_password)); $form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_login click. $form->addInput(array('type'=>'submit','name'=>'btn_login','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.login'))); From 35d297385731a237fba5777518fc72a5383f2414 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 25 Sep 2020 20:07:10 +0000 Subject: [PATCH 032/587] Some more style fixes. --- WEB-INF/lib/form/Combobox.class.php | 2 ++ WEB-INF/lib/form/Form.class.php | 1 + default.css | 18 ++++++++++++++++++ register.php | 2 +- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/WEB-INF/lib/form/Combobox.class.php b/WEB-INF/lib/form/Combobox.class.php index 88f0b50a9..a0ae0e5a0 100644 --- a/WEB-INF/lib/form/Combobox.class.php +++ b/WEB-INF/lib/form/Combobox.class.php @@ -47,6 +47,7 @@ class Combobox extends FormElement { function __construct($name) { $this->class = 'Combobox'; + $this->css_class = 'dropdown-field'; $this->name = $name; } @@ -68,6 +69,7 @@ function getHtml() { if ($this->id=="") $this->id = $this->name; $html = "\n\tcss_class\""; $html .= " name=\"$this->name\" id=\"$this->id\""; if ($this->size!="") diff --git a/WEB-INF/lib/form/Form.class.php b/WEB-INF/lib/form/Form.class.php index 1bbf2253e..d00261015 100644 --- a/WEB-INF/lib/form/Form.class.php +++ b/WEB-INF/lib/form/Form.class.php @@ -118,6 +118,7 @@ function addInput($params) { $el = new Combobox($params["name"]); $el->setData(@$params["data"]); $el->setDataDefault(@$params["empty"]); + if (isset($params['class'])) $el->setCssClass($params['class']); if (isset($params["multiple"])) { $el->setMultiple($params["multiple"]); $el->name .= '[]'; // Add brackets to the end of name to get back an array on POST. diff --git a/default.css b/default.css index d6b8f6571..8e25f8d48 100644 --- a/default.css +++ b/default.css @@ -191,6 +191,12 @@ div.page-hint { display: inline-block; } +input[type=submit] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + input.text-field { width: 220px; } @@ -199,6 +205,10 @@ input.password-field { width: 220px; } +.dropdown-field { + width: 237px; +} + @media screen and (max-width: 600px) { .large-screen-label { @@ -220,6 +230,14 @@ input.password-field { .what-is-it-text { display: none; } + + div.contribute-msg { + display: none; + } + + div.version-and-copyright { + display: none; + } } @media screen and (max-width: 1170px) { diff --git a/register.php b/register.php index 28c6d8bf5..805b586f4 100644 --- a/register.php +++ b/register.php @@ -77,7 +77,7 @@ $longname_lang[] = array('id'=>I18n::getLangFromFilename($lfile),'name'=>$lname); } $longname_lang = mu_sort($longname_lang, 'name'); -$form->addInput(array('type'=>'combobox','name'=>'lang','style'=>'width: 200px','data'=>$longname_lang,'datakeys'=>array('id','name'),'value'=>$cl_lang)); +$form->addInput(array('type'=>'combobox','name'=>'lang','data'=>$longname_lang,'datakeys'=>array('id','name'),'value'=>$cl_lang)); $form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'manager_name','value'=>$cl_manager_name)); $form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'manager_login','value'=>$cl_manager_login)); From 5be184c6a12d5817bff6792a93bb07e544fa4c19 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 25 Sep 2020 20:08:47 +0000 Subject: [PATCH 033/587] Version update for style changes in previous commit. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index a4d2075af..ebdfa18e0 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} {if $show_users} - + - + {/if} {if $show_tasks} - + - + diff --git a/initialize.php b/initialize.php index 9bd298cb8..4b39a7fa2 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5345"); +define("APP_VERSION", "1.19.23.5346"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From e0addd52441a610995f52c21046db220bb5ec76f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 19:00:49 +0000 Subject: [PATCH 091/587] Made project_edit.php mobile friendly. --- WEB-INF/templates/project_edit2.tpl | 40 ++++++++ initialize.php | 2 +- project_edit.php | 36 ++------ project_edit1.php | 136 ++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 31 deletions(-) create mode 100644 WEB-INF/templates/project_edit2.tpl create mode 100644 project_edit1.php diff --git a/WEB-INF/templates/project_edit2.tpl b/WEB-INF/templates/project_edit2.tpl new file mode 100644 index 000000000..8bffb048d --- /dev/null +++ b/WEB-INF/templates/project_edit2.tpl @@ -0,0 +1,40 @@ +{$forms.projectForm.open} +
Anuko Time Tracker 1.19.23.5295 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5296 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index e7b8069a4..b58425fcb 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + From 92abb45c0decac07198b4c84db999ea8db83d701 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 28 Sep 2020 18:17:54 +0000 Subject: [PATCH 034/587] Dutch translation improved. --- WEB-INF/resources/nl.lang.php | 90 +++++++++++++---------------------- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- 3 files changed, 34 insertions(+), 60 deletions(-) diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 7ce3b19c0..0efc55c61 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -71,8 +71,7 @@ 'error.access_denied' => 'Toegang geweigerd.', 'error.sys' => 'Systeem fout.', 'error.db' => 'Database fout.', -// TODO: translate the following. -// 'error.registered_recently' => 'Registered recently.', +'error.registered_recently' => 'Recent geregistreerd.', 'error.feature_disabled' => 'Functie is uitgeschakeld.', 'error.field' => 'Incorrecte gegevens: "{0}".', 'error.empty' => 'Veld "{0}" is leeg.', @@ -105,22 +104,8 @@ 'error.format' => 'Bestandsformaat niet valide.', 'error.user_count' => 'Limiet op aantal gebruikers.', 'error.expired' => 'Verloop datum is bereikt.', - -// TODO: translate error.file_storage and error.remote_work. - -// Meaning of error.file_storage: an (unspecified) error occurred when trying to communicate with remote -// file storage server (the one that handles attachments). It is a generic message telling us that -// "something went wrong" when trying to do some operation with attachments. -// For example, File Storage server could be offline, or Time Tracker config option is wrong, etc. - -// 'error.file_storage' => 'File storage server error.', // See comment in English file. - -// Meaning of error.remote_work: an (unspecified) error occurred when trying to communicate with -// "Remote Work" server, the one that supports the "Work" plugin, see https://www.anuko.com/time_tracker/what_is/work_plugin.htm -// It is a generic message telling us that "something went wrong" when trying to do some operation with Work plugin. -// For example, Remote Work server could be offline, among other things. - -// 'error.remote_work' => 'Remote work server error.', // See comment in English file. +'error.file_storage' => 'Bestand server probleem.', +'error.remote_work' => 'Werk op afstand server probleem.', // Warning messages. 'warn.sure' => 'Ben je er zeker van?', @@ -151,8 +136,7 @@ 'button.disapprove' => 'Afkeuren', // Labels for controls on forms. Labels in this section are used on multiple forms. -// TODO: translate the following. -// 'label.menu' => 'Menu', +'label.menu' => 'Menu', 'label.group_name' => 'Groepsnaam', 'label.address' => 'Adres', 'label.currency' => 'Munteenheid', @@ -259,9 +243,8 @@ 'label.approval' => 'Rapport goedkeuring', 'label.mark_approved' => 'Markeer goedkeuring', 'label.template' => 'Sjabloon', -// TODO: translate the following. -// 'label.bind_templates_with_projects' => 'Bind templates with projects', -// 'label.prepopulate_note' => 'Prepopulate Note field', +'label.bind_templates_with_projects' => 'Verbind sjabloon aan projecten', +'label.prepopulate_note' => 'Vul het notitieveld van tevoren in', 'label.attachments' => 'Bijlagen', 'label.files' => 'Bestanden', 'label.file' => 'Bestand', @@ -271,15 +254,11 @@ 'label.inactive_users' => 'Inactieve medewerkers', 'label.details' => 'Details', 'label.budget' => 'Budget', -// TODO: translate the following. -// 'label.work' => 'Work', // Table column header for work items, see https://www.anuko.com/time_tracker/what_is/work_plugin.htm -// 'label.offer' => 'Offer', // Table column header for offers, see https://www.anuko.com/time_tracker/what_is/work_plugin.htm -// 'label.contractor' => 'Contractor', // Table column header for offers (contractor is someone who offers to do work). - // Technically, it is either an org name or a combination of org and group names - // because both work items and offers are owned by Time Tracker groups of users. -// 'label.how_to_pay' => 'How to pay', // Label for the "How to pay" field on offers, which allows contractors to specify - // how to pay them, for example: paypal email, check by mail to a specific address, etc. -// 'label.moderator_comment' => 'Moderator comment', // Label for "Moderator comment" field that explains something. +'label.work' => 'Werk', +'label.offer' => 'Aanbod', +'label.contractor' => 'Aanbieder', +'label.how_to_pay' => 'Betaalwijze', +'label.moderator_comment' => 'Commentaar', // Entity names. 'entity.time' => 'tijd', @@ -304,8 +283,7 @@ 'title.expenses' => 'Kosten', 'title.edit_expense' => 'Bewerk kosten artikel', 'title.delete_expense' => 'Verwijder kosten artikel', -// TODO: translate the following. -// 'title.expense_files' => 'Expense Item Files', +'title.expense_files' => 'Kosten bestanden', 'title.predefined_expenses' => 'Vaste kosten', 'title.add_predefined_expense' => 'Vaste kosten toevoegen', 'title.edit_predefined_expense' => 'Vaste kosten bewerken', @@ -384,17 +362,15 @@ 'title.active_work' => 'Actief werk', 'title.available_work' => 'Beschikbaar werk', 'title.inactive_work' => 'Inactief werk', -// TODO: translate the following. -// 'title.pending_work' => 'Pending Work', // Work items pending moderator approval. -// 'title.offer' => 'Offer', +'title.pending_work' => 'Werk in afwachting van goedkeuring', +'title.offer' => 'Aanbod', 'title.add_offer' => 'Aanbieding toevoegen', 'title.edit_offer' => 'Aanbieding bewerken', 'title.delete_offer' => 'Aanbieding verwijderen', 'title.active_offers' => 'Actieve aanbiedingen', 'title.available_offers' => 'Beschikbare aanbiedingen', 'title.inactive_offers' => 'Inactieve aanbiedingen', -// TODO: translate the following. -// 'title.pending_offers' => 'Pending Offers', // Offers pending moderator approval. +'title.pending_offers' => 'Aangeboden werk in afwachting van goedkeuring', // Section for common strings inside combo boxes on forms. Strings shared between forms shall be placed here. // Strings that are used in a single form must go to the specific form section. @@ -423,8 +399,7 @@ 'dropdown.status_inactive' => 'inactief', 'dropdown.delete' => 'verwijderen', 'dropdown.do_not_delete' => 'niet verwijderen', -// TODO: translate the following. -// 'dropdown.pending_approval' => 'pending approval', +'dropdown.pending_approval' => 'in afwachting van goedkeuring', 'dropdown.approved' => 'goedgekeurd', 'dropdown.not_approved' => 'afgekeurd', 'dropdown.paid' => 'betaald', @@ -641,24 +616,23 @@ 'form.timesheet_view.disapprove_body' => "Jouw tijdenoverzicht %s is afgekeurd.

%s", // Display Options form. See example at https://timetracker.anuko.com/display_options.php. +// TODO: fix form.display_options.note_on_separate_row. Kolom does not seem correct. Note on separate ROW (not column). 'form.display_options.note_on_separate_row' => 'Notitie in aparte kolom', -// TODO: translate the following. -// 'form.display_options.not_complete_days' => 'Not complete days', -// 'form.display_options.custom_css' => 'Custom CSS', +'form.display_options.not_complete_days' => 'Niet complete dagen', +'form.display_options.custom_css' => 'Aangepaste CSS', // Work plugin strings. See example at https://timetracker.anuko.com/work.php -// TODO: translate the following. -// 'work.error.work_not_available' => 'Work item is not available.', -// 'work.error.offer_not_available' => 'Offer is not available.', -// 'work.type.one_time' => 'one time', // Work type is "one time job" for well defined work ("do exactly this"). -// 'work.type.ongoing' => 'ongoing', // Work type is "ongoing" for complex jobs (billed by the hour, multiple contractors, etc.) -// 'work.label.own_work' => 'Own work', -// 'work.label.own_offers' => 'Own offers', -// 'work.label.offers' => 'Offers', -// 'work.button.send_message' => 'Send message', -// 'work.button.make_offer' => 'Make offer', -// 'work.button.accept' => 'Accept', -// 'work.button.decline' => 'Decline', -// 'work.title.send_message' => 'Sending Message', -// 'work.msg.message_sent' => 'Message sent.', +'work.error.work_not_available' => 'Werk onderdeel is niet beschikbaar.', +'work.error.offer_not_available' => 'Aanbod is niet beschikbaar.', +'work.type.one_time' => 'eenmalig', +'work.type.ongoing' => 'doorlopend', +'work.label.own_work' => 'Eigen werk', +'work.label.own_offers' => 'Eigen aanbod', +'work.label.offers' => 'Aanbiedingen', +'work.button.send_message' => 'Verstuur bericht', +'work.button.make_offer' => 'maak aanbieding', +'work.button.accept' => 'Accepteer', +'work.button.decline' => 'Weiger', +'work.title.send_message' => 'Bericht wordt verstuurd', +'work.msg.message_sent' => 'Bericht is verstuurd.', ); diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index ebdfa18e0..5ef6a669d 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- \n"; + $html .= " \n"; $html .= "
Anuko Time Tracker 1.19.23.5296 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5297 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index b58425fcb..037c4982a 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + From c4488f2a1e7d9c0d2e931fa0b62e0697dab1b650 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 28 Sep 2020 18:49:30 +0000 Subject: [PATCH 035/587] Cosmetic comment fix. --- WEB-INF/resources/nl.lang.php | 3 +-- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 0efc55c61..1705e2cd3 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -616,8 +616,7 @@ 'form.timesheet_view.disapprove_body' => "Jouw tijdenoverzicht %s is afgekeurd.

%s", // Display Options form. See example at https://timetracker.anuko.com/display_options.php. -// TODO: fix form.display_options.note_on_separate_row. Kolom does not seem correct. Note on separate ROW (not column). -'form.display_options.note_on_separate_row' => 'Notitie in aparte kolom', +'form.display_options.note_on_separate_row' => 'Notitie in aparte kolom', // Translator (Henk) comment: "kolom is the right word in Dutch." 'form.display_options.not_complete_days' => 'Niet complete dagen', 'form.display_options.custom_css' => 'Aangepaste CSS', diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 5ef6a669d..ce0bac546 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- +
Anuko Time Tracker 1.19.23.5297 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5298 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 037c4982a..ab4de13ee 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + From f01cf6083d8f021a38aff99321c9dbac680dd54d Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 28 Sep 2020 21:04:47 +0000 Subject: [PATCH 036/587] Incremental cleanup. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/login.tpl | 21 --------------------- login.php | 11 ++--------- 4 files changed, 4 insertions(+), 32 deletions(-) delete mode 100644 WEB-INF/templates/login.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index ce0bac546..dd471c7af 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
-
Anuko Time Tracker 1.19.23.5298 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5299 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index ab4de13ee..ff133ff0d 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/login.tpl b/WEB-INF/templates/login.tpl deleted file mode 100644 index d7d9b93f4..000000000 --- a/WEB-INF/templates/login.tpl +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -
- {$forms.loginForm.open} - {include file="login.`$smarty.const.AUTH_MODULE`.tpl"} - {$forms.loginForm.close} -
- -{if !empty($about_text)} -
{$about_text}
-{/if} diff --git a/login.php b/login.php index 9230f6383..b4822ac82 100644 --- a/login.php +++ b/login.php @@ -85,13 +85,6 @@ $smarty->assign('show_hint', $show_hint); $smarty->assign('onload', 'onLoad="document.loginForm.'.(!$cl_login?'login':'password').'.focus()"'); $smarty->assign('title', $i18n->get('title.login')); -if (defined('DEBUG_MOBILE')) - $smarty->assign('content_page_name', 'login2.tpl'); -else { - $smarty->assign('content_page_name', 'login.tpl'); -} +$smarty->assign('content_page_name', 'login2.tpl'); $smarty->assign('about_text', $i18n->get('form.login.about')); -if (defined('DEBUG_MOBILE')) - $smarty->display('index2.tpl'); -else - $smarty->display('index.tpl'); +$smarty->display('index2.tpl'); From 336d6a82a5e0531ec2b8073948d364bab7d8d81f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 28 Sep 2020 21:09:09 +0000 Subject: [PATCH 037/587] Incremental cleanup. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/login.db.tpl | 21 --------------------- WEB-INF/templates/login.ldap.tpl | 28 ---------------------------- 4 files changed, 2 insertions(+), 51 deletions(-) delete mode 100644 WEB-INF/templates/login.db.tpl delete mode 100644 WEB-INF/templates/login.ldap.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index dd471c7af..6c86dd43a 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
-
Anuko Time Tracker 1.19.23.5299 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5300 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index ff133ff0d..abb4a5bb6 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/login.db.tpl b/WEB-INF/templates/login.db.tpl deleted file mode 100644 index 977d9b996..000000000 --- a/WEB-INF/templates/login.db.tpl +++ /dev/null @@ -1,21 +0,0 @@ - - - {$i18n.label.login}: - - - - {$i18n.label.password}: - - - - - - - - - - - - -
{$forms.loginForm.login.control}
{$forms.loginForm.password.control}
 {$i18n.form.login.forgot_password}
 
{$forms.loginForm.btn_login.control}
- \ No newline at end of file diff --git a/WEB-INF/templates/login.ldap.tpl b/WEB-INF/templates/login.ldap.tpl deleted file mode 100644 index bf285dc29..000000000 --- a/WEB-INF/templates/login.ldap.tpl +++ /dev/null @@ -1,28 +0,0 @@ - - {if $show_hint} - - - - - - - {/if} - - {$i18n.label.login}: - - - - {$i18n.label.password}: - - - - - - - - - - - -
{$i18n.label.ldap_hint}
 
{$forms.loginForm.login.control} @{$Auth_ldap_params.default_domain}
{$forms.loginForm.password.control}
 
 
{$forms.loginForm.btn_login.control}
- \ No newline at end of file From 6356d37222081b4689cb6987a3cc8c8bf3ac8c79 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 28 Sep 2020 21:18:08 +0000 Subject: [PATCH 038/587] Some more cleanup. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/register.tpl | 51 ---------------------------------- register.php | 11 ++------ 4 files changed, 4 insertions(+), 62 deletions(-) delete mode 100644 WEB-INF/templates/register.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 6c86dd43a..7eb578c96 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} +{if $show_start} + + + + + + + + + + +{/if} + + + diff --git a/WEB-INF/templates/work/header.tpl b/WEB-INF/templates/work/header.tpl index 582e76144..75a0d586f 100644 --- a/WEB-INF/templates/work/header.tpl +++ b/WEB-INF/templates/work/header.tpl @@ -1,11 +1,11 @@ - + - + {if $i18n.language.rtl} - + {/if} Time Tracker{if $title} - {$title}{/if} @@ -60,8 +60,8 @@
Anuko Time Tracker 1.19.23.5300 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5301 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index abb4a5bb6..5e45dda42 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/register.tpl b/WEB-INF/templates/register.tpl deleted file mode 100644 index cdf343f2d..000000000 --- a/WEB-INF/templates/register.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{$forms.groupForm.open} - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{$i18n.label.group_name} (*):{$forms.groupForm.group_name.control} {$i18n.label.what_is_it}
{$i18n.label.currency}:{$forms.groupForm.currency.control}
{$i18n.label.language}:{$forms.groupForm.lang.control}
 
{$i18n.label.manager_name} (*):{$forms.groupForm.manager_name.control}
{$i18n.label.manager_login} (*):{$forms.groupForm.manager_login.control}
{$i18n.label.password} (*):{$forms.groupForm.password1.control}
{$i18n.label.confirm_password} (*):{$forms.groupForm.password2.control}
{$i18n.label.email}{if isTrue('EMAIL_REQUIRED')} (*){/if}:{$forms.groupForm.manager_email.control}
{$i18n.label.required_fields}
 
{$forms.groupForm.btn_submit.control}
-
-{$forms.groupForm.close} diff --git a/register.php b/register.php index 805b586f4..a036c26d4 100644 --- a/register.php +++ b/register.php @@ -118,12 +118,5 @@ $smarty->assign('title', $i18n->get('title.add_group')); $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.groupForm.group_name.focus()"'); -if (defined('DEBUG_MOBILE')) - $smarty->assign('content_page_name', 'register2.tpl'); -else { - $smarty->assign('content_page_name', 'register.tpl'); -} -if (defined('DEBUG_MOBILE')) - $smarty->display('index2.tpl'); -else - $smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'register2.tpl'); +$smarty->display('index2.tpl'); From 3b1879fa7a3bdb3043ef7ddf1d0d009448c65645 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 28 Sep 2020 21:39:13 +0000 Subject: [PATCH 039/587] Recoded password_reset.php for mobile access. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/password_reset.tpl | 21 --------------------- WEB-INF/templates/password_reset2.tpl | 13 +++++++++++++ password_reset.php | 6 +++--- 5 files changed, 18 insertions(+), 26 deletions(-) delete mode 100644 WEB-INF/templates/password_reset.tpl create mode 100644 WEB-INF/templates/password_reset2.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 7eb578c96..c24fce3db 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && - ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() || + (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() || $user->isPluginEnabled('cl'))} {/if} - {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode())} {/if} - {if ($smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} + {if (constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} {/if} {if $user->can('view_users') || $user->can('manage_users')} @@ -148,11 +148,11 @@
Anuko Time Tracker 1.19.23.5301 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5302 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 5e45dda42..d444412cf 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/password_reset.tpl b/WEB-INF/templates/password_reset.tpl deleted file mode 100644 index a8dadf957..000000000 --- a/WEB-INF/templates/password_reset.tpl +++ /dev/null @@ -1,21 +0,0 @@ -{$forms.resetPasswordForm.open} - - - - -
- - - - - - - - - - - - -
{$i18n.label.login}:{$forms.resetPasswordForm.login.control}
 
 {$forms.resetPasswordForm.btn_submit.control}
-
-{$forms.resetPasswordForm.close} diff --git a/WEB-INF/templates/password_reset2.tpl b/WEB-INF/templates/password_reset2.tpl new file mode 100644 index 000000000..45a0d5051 --- /dev/null +++ b/WEB-INF/templates/password_reset2.tpl @@ -0,0 +1,13 @@ +{$forms.resetPasswordForm.open} + + + + + + + + + + +
{$forms.resetPasswordForm.login.control}
{$forms.resetPasswordForm.btn_submit.control}
+{$forms.resetPasswordForm.close} diff --git a/password_reset.php b/password_reset.php index 8e3badbc4..af596491d 100644 --- a/password_reset.php +++ b/password_reset.php @@ -39,7 +39,7 @@ $cl_login = $request->getParameter('login'); $form = new Form('resetPasswordForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.reset_password'))); if ($request->isPost()) { @@ -117,5 +117,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.resetPasswordForm.login.focus()"'); $smarty->assign('title', $i18n->get('title.reset_password')); -$smarty->assign('content_page_name', 'password_reset.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'password_reset2.tpl'); +$smarty->display('index2.tpl'); From 0ffecde6a0f5e99c94be8e614be27e68fc599762 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 30 Sep 2020 16:08:42 +0000 Subject: [PATCH 040/587] Added styles for page-messages class. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- default.css | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index c24fce3db..41a8138e5 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} - - + +
Anuko Time Tracker 1.19.23.5302 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5303 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index d444412cf..f0348a191 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/default.css b/default.css index 8e25f8d48..41445cb71 100644 --- a/default.css +++ b/default.css @@ -106,6 +106,12 @@ div.user-details { color: red; } +.page-messages { + margin-top: .5rem; + text-align: center; + color: blue; +} + .page-content { text-align: center; } From 18b9e5d6cb7a0d817bc53da915f4daa5744885f7 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 30 Sep 2020 18:01:12 +0000 Subject: [PATCH 041/587] Recoded password_change.php for mobile access. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/password_change.tpl | 41 -------------------------- WEB-INF/templates/password_change2.tpl | 22 ++++++++++++++ password_change.php | 4 +-- 5 files changed, 26 insertions(+), 45 deletions(-) delete mode 100644 WEB-INF/templates/password_change.tpl create mode 100644 WEB-INF/templates/password_change2.tpl diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 41a8138e5..9906a4660 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
-
Anuko Time Tracker 1.19.23.5303 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5304 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index f0348a191..6c131b1f1 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/password_change.tpl b/WEB-INF/templates/password_change.tpl deleted file mode 100644 index 797f4a358..000000000 --- a/WEB-INF/templates/password_change.tpl +++ /dev/null @@ -1,41 +0,0 @@ -{$forms.newPasswordForm.open} - - - - -
-{if $result_message} - - -
{$result_message}
-{else} - - - - - - - - - - - - - - - - - - - - - - - - - - -
{$i18n.form.change_password.tip}
 
{$i18n.label.password} (*):{$forms.newPasswordForm.password1.control}
{$i18n.label.confirm_password} (*):{$forms.newPasswordForm.password2.control}
 
{$i18n.label.required_fields}
 {$forms.newPasswordForm.btn_save.control}
-{/if} -
-{$forms.newPasswordForm.close} diff --git a/WEB-INF/templates/password_change2.tpl b/WEB-INF/templates/password_change2.tpl new file mode 100644 index 000000000..703c46aaa --- /dev/null +++ b/WEB-INF/templates/password_change2.tpl @@ -0,0 +1,22 @@ +{$forms.newPasswordForm.open} +
{$i18n.form.change_password.tip}
+
+ + + + + + + + + + + + + + + + + +
{$forms.newPasswordForm.password1.control}
{$forms.newPasswordForm.password2.control}
{$i18n.label.required_fields}
{$forms.newPasswordForm.btn_save.control}
+{$forms.newPasswordForm.close} diff --git a/password_change.php b/password_change.php index 5fea82629..9876de233 100644 --- a/password_change.php +++ b/password_change.php @@ -101,5 +101,5 @@ $smarty->assign('forms', array($form->getName() => $form->toArray())); $smarty->assign('title', $i18n->get('title.change_password')); -$smarty->assign('content_page_name', 'password_change.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'password_change2.tpl'); +$smarty->display('index2.tpl'); From e5bab2ede37a71c5b05829e57ce57c1aa7904f89 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 3 Oct 2020 12:42:46 +0000 Subject: [PATCH 042/587] Started to work on a mobile friendly time2.php. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/time2.tpl | 276 ++++++++++++++++++ default.css | 24 ++ time2.php | 507 ++++++++++++++++++++++++++++++++++ 5 files changed, 809 insertions(+), 2 deletions(-) create mode 100644 WEB-INF/templates/time2.tpl create mode 100644 time2.php diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 9906a4660..fa450f819 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
-
Anuko Time Tracker 1.19.23.5304 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5305 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 6c131b1f1..242f95431 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl new file mode 100644 index 000000000..8a0a186ec --- /dev/null +++ b/WEB-INF/templates/time2.tpl @@ -0,0 +1,276 @@ +{include file="time_script.tpl"} + + + +{$forms.timeRecordForm.open} +
{$forms.timeRecordForm.date.control}
+ + + + + +
+ +{if $user_dropdown} + + + + + + +{/if} +{if $show_client} + + + + + + +{/if} + + + + + +
{$forms.timeRecordForm.user.control}
{$forms.timeRecordForm.client.control}
{$forms.timeRecordForm.note1.control}
+
{$forms.timeRecordForm.date.control}
+ + + + + + + + + + + + +{if $show_navigation} + + + +{/if} + + + + +
+ {$i18n.label.day_view} / {$i18n.label.week_view} +
+ +{if $user_dropdown} + + + + +{/if} +{if $show_client} + + + + +{/if} +{if $show_billable} + + + + +{/if} +{if $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + + + {assign var="control_name" value='time_field_'|cat:$timeField['id']} + + + {/foreach} +{/if} +{if $show_project} + + + + +{/if} +{if $show_task} + + + + +{/if} +{if $show_start} + + + + + + + + +{/if} +{if $show_duration} + + + + +{/if} +{if $show_files} + + + + +{/if} +{if $template_dropdown} + + + + +{/if} +
{$i18n.label.user}:{$forms.timeRecordForm.user.control}
{$i18n.label.client}{if $user->isOptionEnabled('client_required')} (*){/if}:{$forms.timeRecordForm.client.control}
 
{$timeField['label']|escape}{if $timeField['required']} (*){/if}:{$forms.timeRecordForm.$control_name.control}
{$i18n.label.project} (*):{$forms.timeRecordForm.project.control}
{$i18n.label.task}{if $task_required} (*){/if}:{$forms.timeRecordForm.task.control}
{$i18n.label.start}:{$forms.timeRecordForm.start.control} 
{$i18n.label.finish}:{$forms.timeRecordForm.finish.control} 
{$i18n.label.duration}:{$forms.timeRecordForm.duration.control} {if $user->getDecimalMark() == ','}{str_replace('.', ',', $i18n.form.time.duration_format)}{else}{$i18n.form.time.duration_format}{/if}
{$i18n.label.file}:{$forms.timeRecordForm.newfile.control}
{$i18n.label.template}:{$forms.timeRecordForm.template.control}
+
+ + +
{$forms.timeRecordForm.date.control}
+
+ + + + + + + + + +
{$i18n.label.note}:{$forms.timeRecordForm.note.control}
{$forms.timeRecordForm.btn_submit.control}
+ + + + + +
+{if $time_records} + + + {if $show_client} + + {/if} + {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + + {/foreach} + {/if} + {if $show_project} + + {/if} + {if $show_task} + + {/if} + {if $show_start} + + + {/if} + + {if $show_note_column} + + {/if} + {if $show_files} + + {/if} + + + + {foreach $time_records as $record} + + {if $show_client} + + {/if} + {* record custom fileds *} + {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + {assign var="control_name" value='time_field_'|cat:$timeField['id']} + + {/foreach} + {/if} + {if $show_project} + + {/if} + {if $show_task} + + {/if} + {if $show_start} + + + {/if} + + {if $show_note_column} + + {/if} + {if $show_files} + {if $record.has_files} + + {else} + + {/if} + {/if} + + + + {if $show_note_row && $record.comment} + + + + + {/if} + {/foreach} +
{$i18n.label.client}{$timeField['label']|escape}{$i18n.label.project}{$i18n.label.task}{$i18n.label.start}{$i18n.label.finish}{$i18n.label.duration}{$i18n.label.note}
{$record.client|escape}{$record.$control_name|escape}{$record.project|escape}{$record.task|escape}{if $record.start}{$record.start}{else} {/if}{if $record.finish}{$record.finish}{else} {/if}{if ($record.duration == '0:00' && $record.start <> '')}{$i18n.form.time.uncompleted}{else}{$record.duration}{/if}{if $record.comment}{$record.comment|escape}{else} {/if}{$i18n.label.files}{$i18n.label.files} + {if $record.approved || $record.timesheet_id || $record.invoice_id} +   + {else} + {$i18n.label.edit} + {if ($record.duration == '0:00' && $record.start <> '')} + + + + + {/if} + {/if} + + {if $record.approved || $record.timesheet_id || $record.invoice_id} +   + {else} + {$i18n.label.delete} + {/if} +
{$i18n.label.note}:{$record.comment|escape}
+{/if} +
+ + + + + + + {if $user->isPluginEnabled('mq')} + + + {if $over_balance} + + {else} + + {/if} + + + + {if $over_quota} + + {else} + + {/if} + + {/if} +
{$i18n.label.week_total}: {$week_total}{$i18n.label.day_total}: {$day_total}
{$i18n.label.month_total}: {$month_total}{$i18n.form.time.over_balance}: {$balance_remaining}{$i18n.form.time.remaining_balance}: {$balance_remaining}
{$i18n.label.quota}: {$month_quota}{$i18n.form.time.over_quota}: {$quota_remaining}{$i18n.form.time.remaining_quota}: {$quota_remaining}
+ +{$forms.timeRecordForm.close} diff --git a/default.css b/default.css index 41445cb71..04c89795c 100644 --- a/default.css +++ b/default.css @@ -215,6 +215,22 @@ input.password-field { width: 237px; } +.small-screen-calendar { + display: none; + width: 210px; + margin-top: 1rem; + margin-left: auto; + margin-right: auto +} + +.large-screen-calendar { + display: inline-block; + width: 210px; + margin-top: 1rem; + margin-left: auto; + margin-right: auto +} + @media screen and (max-width: 600px) { .large-screen-label { @@ -225,6 +241,14 @@ input.password-field { display: block; } + .small-screen-calendar { + display: block; + } + + .large-screen-calendar { + display: none; + } + .small-screen-form-control-separator { display: block; } diff --git a/time2.php b/time2.php new file mode 100644 index 000000000..ced38613f --- /dev/null +++ b/time2.php @@ -0,0 +1,507 @@ +behalf_id && (!$user->can('track_time') || !$user->checkBehalfId())) { + header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. + exit(); +} +if (!$user->behalf_id && !$user->can('track_own_time') && !$user->adjustBehalfId()) { + header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to work on behalf. + exit(); +} +if ($request->isPost()) { + $userChanged = $request->getParameter('user_changed'); // Reused in multiple places below. + if ($userChanged && !($user->can('track_time') && $user->isUserValid($request->getParameter('user')))) { + header('Location: access_denied.php'); // User changed, but no right or wrong user id. + exit(); + } +} +// End of access checks. + +// Determine user for whom we display this page. +if ($request->isPost() && $userChanged) { + $user_id = $request->getParameter('user'); + $user->setOnBehalfUser($user_id); +} else { + $user_id = $user->getUser(); +} + +$group_id = $user->getGroup(); +$config = new ttConfigHelper($user->getConfig()); + +$showClient = $user->isPluginEnabled('cl'); +$showBillable = $user->isPluginEnabled('iv'); +$trackingMode = $user->getTrackingMode(); +$showProject = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; +$showTask = MODE_PROJECTS_AND_TASKS == $trackingMode; +if ($showTask) $taskRequired = $config->getDefinedValue('task_required'); +$recordType = $user->getRecordType(); +$showStart = TYPE_START_FINISH == $recordType || TYPE_ALL == $recordType; +$showDuration = TYPE_DURATION == $recordType || TYPE_ALL == $recordType; +$showFiles = $user->isPluginEnabled('at'); +$showRecordCustomFields = $user->isOptionEnabled('record_custom_fields'); + +// Initialize and store date in session. +$cl_date = $request->getParameter('date', @$_SESSION['date']); +$selected_date = new DateAndTime(DB_DATEFORMAT, $cl_date); +if($selected_date->isError()) + $selected_date = new DateAndTime(DB_DATEFORMAT); +if(!$cl_date) + $cl_date = $selected_date->toString(DB_DATEFORMAT); +$_SESSION['date'] = $cl_date; + +// Use custom fields plugin if it is enabled. +if ($user->isPluginEnabled('cf')) { + require_once('plugins/CustomFields.class.php'); + $custom_fields = new CustomFields(); + $smarty->assign('custom_fields', $custom_fields); +} + +$showNoteColumn = !$config->getDefinedValue('time_note_on_separate_row'); +$showNoteRow = $config->getDefinedValue('time_note_on_separate_row'); +if ($showNoteRow) { + // Determine column span for note field. + $colspan = 0; + if ($showClient) $colspan++; + if ($showRecordCustomFields && $custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $colspan++; + } + } + if ($showProject) $colspan++; + if ($showTask) $colspan++; + if ($showStart) $colspan++; + if ($showFinish) $colspan++; + $colspan++; // There is always a duration. + if ($showFiles) $colspan++; + $colspan++; // There is always an edit column. + // $colspan++; // There is always a delete column. + // $colspan--; // Remove one column for label. + $smarty->assign('colspan', $colspan); +} + +if ($user->isPluginEnabled('mq')){ + require_once('plugins/MonthlyQuota.class.php'); + $quota = new MonthlyQuota(); + $month_quota_minutes = $quota->getUserQuota($selected_date->mYear, $selected_date->mMonth); + $quota_minutes_from_1st = $quota->getUserQuotaFrom1st($selected_date); + $month_total = ttTimeHelper::getTimeForMonth($selected_date); + $month_total_minutes = ttTimeHelper::toMinutes($month_total); + $balance_left = $quota_minutes_from_1st - $month_total_minutes; + $minutes_left = $month_quota_minutes - $month_total_minutes; + + $smarty->assign('month_total', $month_total); + $smarty->assign('month_quota', ttTimeHelper::toAbsDuration($month_quota_minutes)); + $smarty->assign('over_balance', $balance_left < 0); + $smarty->assign('balance_remaining', ttTimeHelper::toAbsDuration($balance_left)); + $smarty->assign('over_quota', $minutes_left < 0); + $smarty->assign('quota_remaining', ttTimeHelper::toAbsDuration($minutes_left)); +} + +// Initialize variables. +$cl_start = trim($request->getParameter('start')); +$cl_finish = trim($request->getParameter('finish')); +$cl_duration = trim($request->getParameter('duration')); +$cl_note = trim($request->getParameter('note')); +$cl_billable = 1; +if ($showBillable) { + if ($request->isPost()) { + $cl_billable = $request->getParameter('billable'); + $_SESSION['billable'] = (int) $cl_billable; + } else + if (isset($_SESSION['billable'])) + $cl_billable = $_SESSION['billable']; +} +$cl_client = $request->getParameter('client', ($request->isPost() ? null : @$_SESSION['client'])); +$_SESSION['client'] = $cl_client; +$cl_project = $request->getParameter('project', ($request->isPost() ? null : @$_SESSION['project'])); +$_SESSION['project'] = $cl_project; +$cl_task = $request->getParameter('task', ($request->isPost() ? null : @$_SESSION['task'])); +$_SESSION['task'] = $cl_task; + +// Handle time custom fields. +$timeCustomFields = array(); +if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $control_name = 'time_field_'.$timeField['id']; + $cl_control_name = $request->getParameter($control_name, ($request->isPost() ? null : @$_SESSION[$control_name])); + $_SESSION[$control_name] = $cl_control_name; + $timeCustomFields[$timeField['id']] = array('field_id' => $timeField['id'], + 'control_name' => $control_name, + 'label' => $timeField['label'], + 'type' => $timeField['type'], + 'required' => $timeField['required'], + 'value' => trim($cl_control_name)); + } +} + +// Elements of timeRecordForm. +$form = new Form('timeRecordForm'); + +// Dropdown for user and a hidden control to indicate user change. +if ($user->can('track_time')) { + $rank = $user->getMaxRankForGroup($group_id); + if ($user->can('track_own_time')) + $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); + else + $options = array('status'=>ACTIVE,'max_rank'=>$rank); + $user_list = $user->getUsers($options); + if (count($user_list) >= 1) { + $form->addInput(array('type'=>'combobox', + 'onchange'=>'document.timeRecordForm.user_changed.value=1;document.timeRecordForm.submit();', + 'name'=>'user', + 'style'=>'width: 250px;', + 'value'=>$user_id, + 'data'=>$user_list, + 'datakeys'=>array('id','name'))); + $form->addInput(array('type'=>'hidden','name'=>'user_changed')); + $smarty->assign('user_dropdown', 1); + } +} + +// Dropdown for clients in MODE_TIME. Use all active clients. +// Note: for other tracking modes the control is added further below. +if (MODE_TIME == $trackingMode && $showClient) { + $active_clients = ttGroupHelper::getActiveClients(true); + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillProjectDropdown(this.value);', + 'name'=>'client', + 'style'=>'width: 250px;', + 'value'=>$cl_client, + 'data'=>$active_clients, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + // Note: in other modes the client list is filtered to relevant clients only. See below. +} + +// Billable checkbox. +if ($showBillable) + $form->addInput(array('type'=>'checkbox','name'=>'billable','value'=>$cl_billable)); + +// If we have time custom fields - add controls for them. +if ($custom_fields && $custom_fields->timeFields) { + foreach ($custom_fields->timeFields as $timeField) { + $field_name = 'time_field_'.$timeField['id']; + if ($timeField['type'] == CustomFields::TYPE_TEXT) { + $form->addInput(array('type'=>'text','name'=>$field_name,'style'=>'width: 250px;','value'=>$timeCustomFields[$timeField['id']]['value'])); + } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { + $form->addInput(array('type'=>'combobox','name'=>$field_name, + 'style'=>'width: 250px;', + 'data'=>CustomFields::getOptions($timeField['id']), + 'value'=>$timeCustomFields[$timeField['id']]['value'], + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + } + } +} + +// If we show project dropdown, add controls for project and client. +if ($showProject) { + // Dropdown for projects assigned to user. + $options['include_templates'] = $user->isPluginEnabled('tp') && $config->getDefinedValue('bind_templates_with_projects'); + $project_list = $user->getAssignedProjects($options); + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', + 'name'=>'project', + 'style'=>'width: 250px;', + 'value'=>$cl_project, + 'data'=>$project_list, + 'datakeys'=>array('id','name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + + // Client dropdown. + if ($showClient) { + $active_clients = ttGroupHelper::getActiveClients(true); + // We need an array of assigned project ids to do some trimming. + foreach($project_list as $project) + $projects_assigned_to_user[] = $project['id']; + + // Build a client list out of active clients. Use only clients that are relevant to user. + // Also trim their associated project list to only assigned projects (to user). + foreach($active_clients as $client) { + $projects_assigned_to_client = explode(',', $client['projects']); + if (is_array($projects_assigned_to_client) && is_array($projects_assigned_to_user)) + $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); + if ($intersection) { + $client['projects'] = implode(',', $intersection); + $client_list[] = $client; + } + } + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillProjectDropdown(this.value);', + 'name'=>'client', + 'style'=>'width: 250px;', + 'value'=>$cl_client, + 'data'=>$client_list, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + } +} + +// Task dropdown. +if ($showTask) { + $task_list = ttGroupHelper::getActiveTasks(); + $form->addInput(array('type'=>'combobox', + 'name'=>'task', + 'style'=>'width: 250px;', + 'value'=>$cl_task, + 'data'=>$task_list, + 'datakeys'=>array('id','name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); +} + +// Start and finish controls. +if ($showStart) { + $form->addInput(array('type'=>'text','name'=>'start','value'=>$cl_start,'onchange'=>"formDisable('start');")); + $form->addInput(array('type'=>'text','name'=>'finish','value'=>$cl_finish,'onchange'=>"formDisable('finish');")); + if ($user->punch_mode && !$user->canOverridePunchMode()) { + // Make the start and finish fields read-only. + $form->getElement('start')->setEnabled(false); + $form->getElement('finish')->setEnabled(false); + } +} + +// Duration control. +if ($showDuration) + $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); + +// File upload control. +if ($showFiles) + $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); + +// If we have templates, add a dropdown to select one. +if ($user->isPluginEnabled('tp')){ + $template_list = ttGroupHelper::getActiveTemplates(); + if (count($template_list) >= 1) { + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillNote(this.value);', + 'name'=>'template', + 'style'=>'width: 250px;', + 'data'=>$template_list, + 'datakeys'=>array('id','name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $smarty->assign('template_dropdown', 1); + $smarty->assign('bind_templates_with_projects', $config->getDefinedValue('bind_templates_with_projects')); + $smarty->assign('prepopulate_note', $config->getDefinedValue('prepopulate_note')); + $smarty->assign('template_list', $template_list); + } +} + +// Note control. +if (!defined('NOTE_INPUT_HEIGHT')) + define('NOTE_INPUT_HEIGHT', 40); +$form->addInput(array('type'=>'textarea','name'=>'note','style'=>'width: 600px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_note)); +$form->addInput(array('type'=>'textarea','name'=>'note1','value'=>$cl_note)); + +// Calendar. +$form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar + +// A hidden control for today's date from user's browser. +$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_submit click. + +// Submit button. +$form->addInput(array('type'=>'submit','name'=>'btn_submit','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.submit'))); + +if ($request->isPost()) { + if ($request->getParameter('btn_submit')) { + // Submit button clicked. + // Validate user input. + if ($showClient && $user->isOptionEnabled('client_required') && !$cl_client) + $err->add($i18n->get('error.client')); + // Validate input in time custom fields. + if ($custom_fields && $custom_fields->timeFields) { + foreach ($timeCustomFields as $timeField) { + // Validation is the same for text and dropdown fields. + if (!ttValidString($timeField['value'], !$timeField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($timeField['label'])); + } + } + if ($showProject) { + if (!$cl_project) $err->add($i18n->get('error.project')); + } + if ($showTask && $taskRequired) { + if (!$cl_task) $err->add($i18n->get('error.task')); + } + if (strlen($cl_duration) == 0) { + if ($cl_start || $cl_finish) { + if (!ttTimeHelper::isValidTime($cl_start)) + $err->add($i18n->get('error.field'), $i18n->get('label.start')); + if ($cl_finish) { + if (!ttTimeHelper::isValidTime($cl_finish)) + $err->add($i18n->get('error.field'), $i18n->get('label.finish')); + if (!ttTimeHelper::isValidInterval($cl_start, $cl_finish)) + $err->add($i18n->get('error.interval'), $i18n->get('label.finish'), $i18n->get('label.start')); + } + } else { + if ($showStart) { + $err->add($i18n->get('error.empty'), $i18n->get('label.start')); + $err->add($i18n->get('error.empty'), $i18n->get('label.finish')); + } + if ($showDuration) + $err->add($i18n->get('error.empty'), $i18n->get('label.duration')); + } + } else { + if (false === ttTimeHelper::postedDurationToMinutes($cl_duration)) + $err->add($i18n->get('error.field'), $i18n->get('label.duration')); + } + if (!ttValidString($cl_note, true)) $err->add($i18n->get('error.field'), $i18n->get('label.note')); + if ($user->isPluginEnabled('tp') && !ttValidTemplateText($cl_note)) { + $err->add($i18n->get('error.field'), $i18n->get('label.note')); + } + if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); + // Finished validating user input. + + // Prohibit creating entries in future. + if (!$user->isOptionEnabled('future_entries')) { + $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); + if ($selected_date->after($browser_today)) + $err->add($i18n->get('error.future_date')); + } + + // Prohibit creating entries in locked range. + if ($user->isDateLocked($selected_date)) + $err->add($i18n->get('error.range_locked')); + + // Prohibit creating another uncompleted record. + if ($err->no()) { + if (($not_completed_rec = ttTimeHelper::getUncompleted($user_id)) && (($cl_finish == '') && ($cl_duration == ''))) + $err->add($i18n->get('error.uncompleted_exists')." ".$i18n->get('error.goto_uncompleted').""); + } + + // Prohibit creating an overlapping record. + if ($err->no()) { + if (ttTimeHelper::overlaps($user_id, $cl_date, $cl_start, $cl_finish)) + $err->add($i18n->get('error.overlap')); + } + + // Insert record. + if ($err->no()) { + $id = ttTimeHelper::insert(array( + 'date' => $cl_date, + 'client' => $cl_client, + 'project' => $cl_project, + 'task' => $cl_task, + 'start' => $cl_start, + 'finish' => $cl_finish, + 'duration' => $cl_duration, + 'note' => $cl_note, + 'billable' => $cl_billable)); + + // Insert time custom fields if we have them. + $result = true; + if ($id && $custom_fields && $custom_fields->timeFields) { + $result = $custom_fields->insertTimeFields($id, $timeCustomFields); + } + + // Put a new file in storage if we have it. + if ($id && $showFiles && $_FILES['newfile']['name']) { + $fileHelper = new ttFileHelper($err); + $fields = array('entity_type'=>'time', + 'entity_id' => $id, + 'file_name' => $_FILES['newfile']['name']); + $fileHelper->putFile($fields); + } + + if ($id && $result && $err->no()) { + header('Location: time.php'); + exit(); + } + $err->add($i18n->get('error.db')); + } + } elseif ($request->getParameter('btn_stop')) { + // Stop button pressed to finish an uncompleted record. + $record_id = $request->getParameter('record_id'); + $record = ttTimeHelper::getRecord($record_id); + $browser_date = $request->getParameter('browser_date'); + $browser_time = $request->getParameter('browser_time'); + + // Can we complete this record? + if ($record['date'] == $browser_date // closing today's record + && ttTimeHelper::isValidInterval($record['start'], $browser_time) // finish time is greater than start time + && !ttTimeHelper::overlaps($user_id, $browser_date, $record['start'], $browser_time)) { // no overlap + $res = ttTimeHelper::update(array( + 'id'=>$record['id'], + 'date'=>$record['date'], + 'client'=>$record['client_id'], + 'project'=>$record['project_id'], + 'task'=>$record['task_id'], + 'start'=>$record['start'], + 'finish'=>$browser_time, + 'note'=>$record['comment'], + 'billable'=>$record['billable'])); + if (!$res) + $err->add($i18n->get('error.db')); + } else { + // Cannot complete, redirect for manual edit. + header('Location: time_edit.php?id='.$record_id); + exit(); + } + } +} // isPost + +$week_total = ttTimeHelper::getTimeForWeek($selected_date); +$timeRecords = ttTimeHelper::getRecords($cl_date, $showFiles); + +$smarty->assign('selected_date', $selected_date); +$smarty->assign('week_total', $week_total); +$smarty->assign('day_total', ttTimeHelper::getTimeForDay($cl_date)); +$smarty->assign('time_records', $timeRecords); +$smarty->assign('show_record_custom_fields', $showRecordCustomFields); +$smarty->assign('show_navigation', $user->isPluginEnabled('wv') && !$user->isOptionEnabled('week_menu')); +$smarty->assign('show_client', $showClient); +$smarty->assign('show_billable', $showBillable); +$smarty->assign('show_project', $showProject); +$smarty->assign('show_task', $showTask); +$smarty->assign('task_required', $taskRequired); +$smarty->assign('show_start', $showStart); +$smarty->assign('show_duration', $showDuration); +$smarty->assign('show_note_column', $showNoteColumn); +$smarty->assign('show_note_row', $showNoteRow); +$smarty->assign('show_files', $showFiles); +$smarty->assign('client_list', $client_list); +$smarty->assign('project_list', $project_list); +$smarty->assign('task_list', $task_list); +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('onload', 'onLoad="fillDropdowns();prepopulateNote();"'); +$smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); +$smarty->assign('title', $i18n->get('title.time')); +$smarty->assign('content_page_name', 'time2.tpl'); +$smarty->display('index2.tpl'); From c0d6b76ac8e1333dd167850f97e3e280841e26cb Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 3 Oct 2020 13:27:56 +0000 Subject: [PATCH 043/587] Added mobile styles for checkboxes. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/time2.tpl | 9 +++++++++ default.css | 5 +++++ rtl.css | 4 ++++ time2.php | 3 --- 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index fa450f819..24b1ca30a 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- {/if} +{if $show_billable} + + + + +{/if} + + + diff --git a/default.css b/default.css index 04c89795c..fd63a814b 100644 --- a/default.css +++ b/default.css @@ -226,11 +226,16 @@ input.password-field { .large-screen-calendar { display: inline-block; width: 210px; + padding-left: 1rem; margin-top: 1rem; margin-left: auto; margin-right: auto } +.checkbox-label { + float: left; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/rtl.css b/rtl.css index 5688a2823..c0328a7aa 100644 --- a/rtl.css +++ b/rtl.css @@ -15,3 +15,7 @@ html { .td-with-input { text-align: right; } + +.checkbox-label { + float: right; +} \ No newline at end of file diff --git a/time2.php b/time2.php index ced38613f..9d52b8c0d 100644 --- a/time2.php +++ b/time2.php @@ -190,7 +190,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'document.timeRecordForm.user_changed.value=1;document.timeRecordForm.submit();', 'name'=>'user', - 'style'=>'width: 250px;', 'value'=>$user_id, 'data'=>$user_list, 'datakeys'=>array('id','name'))); @@ -206,7 +205,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$active_clients, 'datakeys'=>array('id', 'name'), @@ -269,7 +267,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$client_list, 'datakeys'=>array('id', 'name'), From bccb1b5a3633e7ae2563ac092ed5ba571cf20f77 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 3 Oct 2020 13:43:21 +0000 Subject: [PATCH 044/587] Incremental progress on mobile time2.php page. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/time2.tpl | 10 ++++++++++ rtl.css | 2 +- time2.php | 3 +-- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 24b1ca30a..21ffe3a65 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5305 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5306 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 242f95431..157f25ef2 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 8a0a186ec..1b282e0d2 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -28,6 +28,15 @@
 
- {/if} +{if $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + {assign var="control_name" value='time_field_'|cat:$timeField['id']} + + + + + + {/foreach} +{/if} diff --git a/rtl.css b/rtl.css index c0328a7aa..a566e4ae7 100644 --- a/rtl.css +++ b/rtl.css @@ -18,4 +18,4 @@ html { .checkbox-label { float: right; -} \ No newline at end of file +} diff --git a/time2.php b/time2.php index 9d52b8c0d..c212fe87b 100644 --- a/time2.php +++ b/time2.php @@ -221,10 +221,9 @@ foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; if ($timeField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'style'=>'width: 250px;','value'=>$timeCustomFields[$timeField['id']]['value'])); + $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$timeCustomFields[$timeField['id']]['value'])); } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', 'data'=>CustomFields::getOptions($timeField['id']), 'value'=>$timeCustomFields[$timeField['id']]['value'], 'empty'=>array(''=>$i18n->get('dropdown.select')))); From 29f117e5f3e3c2e02f9d21c7da56a26cd07aa100 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 3 Oct 2020 14:06:11 +0000 Subject: [PATCH 045/587] Some more progress on time2.php. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/time2.tpl | 18 ++++++++++++++++-- time2.php | 2 -- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 21ffe3a65..d9d4d9d16 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
Anuko Time Tracker 1.19.23.5306 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5307 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 157f25ef2..08e0a08c5 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 1b282e0d2..4756eed57 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -34,6 +34,16 @@
{$forms.timeRecordForm.$control_name.control}
- {/foreach} {/if} +{if $show_project} + + + + + +{/if} +{if $show_task} + + + + + +{/if} - + - +
Anuko Time Tracker 1.19.23.5307 | Copyright © Anuko | + Anuko Time Tracker 1.19.23.5308 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 08e0a08c5..8ac03c53e 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 4756eed57..aa457c1d2 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -44,12 +44,26 @@
{$forms.timeRecordForm.project.control}
{$forms.timeRecordForm.task.control}
{$forms.timeRecordForm.note1.control}
diff --git a/time2.php b/time2.php index c212fe87b..60fdd6ecd 100644 --- a/time2.php +++ b/time2.php @@ -239,7 +239,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', 'name'=>'project', - 'style'=>'width: 250px;', 'value'=>$cl_project, 'data'=>$project_list, 'datakeys'=>array('id','name'), @@ -278,7 +277,6 @@ $task_list = ttGroupHelper::getActiveTasks(); $form->addInput(array('type'=>'combobox', 'name'=>'task', - 'style'=>'width: 250px;', 'value'=>$cl_task, 'data'=>$task_list, 'datakeys'=>array('id','name'), From 8294fab0e1644e993dc46f3129fcbdaf5d31797e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9as=20Lundgren?= Date: Sun, 4 Oct 2020 16:14:13 +0200 Subject: [PATCH 046/587] Add constant for app version in initialize.php (#103) --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- initialize.php | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index d9d4d9d16..932919af6 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
-
Anuko Time Tracker 1.19.23.5308 | Copyright © Anuko | + Anuko Time Tracker {constant("APP_VERSION")} | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 8ac03c53e..71864e0de 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/initialize.php b/initialize.php index 4c526a13b..3f3d49a4e 100644 --- a/initialize.php +++ b/initialize.php @@ -37,6 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); +define("APP_VERSION", "1.19.23.5308"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 18b55ec52820e5496cced9462e264c2abb04ba57 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 4 Oct 2020 18:54:08 +0000 Subject: [PATCH 047/587] Some refactoring to keep things consistent. --- WEB-INF/templates/header.tpl | 26 +++++++++++++------------- WEB-INF/templates/header2.tpl | 28 ++++++++++++++-------------- WEB-INF/templates/mobile/header.tpl | 10 +++++----- WEB-INF/templates/site_map.tpl | 20 ++++++++++---------- WEB-INF/templates/time2.tpl | 15 +++++++++++++++ WEB-INF/templates/work/header.tpl | 26 +++++++++++++------------- initialize.php | 2 +- 7 files changed, 71 insertions(+), 56 deletions(-) diff --git a/WEB-INF/templates/header.tpl b/WEB-INF/templates/header.tpl index eaf163824..7a1e4d842 100644 --- a/WEB-INF/templates/header.tpl +++ b/WEB-INF/templates/header.tpl @@ -1,12 +1,12 @@ - + - + {if $i18n.language.rtl} - + {/if} {if $user->getCustomCss()} @@ -64,8 +64,8 @@
  {$i18n.menu.logout} - {$i18n.menu.forum} - {$i18n.menu.help} + {$i18n.menu.forum} + {$i18n.menu.help}
@@ -99,8 +99,8 @@ {if $user->can('manage_features')} {$i18n.menu.plugins} {/if} - {$i18n.menu.forum} - {$i18n.menu.help} + {$i18n.menu.forum} + {$i18n.menu.help}
@@ -129,14 +129,14 @@ {$i18n.title.invoices} {/if} {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && - ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() || + (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() || $user->isPluginEnabled('cl'))} {$i18n.menu.charts} {/if} - {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode())} {$i18n.menu.projects} {/if} - {if ($smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} + {if (constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} {$i18n.menu.tasks} {/if} {if $user->can('view_users') || $user->can('manage_users')} @@ -162,11 +162,11 @@
  {$i18n.menu.login} - {if isTrue('MULTIORG_MODE') && $smarty.const.AUTH_MODULE == 'db'} + {if isTrue('MULTIORG_MODE') && constant('AUTH_MODULE') == 'db'} {$i18n.menu.register} {/if} - {$i18n.menu.forum} - {$i18n.menu.help} + {$i18n.menu.forum} + {$i18n.menu.help}
diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl index 9aba06219..1573d6124 100644 --- a/WEB-INF/templates/header2.tpl +++ b/WEB-INF/templates/header2.tpl @@ -1,13 +1,13 @@ - + - + {if $i18n.language.rtl} - + {/if} {if $user->getCustomCss()} @@ -36,7 +36,7 @@ - +
{$i18n.label.menu} {$i18n.menu.help}{$i18n.menu.help}
@@ -50,8 +50,8 @@ - - + +
{$i18n.menu.logout}{$i18n.menu.forum}{$i18n.menu.help}{$i18n.menu.forum}{$i18n.menu.help}
@@ -85,8 +85,8 @@ {if $user->can('manage_features')}
{$i18n.menu.plugins}{$i18n.menu.forum}{$i18n.menu.help}{$i18n.menu.forum}{$i18n.menu.help}
@@ -115,14 +115,14 @@
{$i18n.title.invoices}{$i18n.menu.charts}{$i18n.menu.projects}{$i18n.menu.tasks}
- {if isTrue('MULTIORG_MODE') && $smarty.const.AUTH_MODULE == 'db'} + {if isTrue('MULTIORG_MODE') && constant('AUTH_MODULE') == 'db'} {/if} - - + +
{$i18n.menu.login}{$i18n.menu.register}{$i18n.menu.forum}{$i18n.menu.help}{$i18n.menu.forum}{$i18n.menu.help}
diff --git a/WEB-INF/templates/mobile/header.tpl b/WEB-INF/templates/mobile/header.tpl index 8888e27b6..ccea5e7e1 100644 --- a/WEB-INF/templates/mobile/header.tpl +++ b/WEB-INF/templates/mobile/header.tpl @@ -1,13 +1,13 @@ - + - + {if $i18n.language.rtl} - + {/if} {if $user->getCustomCss()} @@ -83,10 +83,10 @@ {if $user->exists() && $user->isPluginEnabled('ex') && ($user->can('track_own_expenses') || $user->can('track_expenses'))} {$i18n.menu.expenses} {/if} - {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode())} {$i18n.menu.projects} {/if} - {if ($user->can('view_own_tasks') || $user->can('manage_tasks')) && $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()} + {if ($user->can('view_own_tasks') || $user->can('manage_tasks')) && constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode()} {$i18n.menu.tasks} {/if} {if $user->can('view_users') || $user->can('manage_users')} diff --git a/WEB-INF/templates/site_map.tpl b/WEB-INF/templates/site_map.tpl index 695a99093..48b8d40c1 100644 --- a/WEB-INF/templates/site_map.tpl +++ b/WEB-INF/templates/site_map.tpl @@ -12,8 +12,8 @@ {* main menu for admin *}

{$i18n.menu.logout}
- {$i18n.menu.forum}
- {$i18n.menu.help}
+ {$i18n.menu.forum}
+ {$i18n.menu.help}

{* end of main menu for admin *} {else} @@ -38,14 +38,14 @@ {$i18n.title.invoices}
{/if} {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && - ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() || + (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() || $user->isPluginEnabled('cl'))} {$i18n.menu.charts}
{/if} - {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode())} {$i18n.menu.projects}
{/if} - {if ($smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} + {if (constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} {$i18n.menu.tasks}
{/if} {if $user->can('view_users') || $user->can('manage_users')} @@ -71,8 +71,8 @@ {if $user->can('manage_features')} {$i18n.menu.plugins}
{/if} - {$i18n.menu.forum}
- {$i18n.menu.help}
+ {$i18n.menu.forum}
+ {$i18n.menu.help}

{* end of main menu for authorized user *} {/if} @@ -80,11 +80,11 @@ {* main menu for non authorized user *}

{$i18n.menu.login}
- {if isTrue('MULTIORG_MODE') && $smarty.const.AUTH_MODULE == 'db'} + {if isTrue('MULTIORG_MODE') && constant('AUTH_MODULE') == 'db'} {$i18n.menu.register}
{/if} - {$i18n.menu.forum}
- {$i18n.menu.help}
+ {$i18n.menu.forum}
+ {$i18n.menu.help}

{* end of main menu for non authorized user *} {/if} diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index aa457c1d2..91a31bede 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -58,6 +58,21 @@
{$forms.timeRecordForm.task.control}
{$forms.timeRecordForm.start.control} 
{$forms.timeRecordForm.finish.control} 
  {$i18n.menu.logout} - {$i18n.menu.forum} - {$i18n.menu.help} + {$i18n.menu.forum} + {$i18n.menu.help}
@@ -95,8 +95,8 @@ {if $user->can('manage_features')} {$i18n.menu.plugins} {/if} - {$i18n.menu.forum} - {$i18n.menu.help} + {$i18n.menu.forum} + {$i18n.menu.help}
@@ -125,14 +125,14 @@ {$i18n.title.invoices} {/if} {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && - ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() || + (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() || $user->isPluginEnabled('cl'))} {$i18n.menu.charts} {/if} - {if ($user->can('view_own_projects') || $user->can('manage_projects')) && ($smarty.const.MODE_PROJECTS == $user->getTrackingMode() || $smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode())} + {if ($user->can('view_own_projects') || $user->can('manage_projects')) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode())} {$i18n.menu.projects} {/if} - {if ($smarty.const.MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} + {if (constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} {$i18n.menu.tasks} {/if} {if $user->can('view_users') || $user->can('manage_users')} @@ -158,11 +158,11 @@
  {$i18n.menu.login} - {if isTrue('MULTIORG_MODE') && $smarty.const.AUTH_MODULE == 'db'} + {if isTrue('MULTIORG_MODE') && constant('AUTH_MODULE') == 'db'} {$i18n.menu.register} {/if} - {$i18n.menu.forum} - {$i18n.menu.help} + {$i18n.menu.forum} + {$i18n.menu.help}
diff --git a/initialize.php b/initialize.php index 3f3d49a4e..893a5422f 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5308"); +define("APP_VERSION", "1.19.23.5309"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From b144d75b2df15061b13f2b929b6a33ba76162c77 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 4 Oct 2020 21:55:38 +0000 Subject: [PATCH 048/587] A bit more progress on mobile-friendly time2.php. --- WEB-INF/templates/footer.tpl | 2 +- WEB-INF/templates/footer2.tpl | 2 +- WEB-INF/templates/time2.tpl | 14 +++++++++++++- initialize.php | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index 932919af6..a5ae56f90 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
- + {/if} {if $custom_fields && $custom_fields->timeFields} {foreach $custom_fields->timeFields as $timeField} @@ -42,6 +43,7 @@ + {/foreach} {/if} {if $show_project} @@ -50,6 +52,7 @@ + {/if} {if $show_task} @@ -57,6 +60,7 @@ + {/if} {if $show_start} @@ -64,13 +68,21 @@ + + +{/if} +{if $show_duration} + + + + + {/if} - diff --git a/initialize.php b/initialize.php index 893a5422f..6131ebb8f 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5309"); +define("APP_VERSION", "1.19.23.5310"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From fa3f70996fb21010b4f225af1d015e3ab0d53fea Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 4 Oct 2020 22:46:21 +0000 Subject: [PATCH 049/587] More progress on mobile-friendly time2.php. --- WEB-INF/lib/form/Form.class.php | 1 + WEB-INF/lib/form/FormElement.class.php | 2 ++ WEB-INF/lib/form/TextField.class.php | 1 + WEB-INF/resources/en.lang.php | 1 + WEB-INF/templates/time2.tpl | 8 ++++---- img/icon-now.png | Bin 0 -> 1581 bytes time2.php | 6 ++++-- 7 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 img/icon-now.png diff --git a/WEB-INF/lib/form/Form.class.php b/WEB-INF/lib/form/Form.class.php index d00261015..e991f725e 100644 --- a/WEB-INF/lib/form/Form.class.php +++ b/WEB-INF/lib/form/Form.class.php @@ -55,6 +55,7 @@ function addInput($params) { $el = new TextField($params['name']); if (isset($params['class'])) $el->setCssClass($params['class']); if (isset($params['maxlength'])) $el->setMaxLength($params['maxlength']); + if (isset($params['placeholder'])) $el->setPLaceholder($params['placeholder']); break; case 'password': diff --git a/WEB-INF/lib/form/FormElement.class.php b/WEB-INF/lib/form/FormElement.class.php index 096084ef4..ace22d9af 100644 --- a/WEB-INF/lib/form/FormElement.class.php +++ b/WEB-INF/lib/form/FormElement.class.php @@ -32,6 +32,7 @@ class FormElement { var $name; // control name var $form_name = ''; // form name the control is in var $value = ''; // value of the control + var $placeholder = ''; // placeholder var $size = ''; // control size var $max_length = ''; // max length of text in control var $on_change = ''; // what happens when value of control changes @@ -83,6 +84,7 @@ function isEnabled() { return $this->enabled; } function setOnChange($str) { $this->on_change = $str; } function setOnClick($str) { $this->on_click = $str; } + function setPlaceholder($str) { $this->placeholder = $str; } function localize() {} // Localization occurs in derived classes and is dependent on control type. // For example, in calendar control we need to localize day and month names. diff --git a/WEB-INF/lib/form/TextField.class.php b/WEB-INF/lib/form/TextField.class.php index fdfb76837..bb05c6738 100644 --- a/WEB-INF/lib/form/TextField.class.php +++ b/WEB-INF/lib/form/TextField.class.php @@ -49,6 +49,7 @@ function getHtml() { if (!empty($this->size)) $html .= " size=\"$this->size\""; if (!empty($this->style)) $html .= " style=\"$this->style\""; if (!empty($this->title)) $html .= " title=\"$this->title\""; + if (!empty($this->placeholder)) $html .= " placeholder=\"$this->placeholder\""; if($this->isEnabled()) { if (!empty($this->max_length)) $html .= " maxlength=\"$this->max_length\""; diff --git a/WEB-INF/resources/en.lang.php b/WEB-INF/resources/en.lang.php index b052ec602..d17ba4dc9 100644 --- a/WEB-INF/resources/en.lang.php +++ b/WEB-INF/resources/en.lang.php @@ -441,6 +441,7 @@ // Time form. See example at https://timetracker.anuko.com/time.php. 'form.time.duration_format' => '(hh:mm or 0.0h)', +'form.time.duration_placeholder' => 'hh:mm or 0.0h', 'form.time.billable' => 'Billable', 'form.time.uncompleted' => 'Uncompleted', 'form.time.remaining_quota' => 'Remaining quota', diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 18fdd2d8a..eb51d954d 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -66,13 +66,13 @@ - + - + {/if} @@ -80,7 +80,7 @@ - + {/if} @@ -159,7 +159,7 @@ {/if} -{if $show_start} +{if !$show_start} diff --git a/img/icon-now.png b/img/icon-now.png new file mode 100644 index 0000000000000000000000000000000000000000..44cd60462a63ad9732e33138105f077434ee0bf6 GIT binary patch literal 1581 zcmaJ>4{X#_7(c+t+*l$5l|N>dP6rNp?Q5@hYuz2W-R-thZ;rdm*hGb1`)(_1ueY|h z-3W;ZpaCRA`6p2sF4JIw5Ew2HoJ@nsK%I_2h!_LLsY{Ru%M7T&;Op&fOk-%$zVE$$ zzu))!zW2SirM|AFs9-^X&1NeK*80O}e9(IH??>Oq#_tGdm~U1$nh`B-b_hDOc_l3d zv7jn6!!Q)2&bG6#(q_9aBu5*~#?Z68sHt|r^0BAYBtqM4mCMsfL2QL47K6=l!i``5 zcmT&_$&IgMLsTf~gDrCHIvqyV)kVd1ts*Dk%RN|SnnwgGGzBcJDhY#6yYUP!k8Eq1 z#IcNv+3Ln8L^X!$F`uSGjI~pQNI3!Kbl8D|;vC#EjHUoZ0-B^;1fY1<#Zv&wJ~)b| zOL0Ez4`gGZnHz60%_L8f9UUF^4#uwO%_QJBj-+UkrU~Rh7@Y}IND~R8G{@kFhN#O) zQ`Qog#VEwIl9LXre_id0oAuZ*{0hT&Zq|Lbi;JCl$M zLqkjHBHE95X%38Pcke(sM@gLYOQv)slcyw-P=P8;moG-O#qbRw&Qqv8bP;(#bQ zXdxD3@hn)HQm;Yk%Jn znH4KsTt2*E+p0BlPq&X-giA1}Nh z6t}LuI5Rx2t$2LJ;VWhF7rBAFlf&=AOTx`RH8*_VwQG8Q#%LvrER-7AhmQ8J;)4 zcwuDb`p&LfBf}3@)Xe(i>c*$4JjeUON5QRuJjF^ zavj}@_xCLD@fSZh_0SbS)y3T*N IYR!g!0N`&ei2wiq literal 0 HcmV?d00001 diff --git a/time2.php b/time2.php index 60fdd6ecd..4747d02ad 100644 --- a/time2.php +++ b/time2.php @@ -295,8 +295,10 @@ } // Duration control. -if ($showDuration) - $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); +if ($showDuration) { + $placeholder = $user->getDecimalMark() == ',' ? str_replace('.', ',', $i18n->get('form.time.duration_placeholder')) : $i18n->get('form.time.duration_placeholder'); + $form->addInput(array('type'=>'text','name'=>'duration','placeholder'=>$placeholder,'value'=>$cl_duration,'onchange'=>"formDisable('duration');")); +} // File upload control. if ($showFiles) From 1ca2b6d35c3e90987a70285500740b23e53b7311 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 4 Oct 2020 23:10:23 +0000 Subject: [PATCH 050/587] Some more progress on mobile time2.php page, still incomplete. --- WEB-INF/templates/time2.tpl | 22 ++++++++++++++++++---- initialize.php | 2 +- time2.php | 1 - 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index eb51d954d..96f2d090f 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -82,12 +82,26 @@ + +{/if} +{if $show_files} + + + + + + +{/if} +{if $template_dropdown} + + + + + + {/if} - - - - +{* TODO: work in progress down from here... *} diff --git a/initialize.php b/initialize.php index 6131ebb8f..819a1362c 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5310"); +define("APP_VERSION", "1.19.23.5311"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time2.php b/time2.php index 4747d02ad..aa145246c 100644 --- a/time2.php +++ b/time2.php @@ -311,7 +311,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillNote(this.value);', 'name'=>'template', - 'style'=>'width: 250px;', 'data'=>$template_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); From 7dcea55b7b1da128afc0d613e20f659cde172041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9as=20Lundgren?= Date: Tue, 6 Oct 2020 15:36:55 +0200 Subject: [PATCH 051/587] Remove unnecessary stuff from html head (#104) --- WEB-INF/templates/header.tpl | 10 +++++----- WEB-INF/templates/header2.tpl | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/WEB-INF/templates/header.tpl b/WEB-INF/templates/header.tpl index 7a1e4d842..10640cb29 100644 --- a/WEB-INF/templates/header.tpl +++ b/WEB-INF/templates/header.tpl @@ -1,15 +1,15 @@ - + - + - + {if $i18n.language.rtl} - + {/if} {if $user->getCustomCss()} - + {/if} Time Tracker{if $title} - {$title}{/if} diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl index 1573d6124..6bc5f65fe 100644 --- a/WEB-INF/templates/header2.tpl +++ b/WEB-INF/templates/header2.tpl @@ -1,16 +1,16 @@ - + - + - + {if $i18n.language.rtl} - + {/if} {if $user->getCustomCss()} - + {/if} Time Tracker{if $title} - {$title}{/if} @@ -188,4 +188,4 @@ {/if} {* end of output messages *} -
\ No newline at end of file +
From 479fdab665c89cdd57ce1864cba701bf46994f70 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 9 Oct 2020 21:17:02 +0000 Subject: [PATCH 052/587] Resuming work on time2.php. --- WEB-INF/templates/time2.tpl | 100 ++---------------------------------- default.css | 7 +++ initialize.php | 2 +- time2.php | 5 +- 4 files changed, 13 insertions(+), 101 deletions(-) diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 96f2d090f..819c35d94 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -100,29 +100,24 @@
{/if} - -{* TODO: work in progress down from here... *} - + +
Anuko Time Tracker {constant("APP_VERSION")} | Copyright © Anuko | + Anuko Time Tracker {constant('APP_VERSION')} | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/WEB-INF/templates/footer2.tpl b/WEB-INF/templates/footer2.tpl index 71864e0de..8844f56e8 100644 --- a/WEB-INF/templates/footer2.tpl +++ b/WEB-INF/templates/footer2.tpl @@ -1,7 +1,7 @@ {* page-content *} - + diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 91a31bede..18fdd2d8a 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -33,6 +33,7 @@  
{$forms.timeRecordForm.$control_name.control}
{$forms.timeRecordForm.project.control}
{$forms.timeRecordForm.task.control}
{$forms.timeRecordForm.start.control} 
{$forms.timeRecordForm.finish.control} 
{$forms.timeRecordForm.duration.control} {if $user->getDecimalMark() == ','}{str_replace('.', ',', $i18n.form.time.duration_format)}{else}{$i18n.form.time.duration_format}{/if}:
{$forms.timeRecordForm.start.control} {$forms.timeRecordForm.start.control} {$i18n.button.now}
{$forms.timeRecordForm.finish.control} {$forms.timeRecordForm.finish.control}{$i18n.button.now}
{$forms.timeRecordForm.duration.control} {if $user->getDecimalMark() == ','}{str_replace('.', ',', $i18n.form.time.duration_format)}{else}{$i18n.form.time.duration_format}{/if}:{$forms.timeRecordForm.duration.control}
{$forms.timeRecordForm.task.control}
{$i18n.label.start}: {$forms.timeRecordForm.start.control}  {$forms.timeRecordForm.duration.control}
{$forms.timeRecordForm.newfile.control}
{$forms.timeRecordForm.template.control}
{$forms.timeRecordForm.note1.control}{$forms.timeRecordForm.note.control}
{$forms.timeRecordForm.date.control}
{$forms.timeRecordForm.btn_submit.control}
- - - - - - +{* TODO: work in progress down from here... *} {if $show_navigation} @@ -131,95 +126,8 @@ {/if} - - - -
- -{if $user_dropdown} - - - - -{/if} -{if $show_client} - - - - -{/if} -{if $show_billable} - - - - -{/if} -{if $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - - - {assign var="control_name" value='time_field_'|cat:$timeField['id']} - - - {/foreach} -{/if} -{if $show_project} - - - - -{/if} -{if $show_task} - - - - -{/if} -{if !$show_start} - - - - - - - - -{/if} -{if $show_duration} - - - - -{/if} -{if $show_files} - - - - -{/if} -{if $template_dropdown} - - - - -{/if} -
{$i18n.label.user}:{$forms.timeRecordForm.user.control}
{$i18n.label.client}{if $user->isOptionEnabled('client_required')} (*){/if}:{$forms.timeRecordForm.client.control}
 
{$timeField['label']|escape}{if $timeField['required']} (*){/if}:{$forms.timeRecordForm.$control_name.control}
{$i18n.label.project} (*):{$forms.timeRecordForm.project.control}
{$i18n.label.task}{if $task_required} (*){/if}:{$forms.timeRecordForm.task.control}
{$i18n.label.start}:{$forms.timeRecordForm.start.control} 
{$i18n.label.finish}:{$forms.timeRecordForm.finish.control} 
{$i18n.label.duration}:{$forms.timeRecordForm.duration.control} {if $user->getDecimalMark() == ','}{str_replace('.', ',', $i18n.form.time.duration_format)}{else}{$i18n.form.time.duration_format}{/if}
{$i18n.label.file}:{$forms.timeRecordForm.newfile.control}
{$i18n.label.template}:{$forms.timeRecordForm.template.control}
-
- - -
{$forms.timeRecordForm.date.control}
-
- - - - - - - - -
{$i18n.label.note}:{$forms.timeRecordForm.note.control}
{$forms.timeRecordForm.btn_submit.control}
diff --git a/default.css b/default.css index fd63a814b..2f5d054a9 100644 --- a/default.css +++ b/default.css @@ -236,6 +236,13 @@ input.password-field { float: left; } +#note { + width: 100%; + margin: 0; + height: 4rem; + resize: none; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/initialize.php b/initialize.php index 819a1362c..a4f9a088b 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5311"); +define("APP_VERSION", "1.19.23.5312"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time2.php b/time2.php index aa145246c..f87c76c30 100644 --- a/time2.php +++ b/time2.php @@ -322,10 +322,7 @@ } // Note control. -if (!defined('NOTE_INPUT_HEIGHT')) - define('NOTE_INPUT_HEIGHT', 40); -$form->addInput(array('type'=>'textarea','name'=>'note','style'=>'width: 600px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_note)); -$form->addInput(array('type'=>'textarea','name'=>'note1','value'=>$cl_note)); +$form->addInput(array('type'=>'textarea','name'=>'note','value'=>$cl_note)); // Calendar. $form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar From 82559f64f6454db810549ad2a6983cc23361ee99 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 10 Oct 2020 15:12:03 +0000 Subject: [PATCH 053/587] Improved time2.php. --- WEB-INF/templates/time2.tpl | 16 ++++------------ default.css | 4 +--- initialize.php | 2 +- time2.php | 15 ++++++++++++++- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 819c35d94..94f18bcb7 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -1,5 +1,6 @@ {include file="time_script.tpl"} +{* TODO: remove this from here to css *} - {$forms.timeRecordForm.open}
{$forms.timeRecordForm.date.control}
@@ -141,7 +134,7 @@ {foreach $time_records as $record} - + {if $show_client} {/if} @@ -216,17 +209,17 @@ {if $over_balance} - + {else} - + {/if} {if $over_quota} - + {else} - + {/if} {/if} diff --git a/default.css b/default.css index 75eebb146..c353c548f 100644 --- a/default.css +++ b/default.css @@ -281,6 +281,26 @@ input.password-field { text-align: right; } +.not-billable { + color: #ff6666; +} + +.remaining-quota { + color: red; +} + +.remaining-quota-balance { + color: red; +} + +.over-quota { + color: green; +} + +.over-quota-balance { + color: green; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/initialize.php b/initialize.php index abdcdf39b..8d5cd70a3 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5316"); +define("APP_VERSION", "1.19.23.5317"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 02588ee4e26691fdc2d288d9c096f8df563cef42 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 15:29:23 +0000 Subject: [PATCH 058/587] Finished work on time2.php. It should now be usable, although styles needs to be improved. --- WEB-INF/templates/time2.tpl | 151 ++---------------------------------- default.css | 4 + initialize.php | 2 +- 3 files changed, 11 insertions(+), 146 deletions(-) diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 58d053ba9..33aa428e7 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -1,5 +1,11 @@ {include file="time_script.tpl"} +{if $show_navigation} + +{/if} + {$forms.timeRecordForm.open}
{$forms.timeRecordForm.date.control}
{$record.client|escape}
{$i18n.label.month_total}: {$month_total}{$i18n.form.time.over_balance}: {$balance_remaining}{$i18n.form.time.over_balance}: {$balance_remaining}{$i18n.form.time.remaining_balance}: {$balance_remaining}{$i18n.form.time.remaining_balance}: {$balance_remaining}
{$i18n.label.quota}: {$month_quota}{$i18n.form.time.over_quota}: {$quota_remaining}{$i18n.form.time.over_quota}: {$quota_remaining}{$i18n.form.time.remaining_quota}: {$quota_remaining}{$i18n.form.time.remaining_quota}: {$quota_remaining}
@@ -225,148 +231,3 @@ {/if}
- - - - - -{* TODO: work in progress down from here... *} -{* - -{if $show_navigation} - - - -{/if} -
- {$i18n.label.day_view} / {$i18n.label.week_view} -
-*} -{* - - - - -
-{if $time_records} - - - {if $show_client} - - {/if} - {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - - {/foreach} - {/if} - {if $show_project} - - {/if} - {if $show_task} - - {/if} - {if $show_start} - - - {/if} - - {if $show_note_column} - - {/if} - {if $show_files} - - {/if} - - - - {foreach $time_records as $record} - - {if $show_client} - - {/if} - {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - {assign var="control_name" value='time_field_'|cat:$timeField['id']} - - {/foreach} - {/if} - {if $show_project} - - {/if} - {if $show_task} - - {/if} - {if $show_start} - - - {/if} - - {if $show_note_column} - - {/if} - {if $show_files} - {if $record.has_files} - - {else} - - {/if} - {/if} - - - - {if $show_note_row && $record.comment} - - - - - {/if} - {/foreach} -
{$i18n.label.client}{$timeField['label']|escape}{$i18n.label.project}{$i18n.label.task}{$i18n.label.start}{$i18n.label.finish}{$i18n.label.duration}{$i18n.label.note}
{$record.client|escape}{$record.$control_name|escape}{$record.project|escape}{$record.task|escape}{if $record.start}{$record.start}{else} {/if}{if $record.finish}{$record.finish}{else} {/if}{if ($record.duration == '0:00' && $record.start <> '')}{$i18n.form.time.uncompleted}{else}{$record.duration}{/if}{if $record.comment}{$record.comment|escape}{else} {/if}{$i18n.label.files}{$i18n.label.files} - {if $record.approved || $record.timesheet_id || $record.invoice_id} -   - {else} - {$i18n.label.edit} - {if ($record.duration == '0:00' && $record.start <> '')} - - - - - {/if} - {/if} - - {if $record.approved || $record.timesheet_id || $record.invoice_id} -   - {else} - {$i18n.label.delete} - {/if} -
{$i18n.label.note}:{$record.comment|escape}
-{/if} -
-*} -{* - - - - - - {if $user->isPluginEnabled('mq')} - - - {if $over_balance} - - {else} - - {/if} - - - - {if $over_quota} - - {else} - - {/if} - - {/if} -
{$i18n.label.week_total}: {$week_total}{$i18n.label.day_total}: {$day_total}
{$i18n.label.month_total}: {$month_total}{$i18n.form.time.over_balance}: {$balance_remaining}{$i18n.form.time.remaining_balance}: {$balance_remaining}
{$i18n.label.quota}: {$month_quota}{$i18n.form.time.over_quota}: {$quota_remaining}{$i18n.form.time.remaining_quota}: {$quota_remaining}
-*} - diff --git a/default.css b/default.css index c353c548f..2df2d2121 100644 --- a/default.css +++ b/default.css @@ -301,6 +301,10 @@ input.password-field { color: green; } +.optional-nav { + margin-top: .5rem; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/initialize.php b/initialize.php index 8d5cd70a3..9dda5d0d8 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5317"); +define("APP_VERSION", "1.19.23.5318"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 8ae14c590f3f77d136c9fd37242cabcf381cd92c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 16:06:21 +0000 Subject: [PATCH 059/587] Improved td padding on time2.php for day records table. --- default.css | 4 ++++ initialize.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index 2df2d2121..4c0c8697f 100644 --- a/default.css +++ b/default.css @@ -158,6 +158,10 @@ div.page-hint { white-space: nowrap; } +.x-scrollable-table td { + padding: .25rem; +} + .text-cell { text-align: left; } diff --git a/initialize.php b/initialize.php index 9dda5d0d8..488b1fe77 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5318"); +define("APP_VERSION", "1.19.23.5319"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From b014fb5b7352e81e28b5d126be37572cc68aeade Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 18:59:35 +0000 Subject: [PATCH 060/587] Made time_delete.php mobile-friendly. --- WEB-INF/templates/time_delete.tpl | 50 ------------------------------ WEB-INF/templates/time_delete2.tpl | 37 ++++++++++++++++++++++ default.css | 4 +++ initialize.php | 2 +- rtl.css | 20 ++++++++++++ time_delete.php | 4 +-- 6 files changed, 64 insertions(+), 53 deletions(-) delete mode 100644 WEB-INF/templates/time_delete.tpl create mode 100644 WEB-INF/templates/time_delete2.tpl diff --git a/WEB-INF/templates/time_delete.tpl b/WEB-INF/templates/time_delete.tpl deleted file mode 100644 index c8d90be0f..000000000 --- a/WEB-INF/templates/time_delete.tpl +++ /dev/null @@ -1,50 +0,0 @@ -{$forms.timeRecordForm.open} - - - - -
- - -{if $show_project} - -{/if} -{if $show_task} - -{/if} -{if $show_start} - - -{/if} -{if $show_duration} - -{/if} - - - -{if $show_project} - -{/if} -{if $show_task} - -{/if} -{if $show_start} - - -{/if} -{if $show_duration} - -{/if} - - -
{$i18n.label.project}{$i18n.label.task}{$i18n.label.start}{$i18n.label.finish}{$i18n.label.duration}{$i18n.label.note}
{$time_rec.project_name|escape}{$time_rec.task_name|escape}{if $time_rec.start}{$time_rec.start}{else} {/if}{if $time_rec.finish<>$time_rec.start}{$time_rec.finish}{else} {/if}{if ($time_rec.duration == '0:00' && $time_rec.start <> '')}{$i18n.form.time.uncompleted}{else}{$time_rec.duration}{/if}{if $time_rec.comment}{$time_rec.comment|escape}{else} {/if}
- - - - - - - -
 
{$forms.timeRecordForm.delete_button.control}  {$forms.timeRecordForm.cancel_button.control}
-
-{$forms.timeRecordForm.close} diff --git a/WEB-INF/templates/time_delete2.tpl b/WEB-INF/templates/time_delete2.tpl new file mode 100644 index 000000000..9d51fcc62 --- /dev/null +++ b/WEB-INF/templates/time_delete2.tpl @@ -0,0 +1,37 @@ +{$forms.timeRecordForm.open} + + +{if $show_project} + +{/if} +{if $show_task} + +{/if} +{if $show_start} + +{/if} +{if $show_duration} + +{/if} + + + +{if $show_project} + +{/if} +{if $show_task} + +{/if} +{if $show_start} + + +{/if} +{if $show_duration} + +{/if} + + +
{$i18n.label.project}{$i18n.label.task}{$i18n.label.start} + {$i18n.label.finish}{$i18n.label.duration}{$i18n.label.note}
{$time_rec.project_name|escape}{$time_rec.task_name|escape}{if $time_rec.start}{$time_rec.start}{else} {/if}{if $time_rec.finish<>$time_rec.start}{$time_rec.finish}{else} {/if}{if ($time_rec.duration == '0:00' && $time_rec.start <> '')}{$i18n.form.time.uncompleted}{else}{$time_rec.duration}{/if}{if $time_rec.comment}{$time_rec.comment|escape}{else} {/if}
+

{$forms.timeRecordForm.delete_button.control} {$forms.timeRecordForm.cancel_button.control}
+{$forms.timeRecordForm.close} diff --git a/default.css b/default.css index 4c0c8697f..7910d8371 100644 --- a/default.css +++ b/default.css @@ -309,6 +309,10 @@ input.password-field { margin-top: .5rem; } +.button-set { + margin-top: .5rem; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/initialize.php b/initialize.php index 488b1fe77..88850f272 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5319"); +define("APP_VERSION", "1.19.23.5320"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/rtl.css b/rtl.css index a566e4ae7..b47b925ad 100644 --- a/rtl.css +++ b/rtl.css @@ -19,3 +19,23 @@ html { .checkbox-label { float: right; } + +.day-totals-col1 { + text-align: right; +} + +.day-totals-col2 { + text-align: left; +} + +.text-cell { + text-align: right; +} + +.time-cell { + text-align: left; +} + +.note-header-cell { + text-align: left; +} diff --git a/time_delete.php b/time_delete.php index 9cbed727e..f1ec7b575 100644 --- a/time_delete.php +++ b/time_delete.php @@ -93,5 +93,5 @@ $smarty->assign('show_duration', $showDuration); $smarty->assign('forms', array($form->getName() => $form->toArray())); $smarty->assign('title', $i18n->get('title.delete_time_record')); -$smarty->assign('content_page_name', 'time_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'time_delete2.tpl'); +$smarty->display('index2.tpl'); From 3ff66b4fafec233e0b0f2c4f97e04e268606bf3e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 20:11:56 +0000 Subject: [PATCH 061/587] Made time_edit.php mobile-friendly. --- WEB-INF/templates/time_edit.tpl | 108 ----------------------------- WEB-INF/templates/time_edit2.tpl | 113 +++++++++++++++++++++++++++++++ default.css | 1 + initialize.php | 2 +- time_edit.php | 18 ++--- 5 files changed, 122 insertions(+), 120 deletions(-) delete mode 100644 WEB-INF/templates/time_edit.tpl create mode 100644 WEB-INF/templates/time_edit2.tpl diff --git a/WEB-INF/templates/time_edit.tpl b/WEB-INF/templates/time_edit.tpl deleted file mode 100644 index 45c9bc666..000000000 --- a/WEB-INF/templates/time_edit.tpl +++ /dev/null @@ -1,108 +0,0 @@ -{include file="time_script.tpl"} - -{* Conditional include of confirmSave handler. *} -{if $confirm_save} - -{/if} - -{$forms.timeRecordForm.open} - - - - -
- - - - -
- -{if $show_client} - - - - -{/if} -{if $show_billable} - - - - -{/if} -{if $show_paid_status} - - - - -{/if} -{if $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - - - {assign var="control_name" value='time_field_'|cat:$timeField['id']} - - - {/foreach} -{/if} -{if $show_project} - - - - -{/if} -{if $show_task} - - - - -{/if} -{if $show_start} - - - - - - - - -{/if} -{if $show_duration} - - - - -{/if} - - - - -{if $template_dropdown} - - - - -{/if} - - - - - - - - - - - -
{$i18n.label.client}{if $user->isOptionEnabled('client_required')} (*){/if}:{$forms.timeRecordForm.client.control}
 
 
{$timeField['label']|escape}{if $timeField['required']} (*){/if}:{$forms.timeRecordForm.$control_name.control}
{$i18n.label.project} (*):{$forms.timeRecordForm.project.control}
{$i18n.label.task}{if $task_required} (*){/if}:{$forms.timeRecordForm.task.control}
{$i18n.label.start}:{$forms.timeRecordForm.start.control} 
{$i18n.label.finish}:{$forms.timeRecordForm.finish.control} 
{$i18n.label.duration}:{$forms.timeRecordForm.duration.control} {if $user->decimal_mark == ','}{str_replace('.', ',', $i18n.form.time.duration_format)}{else}{$i18n.form.time.duration_format}{/if}
{$i18n.label.date}:{$forms.timeRecordForm.date.control}
{$i18n.label.template}:{$forms.timeRecordForm.template.control}
{$i18n.label.note}:{$forms.timeRecordForm.note.control}
 
{$forms.timeRecordForm.btn_save.control} {$forms.timeRecordForm.btn_copy.control} {$forms.timeRecordForm.btn_delete.control}
-
-
-{$forms.timeRecordForm.close} diff --git a/WEB-INF/templates/time_edit2.tpl b/WEB-INF/templates/time_edit2.tpl new file mode 100644 index 000000000..dc3d78cd0 --- /dev/null +++ b/WEB-INF/templates/time_edit2.tpl @@ -0,0 +1,113 @@ +{include file="time_script.tpl"} + +{* Conditional include of confirmSave handler. *} +{if $confirm_save} + +{/if} + +{$forms.timeRecordForm.open} + + +{if $show_client} + + + + + + +{/if} +{if $show_billable} + + + + + +{/if} +{if $show_paid_status} + + + + + +{/if} +{if $custom_fields && $custom_fields->timeFields} + {foreach $custom_fields->timeFields as $timeField} + {assign var="control_name" value='time_field_'|cat:$timeField['id']} + + + + + + + {/foreach} +{/if} +{if $show_project} + + + + + + +{/if} +{if $show_task} + + + + + + +{/if} +{if $show_start} + + + + + + + + + + + + +{/if} +{if $show_duration} + + + + + + +{/if} + + + + + + +{if $template_dropdown} + + + + + + +{/if} + + + + + + +
{$forms.timeRecordForm.client.control}
 
 
{$forms.timeRecordForm.$control_name.control}
{$forms.timeRecordForm.project.control}
{$forms.timeRecordForm.task.control}
{$forms.timeRecordForm.start.control} {$i18n.button.now}
{$forms.timeRecordForm.finish.control}{$i18n.button.now}
{$forms.timeRecordForm.duration.control}
{$forms.timeRecordForm.date.control}
{$forms.timeRecordForm.template.control}
{$forms.timeRecordForm.note.control}
+
{$forms.timeRecordForm.btn_save.control} {$forms.timeRecordForm.btn_copy.control} {$forms.timeRecordForm.btn_delete.control}
+{$forms.timeRecordForm.close} diff --git a/default.css b/default.css index 7910d8371..21488b480 100644 --- a/default.css +++ b/default.css @@ -311,6 +311,7 @@ input.password-field { .button-set { margin-top: .5rem; + margin-bottom: 1rem; } @media screen and (max-width: 600px) { diff --git a/initialize.php b/initialize.php index 88850f272..261c7af2b 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5320"); +define("APP_VERSION", "1.19.23.5321"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time_edit.php b/time_edit.php index b672c41cb..75b9018f7 100644 --- a/time_edit.php +++ b/time_edit.php @@ -145,7 +145,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$active_clients, 'datakeys'=>array('id', 'name'), @@ -169,7 +168,6 @@ $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$timeCustomFields[$timeField['id']]['value'])); } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', 'data'=>CustomFields::getOptions($timeField['id']), 'value'=>$timeCustomFields[$timeField['id']]['value'], 'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -185,7 +183,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', 'name'=>'project', - 'style'=>'width: 250px;', 'value'=>$cl_project, 'data'=>$project_list, 'datakeys'=>array('id','name'), @@ -212,7 +209,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$client_list, 'datakeys'=>array('id', 'name'), @@ -225,7 +221,6 @@ $task_list = ttGroupHelper::getActiveTasks(); $form->addInput(array('type'=>'combobox', 'name'=>'task', - 'style'=>'width: 250px;', 'value'=>$cl_task, 'data'=>$task_list, 'datakeys'=>array('id','name'), @@ -244,8 +239,10 @@ } // Duration control. -if ($showDuration) - $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); +if ($showDuration) { + $placeholder = $user->getDecimalMark() == ',' ? str_replace('.', ',', $i18n->get('form.time.duration_placeholder')) : $i18n->get('form.time.duration_placeholder'); + $form->addInput(array('type'=>'text','name'=>'duration','placeholder'=>$placeholder,'value'=>$cl_duration,'onchange'=>"formDisable('duration');")); +} // Date field. $form->addInput(array('type'=>'datefield','name'=>'date','maxlength'=>'20','value'=>$cl_date)); @@ -257,7 +254,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillNote(this.value);', 'name'=>'template', - 'style'=>'width: 250px;', 'data'=>$template_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -269,7 +265,7 @@ } // Note control. -$form->addInput(array('type'=>'textarea','name'=>'note','style'=>'width: 250px; height: 200px;','value'=>$cl_note)); +$form->addInput(array('type'=>'textarea','name'=>'note','value'=>$cl_note)); // Hidden control for record id. $form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); @@ -490,5 +486,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="fillDropdowns()"'); $smarty->assign('title', $i18n->get('title.edit_time_record')); -$smarty->assign('content_page_name', 'time_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'time_edit2.tpl'); +$smarty->display('index2.tpl'); From aedd1af74c6e79e7dcae4515cb8c80475a2bbb56 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 20:21:47 +0000 Subject: [PATCH 062/587] Mobile friendlier time entry pages released for user testing. --- initialize.php | 2 +- time.php | 38 ++++++++++++++++++++++---------------- time2.php => time1.php | 38 ++++++++++++++++---------------------- 3 files changed, 39 insertions(+), 39 deletions(-) rename time2.php => time1.php (94%) diff --git a/initialize.php b/initialize.php index 261c7af2b..6910a5469 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5321"); +define("APP_VERSION", "1.19.23.5322"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time.php b/time.php index b249f05b7..e5d1275a1 100644 --- a/time.php +++ b/time.php @@ -177,6 +177,7 @@ // Elements of timeRecordForm. $form = new Form('timeRecordForm'); +$largeScreenCalendarRowSpan = 1; // Number of rows calendar spans on large screens. // Dropdown for user and a hidden control to indicate user change. if ($user->can('track_time')) { @@ -190,11 +191,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'document.timeRecordForm.user_changed.value=1;document.timeRecordForm.submit();', 'name'=>'user', - 'style'=>'width: 250px;', 'value'=>$user_id, 'data'=>$user_list, 'datakeys'=>array('id','name'))); $form->addInput(array('type'=>'hidden','name'=>'user_changed')); + $largeScreenCalendarRowSpan += 2; $smarty->assign('user_dropdown', 1); } } @@ -206,11 +207,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$active_clients, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $largeScreenCalendarRowSpan += 2; // Note: in other modes the client list is filtered to relevant clients only. See below. } @@ -223,14 +224,14 @@ foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; if ($timeField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'style'=>'width: 250px;','value'=>$timeCustomFields[$timeField['id']]['value'])); + $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$timeCustomFields[$timeField['id']]['value'])); } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', 'data'=>CustomFields::getOptions($timeField['id']), 'value'=>$timeCustomFields[$timeField['id']]['value'], 'empty'=>array(''=>$i18n->get('dropdown.select')))); } + $largeScreenCalendarRowSpan += 2; } } @@ -242,11 +243,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', 'name'=>'project', - 'style'=>'width: 250px;', 'value'=>$cl_project, 'data'=>$project_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $largeScreenCalendarRowSpan += 2; // Client dropdown. if ($showClient) { @@ -269,11 +270,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$client_list, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $largeScreenCalendarRowSpan += 2; } } @@ -282,11 +283,11 @@ $task_list = ttGroupHelper::getActiveTasks(); $form->addInput(array('type'=>'combobox', 'name'=>'task', - 'style'=>'width: 250px;', 'value'=>$cl_task, 'data'=>$task_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $largeScreenCalendarRowSpan += 2; } // Start and finish controls. @@ -298,15 +299,21 @@ $form->getElement('start')->setEnabled(false); $form->getElement('finish')->setEnabled(false); } + $largeScreenCalendarRowSpan += 4; } // Duration control. -if ($showDuration) - $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); +if ($showDuration) { + $placeholder = $user->getDecimalMark() == ',' ? str_replace('.', ',', $i18n->get('form.time.duration_placeholder')) : $i18n->get('form.time.duration_placeholder'); + $form->addInput(array('type'=>'text','name'=>'duration','placeholder'=>$placeholder,'value'=>$cl_duration,'onchange'=>"formDisable('duration');")); + $largeScreenCalendarRowSpan += 2; +} // File upload control. -if ($showFiles) +if ($showFiles) { $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); + $largeScreenCalendarRowSpan += 2; +} // If we have templates, add a dropdown to select one. if ($user->isPluginEnabled('tp')){ @@ -315,7 +322,6 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillNote(this.value);', 'name'=>'template', - 'style'=>'width: 250px;', 'data'=>$template_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -323,13 +329,12 @@ $smarty->assign('bind_templates_with_projects', $config->getDefinedValue('bind_templates_with_projects')); $smarty->assign('prepopulate_note', $config->getDefinedValue('prepopulate_note')); $smarty->assign('template_list', $template_list); + $largeScreenCalendarRowSpan += 2; } } // Note control. -if (!defined('NOTE_INPUT_HEIGHT')) - define('NOTE_INPUT_HEIGHT', 40); -$form->addInput(array('type'=>'textarea','name'=>'note','style'=>'width: 600px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_note)); +$form->addInput(array('type'=>'textarea','name'=>'note','value'=>$cl_note)); // Calendar. $form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar @@ -479,6 +484,7 @@ $week_total = ttTimeHelper::getTimeForWeek($selected_date); $timeRecords = ttTimeHelper::getRecords($cl_date, $showFiles); +$smarty->assign('large_screen_calendar_row_span', $largeScreenCalendarRowSpan); $smarty->assign('selected_date', $selected_date); $smarty->assign('week_total', $week_total); $smarty->assign('day_total', ttTimeHelper::getTimeForDay($cl_date)); @@ -502,5 +508,5 @@ $smarty->assign('onload', 'onLoad="fillDropdowns();prepopulateNote();"'); $smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); $smarty->assign('title', $i18n->get('title.time')); -$smarty->assign('content_page_name', 'time.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'time2.tpl'); +$smarty->display('index2.tpl'); diff --git a/time2.php b/time1.php similarity index 94% rename from time2.php rename to time1.php index e5d1275a1..b249f05b7 100644 --- a/time2.php +++ b/time1.php @@ -177,7 +177,6 @@ // Elements of timeRecordForm. $form = new Form('timeRecordForm'); -$largeScreenCalendarRowSpan = 1; // Number of rows calendar spans on large screens. // Dropdown for user and a hidden control to indicate user change. if ($user->can('track_time')) { @@ -191,11 +190,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'document.timeRecordForm.user_changed.value=1;document.timeRecordForm.submit();', 'name'=>'user', + 'style'=>'width: 250px;', 'value'=>$user_id, 'data'=>$user_list, 'datakeys'=>array('id','name'))); $form->addInput(array('type'=>'hidden','name'=>'user_changed')); - $largeScreenCalendarRowSpan += 2; $smarty->assign('user_dropdown', 1); } } @@ -207,11 +206,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', + 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$active_clients, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $largeScreenCalendarRowSpan += 2; // Note: in other modes the client list is filtered to relevant clients only. See below. } @@ -224,14 +223,14 @@ foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; if ($timeField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$timeCustomFields[$timeField['id']]['value'])); + $form->addInput(array('type'=>'text','name'=>$field_name,'style'=>'width: 250px;','value'=>$timeCustomFields[$timeField['id']]['value'])); } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { $form->addInput(array('type'=>'combobox','name'=>$field_name, + 'style'=>'width: 250px;', 'data'=>CustomFields::getOptions($timeField['id']), 'value'=>$timeCustomFields[$timeField['id']]['value'], 'empty'=>array(''=>$i18n->get('dropdown.select')))); } - $largeScreenCalendarRowSpan += 2; } } @@ -243,11 +242,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', 'name'=>'project', + 'style'=>'width: 250px;', 'value'=>$cl_project, 'data'=>$project_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $largeScreenCalendarRowSpan += 2; // Client dropdown. if ($showClient) { @@ -270,11 +269,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', + 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$client_list, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $largeScreenCalendarRowSpan += 2; } } @@ -283,11 +282,11 @@ $task_list = ttGroupHelper::getActiveTasks(); $form->addInput(array('type'=>'combobox', 'name'=>'task', + 'style'=>'width: 250px;', 'value'=>$cl_task, 'data'=>$task_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $largeScreenCalendarRowSpan += 2; } // Start and finish controls. @@ -299,21 +298,15 @@ $form->getElement('start')->setEnabled(false); $form->getElement('finish')->setEnabled(false); } - $largeScreenCalendarRowSpan += 4; } // Duration control. -if ($showDuration) { - $placeholder = $user->getDecimalMark() == ',' ? str_replace('.', ',', $i18n->get('form.time.duration_placeholder')) : $i18n->get('form.time.duration_placeholder'); - $form->addInput(array('type'=>'text','name'=>'duration','placeholder'=>$placeholder,'value'=>$cl_duration,'onchange'=>"formDisable('duration');")); - $largeScreenCalendarRowSpan += 2; -} +if ($showDuration) + $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); // File upload control. -if ($showFiles) { +if ($showFiles) $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); - $largeScreenCalendarRowSpan += 2; -} // If we have templates, add a dropdown to select one. if ($user->isPluginEnabled('tp')){ @@ -322,6 +315,7 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillNote(this.value);', 'name'=>'template', + 'style'=>'width: 250px;', 'data'=>$template_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -329,12 +323,13 @@ $smarty->assign('bind_templates_with_projects', $config->getDefinedValue('bind_templates_with_projects')); $smarty->assign('prepopulate_note', $config->getDefinedValue('prepopulate_note')); $smarty->assign('template_list', $template_list); - $largeScreenCalendarRowSpan += 2; } } // Note control. -$form->addInput(array('type'=>'textarea','name'=>'note','value'=>$cl_note)); +if (!defined('NOTE_INPUT_HEIGHT')) + define('NOTE_INPUT_HEIGHT', 40); +$form->addInput(array('type'=>'textarea','name'=>'note','style'=>'width: 600px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_note)); // Calendar. $form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar @@ -484,7 +479,6 @@ $week_total = ttTimeHelper::getTimeForWeek($selected_date); $timeRecords = ttTimeHelper::getRecords($cl_date, $showFiles); -$smarty->assign('large_screen_calendar_row_span', $largeScreenCalendarRowSpan); $smarty->assign('selected_date', $selected_date); $smarty->assign('week_total', $week_total); $smarty->assign('day_total', ttTimeHelper::getTimeForDay($cl_date)); @@ -508,5 +502,5 @@ $smarty->assign('onload', 'onLoad="fillDropdowns();prepopulateNote();"'); $smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); $smarty->assign('title', $i18n->get('title.time')); -$smarty->assign('content_page_name', 'time2.tpl'); -$smarty->display('index2.tpl'); +$smarty->assign('content_page_name', 'time.tpl'); +$smarty->display('index.tpl'); From ae62ca4be67826ae84091de56cdb11dff69d14cf Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 20:43:55 +0000 Subject: [PATCH 063/587] Security fix: disabling password reset link immediately after password change. --- WEB-INF/lib/ttUserHelper.class.php | 4 ++++ initialize.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/WEB-INF/lib/ttUserHelper.class.php b/WEB-INF/lib/ttUserHelper.class.php index 17ef08c23..3af2fcb32 100644 --- a/WEB-INF/lib/ttUserHelper.class.php +++ b/WEB-INF/lib/ttUserHelper.class.php @@ -324,6 +324,10 @@ static function setPassword($user_id, $password) { $sql = "update tt_users set password = md5(".$mdb2->quote($password).") where id = $user_id"; $affected = $mdb2->exec($sql); + if (!is_a($affected, 'PEAR_Error')) { + $sql = "delete from tt_tmp_refs where user_id = $user_id"; + $affected = $mdb2->exec($sql); + } return (!is_a($affected, 'PEAR_Error')); } diff --git a/initialize.php b/initialize.php index 6910a5469..594ae5e21 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5322"); +define("APP_VERSION", "1.19.23.5323"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From d2f75328eb0a8ac47b897ac8dae54fdafec3e67c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 21:44:59 +0000 Subject: [PATCH 064/587] Security fix: added protection against flooding user mailboxes with too many password reset emails. --- WEB-INF/lib/ttUserHelper.class.php | 28 ++++++++++++++++++++++++++++ initialize.php | 2 +- password_reset.php | 5 +++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/WEB-INF/lib/ttUserHelper.class.php b/WEB-INF/lib/ttUserHelper.class.php index 3af2fcb32..eac057304 100644 --- a/WEB-INF/lib/ttUserHelper.class.php +++ b/WEB-INF/lib/ttUserHelper.class.php @@ -306,6 +306,34 @@ static function delete($user_id) { return true; } + // The recentRefExists determines if a reasonably recent user reference already exists. + // We do it similar to ttRegistrator::registeredRecently(). + static function recentRefExists($user_id) { + $mdb2 = getConnection(); + + $sql = "select count(*) as cnt from tt_tmp_refs where user_id = $user_id and created > now() - interval 15 minute"; + $res = $mdb2->query($sql); + if (is_a($res, 'PEAR_Error')) + return false; + $val = $res->fetchRow(); + if ($val['cnt'] == 0) + return false; // No references in last 15 minutes. + if ($val['cnt'] >= 2) + return true; // 2 or more references in last 15 mintes. + + // If we are here, there was exactly one reference during last 15 minutes. + // Determine if it occurred within the last minute in a separate query. + $sql = "select created from tt_tmp_refs where user_id = $user_id and created > now() - interval 1 minute"; + $res = $mdb2->query($sql); + if (is_a($res, 'PEAR_Error')) + return false; + $val = $res->fetchRow(); + if ($val) + return true; + + return false; + } + // The saveTmpRef saves a temporary reference for user that is used to reset user password. static function saveTmpRef($ref, $user_id) { $mdb2 = getConnection(); diff --git a/initialize.php b/initialize.php index 594ae5e21..afde5964e 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5323"); +define("APP_VERSION", "1.19.23.5324"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/password_reset.php b/password_reset.php index af596491d..01e04f3a1 100644 --- a/password_reset.php +++ b/password_reset.php @@ -64,6 +64,11 @@ if ($err->no()) { $user = new ttUser($cl_login); // Note: reusing $user from initialize.php here. + // Protection against flooding user mailbox with too many password reset emails. + if (ttUserHelper::recentRefExists($user->id)) $err->add($i18n->get('error.access_denied')); + } + + if ($err->no()) { // Prepare and save a temporary reference for user. $temp_ref = md5(uniqid()); ttUserHelper::saveTmpRef($temp_ref, $user->id); From d9472904361495f318c9d0294ffd28acaaeae42f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Oct 2020 22:25:28 +0000 Subject: [PATCH 065/587] Security fix for csv injections. --- WEB-INF/lib/common.lib.php | 9 +++++++++ initialize.php | 2 +- tofile.php | 22 +++++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/WEB-INF/lib/common.lib.php b/WEB-INF/lib/common.lib.php index 725f343c0..e4d4a38f9 100644 --- a/WEB-INF/lib/common.lib.php +++ b/WEB-INF/lib/common.lib.php @@ -459,3 +459,12 @@ function ttRandomString($length = 32) { } return $randomString; } + +// ttNeutralizeForCsv neutralizes user input for export to CSV files +// by removing =, +, -, and @ characters from the beginning of cell values. +// This mitigates a risk of CSV injection, see https://owasp.org/www-community/attacks/CSV_Injection +// Additionally, it replaces each quote character with a double quote. +function ttNeutralizeForCsv($val) { + $result = ltrim($val, '=+-@'); + return str_replace('"', '""', $result); +} diff --git a/initialize.php b/initialize.php index afde5964e..93d019171 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5324"); +define("APP_VERSION", "1.19.23.5325"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/tofile.php b/tofile.php index 8b3ae2302..996ffe9fd 100644 --- a/tofile.php +++ b/tofile.php @@ -218,7 +218,7 @@ foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; $checkbox_control_name = 'show_'.$field_name; - if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$userField['label']).'"'; + if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($userField['label']).'"'; } } if ($bean->getAttribute('chclient')) print ',"'.$i18n->get('label.client').'"'; @@ -229,7 +229,7 @@ foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; $checkbox_control_name = 'show_'.$field_name; - if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$timeField['label']).'"'; + if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($timeField['label']).'"'; } } if ($bean->getAttribute('chstart')) print ',"'.$i18n->get('label.start').'"'; @@ -248,24 +248,24 @@ // Print items. foreach ($items as $item) { print '"'.$item['date'].'"'; - if ($user->can('view_reports') || $user->can('view_all_reports') || $user->isClient()) print ',"'.str_replace('"','""',$item['user']).'"'; + if ($user->can('view_reports') || $user->can('view_all_reports') || $user->isClient()) print ',"'.ttNeutralizeForCsv($item['user']).'"'; // User custom fields. if ($custom_fields && $custom_fields->userFields) { foreach ($custom_fields->userFields as $userField) { $field_name = 'user_field_'.$userField['id']; $checkbox_control_name = 'show_'.$field_name; - if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$item[$field_name]).'"'; + if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($item[$field_name]).'"'; } } - if ($bean->getAttribute('chclient')) print ',"'.str_replace('"','""',$item['client']).'"'; - if ($bean->getAttribute('chproject')) print ',"'.str_replace('"','""',$item['project']).'"'; - if ($bean->getAttribute('chtask')) print ',"'.str_replace('"','""',$item['task']).'"'; + if ($bean->getAttribute('chclient')) print ',"'.ttNeutralizeForCsv($item['client']).'"'; + if ($bean->getAttribute('chproject')) print ',"'.ttNeutralizeForCsv($item['project']).'"'; + if ($bean->getAttribute('chtask')) print ',"'.ttNeutralizeForCsv($item['task']).'"'; // Time custom fields. if ($custom_fields && $custom_fields->timeFields) { foreach ($custom_fields->timeFields as $timeField) { $field_name = 'time_field_'.$timeField['id']; $checkbox_control_name = 'show_'.$field_name; - if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$item[$field_name]).'"'; + if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($item[$field_name]).'"'; } } if ($bean->getAttribute('chstart')) print ',"'.$item['start'].'"'; @@ -277,7 +277,7 @@ print ',"'.$val.'"'; } if ($bean->getAttribute('chunits')) print ',"'.$item['units'].'"'; - if ($bean->getAttribute('chnote')) print ',"'.str_replace('"','""',$item['note']).'"'; + if ($bean->getAttribute('chnote')) print ',"'.ttNeutralizeForCsv($item['note']).'"'; if ($bean->getAttribute('chcost')) { if ($user->can('manage_invoices') || $user->isClient()) print ',"'.$item['cost'].'"'; @@ -290,8 +290,8 @@ $ip = $item['modified'] ? $item['modified_ip'].' '.$item['modified'] : $item['created_ip'].' '.$item['created']; print ',"'.$ip.'"'; } - if ($bean->getAttribute('chinvoice')) print ',"'.str_replace('"','""',$item['invoice']).'"'; - if ($bean->getAttribute('chtimesheet')) print ',"'.str_replace('"','""',$item['timesheet_name']).'"'; + if ($bean->getAttribute('chinvoice')) print ',"'.ttNeutralizeForCsv($item['invoice']).'"'; + if ($bean->getAttribute('chtimesheet')) print ',"'.ttNeutralizeForCsv($item['timesheet_name']).'"'; print "\n"; } } From f4b122289fa6a551b389b0fd20a6dc9395648f7f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 15 Oct 2020 21:57:31 +0000 Subject: [PATCH 066/587] Fixed adjusting today links to match user today. --- WEB-INF/lib/form/Calendar.class.php | 12 +----------- WEB-INF/templates/time_script.tpl | 18 ++++++++++++++++++ initialize.php | 2 +- time.php | 2 +- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/WEB-INF/lib/form/Calendar.class.php b/WEB-INF/lib/form/Calendar.class.php index 1847b3fa8..d335e1503 100644 --- a/WEB-INF/lib/form/Calendar.class.php +++ b/WEB-INF/lib/form/Calendar.class.php @@ -186,21 +186,11 @@ function getHtml() { // Finished printing calendar table. // Print Today link. - $html .= "
name."=".strftime(DB_DATEFORMAT)."\" tabindex=\"-1\">".$i18n->get('label.today')."
name."=".strftime(DB_DATEFORMAT)."\" tabindex=\"-1\">".$i18n->get('label.today')."
\n"; // Add a hidden control for selected date. $html .= "name\" value=\"$selectedDate\">\n"; - - // Add script to adjust today link to match browser today, as PHP may run in a different timezone. - $html .= "\n"; - $html .= "\n\n"; return $html; } diff --git a/WEB-INF/templates/time_script.tpl b/WEB-INF/templates/time_script.tpl index 3d2013832..5834ba3cc 100644 --- a/WEB-INF/templates/time_script.tpl +++ b/WEB-INF/templates/time_script.tpl @@ -312,4 +312,22 @@ function get_time() { var date = new Date(); return date.strftime("%H:%M"); } + +// adjustTodayLinks adjusts today links to match today in user browser on load and also on click. +function adjustTodayLinks() { + var today_links = document.getElementsByClassName("today_link"); + var i; + var browser_today = new Date(); + for (i = 0; i < today_links.length; i++) { + today_links[i].href = '?date='+browser_today.strftime("%Y-%m-%d"); + today_links[i].onclick = function() { + var today = new Date(); + var links = document.getElementsByClassName("today_link"); + var j; + for (j = 0; j < links.length; j++) { + links[j].href = '?date='+today.strftime("%Y-%m-%d"); + } + } + } +} diff --git a/initialize.php b/initialize.php index 93d019171..ac9207d8b 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5325"); +define("APP_VERSION", "1.19.23.5326"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time.php b/time.php index e5d1275a1..af9df005f 100644 --- a/time.php +++ b/time.php @@ -505,7 +505,7 @@ $smarty->assign('project_list', $project_list); $smarty->assign('task_list', $task_list); $smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="fillDropdowns();prepopulateNote();"'); +$smarty->assign('onload', 'onLoad="fillDropdowns();prepopulateNote();adjustTodayLinks()"'); $smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); $smarty->assign('title', $i18n->get('title.time')); $smarty->assign('content_page_name', 'time2.tpl'); From 098297f74391fcb3df684f12151b6e09501c00f6 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 16 Oct 2020 19:56:17 +0000 Subject: [PATCH 067/587] Recoded charts.php for mobile access. --- WEB-INF/templates/charts2.tpl | 79 ++++++++++++ charts.php | 16 ++- charts1.php | 227 ++++++++++++++++++++++++++++++++++ default.css | 31 +++++ initialize.php | 2 +- 5 files changed, 349 insertions(+), 6 deletions(-) create mode 100644 WEB-INF/templates/charts2.tpl create mode 100644 charts1.php diff --git a/WEB-INF/templates/charts2.tpl b/WEB-INF/templates/charts2.tpl new file mode 100644 index 000000000..7a996a82b --- /dev/null +++ b/WEB-INF/templates/charts2.tpl @@ -0,0 +1,79 @@ + + +{$forms.chartForm.open} +

{$forms.chartForm.date.control}
+ + +{if $user_dropdown} + + + + + + +{/if} + + + + + + +{if $chart_selector} + + + + + + +{/if} +
{$forms.chartForm.date.control}
{$forms.chartForm.user.control}
{$forms.chartForm.interval.control}
{$forms.chartForm.type.control}
+ +
+ + + + +
+ + {section name=i loop=$totals} + {if $smarty.section.i.index <= 12} + + {/if} + {/section} +
{$totals[i].name|escape}
+
+
+ +
+ + + +
+ + {section name=i loop=$totals} + {if $smarty.section.i.index <= 12} + + {/if} + {/section} +
{$totals[i].name|escape}
+
+
+{$forms.chartForm.close} diff --git a/charts.php b/charts.php index 942b5ce7b..6f5be7482 100644 --- a/charts.php +++ b/charts.php @@ -112,8 +112,9 @@ // Elements of chartForm. $chart_form = new Form('chartForm'); +$largeScreenCalendarRowSpan = 1; // Number of rows calendar spans on large screens. -// User dropdown. Changes the user "on behalf" of whom we are working. +// User dropdown. Changes the user "on behalf" of whom we are working. if ($user->can('view_charts')) { $rank = $user->getMaxRankForGroup($user->getGroup()); if ($user->can('view_own_charts')) @@ -130,6 +131,7 @@ 'datakeys'=>array('id','name'), )); $chart_form->addInput(array('type'=>'hidden','name'=>'user_changed')); + $largeScreenCalendarRowSpan += 2; $smarty->assign('user_dropdown', 1); } } @@ -149,6 +151,7 @@ 'value' => $cl_interval, 'data' => $intervals )); +$largeScreenCalendarRowSpan += 2; // Chart type options. $chart_selector = (MODE_PROJECTS_AND_TASKS == $tracking_mode || $user->isPluginEnabled('cl')); @@ -168,6 +171,7 @@ 'value' => $cl_type, 'data' => $types )); + $largeScreenCalendarRowSpan += 2; } // Calendar. @@ -196,13 +200,13 @@ foreach($totals as $total) { $data_set->addPoint(new Point( $total['name'], $total['time'])); } -$chart->setDataSet($data_set); +$chart->setDataSet($data_set); // Prepare a file name. $img_dir = TEMPLATE_DIR.'_c/'; // Directory. $file_name = uniqid('chart_').'.png'; // Short file name. Unique ID here is to avoid problems with browser caching. $img_ref = 'WEB-INF/templates_c/'.$file_name; // Image reference for html. -$file_name = $img_dir.$file_name; // Full file name. +$file_name = $img_dir.$file_name; // Full file name. // Clean up the file system from older images. $img_files = glob($img_dir.'chart_*.png'); @@ -219,9 +223,11 @@ $chart->renderEx(array('fileName'=>$file_name,'hideLogo'=>true,'hideTitle'=>true,'hideLabel'=>true)); // At this point libchart usage is complete and we have chart image on disk. +$smarty->assign('large_screen_calendar_row_span', $largeScreenCalendarRowSpan); $smarty->assign('img_file_name', $img_ref); $smarty->assign('chart_selector', $chart_selector); +$smarty->assign('onload', 'onLoad="adjustTodayLinks()"'); $smarty->assign('forms', array($chart_form->getName() => $chart_form->toArray())); $smarty->assign('title', $i18n->get('title.charts')); -$smarty->assign('content_page_name', 'charts.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'charts2.tpl'); +$smarty->display('index2.tpl'); diff --git a/charts1.php b/charts1.php new file mode 100644 index 000000000..3b4ce15a1 --- /dev/null +++ b/charts1.php @@ -0,0 +1,227 @@ +isPluginEnabled('ch')) { + header('Location: feature_disabled.php'); + exit(); +} +if (!$user->exists()) { + header('Location: access_denied.php'); // Nobody to display a chart for. + exit(); +} +if ($user->behalf_id && (!$user->can('view_charts') || !$user->checkBehalfId())) { + header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. + exit(); +} +if (!$user->behalf_id && !$user->can('view_own_charts') && !$user->adjustBehalfId()) { + header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to view on behalf. + exit(); +} +if ($request->isPost() && $request->getParameter('user')) { + if (!$user->isUserValid($request->getParameter('user'))) { + header('Location: access_denied.php'); // Wrong user id on post. + exit(); + } +} +// End of access checks. + +// Determine user for which we display this page. +$userChanged = $request->getParameter('user_changed'); +if ($request->isPost() && $userChanged) { + $user_id = $request->getParameter('user'); + $user->setOnBehalfUser($user_id); +} else { + $user_id = $user->getUser(); +} + +$uc = new ttUserConfig(); +$tracking_mode = $user->getTrackingMode(); + +// Initialize and store date in session. +$cl_date = $request->getParameter('date', @$_SESSION['date']); +if(!$cl_date) { + $now = new DateAndTime(DB_DATEFORMAT); + $cl_date = $now->toString(DB_DATEFORMAT); +} +$_SESSION['date'] = $cl_date; + +if ($request->isPost()) { + $cl_interval = $request->getParameter('interval'); + if (!$cl_interval) $cl_interval = INTERVAL_THIS_MONTH; + $_SESSION['chart_interval'] = $cl_interval; + $uc->setValue(SYSC_CHART_INTERVAL, $cl_interval); + + $cl_type = $request->getParameter('type'); + if (!$cl_type) $cl_type = ttChartHelper::adjustType($cl_type); + $_SESSION['chart_type'] = $cl_type; + $uc->setValue(SYSC_CHART_TYPE, $cl_type); +} else { + // Initialize chart interval. + $cl_interval = $_SESSION['chart_interval']; + if (!$cl_interval) $cl_interval = $uc->getValue(SYSC_CHART_INTERVAL); + if (!$cl_interval) $cl_interval = INTERVAL_THIS_MONTH; + $_SESSION['chart_interval'] = $cl_interval; + + // Initialize chart type. + $cl_type = $_SESSION['chart_type']; + if (!$cl_type) $cl_type = $uc->getValue(SYSC_CHART_TYPE); + $cl_type = ttChartHelper::adjustType($cl_type); + $_SESSION['chart_type'] = $cl_type; +} + +// Elements of chartForm. +$chart_form = new Form('chartForm'); + +// User dropdown. Changes the user "on behalf" of whom we are working. +if ($user->can('view_charts')) { + $rank = $user->getMaxRankForGroup($user->getGroup()); + if ($user->can('view_own_charts')) + $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); + else + $options = array('status'=>ACTIVE,'max_rank'=>$rank); + $user_list = $user->getUsers($options); + if (count($user_list) >= 1) { + $chart_form->addInput(array('type'=>'combobox', + 'onchange'=>'this.form.user_changed.value=1;this.form.submit();', + 'name'=>'user', + 'value'=>$user_id, + 'data'=>$user_list, + 'datakeys'=>array('id','name'), + )); + $chart_form->addInput(array('type'=>'hidden','name'=>'user_changed')); + $smarty->assign('user_dropdown', 1); + } +} + +// Chart interval options. +$intervals = array(); +$intervals[INTERVAL_THIS_DAY] = $i18n->get('dropdown.selected_day'); +$intervals[INTERVAL_THIS_WEEK] = $i18n->get('dropdown.selected_week'); +$intervals[INTERVAL_THIS_MONTH] = $i18n->get('dropdown.selected_month'); +$intervals[INTERVAL_THIS_YEAR] = $i18n->get('dropdown.selected_year'); +$intervals[INTERVAL_ALL_TIME] = $i18n->get('dropdown.all_time'); + +// Chart interval dropdown. +$chart_form->addInput(array('type' => 'combobox', + 'onchange' => 'this.form.submit();', + 'name' => 'interval', + 'value' => $cl_interval, + 'data' => $intervals +)); + +// Chart type options. +$chart_selector = (MODE_PROJECTS_AND_TASKS == $tracking_mode || $user->isPluginEnabled('cl')); +if ($chart_selector) { + $types = array(); + if (MODE_PROJECTS == $tracking_mode || MODE_PROJECTS_AND_TASKS == $tracking_mode) + $types[CHART_PROJECTS] = $i18n->get('dropdown.projects'); + if (MODE_PROJECTS_AND_TASKS == $tracking_mode) + $types[CHART_TASKS] = $i18n->get('dropdown.tasks'); + if ($user->isPluginEnabled('cl')) + $types[CHART_CLIENTS] = $i18n->get('dropdown.clients'); + + // Add chart type dropdown. + $chart_form->addInput(array('type' => 'combobox', + 'onchange' => 'this.form.submit();', + 'name' => 'type', + 'value' => $cl_type, + 'data' => $types + )); +} + +// Calendar. +$chart_form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar + +// Get data for our chart. +$totals = ttChartHelper::getTotals($user_id, $cl_type, $cl_date, $cl_interval); +$smarty->assign('totals', $totals); + +// Prepare chart for drawing. +/* + * We use libchart.php library to draw chart images. It can draw chart labels, too (embed in the image). + * But quality of such auto-scaled text is not good. Therefore, we only use libchart to draw a pie-chart picture with + * auto-calculated percentage markers around it. We print labels (to the side of the picture) ourselves, + * using the same colors libchart is using. For labels printout, the $totals array (which is used for picture points) + * is also passed to charts.tpl Smarty template. + * + * To make all of the above possible with only one database call to obtain $totals we have to print the chart image + * to a file here (see code below). Once the image is available as a .png file, the charts.tpl can render it. + * + * PieChartEx class is a little extension to libchart-provided PieChart class. It allows us to print the chart + * without title, logo, and labels. + */ +$chart = new PieChartEx(300, 300); +$data_set = new XYDataSet(); +foreach($totals as $total) { + $data_set->addPoint(new Point( $total['name'], $total['time'])); +} +$chart->setDataSet($data_set); + +// Prepare a file name. +$img_dir = TEMPLATE_DIR.'_c/'; // Directory. +$file_name = uniqid('chart_').'.png'; // Short file name. Unique ID here is to avoid problems with browser caching. +$img_ref = 'WEB-INF/templates_c/'.$file_name; // Image reference for html. +$file_name = $img_dir.$file_name; // Full file name. + +// Clean up the file system from older images. +$img_files = glob($img_dir.'chart_*.png'); +if (is_array($img_files)) { + foreach($img_files as $file) { + // If file creation time is older than 1 minute, delete it. + if (filemtime($file) < (time() - 60)) { + unlink($file); + } + } +} + +// Write chart image to file system. +$chart->renderEx(array('fileName'=>$file_name,'hideLogo'=>true,'hideTitle'=>true,'hideLabel'=>true)); +// At this point libchart usage is complete and we have chart image on disk. + +$smarty->assign('img_file_name', $img_ref); +$smarty->assign('chart_selector', $chart_selector); +$smarty->assign('forms', array($chart_form->getName() => $chart_form->toArray())); +$smarty->assign('title', $i18n->get('title.charts')); +$smarty->assign('content_page_name', 'charts.tpl'); +$smarty->display('index.tpl'); diff --git a/default.css b/default.css index 21488b480..3f737b048 100644 --- a/default.css +++ b/default.css @@ -180,6 +180,14 @@ div.page-hint { display: table-cell; } +.large-screen-chart-list { + display: table-cell; +} + +.small-screen-chart-list { + display: none; +} + .small-screen-label { text-align: left; display: none; @@ -247,6 +255,21 @@ input.password-field { width: 237px; } +.chart-image { + width: 300px; + height: 300px; +} + +.chart-color-cell { + width: .4rem; + height: 1rem; +} + +.chart-description-cell { + text-align: left; + padding-left: .25rem; +} + .small-screen-calendar { display: none; width: 210px; @@ -320,6 +343,14 @@ input.password-field { display: none; } + .large-screen-chart-list { + display: none; + } + + .small-screen-chart-list { + display: table-cell; + } + .small-screen-label { display: block; } diff --git a/initialize.php b/initialize.php index ac9207d8b..afbc0c358 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5326"); +define("APP_VERSION", "1.19.23.5327"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 9ee1e3c1cb8869d12dd786cc42d7d21e8a1a12ff Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 18 Oct 2020 17:40:16 +0000 Subject: [PATCH 068/587] Changed software license to SSPL going forward. --- WEB-INF/templates/charts2.tpl | 4 +- initialize.php | 2 +- license.txt | 179 +++++++++++++++++++++++++++++++--- license_old.txt | 20 ++++ 4 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 license_old.txt diff --git a/WEB-INF/templates/charts2.tpl b/WEB-INF/templates/charts2.tpl index 7a996a82b..d3e8ffa0c 100644 --- a/WEB-INF/templates/charts2.tpl +++ b/WEB-INF/templates/charts2.tpl @@ -51,7 +51,7 @@ function adjustTodayLinks() {
- +
{section name=i loop=$totals} {if $smarty.section.i.index <= 12} @@ -66,7 +66,7 @@ function adjustTodayLinks() {
{$totals[i].name|escape}
+
- +
{section name=i loop=$totals} {if $smarty.section.i.index <= 12} diff --git a/initialize.php b/initialize.php index afbc0c358..bcd8c4fc8 100644 --- a/initialize.php +++ b/initialize.php @@ -37,7 +37,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5327"); +define("APP_VERSION", "1.19.23.5328"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/license.txt b/license.txt index eaa424c64..5c63aca6f 100644 --- a/license.txt +++ b/license.txt @@ -1,20 +1,171 @@ -Anuko Time Tracker +Server Side Public License -Copyright Anuko International Ltd. (https://www.anuko.com) +VERSION 1, OCTOBER 16, 2018 -LIBERAL FREEWARE LICENSE: This source code document may be used -by anyone for any purpose, and freely redistributed alone or in -combination with other software, provided that the license is obeyed. +Copyright © 2018 MongoDB, Inc. -There are only two ways to violate the license: +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. +TERMS AND CONDITIONS +0. Definitions. -1. To redistribute this code in source form, with the copyright notice or - license removed or altered. (Distributing in compiled forms without - embedded copyright notices is permitted). +“This License” refers to Server Side Public License. -2. To redistribute modified versions of this code in *any* form - that bears insufficient indications that the modifications are - not the work of the original author(s). +“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based on the Program. + +To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. +1. Source Code. + +The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. + +A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. +2. Basic Permissions. + +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program, subject to section 13. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + +Subject to section 13, you may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. +3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. +4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. +5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. +6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. +7. Additional Terms. + +“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. +8. Termination. + +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. +9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. +10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. +11. Patents. + +A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. +12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot use, propagate or convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not use, propagate or convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. +13. Offering the Program as a Service. + +If you make the functionality of the Program or a modified version available to third parties as a service, you must make the Service Source Code available via network download to everyone at no charge, under the terms of this License. Making the functionality of the Program or modified version available to third parties as a service includes, without limitation, enabling third parties to interact with the functionality of the Program or modified version remotely through a computer network, offering a service the value of which entirely or primarily derives from the value of the Program or modified version, or offering a service that accomplishes for users the primary purpose of the Program or modified version. + +“Service Source Code” means the Corresponding Source for the Program or the modified version, and the Corresponding Source for all programs that you use to make the Program or modified version available as a service, including, without limitation, management software, user interfaces, application program interfaces, automation software, monitoring software, backup software, storage software and hosting software, all such that a user could run an instance of the service using the Service Source Code you make available. +14. Revised Versions of this License. + +MongoDB, Inc. may publish revised and/or new versions of the Server Side Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the Server Side Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by MongoDB, Inc. If the Program does not specify a version number of the Server Side Public License, you may choose any version ever published by MongoDB, Inc. + +If the Program specifies that a proxy can decide which future versions of the Server Side Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. +15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. +16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS -This license applies to this document only, not any other software that it -may be combined with. diff --git a/license_old.txt b/license_old.txt new file mode 100644 index 000000000..115ac2c43 --- /dev/null +++ b/license_old.txt @@ -0,0 +1,20 @@ +Anuko Time Tracker + +Copyright Anuko International Ltd. (https://www.anuko.com) + +LIBERAL FREEWARE LICENSE: This source code document may be used +by anyone for any purpose, and freely redistributed alone or in +combination with other software, provided that the license is obeyed. + +There are only two ways to violate the license: + +1. To redistribute this code in source form, with the copyright notice or + license removed or altered. (Distributing in compiled forms without + embedded copyright notices is permitted). + +2. To redistribute modified versions of this code in *any* form + that bears insufficient indications that the modifications are + not the work of the original author(s). + +This license applies to this document only, not any other software that it +may be combined with. From aa895eb7dcfa199a1bf939408a77b24b82e7c82c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 18 Oct 2020 20:45:44 +0000 Subject: [PATCH 069/587] Cosmetic style improvements on charts.php. --- WEB-INF/templates/charts2.tpl | 7 +++++-- charts.php | 28 ++-------------------------- default.css | 34 ++++++---------------------------- 3 files changed, 13 insertions(+), 56 deletions(-) diff --git a/WEB-INF/templates/charts2.tpl b/WEB-INF/templates/charts2.tpl index d3e8ffa0c..d79ac852f 100644 --- a/WEB-INF/templates/charts2.tpl +++ b/WEB-INF/templates/charts2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. (https://www.anuko.com +License: See license.txt *} + diff --git a/WEB-INF/lib/smarty/plugins/block.php.php b/WEB-INF/lib/smarty/plugins/block.php.php deleted file mode 100644 index 8fedd8b43..000000000 --- a/WEB-INF/lib/smarty/plugins/block.php.php +++ /dev/null @@ -1,27 +0,0 @@ -allow_php_tag) { - throw new SmartyException("{php} is deprecated, set allow_php_tag = true to enable"); - } - eval($content); - return ''; -} - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/block.textformat.php b/WEB-INF/lib/smarty/plugins/block.textformat.php index 517fd62dd..5e494637e 100644 --- a/WEB-INF/lib/smarty/plugins/block.textformat.php +++ b/WEB-INF/lib/smarty/plugins/block.textformat.php @@ -2,41 +2,51 @@ /** * Smarty plugin to format text blocks * - * @package Smarty + * @package Smarty * @subpackage PluginsBlock */ - /** * Smarty {textformat}{/textformat} block plugin - * - * Type: block function
- * Name: textformat
+ * Type: block function + * Name: textformat * Purpose: format text a certain way with preset styles - * or custom wrap/indent settings
- * - * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat} - * (Smarty online manual) - * @param array $params parameters - *
- * Params:   style: string (email)
- *            indent: integer (0)
- *            wrap: integer (80)
- *            wrap_char string ("\n")
- *            indent_char: string (" ")
- *            wrap_boundary: boolean (true)
- * 
- * @author Monte Ohrt - * @param string $content contents of the block - * @param object $template template object - * @param boolean &$repeat repeat flag + * or custom wrap/indent settings + * Params: + * + * - style - string (email) + * - indent - integer (0) + * - wrap - integer (80) + * - wrap_char - string ("\n") + * - indent_char - string (" ") + * - wrap_boundary - boolean (true) + * + * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * + * @param array $params parameters + * @param string $content contents of the block + * @param Smarty_Internal_Template $template template object + * @param boolean &$repeat repeat flag + * * @return string content re-formatted + * @author Monte Ohrt + * @throws \SmartyException */ -function smarty_block_textformat($params, $content, $template, &$repeat) +function smarty_block_textformat($params, $content, Smarty_Internal_Template $template, &$repeat) { if (is_null($content)) { return; - } - + } + if (Smarty::$_MBSTRING) { + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_modifier_mb_wordwrap', + 'file' => SMARTY_PLUGINS_DIR . 'modifier.mb_wordwrap.php' + ) + ) + ); + } $style = null; $indent = 0; $indent_first = 0; @@ -45,7 +55,6 @@ function smarty_block_textformat($params, $content, $template, &$repeat) $wrap_char = "\n"; $wrap_cut = false; $assign = null; - foreach ($params as $_key => $_val) { switch ($_key) { case 'style': @@ -54,49 +63,59 @@ function smarty_block_textformat($params, $content, $template, &$repeat) case 'assign': $$_key = (string)$_val; break; - case 'indent': case 'indent_first': case 'wrap': $$_key = (int)$_val; break; - case 'wrap_cut': $$_key = (bool)$_val; break; - default: - trigger_error("textformat: unknown attribute '$_key'"); - } - } - - if ($style == 'email') { + trigger_error("textformat: unknown attribute '{$_key}'"); + } + } + if ($style === 'email') { $wrap = 72; - } + } // split into paragraphs - $_paragraphs = preg_split('![\r\n][\r\n]!', $content); - $_output = ''; - - for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) { - if ($_paragraphs[$_x] == '') { + $_paragraphs = preg_split('![\r\n]{2}!', $content); + foreach ($_paragraphs as &$_paragraph) { + if (!$_paragraph) { continue; - } + } // convert mult. spaces & special chars to single space - $_paragraphs[$_x] = preg_replace(array('!\s+!', '!(^\s+)|(\s+$)!'), array(' ', ''), $_paragraphs[$_x]); + $_paragraph = + preg_replace( + array( + '!\s+!' . Smarty::$_UTF8_MODIFIER, + '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER + ), + array( + ' ', + '' + ), + $_paragraph + ); // indent first line if ($indent_first > 0) { - $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x]; - } + $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph; + } // wordwrap sentences - $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut); + if (Smarty::$_MBSTRING) { + $_paragraph = smarty_modifier_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } else { + $_paragraph = wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut); + } // indent lines if ($indent > 0) { - $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]); - } - } + $_paragraph = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraph); + } + } $_output = implode($wrap_char . $wrap_char, $_paragraphs); - - return $assign ? $template->assign($assign, $_output) : $_output; -} - -?> \ No newline at end of file + if ($assign) { + $template->assign($assign, $_output); + } else { + return $_output; + } +} diff --git a/WEB-INF/lib/smarty/plugins/function.counter.php b/WEB-INF/lib/smarty/plugins/function.counter.php index 7c50bd44b..a4129e77c 100644 --- a/WEB-INF/lib/smarty/plugins/function.counter.php +++ b/WEB-INF/lib/smarty/plugins/function.counter.php @@ -1,78 +1,62 @@ - * Name: counter
+ * Type: function + * Name: counter * Purpose: print out a counter value + * * @author Monte Ohrt - * @link http://smarty.php.net/manual/en/language.function.counter.php {counter} - * (Smarty online manual) - * @param array parameters - * @param Smarty - * @param object $template template object + * @link http://www.smarty.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * * @return string|null */ function smarty_function_counter($params, $template) { static $counters = array(); - - $name = (isset($params['name'])) ? $params['name'] : 'default'; - if (!isset($counters[$name])) { - $counters[$name] = array( - 'start'=>1, - 'skip'=>1, - 'direction'=>'up', - 'count'=>1 - ); + $name = (isset($params[ 'name' ])) ? $params[ 'name' ] : 'default'; + if (!isset($counters[ $name ])) { + $counters[ $name ] = array('start' => 1, 'skip' => 1, 'direction' => 'up', 'count' => 1); } - $counter =& $counters[$name]; - - if (isset($params['start'])) { - $counter['start'] = $counter['count'] = (int)$params['start']; + $counter =& $counters[ $name ]; + if (isset($params[ 'start' ])) { + $counter[ 'start' ] = $counter[ 'count' ] = (int)$params[ 'start' ]; } - - if (!empty($params['assign'])) { - $counter['assign'] = $params['assign']; + if (!empty($params[ 'assign' ])) { + $counter[ 'assign' ] = $params[ 'assign' ]; } - - if (isset($counter['assign'])) { - $template->assign($counter['assign'], $counter['count']); + if (isset($counter[ 'assign' ])) { + $template->assign($counter[ 'assign' ], $counter[ 'count' ]); } - - if (isset($params['print'])) { - $print = (bool)$params['print']; + if (isset($params[ 'print' ])) { + $print = (bool)$params[ 'print' ]; } else { - $print = empty($counter['assign']); + $print = empty($counter[ 'assign' ]); } - if ($print) { - $retval = $counter['count']; + $retval = $counter[ 'count' ]; } else { $retval = null; } - - if (isset($params['skip'])) { - $counter['skip'] = $params['skip']; + if (isset($params[ 'skip' ])) { + $counter[ 'skip' ] = $params[ 'skip' ]; + } + if (isset($params[ 'direction' ])) { + $counter[ 'direction' ] = $params[ 'direction' ]; } - - if (isset($params['direction'])) { - $counter['direction'] = $params['direction']; + if ($counter[ 'direction' ] === 'down') { + $counter[ 'count' ] -= $counter[ 'skip' ]; + } else { + $counter[ 'count' ] += $counter[ 'skip' ]; } - - if ($counter['direction'] == "down") - $counter['count'] -= $counter['skip']; - else - $counter['count'] += $counter['skip']; - return $retval; - } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/function.cycle.php b/WEB-INF/lib/smarty/plugins/function.cycle.php index 98e3e2878..07ffcc5e2 100644 --- a/WEB-INF/lib/smarty/plugins/function.cycle.php +++ b/WEB-INF/lib/smarty/plugins/function.cycle.php @@ -2,105 +2,91 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFunction */ - /** * Smarty {cycle} function plugin + * Type: function + * Name: cycle + * Date: May 3, 2002 + * Purpose: cycle through given values + * Params: * - * Type: function
- * Name: cycle
- * Date: May 3, 2002
- * Purpose: cycle through given values
- * Input: - * - name = name of cycle (optional) - * - values = comma separated list of values to cycle, - * or an array of values to cycle - * (this can be left out for subsequent calls) - * - reset = boolean - resets given var to true - * - print = boolean - print var or not. default is true - * - advance = boolean - whether or not to advance the cycle - * - delimiter = the value delimiter, default is "," - * - assign = boolean, assigns to template var instead of - * printed. + * - name - name of cycle (optional) + * - values - comma separated list of values to cycle, or an array of values to cycle + * (this can be left out for subsequent calls) + * - reset - boolean - resets given var to true + * - print - boolean - print var or not. default is true + * - advance - boolean - whether or not to advance the cycle + * - delimiter - the value delimiter, default is "," + * - assign - boolean, assigns to template var instead of printed. + * + * Examples: * - * Examples:
- *
  * {cycle values="#eeeeee,#d0d0d0d"}
  * {cycle name=row values="one,two,three" reset=true}
  * {cycle name=row}
- * 
- * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle} - * (Smarty online manual) - * @author Monte Ohrt - * @author credit to Mark Priatel - * @author credit to Gerard - * @author credit to Jason Sweat - * @version 1.3 - * @param array - * @param object $template template object + * + * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * * @return string|null */ - function smarty_function_cycle($params, $template) { static $cycle_vars; - - $name = (empty($params['name'])) ? 'default' : $params['name']; - $print = (isset($params['print'])) ? (bool)$params['print'] : true; - $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true; - $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false; - - if (!in_array('values', array_keys($params))) { - if(!isset($cycle_vars[$name]['values'])) { - trigger_error("cycle: missing 'values' parameter"); + $name = (empty($params[ 'name' ])) ? 'default' : $params[ 'name' ]; + $print = (isset($params[ 'print' ])) ? (bool)$params[ 'print' ] : true; + $advance = (isset($params[ 'advance' ])) ? (bool)$params[ 'advance' ] : true; + $reset = (isset($params[ 'reset' ])) ? (bool)$params[ 'reset' ] : false; + if (!isset($params[ 'values' ])) { + if (!isset($cycle_vars[ $name ][ 'values' ])) { + trigger_error('cycle: missing \'values\' parameter'); return; } } else { - if(isset($cycle_vars[$name]['values']) - && $cycle_vars[$name]['values'] != $params['values'] ) { - $cycle_vars[$name]['index'] = 0; + if (isset($cycle_vars[ $name ][ 'values' ]) && $cycle_vars[ $name ][ 'values' ] !== $params[ 'values' ]) { + $cycle_vars[ $name ][ 'index' ] = 0; } - $cycle_vars[$name]['values'] = $params['values']; + $cycle_vars[ $name ][ 'values' ] = $params[ 'values' ]; } - - if (isset($params['delimiter'])) { - $cycle_vars[$name]['delimiter'] = $params['delimiter']; - } elseif (!isset($cycle_vars[$name]['delimiter'])) { - $cycle_vars[$name]['delimiter'] = ','; + if (isset($params[ 'delimiter' ])) { + $cycle_vars[ $name ][ 'delimiter' ] = $params[ 'delimiter' ]; + } elseif (!isset($cycle_vars[ $name ][ 'delimiter' ])) { + $cycle_vars[ $name ][ 'delimiter' ] = ','; } - - if(is_array($cycle_vars[$name]['values'])) { - $cycle_array = $cycle_vars[$name]['values']; + if (is_array($cycle_vars[ $name ][ 'values' ])) { + $cycle_array = $cycle_vars[ $name ][ 'values' ]; } else { - $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); + $cycle_array = explode($cycle_vars[ $name ][ 'delimiter' ], $cycle_vars[ $name ][ 'values' ]); } - - if(!isset($cycle_vars[$name]['index']) || $reset ) { - $cycle_vars[$name]['index'] = 0; + if (!isset($cycle_vars[ $name ][ 'index' ]) || $reset) { + $cycle_vars[ $name ][ 'index' ] = 0; } - - if (isset($params['assign'])) { + if (isset($params[ 'assign' ])) { $print = false; - $template->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); + $template->assign($params[ 'assign' ], $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]); } - - if($print) { - $retval = $cycle_array[$cycle_vars[$name]['index']]; + if ($print) { + $retval = $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]; } else { $retval = null; } - - if($advance) { - if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { - $cycle_vars[$name]['index'] = 0; + if ($advance) { + if ($cycle_vars[ $name ][ 'index' ] >= count($cycle_array) - 1) { + $cycle_vars[ $name ][ 'index' ] = 0; } else { - $cycle_vars[$name]['index']++; + $cycle_vars[ $name ][ 'index' ]++; } } - return $retval; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/function.fetch.php b/WEB-INF/lib/smarty/plugins/function.fetch.php index 2b09fb947..768761b23 100644 --- a/WEB-INF/lib/smarty/plugins/function.fetch.php +++ b/WEB-INF/lib/smarty/plugins/function.fetch.php @@ -2,215 +2,203 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFunction */ - /** * Smarty {fetch} plugin - * - * Type: function
- * Name: fetch
+ * Type: function + * Name: fetch * Purpose: fetch file, web or ftp data and display results - * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch} - * (Smarty online manual) + * + * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) * @author Monte Ohrt - * @param array $params parameters - * @param object $template template object - * @return string|null if the assign parameter is passed, Smarty assigns the - * result to a template variable + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * + * @throws SmartyException + * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable */ function smarty_function_fetch($params, $template) { - if (empty($params['file'])) { - trigger_error("[plugin] fetch parameter 'file' cannot be empty",E_USER_NOTICE); + if (empty($params[ 'file' ])) { + trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE); return; } - - $content = ''; - if (isset($template->security_policy) && !preg_match('!^(http|ftp)://!i', $params['file'])) { - if(!$template->security_policy->isTrustedResourceDir($params['file'])) { - return; - } - - // fetch the file - if($fp = @fopen($params['file'],'r')) { - while(!feof($fp)) { - $content .= fgets ($fp,4096); + // strip file protocol + if (stripos($params[ 'file' ], 'file://') === 0) { + $params[ 'file' ] = substr($params[ 'file' ], 7); + } + $protocol = strpos($params[ 'file' ], '://'); + if ($protocol !== false) { + $protocol = strtolower(substr($params[ 'file' ], 0, $protocol)); + } + if (isset($template->smarty->security_policy)) { + if ($protocol) { + // remote resource (or php stream, …) + if (!$template->smarty->security_policy->isTrustedUri($params[ 'file' ])) { + return; } - fclose($fp); } else { - trigger_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'',E_USER_NOTICE); - return; + // local file + if (!$template->smarty->security_policy->isTrustedResourceDir($params[ 'file' ])) { + return; + } } - } else { - // not a local file - if(preg_match('!^http://!i',$params['file'])) { - // http fetch - if($uri_parts = parse_url($params['file'])) { - // set defaults - $host = $server_name = $uri_parts['host']; - $timeout = 30; - $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; - $agent = "Smarty Template Engine ".$template->_version; - $referer = ""; - $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; - $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; - $_is_proxy = false; - if(empty($uri_parts['port'])) { - $port = 80; - } else { - $port = $uri_parts['port']; - } - if(!empty($uri_parts['user'])) { - $user = $uri_parts['user']; - } - if(!empty($uri_parts['pass'])) { - $pass = $uri_parts['pass']; - } - // loop through parameters, setup headers - foreach($params as $param_key => $param_value) { - switch($param_key) { - case "file": - case "assign": - case "assign_headers": - break; - case "user": - if(!empty($param_value)) { - $user = $param_value; - } - break; - case "pass": - if(!empty($param_value)) { - $pass = $param_value; - } - break; - case "accept": - if(!empty($param_value)) { - $accept = $param_value; - } - break; - case "header": - if(!empty($param_value)) { - if(!preg_match('![\w\d-]+: .+!',$param_value)) { - trigger_error("[plugin] invalid header format '".$param_value."'",E_USER_NOTICE); - return; - } else { - $extra_headers[] = $param_value; - } - } - break; - case "proxy_host": - if(!empty($param_value)) { - $proxy_host = $param_value; - } - break; - case "proxy_port": - if(!preg_match('!\D!', $param_value)) { - $proxy_port = (int) $param_value; - } else { - trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE); + } + $content = ''; + if ($protocol === 'http') { + // http fetch + if ($uri_parts = parse_url($params[ 'file' ])) { + // set defaults + $host = $server_name = $uri_parts[ 'host' ]; + $timeout = 30; + $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*'; + $agent = 'Smarty Template Engine ' . Smarty::SMARTY_VERSION; + $referer = ''; + $uri = !empty($uri_parts[ 'path' ]) ? $uri_parts[ 'path' ] : '/'; + $uri .= !empty($uri_parts[ 'query' ]) ? '?' . $uri_parts[ 'query' ] : ''; + $_is_proxy = false; + if (empty($uri_parts[ 'port' ])) { + $port = 80; + } else { + $port = $uri_parts[ 'port' ]; + } + if (!empty($uri_parts[ 'user' ])) { + $user = $uri_parts[ 'user' ]; + } + if (!empty($uri_parts[ 'pass' ])) { + $pass = $uri_parts[ 'pass' ]; + } + // loop through parameters, setup headers + foreach ($params as $param_key => $param_value) { + switch ($param_key) { + case 'file': + case 'assign': + case 'assign_headers': + break; + case 'user': + if (!empty($param_value)) { + $user = $param_value; + } + break; + case 'pass': + if (!empty($param_value)) { + $pass = $param_value; + } + break; + case 'accept': + if (!empty($param_value)) { + $accept = $param_value; + } + break; + case 'header': + if (!empty($param_value)) { + if (!preg_match('![\w\d-]+: .+!', $param_value)) { + trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE); return; - } - break; - case "agent": - if(!empty($param_value)) { - $agent = $param_value; - } - break; - case "referer": - if(!empty($param_value)) { - $referer = $param_value; - } - break; - case "timeout": - if(!preg_match('!\D!', $param_value)) { - $timeout = (int) $param_value; } else { - trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE); - return; + $extra_headers[] = $param_value; } - break; - default: - trigger_error("[plugin] unrecognized attribute '".$param_key."'",E_USER_NOTICE); + } + break; + case 'proxy_host': + if (!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case 'proxy_port': + if (!preg_match('!\D!', $param_value)) { + $proxy_port = (int)$param_value; + } else { + trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE); return; - } + } + break; + case 'agent': + if (!empty($param_value)) { + $agent = $param_value; + } + break; + case 'referer': + if (!empty($param_value)) { + $referer = $param_value; + } + break; + case 'timeout': + if (!preg_match('!\D!', $param_value)) { + $timeout = (int)$param_value; + } else { + trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE); + return; + } + break; + default: + trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE); + return; } - if(!empty($proxy_host) && !empty($proxy_port)) { - $_is_proxy = true; - $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); + } + if (!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout); + } else { + $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout); + } + if (!$fp) { + trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE); + return; + } else { + if ($_is_proxy) { + fputs($fp, 'GET ' . $params[ 'file' ] . " HTTP/1.0\r\n"); } else { - $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); + fputs($fp, "GET $uri HTTP/1.0\r\n"); } - - if(!$fp) { - trigger_error("[plugin] unable to fetch: $errstr ($errno)",E_USER_NOTICE); - return; - } else { - if($_is_proxy) { - fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); - } else { - fputs($fp, "GET $uri HTTP/1.0\r\n"); - } - if(!empty($host)) { - fputs($fp, "Host: $host\r\n"); - } - if(!empty($accept)) { - fputs($fp, "Accept: $accept\r\n"); - } - if(!empty($agent)) { - fputs($fp, "User-Agent: $agent\r\n"); - } - if(!empty($referer)) { - fputs($fp, "Referer: $referer\r\n"); - } - if(isset($extra_headers) && is_array($extra_headers)) { - foreach($extra_headers as $curr_header) { - fputs($fp, $curr_header."\r\n"); - } - } - if(!empty($user) && !empty($pass)) { - fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); - } - - fputs($fp, "\r\n"); - while(!feof($fp)) { - $content .= fgets($fp,4096); - } - fclose($fp); - $csplit = preg_split("!\r\n\r\n!",$content,2); - - $content = $csplit[1]; - - if(!empty($params['assign_headers'])) { - $template->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0])); + if (!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if (!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if (!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if (!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if (isset($extra_headers) && is_array($extra_headers)) { + foreach ($extra_headers as $curr_header) { + fputs($fp, $curr_header . "\r\n"); } } - } else { - trigger_error("[plugin fetch] unable to parse URL, check syntax",E_USER_NOTICE); - return; - } - } else { - // ftp fetch - if($fp = @fopen($params['file'],'r')) { - while(!feof($fp)) { - $content .= fgets ($fp,4096); + if (!empty($user) && !empty($pass)) { + fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n"); + } + fputs($fp, "\r\n"); + while (!feof($fp)) { + $content .= fgets($fp, 4096); } fclose($fp); - } else { - trigger_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'',E_USER_NOTICE); - return; + $csplit = preg_split("!\r\n\r\n!", $content, 2); + $content = $csplit[ 1 ]; + if (!empty($params[ 'assign_headers' ])) { + $template->assign($params[ 'assign_headers' ], preg_split("!\r\n!", $csplit[ 0 ])); + } } + } else { + trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE); + return; + } + } else { + $content = @file_get_contents($params[ 'file' ]); + if ($content === false) { + throw new SmartyException("{fetch} cannot read resource '" . $params[ 'file' ] . "'"); } - } - - - if (!empty($params['assign'])) { - $template->assign($params['assign'],$content); + if (!empty($params[ 'assign' ])) { + $template->assign($params[ 'assign' ], $content); } else { return $content; } } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/function.html_checkboxes.php b/WEB-INF/lib/smarty/plugins/function.html_checkboxes.php index 6a1a3ffdc..302358edd 100644 --- a/WEB-INF/lib/smarty/plugins/function.html_checkboxes.php +++ b/WEB-INF/lib/smarty/plugins/function.html_checkboxes.php @@ -2,142 +2,285 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFunction */ - /** * Smarty {html_checkboxes} function plugin - * - * File: function.html_checkboxes.php
- * Type: function
- * Name: html_checkboxes
- * Date: 24.Feb.2003
- * Purpose: Prints out a list of checkbox input types
+ * File: function.html_checkboxes.php + * Type: function + * Name: html_checkboxes + * Date: 24.Feb.2003 + * Purpose: Prints out a list of checkbox input types * Examples: - *
+ *
  * {html_checkboxes values=$ids output=$names}
  * {html_checkboxes values=$ids name='box' separator='
' output=$names} * {html_checkboxes values=$ids checked=$checked separator='
' output=$names} - *
- * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} - * (Smarty online manual) - * @author Christopher Kvarme - * @author credits to Monte Ohrt - * @version 1.0 - * @param array $params parameters - * Input:
- * - name (optional) - string default "checkbox" - * - values (required) - array - * - options (optional) - associative array - * - checked (optional) - array default not set - * - separator (optional) - ie
or   - * - output (optional) - the output next to each checkbox - * - assign (optional) - assign the output as an array to this variable - * @param object $template template object + * + * Params: + * + * - name (optional) - string default "checkbox" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
or   + * - output (optional) - the output next to each checkbox + * - assign (optional) - assign the output as an array to this variable + * - escape (optional) - escape the content (not value), defaults to true + * + * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object + * * @return string - * @uses smarty_function_escape_special_chars() + * @uses smarty_function_escape_special_chars() + * @throws \SmartyException */ -function smarty_function_html_checkboxes($params, $template) +function smarty_function_html_checkboxes($params, Smarty_Internal_Template $template) { - require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php'); - + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_function_escape_special_chars', + 'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php' + ) + ) + ); $name = 'checkbox'; $values = null; $options = null; - $selected = null; + $selected = array(); $separator = ''; + $escape = true; $labels = true; + $label_ids = false; $output = null; - $extra = ''; - - foreach($params as $_key => $_val) { - switch($_key) { + foreach ($params as $_key => $_val) { + switch ($_key) { case 'name': case 'separator': - $$_key = $_val; + $$_key = (string)$_val; break; - + case 'escape': case 'labels': + case 'label_ids': $$_key = (bool)$_val; break; - case 'options': $$_key = (array)$_val; break; - case 'values': case 'output': $$_key = array_values((array)$_val); break; - case 'checked': case 'selected': - $selected = array_map('strval', array_values((array)$_val)); + if (is_array($_val)) { + $selected = array(); + foreach ($_val as $_sel) { + if (is_object($_sel)) { + if (method_exists($_sel, '__toString')) { + $_sel = smarty_function_escape_special_chars((string)$_sel->__toString()); + } else { + trigger_error( + 'html_checkboxes: selected attribute contains an object of class \'' . + get_class($_sel) . '\' without __toString() method', + E_USER_NOTICE + ); + continue; + } + } else { + $_sel = smarty_function_escape_special_chars((string)$_sel); + } + $selected[ $_sel ] = true; + } + } elseif (is_object($_val)) { + if (method_exists($_val, '__toString')) { + $selected = smarty_function_escape_special_chars((string)$_val->__toString()); + } else { + trigger_error( + 'html_checkboxes: selected attribute is an object of class \'' . get_class($_val) . + '\' without __toString() method', + E_USER_NOTICE + ); + } + } else { + $selected = smarty_function_escape_special_chars((string)$_val); + } break; - case 'checkboxes': - trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING); + trigger_error( + 'html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', + E_USER_WARNING + ); $options = (array)$_val; break; - case 'assign': break; - + case 'strict': + break; + case 'disabled': + case 'readonly': + if (!empty($params[ 'strict' ])) { + if (!is_scalar($_val)) { + trigger_error( + "html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute", + E_USER_NOTICE + ); + } + if ($_val === true || $_val === $_key) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"'; + } + break; + } + // omit break; to fall through! + // no break default: - if(!is_array($_val)) { - $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + if (!is_array($_val)) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"'; } else { - trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + trigger_error("html_checkboxes: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE); } break; } } - - if (!isset($options) && !isset($values)) - return ''; /* raise error here? */ - - settype($selected, 'array'); + if (!isset($options) && !isset($values)) { + return ''; + } /* raise error here? */ $_html_result = array(); - if (isset($options)) { - - foreach ($options as $_key=>$_val) - $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); - - + foreach ($options as $_key => $_val) { + $_html_result[] = + smarty_function_html_checkboxes_output( + $name, + $_key, + $_val, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape + ); + } } else { - foreach ($values as $_i=>$_key) { - $_val = isset($output[$_i]) ? $output[$_i] : ''; - $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + foreach ($values as $_i => $_key) { + $_val = isset($output[ $_i ]) ? $output[ $_i ] : ''; + $_html_result[] = + smarty_function_html_checkboxes_output( + $name, + $_key, + $_val, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape + ); } - } - - if(!empty($params['assign'])) { - $template->assign($params['assign'], $_html_result); + if (!empty($params[ 'assign' ])) { + $template->assign($params[ 'assign' ], $_html_result); } else { - return implode("\n",$_html_result); + return implode("\n", $_html_result); } - } -function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) { +/** + * @param $name + * @param $value + * @param $output + * @param $selected + * @param $extra + * @param $separator + * @param $labels + * @param $label_ids + * @param bool $escape + * + * @return string + */ +function smarty_function_html_checkboxes_output( + $name, + $value, + $output, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape = true +) { $_output = ''; - if ($labels) $_output .= '
{$totals[i].name|escape}
\n"; - if (!empty($caption)) { $output .= '\n"; - } - + } if (is_array($cols)) { - $cols = ($hdir == 'right') ? $cols : array_reverse($cols); + $cols = ($hdir === 'right') ? $cols : array_reverse($cols); $output .= "\n"; - for ($r = 0; $r < $cols_count; $r++) { $output .= ''; - $output .= $cols[$r]; + $output .= $cols[ $r ]; $output .= "\n"; - } + } $output .= "\n"; - } - + } $output .= "\n"; for ($r = 0; $r < $rows; $r++) { $output .= "\n"; - $rx = ($vdir == 'down') ? $r * $cols_count : ($rows-1 - $r) * $cols_count; - + $rx = ($vdir === 'down') ? $r * $cols_count : ($rows - 1 - $r) * $cols_count; for ($c = 0; $c < $cols_count; $c++) { - $x = ($hdir == 'right') ? $rx + $c : $rx + $cols_count-1 - $c; - if ($inner != 'cols') { + $x = ($hdir === 'right') ? $rx + $c : $rx + $cols_count - 1 - $c; + if ($inner !== 'cols') { /* shuffle x to loop over rows*/ $x = floor($x / $cols_count) + ($x % $cols_count) * $rows; - } - + } if ($x < $loop_count) { - $output .= "" . $loop[$x] . "\n"; + $output .= "" . $loop[ $x ] . "\n"; } else { $output .= "$trailpad\n"; - } - } + } + } $output .= "\n"; - } + } $output .= "\n"; $output .= "
' . $caption . "
\n"; - return $output; -} +} +/** + * @param $name + * @param $var + * @param $no + * + * @return string + */ function smarty_function_html_table_cycle($name, $var, $no) { if (!is_array($var)) { $ret = $var; } else { - $ret = $var[$no % count($var)]; - } - + $ret = $var[ $no % count($var) ]; + } return ($ret) ? ' ' . $ret : ''; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/function.mailto.php b/WEB-INF/lib/smarty/plugins/function.mailto.php index 976218f53..27351df82 100644 --- a/WEB-INF/lib/smarty/plugins/function.mailto.php +++ b/WEB-INF/lib/smarty/plugins/function.mailto.php @@ -1,65 +1,63 @@ - * Name: mailto
+ * Type: function + * Name: mailto * Date: May 21, 2002 - * Purpose: automate mailto address link creation, and optionally - * encode them.
- * + * Purpose: automate mailto address link creation, and optionally encode them. + * Params: + * + * - address - (required) - e-mail address + * - text - (optional) - text to display, default is address + * - encode - (optional) - can be one of: + * * none : no encoding (default) + * * javascript : encode with javascript + * * javascript_charcode : encode with javascript charcode + * * hex : encode with hexadecimal (no javascript) + * - cc - (optional) - address(es) to carbon copy + * - bcc - (optional) - address(es) to blind carbon copy + * - subject - (optional) - e-mail subject + * - newsgroups - (optional) - newsgroup(s) to post to + * - followupto - (optional) - address(es) to follow up to + * - extra - (optional) - extra tags for the href link + * * Examples: - *
+ *
  * {mailto address="me@domain.com"}
  * {mailto address="me@domain.com" encode="javascript"}
  * {mailto address="me@domain.com" encode="hex"}
  * {mailto address="me@domain.com" subject="Hello to you!"}
  * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
  * {mailto address="me@domain.com" extra='class="mailto"'}
- * 
- * - * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto} - * (Smarty online manual) + * + * @link http://www.smarty.net/manual/en/language.function.mailto.php {mailto} + * (Smarty online manual) * @version 1.2 - * @author Monte Ohrt - * @author credits to Jason Sweat (added cc, bcc and subject functionality) + * @author Monte Ohrt + * @author credits to Jason Sweat (added cc, bcc and subject functionality) + * * @param array $params parameters - * Input:
- * - address = e-mail address - * - text = (optional) text to display, default is address - * - encode = (optional) can be one of: - * * none : no encoding (default) - * * javascript : encode with javascript - * * javascript_charcode : encode with javascript charcode - * * hex : encode with hexidecimal (no javascript) - * - cc = (optional) address(es) to carbon copy - * - bcc = (optional) address(es) to blind carbon copy - * - subject = (optional) e-mail subject - * - newsgroups = (optional) newsgroup(s) to post to - * - followupto = (optional) address(es) to follow up to - * - extra = (optional) extra tags for the href link - * @param object $template template object - * @return string + * + * @return string */ -function smarty_function_mailto($params, $template) +function smarty_function_mailto($params) { + static $_allowed_encoding = + array('javascript' => true, 'javascript_charcode' => true, 'hex' => true, 'none' => true); $extra = ''; - - if (empty($params['address'])) { - trigger_error("mailto: missing 'address' parameter",E_USER_WARNING); + if (empty($params[ 'address' ])) { + trigger_error("mailto: missing 'address' parameter", E_USER_WARNING); return; } else { - $address = $params['address']; - } - - $text = $address; + $address = $params[ 'address' ]; + } + $text = $address; // netscape and mozilla do not decode %40 (@) in BCC field (bug?) // so, don't encode it. $search = array('%40', '%2C'); @@ -70,87 +68,70 @@ function smarty_function_mailto($params, $template) case 'cc': case 'bcc': case 'followupto': - if (!empty($value)) + if (!empty($value)) { $mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value)); + } break; - case 'subject': case 'newsgroups': $mail_parms[] = $var . '=' . rawurlencode($value); break; - case 'extra': case 'text': $$var = $value; - + // no break default: - } - } - - $mail_parm_vals = ''; - for ($i = 0; $i < count($mail_parms); $i++) { - $mail_parm_vals .= (0 == $i) ? '?' : '&'; - $mail_parm_vals .= $mail_parms[$i]; - } - $address .= $mail_parm_vals; - - $encode = (empty($params['encode'])) ? 'none' : $params['encode']; - if (!in_array($encode, array('javascript', 'javascript_charcode', 'hex', 'none'))) { - trigger_error("mailto: 'encode' parameter must be none, javascript or hex",E_USER_WARNING); + } + } + if ($mail_parms) { + $address .= '?' . join('&', $mail_parms); + } + $encode = (empty($params[ 'encode' ])) ? 'none' : $params[ 'encode' ]; + if (!isset($_allowed_encoding[ $encode ])) { + trigger_error( + "mailto: 'encode' parameter must be none, javascript, javascript_charcode or hex", + E_USER_WARNING + ); return; - } - - if ($encode == 'javascript') { + } + // FIXME: (rodneyrehm) document.write() excues me what? 1998 has passed! + if ($encode === 'javascript') { $string = 'document.write(\'' . $text . '\');'; - $js_encode = ''; - for ($x = 0; $x < strlen($string); $x++) { - $js_encode .= '%' . bin2hex($string[$x]); - } - + for ($x = 0, $_length = strlen($string); $x < $_length; $x++) { + $js_encode .= '%' . bin2hex($string[ $x ]); + } return ''; - } elseif ($encode == 'javascript_charcode') { + } elseif ($encode === 'javascript_charcode') { $string = '' . $text . ''; - - for($x = 0, $y = strlen($string); $x < $y; $x++) { - $ord[] = ord($string[$x]); - } - - $_ret = "\n"; - + for ($x = 0, $y = strlen($string); $x < $y; $x++) { + $ord[] = ord($string[ $x ]); + } + $_ret = "\n"; return $_ret; - } elseif ($encode == 'hex') { + } elseif ($encode === 'hex') { preg_match('!^(.*)(\?.*)$!', $address, $match); - if (!empty($match[2])) { - trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.",E_USER_WARNING); + if (!empty($match[ 2 ])) { + trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.", E_USER_WARNING); return; - } + } $address_encode = ''; - for ($x = 0; $x < strlen($address); $x++) { - if (preg_match('!\w!', $address[$x])) { - $address_encode .= '%' . bin2hex($address[$x]); + for ($x = 0, $_length = strlen($address); $x < $_length; $x++) { + if (preg_match('!\w!' . Smarty::$_UTF8_MODIFIER, $address[ $x ])) { + $address_encode .= '%' . bin2hex($address[ $x ]); } else { - $address_encode .= $address[$x]; - } - } + $address_encode .= $address[ $x ]; + } + } $text_encode = ''; - for ($x = 0; $x < strlen($text); $x++) { - $text_encode .= '&#x' . bin2hex($text[$x]) . ';'; - } - + for ($x = 0, $_length = strlen($text); $x < $_length; $x++) { + $text_encode .= '&#x' . bin2hex($text[ $x ]) . ';'; + } $mailto = "mailto:"; return '' . $text_encode . ''; } else { // no encoding return '' . $text . ''; - } -} - -?> \ No newline at end of file + } +} diff --git a/WEB-INF/lib/smarty/plugins/function.math.php b/WEB-INF/lib/smarty/plugins/function.math.php index cd90020a4..7348d9649 100644 --- a/WEB-INF/lib/smarty/plugins/function.math.php +++ b/WEB-INF/lib/smarty/plugins/function.math.php @@ -1,83 +1,112 @@ + * + * @param array $params parameters + * @param Smarty_Internal_Template $template template object * - * Type: function
- * Name: math
- * Purpose: handle math computations in template
- * @link http://smarty.php.net/manual/en/language.function.math.php {math} - * (Smarty online manual) - * @author Monte Ohrt - * @param array $params parameters - * @param object $template template object * @return string|null */ function smarty_function_math($params, $template) { + static $_allowed_funcs = + array( + 'int' => true, + 'abs' => true, + 'ceil' => true, + 'cos' => true, + 'exp' => true, + 'floor' => true, + 'log' => true, + 'log10' => true, + 'max' => true, + 'min' => true, + 'pi' => true, + 'pow' => true, + 'rand' => true, + 'round' => true, + 'sin' => true, + 'sqrt' => true, + 'srand' => true, + 'tan' => true + ); // be sure equation parameter is present - if (empty($params['equation'])) { - trigger_error("math: missing equation parameter",E_USER_WARNING); + if (empty($params[ 'equation' ])) { + trigger_error("math: missing equation parameter", E_USER_WARNING); return; } - - $equation = $params['equation']; - + $equation = $params[ 'equation' ]; // make sure parenthesis are balanced - if (substr_count($equation,"(") != substr_count($equation,")")) { - trigger_error("math: unbalanced parenthesis",E_USER_WARNING); + if (substr_count($equation, '(') !== substr_count($equation, ')')) { + trigger_error("math: unbalanced parenthesis", E_USER_WARNING); return; } - - // match all vars in equation, make sure all are passed - preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match); - $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10', - 'max','min','pi','pow','rand','round','sin','sqrt','srand','tan'); - - foreach($match[1] as $curr_var) { - if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) { - trigger_error("math: function call $curr_var not allowed",E_USER_WARNING); - return; - } + // disallow backticks + if (strpos($equation, '`') !== false) { + trigger_error("math: backtick character not allowed in equation", E_USER_WARNING); + return; } - - foreach($params as $key => $val) { - if ($key != "equation" && $key != "format" && $key != "assign") { + // also disallow dollar signs + if (strpos($equation, '$') !== false) { + trigger_error("math: dollar signs not allowed in equation", E_USER_WARNING); + return; + } + foreach ($params as $key => $val) { + if ($key !== 'equation' && $key !== 'format' && $key !== 'assign') { // make sure value is not empty - if (strlen($val)==0) { - trigger_error("math: parameter $key is empty",E_USER_WARNING); + if (strlen($val) === 0) { + trigger_error("math: parameter '{$key}' is empty", E_USER_WARNING); return; } if (!is_numeric($val)) { - trigger_error("math: parameter $key: is not numeric",E_USER_WARNING); + trigger_error("math: parameter '{$key}' is not numeric", E_USER_WARNING); return; } + } + } + // match all vars in equation, make sure all are passed + preg_match_all('!(?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)!', $equation, $match); + foreach ($match[ 1 ] as $curr_var) { + if ($curr_var && !isset($params[ $curr_var ]) && !isset($_allowed_funcs[ $curr_var ])) { + trigger_error( + "math: function call '{$curr_var}' not allowed, or missing parameter '{$curr_var}'", + E_USER_WARNING + ); + return; + } + } + foreach ($params as $key => $val) { + if ($key !== 'equation' && $key !== 'format' && $key !== 'assign') { $equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation); } } $smarty_math_result = null; - eval("\$smarty_math_result = ".$equation.";"); - - if (empty($params['format'])) { - if (empty($params['assign'])) { + eval("\$smarty_math_result = " . $equation . ";"); + if (empty($params[ 'format' ])) { + if (empty($params[ 'assign' ])) { return $smarty_math_result; } else { - $template->assign($params['assign'],$smarty_math_result); + $template->assign($params[ 'assign' ], $smarty_math_result); } } else { - if (empty($params['assign'])){ - printf($params['format'],$smarty_math_result); + if (empty($params[ 'assign' ])) { + printf($params[ 'format' ], $smarty_math_result); } else { - $template->assign($params['assign'],sprintf($params['format'],$smarty_math_result)); + $template->assign($params[ 'assign' ], sprintf($params[ 'format' ], $smarty_math_result)); } } } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifier.capitalize.php b/WEB-INF/lib/smarty/plugins/modifier.capitalize.php index cd24589d8..c5fc400a6 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.capitalize.php +++ b/WEB-INF/lib/smarty/plugins/modifier.capitalize.php @@ -1,37 +1,145 @@ - * Name: capitalize
+ * Type: modifier + * Name: capitalize * Purpose: capitalize words in the string - * - * @link - * @author Monte Ohrt - * @param string $ - * @return string + * {@internal {$string|capitalize:true:true} is the fastest option for MBString enabled systems }} + * + * @param string $string string to capitalize + * @param boolean $uc_digits also capitalize "x123" to "X123" + * @param boolean $lc_rest capitalize first letters, lowercase all following letters "aAa" to "Aaa" + * + * @return string capitalized string + * @author Monte Ohrt + * @author Rodney Rehm */ -function smarty_modifier_capitalize($string, $uc_digits = false) -{ - // uppercase with php function ucwords - $upper_string = ucwords($string); - // check for any missed hyphenated words - $upper_string = preg_replace("!(^|[^\p{L}'])([\p{Ll}])!ue", "'\\1'.ucfirst('\\2')", $upper_string); +function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false) +{ + if (Smarty::$_MBSTRING) { + if ($lc_rest) { + // uppercase (including hyphenated words) + $upper_string = mb_convert_case($string, MB_CASE_TITLE, Smarty::$_CHARSET); + } else { + // uppercase word breaks + $upper_string = preg_replace_callback( + "!(^|[^\p{L}'])([\p{Ll}])!S" . Smarty::$_UTF8_MODIFIER, + 'smarty_mod_cap_mbconvert_cb', + $string + ); + } + // check uc_digits case + if (!$uc_digits) { + if (preg_match_all( + "!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . Smarty::$_UTF8_MODIFIER, + $string, + $matches, + PREG_OFFSET_CAPTURE + ) + ) { + foreach ($matches[ 1 ] as $match) { + $upper_string = + substr_replace( + $upper_string, + mb_strtolower($match[ 0 ], Smarty::$_CHARSET), + $match[ 1 ], + strlen($match[ 0 ]) + ); + } + } + } + $upper_string = + preg_replace_callback( + "!((^|\s)['\"])(\w)!" . Smarty::$_UTF8_MODIFIER, + 'smarty_mod_cap_mbconvert2_cb', + $upper_string + ); + return $upper_string; + } + // lowercase first + if ($lc_rest) { + $string = strtolower($string); + } + // uppercase (including hyphenated words) + $upper_string = + preg_replace_callback( + "!(^|[^\p{L}'])([\p{Ll}])!S" . Smarty::$_UTF8_MODIFIER, + 'smarty_mod_cap_ucfirst_cb', + $string + ); // check uc_digits case if (!$uc_digits) { - if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!u", $string, $matches, PREG_OFFSET_CAPTURE)) { - foreach($matches[1] as $match) - $upper_string = substr_replace($upper_string, $match[0], $match[1], strlen($match[0])); - } - } + if (preg_match_all( + "!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . Smarty::$_UTF8_MODIFIER, + $string, + $matches, + PREG_OFFSET_CAPTURE + ) + ) { + foreach ($matches[ 1 ] as $match) { + $upper_string = + substr_replace($upper_string, strtolower($match[ 0 ]), $match[ 1 ], strlen($match[ 0 ])); + } + } + } + $upper_string = preg_replace_callback( + "!((^|\s)['\"])(\w)!" . Smarty::$_UTF8_MODIFIER, + 'smarty_mod_cap_ucfirst2_cb', + $upper_string + ); return $upper_string; -} +} + +/** + * + * Bug: create_function() use exhausts memory when used in long loops + * Fix: use declared functions for callbacks instead of using create_function() + * Note: This can be fixed using anonymous functions instead, but that requires PHP >= 5.3 + * + * @author Kyle Renfrow + */ +/** + * @param $matches + * + * @return string + */ +function smarty_mod_cap_mbconvert_cb($matches) +{ + return stripslashes($matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 2 ]), MB_CASE_UPPER, Smarty::$_CHARSET); +} + +/** + * @param $matches + * + * @return string + */ +function smarty_mod_cap_mbconvert2_cb($matches) +{ + return stripslashes($matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 3 ]), MB_CASE_UPPER, Smarty::$_CHARSET); +} -?> \ No newline at end of file +/** + * @param $matches + * + * @return string + */ +function smarty_mod_cap_ucfirst_cb($matches) +{ + return stripslashes($matches[ 1 ]) . ucfirst(stripslashes($matches[ 2 ])); +} + +/** + * @param $matches + * + * @return string + */ +function smarty_mod_cap_ucfirst2_cb($matches) +{ + return stripslashes($matches[ 1 ]) . ucfirst(stripslashes($matches[ 3 ])); +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.date_format.php b/WEB-INF/lib/smarty/plugins/modifier.date_format.php index 3656c1c88..c8e88c5c9 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.date_format.php +++ b/WEB-INF/lib/smarty/plugins/modifier.date_format.php @@ -1,61 +1,85 @@ - * Name: date_format
- * Purpose: format datestamps via strftime
- * Input:
+ * Type: modifier + * Name: date_format + * Purpose: format datestamps via strftime + * Input: * - string: input date string * - format: strftime format for output * - default_date: default date if $string is empty - * - * @link http://smarty.php.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual) - * @author Monte Ohrt - * @param string $ - * @param string $ - * @param string $ + * + * @link http://www.smarty.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual) + * @author Monte Ohrt + * + * @param string $string input date string + * @param string $format strftime format for output + * @param string $default_date default date if $string is empty + * @param string $formatter either 'strftime' or 'auto' + * * @return string |void - * @uses smarty_make_timestamp() + * @uses smarty_make_timestamp() */ -function smarty_modifier_date_format($string, $format = SMARTY_RESOURCE_DATE_FORMAT, $default_date = '',$formatter='auto') +function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto') { + if ($format === null) { + $format = Smarty::$_DATE_FORMAT; + } /** - * Include the {@link shared.make_timestamp.php} plugin - */ - require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php'); - if ($string != '') { + * require_once the {@link shared.make_timestamp.php} plugin + */ + static $is_loaded = false; + if (!$is_loaded) { + if (!is_callable('smarty_make_timestamp')) { + include_once SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php'; + } + $is_loaded = true; + } + if (!empty($string) && $string !== '0000-00-00' && $string !== '0000-00-00 00:00:00') { $timestamp = smarty_make_timestamp($string); - } elseif ($default_date != '') { + } elseif (!empty($default_date)) { $timestamp = smarty_make_timestamp($default_date); } else { return; - } - if($formatter=='strftime'||($formatter=='auto'&&strpos($format,'%')!==false)) { - if (DS == '\\') { - $_win_from = array('%D', '%h', '%n', '%r', '%R', '%t', '%T'); - $_win_to = array('%m/%d/%y', '%b', "\n", '%I:%M:%S %p', '%H:%M', "\t", '%H:%M:%S'); + } + if ($formatter === 'strftime' || ($formatter === 'auto' && strpos($format, '%') !== false)) { + if (Smarty::$_IS_WINDOWS) { + $_win_from = array( + '%D', + '%h', + '%n', + '%r', + '%R', + '%t', + '%T' + ); + $_win_to = array( + '%m/%d/%y', + '%b', + "\n", + '%I:%M:%S %p', + '%H:%M', + "\t", + '%H:%M:%S' + ); if (strpos($format, '%e') !== false) { $_win_from[] = '%e'; $_win_to[] = sprintf('%\' 2d', date('j', $timestamp)); - } + } if (strpos($format, '%l') !== false) { $_win_from[] = '%l'; $_win_to[] = sprintf('%\' 2d', date('h', $timestamp)); - } + } $format = str_replace($_win_from, $_win_to, $format); - } + } return strftime($format, $timestamp); } else { return date($format, $timestamp); } -} - -?> \ No newline at end of file +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.debug_print_var.php b/WEB-INF/lib/smarty/plugins/modifier.debug_print_var.php index 013337ae0..78397d017 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.debug_print_var.php +++ b/WEB-INF/lib/smarty/plugins/modifier.debug_print_var.php @@ -1,55 +1,62 @@ - * Name: debug_print_var
+ * Type: modifier + * Name: debug_print_var * Purpose: formats variable contents for display in the console - * - * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php debug_print_var (Smarty online manual) - * @author Monte Ohrt - * @param array $ |object - * @param integer $ - * @param integer $ - * @return string + * + * @author Monte Ohrt + * + * @param array|object $var variable to be formatted + * @param int $max maximum recursion depth if $var is an array or object + * @param int $length maximum string length if $var is a string + * @param int $depth actual recursion depth + * @param array $objects processed objects in actual depth to prevent recursive object processing + * + * @return string */ -function smarty_modifier_debug_print_var ($var, $depth = 0, $length = 40) +function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array()) { - $_replace = array("\n" => '\n', - "\r" => '\r', - "\t" => '\t' - ); - + $_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t'); switch (gettype($var)) { - case 'array' : + case 'array': $results = 'Array (' . count($var) . ')'; + if ($depth === $max) { + break; + } foreach ($var as $curr_key => $curr_val) { - $results .= '
' . str_repeat(' ', $depth * 2) - . '' . strtr($curr_key, $_replace) . ' => ' - . smarty_modifier_debug_print_var($curr_val, ++$depth, $length); + $results .= '
' . str_repeat(' ', $depth * 2) . '' . strtr($curr_key, $_replace) . + ' => ' . + smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects); $depth--; - } + } break; - case 'object' : + case 'object': $object_vars = get_object_vars($var); $results = '' . get_class($var) . ' Object (' . count($object_vars) . ')'; + if (in_array($var, $objects)) { + $results .= ' called recursive'; + break; + } + if ($depth === $max) { + break; + } + $objects[] = $var; foreach ($object_vars as $curr_key => $curr_val) { - $results .= '
' . str_repeat(' ', $depth * 2) - . ' ->' . strtr($curr_key, $_replace) . ' = ' - . smarty_modifier_debug_print_var($curr_val, ++$depth, $length); + $results .= '
' . str_repeat(' ', $depth * 2) . ' ->' . strtr($curr_key, $_replace) . + ' = ' . smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects); $depth--; - } + } break; - case 'boolean' : - case 'NULL' : - case 'resource' : + case 'boolean': + case 'NULL': + case 'resource': if (true === $var) { $results = 'true'; } elseif (false === $var) { @@ -57,31 +64,40 @@ function smarty_modifier_debug_print_var ($var, $depth = 0, $length = 40) } elseif (null === $var) { $results = 'null'; } else { - $results = htmlspecialchars((string) $var); - } + $results = htmlspecialchars((string)$var); + } $results = '' . $results . ''; break; - case 'integer' : - case 'float' : - $results = htmlspecialchars((string) $var); + case 'integer': + case 'float': + $results = htmlspecialchars((string)$var); break; - case 'string' : + case 'string': $results = strtr($var, $_replace); - if (strlen($var) > $length) { - $results = substr($var, 0, $length - 3) . '...'; - } - $results = htmlspecialchars('"' . $results . '"'); + if (Smarty::$_MBSTRING) { + if (mb_strlen($var, Smarty::$_CHARSET) > $length) { + $results = mb_substr($var, 0, $length - 3, Smarty::$_CHARSET) . '...'; + } + } else { + if (isset($var[ $length ])) { + $results = substr($var, 0, $length - 3) . '...'; + } + } + $results = htmlspecialchars('"' . $results . '"', ENT_QUOTES, Smarty::$_CHARSET); break; - case 'unknown type' : - default : - $results = strtr((string) $var, $_replace); - if (strlen($results) > $length) { - $results = substr($results, 0, $length - 3) . '...'; - } - $results = htmlspecialchars($results); - } - + case 'unknown type': + default: + $results = strtr((string)$var, $_replace); + if (Smarty::$_MBSTRING) { + if (mb_strlen($results, Smarty::$_CHARSET) > $length) { + $results = mb_substr($results, 0, $length - 3, Smarty::$_CHARSET) . '...'; + } + } else { + if (strlen($results) > $length) { + $results = substr($results, 0, $length - 3) . '...'; + } + } + $results = htmlspecialchars($results, ENT_QUOTES, Smarty::$_CHARSET); + } return $results; -} - -?> \ No newline at end of file +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.escape.php b/WEB-INF/lib/smarty/plugins/modifier.escape.php index 37bc0e30e..150901c7c 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.escape.php +++ b/WEB-INF/lib/smarty/plugins/modifier.escape.php @@ -1,91 +1,255 @@ - * Name: escape
+ * Type: modifier + * Name: escape * Purpose: escape string for output - * - * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual) - * @author Monte Ohrt - * @param string $string input string - * @param string $esc_type escape type - * @param string $char_set character set + * + * @link http://www.smarty.net/docs/en/language.modifier.escape + * @author Monte Ohrt + * + * @param string $string input string + * @param string $esc_type escape type + * @param string $char_set character set, used for htmlspecialchars() or htmlentities() + * @param boolean $double_encode encode already encoded entitites again, used for htmlspecialchars() or htmlentities() + * * @return string escaped input string */ -function smarty_modifier_escape($string, $esc_type = 'html', $char_set = SMARTY_RESOURCE_CHAR_SET) +function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true) { + static $_double_encode = null; + static $is_loaded_1 = false; + static $is_loaded_2 = false; + if ($_double_encode === null) { + $_double_encode = version_compare(PHP_VERSION, '5.2.3', '>='); + } + if (!$char_set) { + $char_set = Smarty::$_CHARSET; + } switch ($esc_type) { case 'html': - return htmlspecialchars($string, ENT_QUOTES, $char_set); - + if ($_double_encode) { + // php >=5.3.2 - go native + return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); + } else { + if ($double_encode) { + // php <5.2.3 - only handle double encoding + return htmlspecialchars($string, ENT_QUOTES, $char_set); + } else { + // php <5.2.3 - prevent double encoding + $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); + $string = htmlspecialchars($string, ENT_QUOTES, $char_set); + $string = str_replace( + array( + '%%%SMARTY_START%%%', + '%%%SMARTY_END%%%' + ), + array( + '&', + ';' + ), + $string + ); + return $string; + } + } + // no break case 'htmlall': - return htmlentities($string, ENT_QUOTES, $char_set); - + if (Smarty::$_MBSTRING) { + // mb_convert_encoding ignores htmlspecialchars() + if ($_double_encode) { + // php >=5.3.2 - go native + $string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); + } else { + if ($double_encode) { + // php <5.2.3 - only handle double encoding + $string = htmlspecialchars($string, ENT_QUOTES, $char_set); + } else { + // php <5.2.3 - prevent double encoding + $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); + $string = htmlspecialchars($string, ENT_QUOTES, $char_set); + $string = + str_replace( + array( + '%%%SMARTY_START%%%', + '%%%SMARTY_END%%%' + ), + array( + '&', + ';' + ), + $string + ); + return $string; + } + } + // htmlentities() won't convert everything, so use mb_convert_encoding + return mb_convert_encoding($string, 'HTML-ENTITIES', $char_set); + } + // no MBString fallback + if ($_double_encode) { + return htmlentities($string, ENT_QUOTES, $char_set, $double_encode); + } else { + if ($double_encode) { + return htmlentities($string, ENT_QUOTES, $char_set); + } else { + $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); + $string = htmlentities($string, ENT_QUOTES, $char_set); + $string = str_replace( + array( + '%%%SMARTY_START%%%', + '%%%SMARTY_END%%%' + ), + array( + '&', + ';' + ), + $string + ); + return $string; + } + } + // no break case 'url': return rawurlencode($string); - case 'urlpathinfo': return str_replace('%2F', '/', rawurlencode($string)); - - case 'quotes': + case 'quotes': // escape unescaped single quotes return preg_replace("%(? '\\\\', "'" => "\\'", '"' => '\\"', "\r" => '\\r', "\n" => '\\n', ' '<\/')); - - case 'mail': - require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php'); - return smarty_mb_str_replace(array('@', '.'), array(' [AT] ', ' [DOT] '), $string); - - case 'nonstd': + return strtr( + $string, + array( + '\\' => '\\\\', + "'" => "\\'", + '"' => '\\"', + "\r" => '\\r', + "\n" => '\\n', + ' '<\/' + ) + ); + case 'mail': + if (Smarty::$_MBSTRING) { + if (!$is_loaded_2) { + if (!is_callable('smarty_mb_str_replace')) { + include_once SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php'; + } + $is_loaded_2 = true; + } + return smarty_mb_str_replace( + array( + '@', + '.' + ), + array( + ' [AT] ', + ' [DOT] ' + ), + $string + ); + } + // no MBString fallback + return str_replace( + array( + '@', + '.' + ), + array( + ' [AT] ', + ' [DOT] ' + ), + $string + ); + case 'nonstd': // escape non-standard chars, such as ms document quotes - $_res = ''; - for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) { - $_ord = ord(substr($string, $_i, 1)); + $return = ''; + if (Smarty::$_MBSTRING) { + if (!$is_loaded_1) { + if (!is_callable('smarty_mb_to_unicode')) { + include_once SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php'; + } + $is_loaded_1 = true; + } + foreach (smarty_mb_to_unicode($string, Smarty::$_CHARSET) as $unicode) { + if ($unicode >= 126) { + $return .= '&#' . $unicode . ';'; + } else { + $return .= chr($unicode); + } + } + return $return; + } + $_length = strlen($string); + for ($_i = 0; $_i < $_length; $_i++) { + $_ord = ord(substr($string, $_i, 1)); // non-standard char, escape it if ($_ord >= 126) { - $_res .= '&#' . $_ord . ';'; + $return .= '&#' . $_ord . ';'; } else { - $_res .= substr($string, $_i, 1); - } - } - return $_res; - + $return .= substr($string, $_i, 1); + } + } + return $return; default: return $string; - } -} - -?> \ No newline at end of file + } +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.mb_wordwrap.php b/WEB-INF/lib/smarty/plugins/modifier.mb_wordwrap.php new file mode 100644 index 000000000..1cd625b64 --- /dev/null +++ b/WEB-INF/lib/smarty/plugins/modifier.mb_wordwrap.php @@ -0,0 +1,71 @@ + $width) { + if ($cut) { + $_tokens = preg_split( + '!(.{' . $width . '})!S' . Smarty::$_UTF8_MODIFIER, + $_token, + -1, + PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE + ); + } + } + foreach ($_tokens as $token) { + $_space = !!preg_match('!^\s$!S' . Smarty::$_UTF8_MODIFIER, $token); + $token_length = mb_strlen($token, Smarty::$_CHARSET); + $length += $token_length; + if ($length > $width) { + // remove space before inserted break + if ($_previous) { + $t = mb_substr($t, 0, -1, Smarty::$_CHARSET); + } + if (!$_space) { + // add the break before the token + if (!empty($t)) { + $t .= $break; + } + $length = $token_length; + } + } elseif ($token === "\n") { + // hard break must reset counters + $length = 0; + } + $_previous = $_space; + // add the token + $t .= $token; + } + } + return $t; +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.regex_replace.php b/WEB-INF/lib/smarty/plugins/modifier.regex_replace.php index 9f148800e..7eb550695 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.regex_replace.php +++ b/WEB-INF/lib/smarty/plugins/modifier.regex_replace.php @@ -2,45 +2,54 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifier */ - /** * Smarty regex_replace modifier plugin - * - * Type: modifier
- * Name: regex_replace
+ * Type: modifier + * Name: regex_replace * Purpose: regular expression search/replace - * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php + * + * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php * regex_replace (Smarty online manual) - * @author Monte Ohrt - * @param string - * @param string|array - * @param string|array + * @author Monte Ohrt + * + * @param string $string input string + * @param string|array $search regular expression(s) to search for + * @param string|array $replace string(s) that should be replaced + * @param int $limit the maximum number of replacements + * * @return string */ -function smarty_modifier_regex_replace($string, $search, $replace) +function smarty_modifier_regex_replace($string, $search, $replace, $limit = -1) { - if(is_array($search)) { - foreach($search as $idx => $s) - $search[$idx] = _smarty_regex_replace_check($s); + if (is_array($search)) { + foreach ($search as $idx => $s) { + $search[ $idx ] = _smarty_regex_replace_check($s); + } } else { - $search = _smarty_regex_replace_check($search); - } - - return preg_replace($search, $replace, $string); + $search = _smarty_regex_replace_check($search); + } + return preg_replace($search, $replace, $string, $limit); } +/** + * @param string $search string(s) that should be replaced + * + * @return string + * @ignore + */ function _smarty_regex_replace_check($search) { - if (($pos = strpos($search,"\0")) !== false) - $search = substr($search,0,$pos); - if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) { - /* remove eval-modifier from $search */ - $search = substr($search, 0, -strlen($match[1])) . preg_replace('![e\s]+!', '', $match[1]); + // null-byte injection detection + // anything behind the first null-byte is ignored + if (($pos = strpos($search, "\0")) !== false) { + $search = substr($search, 0, $pos); + } + // remove eval-modifier from $search + if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[ 1 ], 'e') !== false)) { + $search = substr($search, 0, -strlen($match[ 1 ])) . preg_replace('![e\s]+!', '', $match[ 1 ]); } return $search; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifier.replace.php b/WEB-INF/lib/smarty/plugins/modifier.replace.php index 0636a1914..a98f5a4a6 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.replace.php +++ b/WEB-INF/lib/smarty/plugins/modifier.replace.php @@ -1,29 +1,37 @@ - * Name: replace
+ * Type: modifier + * Name: replace * Purpose: simple search/replace - * - * @link http://smarty.php.net/manual/en/language.modifier.replace.php replace (Smarty online manual) - * @author Monte Ohrt - * @author Uwe Tews - * @param string $ - * @param string $ - * @param string $ - * @return string + * + * @link http://smarty.php.net/manual/en/language.modifier.replace.php replace (Smarty online manual) + * @author Monte Ohrt + * @author Uwe Tews + * + * @param string $string input string + * @param string $search text to search for + * @param string $replace replacement text + * + * @return string */ function smarty_modifier_replace($string, $search, $replace) { - require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php'); - return smarty_mb_str_replace($search, $replace, $string); -} - -?> \ No newline at end of file + static $is_loaded = false; + if (Smarty::$_MBSTRING) { + if (!$is_loaded) { + if (!is_callable('smarty_mb_str_replace')) { + include_once SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php'; + } + $is_loaded = true; + } + return smarty_mb_str_replace($search, $replace, $string); + } + return str_replace($search, $replace, $string); +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.spacify.php b/WEB-INF/lib/smarty/plugins/modifier.spacify.php index f14e026bc..98efd4b30 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.spacify.php +++ b/WEB-INF/lib/smarty/plugins/modifier.spacify.php @@ -1,37 +1,26 @@ - * Name: spacify
+ * Type: modifier + * Name: spacify * Purpose: add spaces between characters in a string - * - * @link http://smarty.php.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual) - * @author Monte Ohrt - * @param string $ - * @param string $ - * @return string + * + * @link http://smarty.php.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual) + * @author Monte Ohrt + * + * @param string $string input string + * @param string $spacify_char string to insert between characters. + * + * @return string */ function smarty_modifier_spacify($string, $spacify_char = ' ') -{ - // mb_ functions available? - if (function_exists('mb_strlen') && mb_detect_encoding($string, 'UTF-8, ISO-8859-1') === 'UTF-8') { - $strlen = mb_strlen($string); - while ($strlen) { - $array[] = mb_substr($string, 0, 1, "UTF-8"); - $string = mb_substr($string, 1, $strlen, "UTF-8"); - $strlen = mb_strlen($string); - } - return implode($spacify_char, $array); - } else { - return implode($spacify_char, preg_split('//', $string, -1)); - } -} - -?> \ No newline at end of file +{ + // well… what about charsets besides latin and UTF-8? + return implode($spacify_char, preg_split('//' . Smarty::$_UTF8_MODIFIER, $string, -1, PREG_SPLIT_NO_EMPTY)); +} diff --git a/WEB-INF/lib/smarty/plugins/modifier.truncate.php b/WEB-INF/lib/smarty/plugins/modifier.truncate.php index 0e9d4b9f2..bb881bf6e 100644 --- a/WEB-INF/lib/smarty/plugins/modifier.truncate.php +++ b/WEB-INF/lib/smarty/plugins/modifier.truncate.php @@ -2,66 +2,61 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifier */ - /** * Smarty truncate modifier plugin - * - * Type: modifier
- * Name: truncate
+ * Type: modifier + * Name: truncate * Purpose: Truncate a string to a certain length if necessary, * optionally splitting in the middle of a word, and * appending the $etc string or inserting $etc into the middle. - * - * @link http://smarty.php.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual) - * @author Monte Ohrt - * @param string $string input string - * @param integer $length lenght of truncated text - * @param string $etc end string + * + * @link http://smarty.php.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual) + * @author Monte Ohrt + * + * @param string $string input string + * @param integer $length length of truncated text + * @param string $etc end string * @param boolean $break_words truncate at word boundary - * @param boolean $middle truncate in the middle of text + * @param boolean $middle truncate in the middle of text + * * @return string truncated string */ -function smarty_modifier_truncate($string, $length = 80, $etc = '...', - $break_words = false, $middle = false) +function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false) { - if ($length == 0) + if ($length === 0) { return ''; - - if (is_callable('mb_strlen')) { - if (mb_detect_encoding($string, 'UTF-8, ISO-8859-1') === 'UTF-8') { - // $string has utf-8 encoding - if (mb_strlen($string) > $length) { - $length -= min($length, mb_strlen($etc)); - if (!$break_words && !$middle) { - $string = preg_replace('/\s+?(\S+)?$/u', '', mb_substr($string, 0, $length + 1)); - } - if (!$middle) { - return mb_substr($string, 0, $length) . $etc; - } else { - return mb_substr($string, 0, $length / 2) . $etc . mb_substr($string, - $length / 2); - } - } else { - return $string; - } - } - } - // $string has no utf-8 encoding - if (strlen($string) > $length) { + } + if (Smarty::$_MBSTRING) { + if (mb_strlen($string, Smarty::$_CHARSET) > $length) { + $length -= min($length, mb_strlen($etc, Smarty::$_CHARSET)); + if (!$break_words && !$middle) { + $string = preg_replace( + '/\s+?(\S+)?$/' . Smarty::$_UTF8_MODIFIER, + '', + mb_substr($string, 0, $length + 1, Smarty::$_CHARSET) + ); + } + if (!$middle) { + return mb_substr($string, 0, $length, Smarty::$_CHARSET) . $etc; + } + return mb_substr($string, 0, $length / 2, Smarty::$_CHARSET) . $etc . + mb_substr($string, -$length / 2, $length, Smarty::$_CHARSET); + } + return $string; + } + // no MBString fallback + if (isset($string[ $length ])) { $length -= min($length, strlen($etc)); if (!$break_words && !$middle) { $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length + 1)); - } + } if (!$middle) { return substr($string, 0, $length) . $etc; - } else { - return substr($string, 0, $length / 2) . $etc . substr($string, - $length / 2); - } - } else { - return $string; - } -} - -?> \ No newline at end of file + } + return substr($string, 0, $length / 2) . $etc . substr($string, -$length / 2); + } + return $string; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.cat.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.cat.php index 693722267..21d0e6624 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.cat.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.cat.php @@ -2,28 +2,27 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty cat modifier plugin - * - * Type: modifier
- * Name: cat
+ * Type: modifier + * Name: cat * Date: Feb 24, 2003 * Purpose: catenate a value to a variable * Input: string to catenate * Example: {$var|cat:"foo"} - * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat - * (Smarty online manual) - * @author Uwe Tews + * + * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat + * (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_cat($params, $compiler) +function smarty_modifiercompiler_cat($params) { - return '('.implode(').(', $params).')'; + return '(' . implode(').(', $params) . ')'; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_characters.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_characters.php index 12a87c488..6c44278af 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_characters.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_characters.php @@ -2,38 +2,31 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty count_characters modifier plugin - * - * Type: modifier
- * Name: count_characteres
+ * Type: modifier + * Name: count_characters * Purpose: count the number of characters in a text - * - * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online + * manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_count_characters($params, $compiler) +function smarty_modifiercompiler_count_characters($params) { - // mb_ functions available? - if (function_exists('mb_strlen')) { - // count also spaces? - if (isset($params[1]) && $params[1] == 'true') { - return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? mb_strlen(' . $params[0] . ', SMARTY_RESOURCE_CHAR_SET) : strlen(' . $params[0] . '))'; - } - return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? preg_match_all(\'#[^\s\pZ]#u\', ' . $params[0] . ', $tmp) : preg_match_all(\'/[^\s]/\',' . $params[0] . ', $tmp))'; - } else { - // count also spaces? - if (isset($params[1]) && $params[1] == 'true') { - return 'strlen(' . $params[0] . ')'; - } - return 'preg_match_all(\'/[^\s]/\',' . $params[0] . ', $tmp)'; - } + if (!isset($params[ 1 ]) || $params[ 1 ] !== 'true') { + return 'preg_match_all(\'/[^\s]/' . Smarty::$_UTF8_MODIFIER . '\',' . $params[ 0 ] . ', $tmp)'; + } + if (Smarty::$_MBSTRING) { + return 'mb_strlen(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')'; + } + // no MBString fallback + return 'strlen(' . $params[ 0 ] . ')'; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_paragraphs.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_paragraphs.php index d221e3dc2..e214a56f0 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_paragraphs.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_paragraphs.php @@ -2,26 +2,25 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty count_paragraphs modifier plugin - * - * Type: modifier
- * Name: count_paragraphs
+ * Type: modifier + * Name: count_paragraphs * Purpose: count the number of paragraphs in a text - * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php + * + * @link http://www.smarty.net/manual/en/language.modifier.count.paragraphs.php * count_paragraphs (Smarty online manual) - * @author Uwe Tews + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_count_paragraphs($params, $compiler) +function smarty_modifiercompiler_count_paragraphs($params) { // count \r or \n characters - return '(preg_match_all(\'#[\r\n]+#\', ' . $params[0] . ', $tmp)+1)'; + return '(preg_match_all(\'#[\r\n]+#\', ' . $params[ 0 ] . ', $tmp)+1)'; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_sentences.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_sentences.php index 6d0bcf660..027745635 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_sentences.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_sentences.php @@ -2,26 +2,25 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty count_sentences modifier plugin - * - * Type: modifier
+ * Type: modifier * Name: count_sentences * Purpose: count the number of sentences in a text - * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php + * + * @link http://www.smarty.net/manual/en/language.modifier.count.paragraphs.php * count_sentences (Smarty online manual) - * @author Uwe Tews + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_count_sentences($params, $compiler) +function smarty_modifiercompiler_count_sentences($params) { - // find periods with a word before but not after. - return 'preg_match_all(\'/[^\s]\.(?!\w)/\', ' . $params[0] . ', $tmp)'; + // find periods, question marks, exclamation marks with a word before but not after. + return 'preg_match_all("#\w[\.\?\!](\W|$)#S' . Smarty::$_UTF8_MODIFIER . '", ' . $params[ 0 ] . ', $tmp)'; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_words.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_words.php index 82bc47866..6d889da5c 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.count_words.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.count_words.php @@ -1,31 +1,31 @@ - * Name: count_words
+ * Type: modifier + * Name: count_words * Purpose: count the number of words in a text - * - * @link http://smarty.php.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code -*/ -function smarty_modifiercompiler_count_words($params, $compiler) -{ - // mb_ functions available? - if (function_exists('mb_strlen')) { - return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? preg_match_all(\'#[\w\pL]+#u\', ' . $params[0] . ', $tmp) : preg_match_all(\'#\w+#\',' . $params[0] . ', $tmp))'; - } else { - return 'str_word_count(' . $params[0] . ')'; - } -} - -?> \ No newline at end of file + */ +function smarty_modifiercompiler_count_words($params) +{ + if (Smarty::$_MBSTRING) { + // return 'preg_match_all(\'#[\w\pL]+#' . Smarty::$_UTF8_MODIFIER . '\', ' . $params[0] . ', $tmp)'; + // expression taken from http://de.php.net/manual/en/function.str-word-count.php#85592 + return 'preg_match_all(\'/\p{L}[\p{L}\p{Mn}\p{Pd}\\\'\x{2019}]*/' . Smarty::$_UTF8_MODIFIER . '\', ' . + $params[ 0 ] . ', $tmp)'; + } + // no MBString fallback + return 'str_word_count(' . $params[ 0 ] . ')'; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.default.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.default.php index efbbaef80..ae886c4b2 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.default.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.default.php @@ -2,32 +2,31 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty default modifier plugin - * - * Type: modifier
- * Name: default
+ * Type: modifier + * Name: default * Purpose: designate default value for empty variables - * - * @link http://smarty.php.net/manual/en/language.modifier.default.php default (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.default.php default (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_default ($params, $compiler) +function smarty_modifiercompiler_default($params) { - $output = $params[0]; - if (!isset($params[1])) { - $params[1] = "''"; - } - for ($i = 1, $cnt = count($params); $i < $cnt; $i++) { - $output = '(($tmp = @' . $output . ')===null||$tmp===\'\' ? ' . $params[$i] . ' : $tmp)'; - } + $output = $params[ 0 ]; + if (!isset($params[ 1 ])) { + $params[ 1 ] = "''"; + } + array_shift($params); + foreach ($params as $param) { + $output = '(($tmp = @' . $output . ')===null||$tmp===\'\' ? ' . $param . ' : $tmp)'; + } return $output; -} - -?> \ No newline at end of file +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.escape.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.escape.php new file mode 100644 index 000000000..e0763adce --- /dev/null +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.escape.php @@ -0,0 +1,112 @@ +template->_checkPlugins( + array( + array( + 'function' => 'smarty_literal_compiler_param', + 'file' => SMARTY_PLUGINS_DIR . 'shared.literal_compiler_param.php' + ) + ) + ); + if ($_double_encode === null) { + $_double_encode = version_compare(PHP_VERSION, '5.2.3', '>='); + } + try { + $esc_type = smarty_literal_compiler_param($params, 1, 'html'); + $char_set = smarty_literal_compiler_param($params, 2, Smarty::$_CHARSET); + $double_encode = smarty_literal_compiler_param($params, 3, true); + if (!$char_set) { + $char_set = Smarty::$_CHARSET; + } + switch ($esc_type) { + case 'html': + if ($_double_encode) { + return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . + var_export($double_encode, true) . ')'; + } elseif ($double_encode) { + return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')'; + } else { + // fall back to modifier.escape.php + } + // no break + case 'htmlall': + if (Smarty::$_MBSTRING) { + if ($_double_encode) { + // php >=5.2.3 - go native + return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . + var_export($char_set, true) . ', ' . var_export($double_encode, true) . + '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')'; + } elseif ($double_encode) { + // php <5.2.3 - only handle double encoding + return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . + var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')'; + } else { + // fall back to modifier.escape.php + } + } + // no MBString fallback + if ($_double_encode) { + // php >=5.2.3 - go native + return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . + var_export($double_encode, true) . ')'; + } elseif ($double_encode) { + // php <5.2.3 - only handle double encoding + return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')'; + } else { + // fall back to modifier.escape.php + } + // no break + case 'url': + return 'rawurlencode(' . $params[ 0 ] . ')'; + case 'urlpathinfo': + return 'str_replace("%2F", "/", rawurlencode(' . $params[ 0 ] . '))'; + case 'quotes': + // escape unescaped single quotes + return 'preg_replace("%(? "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", " "<\/" ))'; + } + } catch (SmartyException $e) { + // pass through to regular plugin fallback + } + // could not optimize |escape call, so fallback to regular plugin + if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) { + $compiler->required_plugins[ 'nocache' ][ 'escape' ][ 'modifier' ][ 'file' ] = + SMARTY_PLUGINS_DIR . 'modifier.escape.php'; + $compiler->required_plugins[ 'nocache' ][ 'escape' ][ 'modifier' ][ 'function' ] = + 'smarty_modifier_escape'; + } else { + $compiler->required_plugins[ 'compiled' ][ 'escape' ][ 'modifier' ][ 'file' ] = + SMARTY_PLUGINS_DIR . 'modifier.escape.php'; + $compiler->required_plugins[ 'compiled' ][ 'escape' ][ 'modifier' ][ 'function' ] = + 'smarty_modifier_escape'; + } + return 'smarty_modifier_escape(' . join(', ', $params) . ')'; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.from_charset.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.from_charset.php new file mode 100644 index 000000000..acce7784b --- /dev/null +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.from_charset.php @@ -0,0 +1,30 @@ + - * Name: indent
+ * Type: modifier + * Name: indent * Purpose: indent lines of text - * @link http://smarty.php.net/manual/en/language.modifier.indent.php - * indent (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.indent.php indent (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ - -function smarty_modifiercompiler_indent($params, $compiler) +function smarty_modifiercompiler_indent($params) { - if (!isset($params[1])) { - $params[1] = 4; - } - if (!isset($params[2])) { - $params[2] = "' '"; - } - return 'preg_replace(\'!^!m\',str_repeat(' . $params[2] . ',' . $params[1] . '),' . $params[0] . ')'; + if (!isset($params[ 1 ])) { + $params[ 1 ] = 4; + } + if (!isset($params[ 2 ])) { + $params[ 2 ] = "' '"; + } + return 'preg_replace(\'!^!m\',str_repeat(' . $params[ 2 ] . ',' . $params[ 1 ] . '),' . $params[ 0 ] . ')'; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.lower.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.lower.php index 13858d48d..0d899a002 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.lower.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.lower.php @@ -1,31 +1,29 @@ - * Name: lower
+ * Type: modifier + * Name: lower * Purpose: convert string to lowercase - * - * @link http://smarty.php.net/manual/en/language.modifier.lower.php lower (Smarty online manual) - * @author Monte Ohrt - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.lower.php lower (Smarty online manual) + * @author Monte Ohrt + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ - -function smarty_modifiercompiler_lower($params, $compiler) +function smarty_modifiercompiler_lower($params) { - if (function_exists('mb_strtolower')) { - return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? mb_strtolower(' . $params[0] . ',SMARTY_RESOURCE_CHAR_SET) : strtolower(' . $params[0] . '))' ; - } else { - return 'strtolower(' . $params[0] . ')'; - } -} - -?> \ No newline at end of file + if (Smarty::$_MBSTRING) { + return 'mb_strtolower(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')'; + } + // no MBString fallback + return 'strtolower(' . $params[ 0 ] . ')'; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.noprint.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.noprint.php index 5fac7b6cc..1275190e0 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.noprint.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.noprint.php @@ -2,23 +2,19 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty noprint modifier plugin - * - * Type: modifier
- * Name: noprint
+ * Type: modifier + * Name: noprint * Purpose: return an empty string - * @author Uwe Tews - * @param array $params parameters + * + * @author Uwe Tews * @return string with compiled code */ -function smarty_modifiercompiler_noprint($params, $compiler) +function smarty_modifiercompiler_noprint() { return "''"; } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.string_format.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.string_format.php index de4054ec9..663094311 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.string_format.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.string_format.php @@ -1,26 +1,24 @@ - * Name: string_format
+ * Type: modifier + * Name: string_format * Purpose: format strings via sprintf - * - * @link http://smarty.php.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_string_format($params, $compiler) +function smarty_modifiercompiler_string_format($params) { - return 'sprintf(' . $params[1] . ',' . $params[0] . ')'; -} - -?> \ No newline at end of file + return 'sprintf(' . $params[ 1 ] . ',' . $params[ 0 ] . ')'; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.strip.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.strip.php index 83c36391e..04ea332c5 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.strip.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.strip.php @@ -2,32 +2,29 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty strip modifier plugin - * - * Type: modifier
- * Name: strip
+ * Type: modifier + * Name: strip * Purpose: Replace all repeated spaces, newlines, tabs - * with a single space or supplied replacement string.
+ * with a single space or supplied replacement string. * Example: {$var|strip} {$var|strip:" "} * Date: September 25th, 2002 - * - * @link http://smarty.php.net/manual/en/language.modifier.strip.php strip (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/manual/en/language.modifier.strip.php strip (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ - -function smarty_modifiercompiler_strip($params, $compiler) +function smarty_modifiercompiler_strip($params) { - if (!isset($params[1])) { - $params[1] = "' '"; - } - return "preg_replace('!\s+!', {$params[1]},{$params[0]})"; -} - -?> \ No newline at end of file + if (!isset($params[ 1 ])) { + $params[ 1 ] = "' '"; + } + return "preg_replace('!\s+!" . Smarty::$_UTF8_MODIFIER . "', {$params[1]},{$params[0]})"; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.strip_tags.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.strip_tags.php index ec1a96590..1bca1a28e 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.strip_tags.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.strip_tags.php @@ -2,33 +2,27 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty strip_tags modifier plugin - * - * Type: modifier
- * Name: strip_tags
+ * Type: modifier + * Name: strip_tags * Purpose: strip html tags from text - * - * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php strip_tags (Smarty online manual) - * @author Uwe Tews + * + * @link http://www.smarty.net/docs/en/language.modifier.strip.tags.tpl strip_tags (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ - -function smarty_modifiercompiler_strip_tags($params, $compiler) +function smarty_modifiercompiler_strip_tags($params) { - if (!isset($params[1])) { - $params[1] = true; - } - if ($params[1] === true) { + if (!isset($params[ 1 ]) || $params[ 1 ] === true || trim($params[ 1 ], '"') === 'true') { return "preg_replace('!<[^>]*?>!', ' ', {$params[0]})"; } else { - return 'strip_tags(' . $params[0] . ')'; - } -} - -?> \ No newline at end of file + return 'strip_tags(' . $params[ 0 ] . ')'; + } +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.to_charset.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.to_charset.php new file mode 100644 index 000000000..d652eab1b --- /dev/null +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.to_charset.php @@ -0,0 +1,30 @@ + - * Name: lower
+ * Type: modifier + * Name: lower * Purpose: convert string to uppercase - * - * @link http://smarty.php.net/manual/en/language.modifier.upper.php lower (Smarty online manual) - * @author Uwe Tews + * + * @link http://smarty.php.net/manual/en/language.modifier.upper.php lower (Smarty online manual) + * @author Uwe Tews + * * @param array $params parameters + * * @return string with compiled code */ -function smarty_modifiercompiler_upper($params, $compiler) +function smarty_modifiercompiler_upper($params) { - if (function_exists('mb_strtoupper')) { - return '((mb_detect_encoding(' . $params[0] . ', \'UTF-8, ISO-8859-1\') === \'UTF-8\') ? mb_strtoupper(' . $params[0] . ',SMARTY_RESOURCE_CHAR_SET) : strtoupper(' . $params[0] . '))' ; - } else { - return 'strtoupper(' . $params[0] . ')'; - } -} - -?> \ No newline at end of file + if (Smarty::$_MBSTRING) { + return 'mb_strtoupper(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')'; + } + // no MBString fallback + return 'strtoupper(' . $params[ 0 ] . ')'; +} diff --git a/WEB-INF/lib/smarty/plugins/modifiercompiler.wordwrap.php b/WEB-INF/lib/smarty/plugins/modifiercompiler.wordwrap.php index ff593c728..8565f140e 100644 --- a/WEB-INF/lib/smarty/plugins/modifiercompiler.wordwrap.php +++ b/WEB-INF/lib/smarty/plugins/modifiercompiler.wordwrap.php @@ -2,34 +2,38 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsModifierCompiler */ - /** * Smarty wordwrap modifier plugin - * - * Type: modifier
- * Name: wordwrap
+ * Type: modifier + * Name: wordwrap * Purpose: wrap a string of text at a given length - * - * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual) - * @author Uwe Tews - * @param array $params parameters + * + * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual) + * @author Uwe Tews + * + * @param array $params parameters + * @param \Smarty_Internal_TemplateCompilerBase $compiler + * * @return string with compiled code + * @throws \SmartyException */ -function smarty_modifiercompiler_wordwrap($params, $compiler) +function smarty_modifiercompiler_wordwrap($params, Smarty_Internal_TemplateCompilerBase $compiler) { - if (!isset($params[1])) { - $params[1] = 80; - } - if (!isset($params[2])) { - $params[2] = '"\n"'; - } - if (!isset($params[3])) { - $params[3] = 'false'; - } - return 'wordwrap(' . $params[0] . ',' . $params[1] . ',' . $params[2] . ',' . $params[3] . ')'; -} - -?> \ No newline at end of file + if (!isset($params[ 1 ])) { + $params[ 1 ] = 80; + } + if (!isset($params[ 2 ])) { + $params[ 2 ] = '"\n"'; + } + if (!isset($params[ 3 ])) { + $params[ 3 ] = 'false'; + } + $function = 'wordwrap'; + if (Smarty::$_MBSTRING) { + $function = $compiler->getPlugin('mb_wordwrap', 'modifier'); + } + return $function . '(' . $params[ 0 ] . ',' . $params[ 1 ] . ',' . $params[ 2 ] . ',' . $params[ 3 ] . ')'; +} diff --git a/WEB-INF/lib/smarty/plugins/outputfilter.trimwhitespace.php b/WEB-INF/lib/smarty/plugins/outputfilter.trimwhitespace.php index 20e9bb600..7e4503a1c 100644 --- a/WEB-INF/lib/smarty/plugins/outputfilter.trimwhitespace.php +++ b/WEB-INF/lib/smarty/plugins/outputfilter.trimwhitespace.php @@ -2,76 +2,88 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFilter */ - /** * Smarty trimwhitespace outputfilter plugin + * Trim unnecessary whitespace from HTML markup. + * + * @author Rodney Rehm * - * File: outputfilter.trimwhitespace.php
- * Type: outputfilter
- * Name: trimwhitespace
- * Date: Jan 25, 2003
- * Purpose: trim leading white space and blank lines from - * template source after it gets interpreted, cleaning - * up code and saving bandwidth. Does not affect - * <
>
and blocks.
- * Install: Drop into the plugin directory, call - * $smarty->load_filter('output','trimwhitespace'); - * from application. - * @author Monte Ohrt - * @author Contributions from Lars Noschinski - * @version 1.3 * @param string $source input string - * @param object &$smarty Smarty object + * * @return string filtered output + * @todo substr_replace() is not overloaded by mbstring.func_overload - so this function might fail! */ -function smarty_outputfilter_trimwhitespace($source, $smarty) +function smarty_outputfilter_trimwhitespace($source) { - // Pull out the script blocks - preg_match_all("!]*?>.*?!is", $source, $match); - $_script_blocks = $match[0]; - $source = preg_replace("!]*?>.*?!is", - '@@@SMARTY:TRIM:SCRIPT@@@', $source); - - // Pull out the pre blocks - preg_match_all("!]*?>.*?!is", $source, $match); - $_pre_blocks = $match[0]; - $source = preg_replace("!]*?>.*?!is", - '@@@SMARTY:TRIM:PRE@@@', $source); - - // Pull out the textarea blocks - preg_match_all("!]*?>.*?!is", $source, $match); - $_textarea_blocks = $match[0]; - $source = preg_replace("!]*?>.*?!is", - '@@@SMARTY:TRIM:TEXTAREA@@@', $source); - - // remove all leading spaces, tabs and carriage returns NOT - // preceeded by a php close tag. - $source = trim(preg_replace('/((?)\n)[\s]+/m', '\1', $source)); - - // replace textarea blocks - smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source); - - // replace pre blocks - smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source); - - // replace script blocks - smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source); - + $store = array(); + $_store = 0; + $_offset = 0; + // Unify Line-Breaks to \n + $source = preg_replace('/\015\012|\015|\012/', "\n", $source); + // capture Internet Explorer and KnockoutJS Conditional Comments + if (preg_match_all( + '##is', + $source, + $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + ) + ) { + foreach ($matches as $match) { + $store[] = $match[ 0 ][ 0 ]; + $_length = strlen($match[ 0 ][ 0 ]); + $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@'; + $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length); + $_offset += $_length - strlen($replace); + $_store++; + } + } + // Strip all HTML-Comments + // yes, even the ones in '; + } elseif (strpos($lex->value, $lex->smarty->left_delimiter) === 0) { + if ($lex->isAutoLiteral()) { + $lex->token = Smarty_Internal_Templateparser::TP_TEXT; + return; + } + $closeTag = "{$lex->smarty->left_delimiter}/php{$lex->smarty->right_delimiter}"; + if ($lex->value === $closeTag) { + $lex->compiler->trigger_template_error("unexpected closing tag '{$closeTag}'"); + } + $lex->phpType = 'tag'; + } + if ($lex->phpType === 'unmatched') { + return; + } + if (($lex->phpType === 'php' || $lex->phpType === 'asp') + && + ($lex->compiler->php_handling === Smarty::PHP_PASSTHRU || + $lex->compiler->php_handling === Smarty::PHP_QUOTE) + ) { + return; + } + $start = $lex->counter + strlen($lex->value); + $body = true; + if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) { + $close = $match[ 0 ][ 1 ]; + } else { + $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'"); + } + while ($body) { + if (preg_match( + '~([/][*])|([/][/][^\n]*)|(\'[^\'\\\\]*(?:\\.[^\'\\\\]*)*\')|("[^"\\\\]*(?:\\.[^"\\\\]*)*")~', + $lex->data, + $match, + PREG_OFFSET_CAPTURE, + $start + ) + ) { + $value = $match[ 0 ][ 0 ]; + $from = $pos = $match[ 0 ][ 1 ]; + if ($pos > $close) { + $body = false; + } else { + $start = $pos + strlen($value); + $phpCommentStart = $value === '/*'; + if ($phpCommentStart) { + $phpCommentEnd = preg_match('~([*][/])~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start); + if ($phpCommentEnd) { + $pos2 = $match[ 0 ][ 1 ]; + $start = $pos2 + strlen($match[ 0 ][ 0 ]); + } + } + while ($close > $pos && $close < $start) { + if (preg_match( + '~' . preg_quote($closeTag, '~') . '~i', + $lex->data, + $match, + PREG_OFFSET_CAPTURE, + $from + ) + ) { + $close = $match[ 0 ][ 1 ]; + $from = $close + strlen($match[ 0 ][ 0 ]); + } else { + $lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'"); + } + } + if ($phpCommentStart && (!$phpCommentEnd || $pos2 > $close)) { + $lex->taglineno = $lex->line + substr_count(substr($lex->data, $lex->counter, $start), "\n"); + $lex->compiler->trigger_template_error("missing PHP comment closing tag '*/'"); + } + } + } else { + $body = false; + } + } + $lex->value = substr($lex->data, $lex->counter, $close + strlen($closeTag) - $lex->counter); + } + + /* + * Call back function for $php_handling = PHP_QUOTE + * + */ + /** + * @param $match + * + * @return string + */ + private function quote($match) + { + return htmlspecialchars($match[ 0 ], ENT_QUOTES); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_print_expression.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_print_expression.php index 5a9c93191..23cae8aef 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_print_expression.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_print_expression.php @@ -1,77 +1,161 @@ compiler = $compiler; // check and get attributes - $_attr = $this->_get_attributes($args); - // nocache option - if ($_attr['nocache'] === true) { - $this->compiler->tag_nocache = true; - } - // filter handling - if ($_attr['nofilter'] === true) { - $_filter = 'false'; - } else { - $_filter = 'true'; - } - // compiled output - // compiled output - if (isset($_attr['assign'])) { + $_attr = $this->getAttributes($compiler, $args); + $output = $parameter[ 'value' ]; + // tag modifier + if (!empty($parameter[ 'modifierlist' ])) { + $output = $compiler->compileTag( + 'private_modifier', + array(), + array( + 'modifierlist' => $parameter[ 'modifierlist' ], + 'value' => $output + ) + ); + } + if (isset($_attr[ 'assign' ])) { // assign output to variable - $output = "assign({$_attr['assign']},{$parameter['value']});?>"; + return "assign({$_attr['assign']},{$output});?>"; } else { // display value - if (!$_attr['nofilter'] && isset($this->compiler->smarty->registered_filters['variable'])) { - $output = "Smarty_Internal_Filter_Handler::runFilter('variable', {$parameter['value']}, \$_smarty_tpl, {$_filter})"; - } else { - $output = $parameter['value']; - } - if (!$_attr['nofilter'] && !empty($this->compiler->smarty->default_modifiers)) { - $modifierlist = array(); - foreach ($this->compiler->smarty->default_modifiers as $key => $single_default_modifier) { - preg_match_all('/(\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|:|[^:]+)/', $single_default_modifier, $mod_array); - for ($i = 0, $count = count($mod_array[0]);$i < $count;$i++) { - if ($mod_array[0][$i] != ':') { - $modifierlist[$key][] = $mod_array[0][$i]; - } - } - } - $output = $this->compiler->compileTag('private_modifier', array(), array('modifierlist' => $modifierlist, 'value' => $output)); - } - if (!empty($parameter['modifierlist'])) { - $output = $this->compiler->compileTag('private_modifier', array(), array('modifierlist' => $parameter['modifierlist'], 'value' => $output)); - } - $this->compiler->has_output = true; - $output = ""; - } + if (!$_attr[ 'nofilter' ]) { + // default modifier + if (!empty($compiler->smarty->default_modifiers)) { + if (empty($compiler->default_modifier_list)) { + $modifierlist = array(); + foreach ($compiler->smarty->default_modifiers as $key => $single_default_modifier) { + preg_match_all( + '/(\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|:|[^:]+)/', + $single_default_modifier, + $mod_array + ); + for ($i = 0, $count = count($mod_array[ 0 ]); $i < $count; $i++) { + if ($mod_array[ 0 ][ $i ] !== ':') { + $modifierlist[ $key ][] = $mod_array[ 0 ][ $i ]; + } + } + } + $compiler->default_modifier_list = $modifierlist; + } + $output = $compiler->compileTag( + 'private_modifier', + array(), + array( + 'modifierlist' => $compiler->default_modifier_list, + 'value' => $output + ) + ); + } + // autoescape html + if ($compiler->template->smarty->escape_html) { + $output = "htmlspecialchars({$output}, ENT_QUOTES, '" . addslashes(Smarty::$_CHARSET) . "')"; + } + // loop over registered filters + if (!empty($compiler->template->smarty->registered_filters[ Smarty::FILTER_VARIABLE ])) { + foreach ($compiler->template->smarty->registered_filters[ Smarty::FILTER_VARIABLE ] as $key => + $function) { + if (!is_array($function)) { + $output = "{$function}({$output},\$_smarty_tpl)"; + } elseif (is_object($function[ 0 ])) { + $output = + "\$_smarty_tpl->smarty->registered_filters[Smarty::FILTER_VARIABLE]['{$key}'][0]->{$function[1]}({$output},\$_smarty_tpl)"; + } else { + $output = "{$function[0]}::{$function[1]}({$output},\$_smarty_tpl)"; + } + } + } + // auto loaded filters + if (isset($compiler->smarty->autoload_filters[ Smarty::FILTER_VARIABLE ])) { + foreach ((array)$compiler->template->smarty->autoload_filters[ Smarty::FILTER_VARIABLE ] as $name) { + $result = $this->compile_variable_filter($compiler, $name, $output); + if ($result !== false) { + $output = $result; + } else { + // not found, throw exception + throw new SmartyException("Unable to load variable filter '{$name}'"); + } + } + } + foreach ($compiler->variable_filters as $filter) { + if (count($filter) === 1 + && ($result = $this->compile_variable_filter($compiler, $filter[ 0 ], $output)) !== false + ) { + $output = $result; + } else { + $output = $compiler->compileTag( + 'private_modifier', + array(), + array('modifierlist' => array($filter), 'value' => $output) + ); + } + } + } + $output = "\n"; + } return $output; - } -} + } -?> \ No newline at end of file + /** + * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object + * @param string $name name of variable filter + * @param string $output embedded output + * + * @return string + * @throws \SmartyException + */ + private function compile_variable_filter(Smarty_Internal_TemplateCompilerBase $compiler, $name, $output) + { + $function = $compiler->getPlugin($name, 'variablefilter'); + if ($function) { + return "{$function}({$output},\$_smarty_tpl)"; + } else { + // not found + return false; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_block.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_block.php index b8f239d81..0f818d1b3 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_block.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_block.php @@ -1,95 +1,72 @@ compiler = $compiler; - if (strlen($tag) < 6 || substr($tag,-5) != 'close') { - // opening tag of block plugin - // check and get attributes - $_attr = $this->_get_attributes($args); - if ($_attr['nocache']) { - $this->compiler->tag_nocache = true; - } - unset($_attr['nocache']); - // convert attributes into parameter array string - $_paramsArray = array(); - foreach ($_attr as $_key => $_value) { - if (is_int($_key)) { - $_paramsArray[] = "$_key=>$_value"; - } elseif ($this->compiler->template->caching && in_array($_key,$compiler->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$tag][2])) { - $_value = str_replace("'","^#^",$_value); - $_paramsArray[] = "'$_key'=>^#^.var_export($_value,true).^#^"; + if (isset($compiler->smarty->registered_plugins[ Smarty::PLUGIN_BLOCK ][ $tag ])) { + $tag_info = $compiler->smarty->registered_plugins[ Smarty::PLUGIN_BLOCK ][ $tag ]; + $callback = $tag_info[ 0 ]; + if (is_array($callback)) { + if (is_object($callback[ 0 ])) { + $callable = "array(\$_block_plugin{$this->nesting}, '{$callback[1]}')"; + $callback = + array("\$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]", "->{$callback[1]}"); } else { - $_paramsArray[] = "'$_key'=>$_value"; - } - } - $_params = 'array(' . implode(",", $_paramsArray) . ')'; - - $this->_open_tag($tag, array($_params, $this->compiler->nocache)); - // maybe nocache because of nocache variables or nocache plugin - $this->compiler->nocache = !$compiler->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$tag][1] | $this->compiler->nocache | $this->compiler->tag_nocache; - $function = $compiler->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$tag][0]; - // compile code - if (!is_array($function)) { - $output = "smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; {$function}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; - } else if (is_object($function[0])) { - $output = "smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; \$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]->{$function[1]}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; + $callable = "array(\$_block_plugin{$this->nesting}, '{$callback[1]}')"; + $callback = + array("\$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]", "::{$callback[1]}"); + } } else { - $output = "smarty->_tag_stack[] = array('{$tag}', {$_params}); \$_block_repeat=true; {$function[0]}::{$function[1]}({$_params}, null, \$_smarty_tpl, \$_block_repeat);while (\$_block_repeat) { ob_start();?>"; - } + $callable = "\$_block_plugin{$this->nesting}"; + $callback = array("\$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0]", ''); + } } else { - // must endblock be nocache? - if ($this->compiler->nocache) { - $this->compiler->tag_nocache = true; - } - $base_tag = substr($tag, 0, -5); - // closing tag of block plugin, restore nocache - list($_params, $this->compiler->nocache) = $this->_close_tag($base_tag); - // This tag does create output - $this->compiler->has_output = true; - $function = $compiler->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$base_tag][0]; - // compile code - if (!isset($parameter['modifier_list'])) { - $mod_pre = $mod_post =''; + $tag_info = $compiler->default_handler_plugins[ Smarty::PLUGIN_BLOCK ][ $tag ]; + $callback = $tag_info[ 0 ]; + if (is_array($callback)) { + $callable = "array('{$callback[0]}', '{$callback[1]}')"; + $callback = "{$callback[1]}::{$callback[1]}"; } else { - $mod_pre = ' ob_start(); '; - $mod_post = 'echo '.$this->compiler->compileTag('private_modifier',array(),array('modifierlist'=>$parameter['modifier_list'],'value'=>'ob_get_clean()')).';'; + $callable = null; } - if (!is_array($function)) { - $output = "smarty->_tag_stack);?>"; - } else if (is_object($function[0])) { - $output = "smarty->registered_plugins['block']['{$base_tag}'][0][0]->{$function[1]}({$_params}, \$_block_content, \$_smarty_tpl, \$_block_repeat); ".$mod_post."} array_pop(\$_smarty_tpl->smarty->_tag_stack);?>"; + } + $compiler->tag_nocache = !$tag_info[ 1 ] | $compiler->tag_nocache; + $_paramsArray = array(); + foreach ($_attr as $_key => $_value) { + if (is_int($_key)) { + $_paramsArray[] = "$_key=>$_value"; + } elseif ($compiler->template->caching && in_array($_key, $tag_info[ 2 ])) { + $_value = str_replace('\'', "^#^", $_value); + $_paramsArray[] = "'$_key'=>^#^.var_export($_value,true).^#^"; } else { - $output = "smarty->_tag_stack);?>"; - } - } - return $output."\n"; - } -} - -?> \ No newline at end of file + $_paramsArray[] = "'$_key'=>$_value"; + } + } + return array($callback, $_paramsArray, $callable); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_function.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_function.php index 96236fa9b..2591107d2 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_function.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_registered_function.php @@ -1,67 +1,91 @@ compiler = $compiler; - // This tag does create output - $this->compiler->has_output = true; // check and get attributes - $_attr = $this->_get_attributes($args); - if ($_attr['nocache']) { - $this->compiler->tag_nocache = true; + $_attr = $this->getAttributes($compiler, $args); + unset($_attr[ 'nocache' ]); + if (isset($compiler->smarty->registered_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ])) { + $tag_info = $compiler->smarty->registered_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ]; + $is_registered = true; + } else { + $tag_info = $compiler->default_handler_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ]; + $is_registered = false; } - unset($_attr['nocache']); - // not cachable? - $this->compiler->tag_nocache = $this->compiler->tag_nocache || !$compiler->smarty->registered_plugins[Smarty::PLUGIN_FUNCTION][$tag][1]; + // not cacheable? + $compiler->tag_nocache = $compiler->tag_nocache || !$tag_info[ 1 ]; // convert attributes into parameter array string $_paramsArray = array(); foreach ($_attr as $_key => $_value) { if (is_int($_key)) { $_paramsArray[] = "$_key=>$_value"; - } elseif ($this->compiler->template->caching && in_array($_key,$compiler->smarty->registered_plugins[Smarty::PLUGIN_FUNCTION][$tag][2])) { - $_value = str_replace("'","^#^",$_value); + } elseif ($compiler->template->caching && in_array($_key, $tag_info[ 2 ])) { + $_value = str_replace('\'', "^#^", $_value); $_paramsArray[] = "'$_key'=>^#^.var_export($_value,true).^#^"; } else { $_paramsArray[] = "'$_key'=>$_value"; - } - } - $_params = 'array(' . implode(",", $_paramsArray) . ')'; - $function = $compiler->smarty->registered_plugins[Smarty::PLUGIN_FUNCTION][$tag][0]; + } + } + $_params = 'array(' . implode(',', $_paramsArray) . ')'; // compile code - if (!is_array($function)) { - $output = "\n"; - } else if (is_object($function[0])) { - $output = "smarty->registered_plugins[Smarty::PLUGIN_FUNCTION]['{$tag}'][0][0]->{$function[1]}({$_params},\$_smarty_tpl);?>\n"; + if ($is_registered) { + $output = + "call_user_func_array( \$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_FUNCTION]['{$tag}'][0], array( {$_params},\$_smarty_tpl ) )"; } else { - $output = "\n"; - } + $function = $tag_info[ 0 ]; + if (!is_array($function)) { + $output = "{$function}({$_params},\$_smarty_tpl)"; + } else { + $output = "{$function[0]}::{$function[1]}({$_params},\$_smarty_tpl)"; + } + } + if (!empty($parameter[ 'modifierlist' ])) { + $output = $compiler->compileTag( + 'private_modifier', + array(), + array( + 'modifierlist' => $parameter[ 'modifierlist' ], + 'value' => $output + ) + ); + } + $output = "\n"; return $output; - } -} - -?> \ No newline at end of file + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php index 5d6ae8015..b317c9f33 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php @@ -1,99 +1,126 @@ getVariable('smarty')->value$parameter"; - case 'section': - return "\$_smarty_tpl->getVariable('smarty')->value$parameter"; - case 'capture': - return "Smarty::\$_smarty_vars$parameter"; - case 'now': - return 'time()'; - case 'cookies': - if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { - $compiler->trigger_template_error("(secure mode) super globals not permitted"); + $_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2)); + $variable = strtolower($compiler->getId($_index[ 0 ])); + if ($variable === false) { + $compiler->trigger_template_error("special \$Smarty variable name index can not be variable", null, true); + } + if (!isset($compiler->smarty->security_policy) + || $compiler->smarty->security_policy->isTrustedSpecialSmartyVar($variable, $compiler) + ) { + switch ($variable) { + case 'foreach': + case 'section': + if (!isset(Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ])) { + $class = 'Smarty_Internal_Compile_' . ucfirst($variable); + Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ] = new $class; + } + return Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ]->compileSpecialVariable( + array(), + $compiler, + $_index + ); + case 'capture': + if (class_exists('Smarty_Internal_Compile_Capture')) { + return Smarty_Internal_Compile_Capture::compileSpecialVariable(array(), $compiler, $_index); + } + return ''; + case 'now': + return 'time()'; + case 'cookies': + if (isset($compiler->smarty->security_policy) + && !$compiler->smarty->security_policy->allow_super_globals + ) { + $compiler->trigger_template_error("(secure mode) super globals not permitted"); + break; + } + $compiled_ref = '$_COOKIE'; break; - } - $compiled_ref = '$_COOKIE'; - break; - - case 'get': - case 'post': - case 'env': - case 'server': - case 'session': - case 'request': - if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { - $compiler->trigger_template_error("(secure mode) super globals not permitted"); + case 'get': + case 'post': + case 'env': + case 'server': + case 'session': + case 'request': + if (isset($compiler->smarty->security_policy) + && !$compiler->smarty->security_policy->allow_super_globals + ) { + $compiler->trigger_template_error("(secure mode) super globals not permitted"); + break; + } + $compiled_ref = '$_' . strtoupper($variable); break; - } - $compiled_ref = '$_'.strtoupper($variable); - break; - - case 'template': - return 'basename($_smarty_tpl->getTemplateFilepath())'; - - case 'current_dir': - return 'dirname($_smarty_tpl->getTemplateFilepath())'; - - case 'version': - $_version = Smarty::SMARTY_VERSION; - return "'$_version'"; - - case 'const': - if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_constants) { - $compiler->trigger_template_error("(secure mode) constants not permitted"); + case 'template': + return 'basename($_smarty_tpl->source->filepath)'; + case 'template_object': + return '$_smarty_tpl'; + case 'current_dir': + return 'dirname($_smarty_tpl->source->filepath)'; + case 'version': + return "Smarty::SMARTY_VERSION"; + case 'const': + if (isset($compiler->smarty->security_policy) + && !$compiler->smarty->security_policy->allow_constants + ) { + $compiler->trigger_template_error("(secure mode) constants not permitted"); + break; + } + if (strpos($_index[ 1 ], '$') === false && strpos($_index[ 1 ], '\'') === false) { + return "@constant('{$_index[1]}')"; + } else { + return "@constant({$_index[1]})"; + } + // no break + case 'config': + if (isset($_index[ 2 ])) { + return "(is_array(\$tmp = \$_smarty_tpl->smarty->ext->configload->_getConfigVariable(\$_smarty_tpl, $_index[1])) ? \$tmp[$_index[2]] : null)"; + } else { + return "\$_smarty_tpl->smarty->ext->configload->_getConfigVariable(\$_smarty_tpl, $_index[1])"; + } + // no break + case 'ldelim': + return "\$_smarty_tpl->smarty->left_delimiter"; + case 'rdelim': + return "\$_smarty_tpl->smarty->right_delimiter"; + default: + $compiler->trigger_template_error('$smarty.' . trim($_index[ 0 ], "'") . ' is not defined'); break; - } - return '@' . trim($_index[1], "'"); - - case 'config': - return "\$_smarty_tpl->getConfigVariable($_index[1])"; - case 'ldelim': - $_ldelim = $compiler->smarty->left_delimiter; - return "'$_ldelim'"; - - case 'rdelim': - $_rdelim = $compiler->smarty->right_delimiter; - return "'$_rdelim'"; - - default: - $compiler->trigger_template_error('$smarty.' . trim($_index[0], "'") . ' is invalid'); - break; - } - if (isset($_index[1])) { - array_shift($_index); - foreach ($_index as $_ind) { - $compiled_ref = $compiled_ref . "[$_ind]"; - } - } - return $compiled_ref; - } -} - -?> \ No newline at end of file + } + if (isset($_index[ 1 ])) { + array_shift($_index); + foreach ($_index as $_ind) { + $compiled_ref = $compiled_ref . "[$_ind]"; + } + } + return $compiled_ref; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_rdelim.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_rdelim.php index 6436bfd16..1cc340c18 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_rdelim.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_rdelim.php @@ -1,37 +1,34 @@ compiler = $compiler; - $_attr = $this->_get_attributes($args); - if ($_attr['nocache'] === true) { - $this->compiler->trigger_template_error('nocache option not allowed', $this->compiler->lex->taglineno); - } - // this tag does not return compiled code - $this->compiler->has_code = true; - return $this->compiler->smarty->right_delimiter; - } + parent::compile($args, $compiler); + return $compiler->smarty->right_delimiter; + } } - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_section.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_section.php index 0768b026e..0dee20820 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_section.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_section.php @@ -1,173 +1,462 @@ compiler = $compiler; + $compiler->loopNesting++; // check and get attributes - $_attr = $this->_get_attributes($args); - - $this->_open_tag('section', array('section',$this->compiler->nocache)); + $_attr = $this->getAttributes($compiler, $args); + $attributes = array('name' => $compiler->getId($_attr[ 'name' ])); + unset($_attr[ 'name' ]); + foreach ($attributes as $a => $v) { + if ($v === false) { + $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true); + } + } + $local = "\$__section_{$attributes['name']}_" . $this->counter++ . '_'; + $sectionVar = "\$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}']"; + $this->openTag($compiler, 'section', array('section', $compiler->nocache, $local, $sectionVar)); // maybe nocache because of nocache variables - $this->compiler->nocache = $this->compiler->nocache | $this->compiler->tag_nocache; - - $output = "tpl_vars['smarty']->value['section'][$section_name]);\n"; - $section_props = "\$_smarty_tpl->tpl_vars['smarty']->value['section'][$section_name]"; - + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + $initLocal = array(); + $initNamedProperty = array(); + $initFor = array(); + $incFor = array(); + $cmpFor = array(); + $propValue = array( + 'index' => "{$sectionVar}->value['index']", 'show' => 'true', 'step' => 1, + 'iteration' => "{$local}iteration", + ); + $propType = array('index' => 2, 'iteration' => 2, 'show' => 0, 'step' => 0,); + // search for used tag attributes + $this->scanForProperties($attributes, $compiler); + if (!empty($this->matchResults[ 'named' ])) { + $namedAttr = $this->matchResults[ 'named' ]; + } + if (isset($_attr[ 'properties' ]) && preg_match_all("/['](.*?)[']/", $_attr[ 'properties' ], $match)) { + foreach ($match[ 1 ] as $prop) { + if (in_array($prop, $this->nameProperties)) { + $namedAttr[ $prop ] = true; + } else { + $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); + } + } + } + $namedAttr[ 'index' ] = true; + $output = " $attr_value) { switch ($attr_name) { case 'loop': - $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n"; + if (is_numeric($attr_value)) { + $v = (int)$attr_value; + $t = 0; + } else { + $v = "(is_array(@\$_loop=$attr_value) ? count(\$_loop) : max(0, (int) \$_loop))"; + $t = 1; + } + if ($t === 1) { + $initLocal[ 'loop' ] = $v; + $v = "{$local}loop"; + } break; - case 'show': - if (is_bool($attr_value)) - $show_attr_value = $attr_value ? 'true' : 'false'; - else - $show_attr_value = "(bool)$attr_value"; - $output .= "{$section_props}['show'] = $show_attr_value;\n"; + if (is_bool($attr_value)) { + $v = $attr_value ? 'true' : 'false'; + $t = 0; + } else { + $v = "(bool) $attr_value"; + $t = 3; + } break; - - case 'name': - $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; + case 'step': + if (is_numeric($attr_value)) { + $v = (int)$attr_value; + $v = ($v === 0) ? 1 : $v; + $t = 0; + break; + } + $initLocal[ 'step' ] = "((int)@$attr_value) === 0 ? 1 : (int)@$attr_value"; + $v = "{$local}step"; + $t = 2; break; - case 'max': case 'start': - $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n"; - break; - - case 'step': - $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n"; + if (is_numeric($attr_value)) { + $v = (int)$attr_value; + $t = 0; + break; + } + $v = "(int)@$attr_value"; + $t = 3; break; - } - } - - if (!isset($_attr['show'])) - $output .= "{$section_props}['show'] = true;\n"; - - if (!isset($_attr['loop'])) - $output .= "{$section_props}['loop'] = 1;\n"; - - if (!isset($_attr['max'])) - $output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; - else - $output .= "if ({$section_props}['max'] < 0)\n" . " {$section_props}['max'] = {$section_props}['loop'];\n"; - - if (!isset($_attr['step'])) - $output .= "{$section_props}['step'] = 1;\n"; - - if (!isset($_attr['start'])) - $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n"; - else { - $output .= "if ({$section_props}['start'] < 0)\n" . " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" . "else\n" . " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n"; - } - - $output .= "if ({$section_props}['show']) {\n"; - if (!isset($_attr['start']) && !isset($_attr['step']) && !isset($_attr['max'])) { - $output .= " {$section_props}['total'] = {$section_props}['loop'];\n"; + } + if ($t === 3 && $compiler->getId($attr_value)) { + $t = 1; + } + $propValue[ $attr_name ] = $v; + $propType[ $attr_name ] = $t; + } + if (isset($namedAttr[ 'step' ])) { + $initNamedProperty[ 'step' ] = $propValue[ 'step' ]; + } + if (isset($namedAttr[ 'iteration' ])) { + $propValue[ 'iteration' ] = "{$sectionVar}->value['iteration']"; + } + $incFor[ 'iteration' ] = "{$propValue['iteration']}++"; + $initFor[ 'iteration' ] = "{$propValue['iteration']} = 1"; + if ($propType[ 'step' ] === 0) { + if ($propValue[ 'step' ] === 1) { + $incFor[ 'index' ] = "{$sectionVar}->value['index']++"; + } elseif ($propValue[ 'step' ] > 1) { + $incFor[ 'index' ] = "{$sectionVar}->value['index'] += {$propValue['step']}"; + } else { + $incFor[ 'index' ] = "{$sectionVar}->value['index'] -= " . -$propValue[ 'step' ]; + } } else { - $output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n"; - } - $output .= " if ({$section_props}['total'] == 0)\n" . " {$section_props}['show'] = false;\n" . "} else\n" . " {$section_props}['total'] = 0;\n"; - - $output .= "if ({$section_props}['show']):\n"; - $output .= " - for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1; - {$section_props}['iteration'] <= {$section_props}['total']; - {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n"; - $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n"; - $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n"; - $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n"; - $output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n"; - $output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n"; - - $output .= "?>"; + $incFor[ 'index' ] = "{$sectionVar}->value['index'] += {$propValue['step']}"; + } + if (!isset($propValue[ 'max' ])) { + $propValue[ 'max' ] = $propValue[ 'loop' ]; + $propType[ 'max' ] = $propType[ 'loop' ]; + } elseif ($propType[ 'max' ] !== 0) { + $propValue[ 'max' ] = "{$propValue['max']} < 0 ? {$propValue['loop']} : {$propValue['max']}"; + $propType[ 'max' ] = 1; + } else { + if ($propValue[ 'max' ] < 0) { + $propValue[ 'max' ] = $propValue[ 'loop' ]; + $propType[ 'max' ] = $propType[ 'loop' ]; + } + } + if (!isset($propValue[ 'start' ])) { + $start_code = + array(1 => "{$propValue['step']} > 0 ? ", 2 => '0', 3 => ' : ', 4 => $propValue[ 'loop' ], 5 => ' - 1'); + if ($propType[ 'loop' ] === 0) { + $start_code[ 5 ] = ''; + $start_code[ 4 ] = $propValue[ 'loop' ] - 1; + } + if ($propType[ 'step' ] === 0) { + if ($propValue[ 'step' ] > 0) { + $start_code = array(1 => '0'); + $propType[ 'start' ] = 0; + } else { + $start_code[ 1 ] = $start_code[ 2 ] = $start_code[ 3 ] = ''; + $propType[ 'start' ] = $propType[ 'loop' ]; + } + } else { + $propType[ 'start' ] = 1; + } + $propValue[ 'start' ] = join('', $start_code); + } else { + $start_code = + array( + 1 => "{$propValue['start']} < 0 ? ", 2 => 'max(', 3 => "{$propValue['step']} > 0 ? ", 4 => '0', + 5 => ' : ', 6 => '-1', 7 => ', ', 8 => "{$propValue['start']} + {$propValue['loop']}", 10 => ')', + 11 => ' : ', 12 => 'min(', 13 => $propValue[ 'start' ], 14 => ', ', + 15 => "{$propValue['step']} > 0 ? ", 16 => $propValue[ 'loop' ], 17 => ' : ', + 18 => $propType[ 'loop' ] === 0 ? $propValue[ 'loop' ] - 1 : "{$propValue['loop']} - 1", + 19 => ')' + ); + if ($propType[ 'step' ] === 0) { + $start_code[ 3 ] = $start_code[ 5 ] = $start_code[ 15 ] = $start_code[ 17 ] = ''; + if ($propValue[ 'step' ] > 0) { + $start_code[ 6 ] = $start_code[ 18 ] = ''; + } else { + $start_code[ 4 ] = $start_code[ 16 ] = ''; + } + } + if ($propType[ 'start' ] === 0) { + if ($propType[ 'loop' ] === 0) { + $start_code[ 8 ] = $propValue[ 'start' ] + $propValue[ 'loop' ]; + } + $propType[ 'start' ] = $propType[ 'step' ] + $propType[ 'loop' ]; + $start_code[ 1 ] = ''; + if ($propValue[ 'start' ] < 0) { + for ($i = 11; $i <= 19; $i++) { + $start_code[ $i ] = ''; + } + if ($propType[ 'start' ] === 0) { + $start_code = array( + max( + $propValue[ 'step' ] > 0 ? 0 : -1, + $propValue[ 'start' ] + $propValue[ 'loop' ] + ) + ); + } + } else { + for ($i = 1; $i <= 11; $i++) { + $start_code[ $i ] = ''; + } + if ($propType[ 'start' ] === 0) { + $start_code = + array( + min( + $propValue[ 'step' ] > 0 ? $propValue[ 'loop' ] : $propValue[ 'loop' ] - 1, + $propValue[ 'start' ] + ) + ); + } + } + } + $propValue[ 'start' ] = join('', $start_code); + } + if ($propType[ 'start' ] !== 0) { + $initLocal[ 'start' ] = $propValue[ 'start' ]; + $propValue[ 'start' ] = "{$local}start"; + } + $initFor[ 'index' ] = "{$sectionVar}->value['index'] = {$propValue['start']}"; + if (!isset($_attr[ 'start' ]) && !isset($_attr[ 'step' ]) && !isset($_attr[ 'max' ])) { + $propValue[ 'total' ] = $propValue[ 'loop' ]; + $propType[ 'total' ] = $propType[ 'loop' ]; + } else { + $propType[ 'total' ] = + $propType[ 'start' ] + $propType[ 'loop' ] + $propType[ 'step' ] + $propType[ 'max' ]; + if ($propType[ 'total' ] === 0) { + $propValue[ 'total' ] = + min( + ceil( + ($propValue[ 'step' ] > 0 ? $propValue[ 'loop' ] - $propValue[ 'start' ] : + (int)$propValue[ 'start' ] + 1) / abs($propValue[ 'step' ]) + ), + $propValue[ 'max' ] + ); + } else { + $total_code = array( + 1 => 'min(', 2 => 'ceil(', 3 => '(', 4 => "{$propValue['step']} > 0 ? ", + 5 => $propValue[ 'loop' ], 6 => ' - ', 7 => $propValue[ 'start' ], 8 => ' : ', + 9 => $propValue[ 'start' ], 10 => '+ 1', 11 => ')', 12 => '/ ', 13 => 'abs(', + 14 => $propValue[ 'step' ], 15 => ')', 16 => ')', 17 => ", {$propValue['max']})", + ); + if (!isset($propValue[ 'max' ])) { + $total_code[ 1 ] = $total_code[ 17 ] = ''; + } + if ($propType[ 'loop' ] + $propType[ 'start' ] === 0) { + $total_code[ 5 ] = $propValue[ 'loop' ] - $propValue[ 'start' ]; + $total_code[ 6 ] = $total_code[ 7 ] = ''; + } + if ($propType[ 'start' ] === 0) { + $total_code[ 9 ] = (int)$propValue[ 'start' ] + 1; + $total_code[ 10 ] = ''; + } + if ($propType[ 'step' ] === 0) { + $total_code[ 13 ] = $total_code[ 15 ] = ''; + if ($propValue[ 'step' ] === 1 || $propValue[ 'step' ] === -1) { + $total_code[ 2 ] = $total_code[ 12 ] = $total_code[ 14 ] = $total_code[ 16 ] = ''; + } elseif ($propValue[ 'step' ] < 0) { + $total_code[ 14 ] = -$propValue[ 'step' ]; + } + $total_code[ 4 ] = ''; + if ($propValue[ 'step' ] > 0) { + $total_code[ 8 ] = $total_code[ 9 ] = $total_code[ 10 ] = ''; + } else { + $total_code[ 5 ] = $total_code[ 6 ] = $total_code[ 7 ] = $total_code[ 8 ] = ''; + } + } + $propValue[ 'total' ] = join('', $total_code); + } + } + if (isset($namedAttr[ 'loop' ])) { + $initNamedProperty[ 'loop' ] = "'loop' => {$propValue['loop']}"; + } + if (isset($namedAttr[ 'total' ])) { + $initNamedProperty[ 'total' ] = "'total' => {$propValue['total']}"; + if ($propType[ 'total' ] > 0) { + $propValue[ 'total' ] = "{$sectionVar}->value['total']"; + } + } elseif ($propType[ 'total' ] > 0) { + $initLocal[ 'total' ] = $propValue[ 'total' ]; + $propValue[ 'total' ] = "{$local}total"; + } + $cmpFor[ 'iteration' ] = "{$propValue['iteration']} <= {$propValue['total']}"; + foreach ($initLocal as $key => $code) { + $output .= "{$local}{$key} = {$code};\n"; + } + $_vars = 'array(' . join(', ', $initNamedProperty) . ')'; + $output .= "{$sectionVar} = new Smarty_Variable({$_vars});\n"; + $cond_code = "{$propValue['total']} !== 0"; + if ($propType[ 'total' ] === 0) { + if ($propValue[ 'total' ] === 0) { + $cond_code = 'false'; + } else { + $cond_code = 'true'; + } + } + if ($propType[ 'show' ] > 0) { + $output .= "{$local}show = {$propValue['show']} ? {$cond_code} : false;\n"; + $output .= "if ({$local}show) {\n"; + } elseif ($propValue[ 'show' ] === 'true') { + $output .= "if ({$cond_code}) {\n"; + } else { + $output .= "if (false) {\n"; + } + $jinit = join(', ', $initFor); + $jcmp = join(', ', $cmpFor); + $jinc = join(', ', $incFor); + $output .= "for ({$jinit}; {$jcmp}; {$jinc}){\n"; + if (isset($namedAttr[ 'rownum' ])) { + $output .= "{$sectionVar}->value['rownum'] = {$propValue['iteration']};\n"; + } + if (isset($namedAttr[ 'index_prev' ])) { + $output .= "{$sectionVar}->value['index_prev'] = {$propValue['index']} - {$propValue['step']};\n"; + } + if (isset($namedAttr[ 'index_next' ])) { + $output .= "{$sectionVar}->value['index_next'] = {$propValue['index']} + {$propValue['step']};\n"; + } + if (isset($namedAttr[ 'first' ])) { + $output .= "{$sectionVar}->value['first'] = ({$propValue['iteration']} === 1);\n"; + } + if (isset($namedAttr[ 'last' ])) { + $output .= "{$sectionVar}->value['last'] = ({$propValue['iteration']} === {$propValue['total']});\n"; + } + $output .= '?>'; return $output; - } -} + } +} /** -* Smarty Internal Plugin Compile Sectionelse Class -*/ -class Smarty_Internal_Compile_Sectionelse extends Smarty_Internal_CompileBase { + * Smarty Internal Plugin Compile Sectionelse Class + * + * @package Smarty + * @subpackage Compiler + */ +class Smarty_Internal_Compile_Sectionelse extends Smarty_Internal_CompileBase +{ /** * Compiles code for the {sectionelse} tag - * - * @param array $args array with attributes from parser - * @param object $compiler compiler object + * + * @param array $args array with attributes from parser + * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object + * * @return string compiled code */ - public function compile($args, $compiler) + public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) { - $this->compiler = $compiler; // check and get attributes - $_attr = $this->_get_attributes($args); - - list($_open_tag, $nocache) = $this->_close_tag(array('section')); - $this->_open_tag('sectionelse',array('sectionelse', $nocache)); - - return ""; - } -} + $_attr = $this->getAttributes($compiler, $args); + list($openTag, $nocache, $local, $sectionVar) = $this->closeTag($compiler, array('section')); + $this->openTag($compiler, 'sectionelse', array('sectionelse', $nocache, $local, $sectionVar)); + return ""; + } +} /** * Smarty Internal Plugin Compile Sectionclose Class + * + * @package Smarty + * @subpackage Compiler */ -class Smarty_Internal_Compile_Sectionclose extends Smarty_Internal_CompileBase { +class Smarty_Internal_Compile_Sectionclose extends Smarty_Internal_CompileBase +{ /** * Compiles code for the {/section} tag - * - * @param array $args array with attributes from parser - * @param object $compiler compiler object + * + * @param array $args array with attributes from parser + * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object + * * @return string compiled code */ - public function compile($args, $compiler) + public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) { - $this->compiler = $compiler; - // check and get attributes - $_attr = $this->_get_attributes($args); - + $compiler->loopNesting--; // must endblock be nocache? - if ($this->compiler->nocache) { - $this->compiler->tag_nocache = true; + if ($compiler->nocache) { + $compiler->tag_nocache = true; } - - list($_open_tag, $this->compiler->nocache) = $this->_close_tag(array('section', 'sectionelse')); - - if ($_open_tag == 'sectionelse') - return ""; - else - return ""; - } -} - -?> \ No newline at end of file + list($openTag, $compiler->nocache, $local, $sectionVar) = + $this->closeTag($compiler, array('section', 'sectionelse')); + $output = "'; + return $output; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_setfilter.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_setfilter.php new file mode 100644 index 000000000..70e2e2f9f --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_setfilter.php @@ -0,0 +1,68 @@ +variable_filter_stack[] = $compiler->variable_filters; + $compiler->variable_filters = $parameter[ 'modifier_list' ]; + // this tag does not return compiled code + $compiler->has_code = false; + return true; + } +} + +/** + * Smarty Internal Plugin Compile Setfilterclose Class + * + * @package Smarty + * @subpackage Compiler + */ +class Smarty_Internal_Compile_Setfilterclose extends Smarty_Internal_CompileBase +{ + /** + * Compiles code for the {/setfilter} tag + * This tag does not generate compiled output. It resets variable filter. + * + * @param array $args array with attributes from parser + * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object + * + * @return string compiled code + */ + public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) + { + $_attr = $this->getAttributes($compiler, $args); + // reset variable filter to previous state + if (count($compiler->variable_filter_stack)) { + $compiler->variable_filters = array_pop($compiler->variable_filter_stack); + } else { + $compiler->variable_filters = array(); + } + // this tag does not return compiled code + $compiler->has_code = false; + return true; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_shared_inheritance.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_shared_inheritance.php new file mode 100644 index 000000000..d90262e60 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_shared_inheritance.php @@ -0,0 +1,49 @@ +prefixCompiledCode .= "_loadInheritance();\n\$_smarty_tpl->inheritance->init(\$_smarty_tpl, " . + var_export($initChildSequence, true) . ");\n?>\n"; + } + + /** + * Register post compile callback to compile inheritance initialization code + * + * @param \Smarty_Internal_TemplateCompilerBase $compiler + * @param bool|false $initChildSequence if true force child template + */ + public function registerInit(Smarty_Internal_TemplateCompilerBase $compiler, $initChildSequence = false) + { + if ($initChildSequence || !isset($compiler->_cache[ 'inheritanceInit' ])) { + $compiler->registerPostCompileCallback( + array('Smarty_Internal_Compile_Shared_Inheritance', 'postCompile'), + array($initChildSequence), + 'inheritanceInit', + $initChildSequence + ); + $compiler->_cache[ 'inheritanceInit' ] = true; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_while.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_while.php index 7e87a2291..5aa3a7330 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_while.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_while.php @@ -1,82 +1,100 @@ compiler = $compiler; + $compiler->loopNesting++; // check and get attributes - $_attr = $this->_get_attributes($args); - $this->_open_tag('while', $this->compiler->nocache); - + $_attr = $this->getAttributes($compiler, $args); + $this->openTag($compiler, 'while', $compiler->nocache); + if (!array_key_exists('if condition', $parameter)) { + $compiler->trigger_template_error('missing while condition', null, true); + } // maybe nocache because of nocache variables - $this->compiler->nocache = $this->compiler->nocache | $this->compiler->tag_nocache; - if (is_array($parameter['if condition'])) { - if ($this->compiler->nocache) { - $_nocache = ',true'; - // create nocache var to make it know for further compiling - if (is_array($parameter['if condition']['var'])) { - $this->compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true); - } else { - $this->compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true); - } - } else { - $_nocache = ''; - } - if (is_array($parameter['if condition']['var'])) { - $_output = "tpl_vars[".$parameter['if condition']['var']['var']."]) || !is_array(\$_smarty_tpl->tpl_vars[".$parameter['if condition']['var']['var']."]->value)) \$_smarty_tpl->createLocalArrayVariable(".$parameter['if condition']['var']['var']."$_nocache);\n"; - $_output .= "while (\$_smarty_tpl->tpl_vars[".$parameter['if condition']['var']['var']."]->value".$parameter['if condition']['var']['smarty_internal_index']." = ".$parameter['if condition']['value']."){?>"; + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + if (is_array($parameter[ 'if condition' ])) { + if ($compiler->nocache) { + // create nocache var to make it know for further compiling + if (is_array($parameter[ 'if condition' ][ 'var' ])) { + $var = $parameter[ 'if condition' ][ 'var' ][ 'var' ]; + } else { + $var = $parameter[ 'if condition' ][ 'var' ]; + } + $compiler->setNocacheInVariable($var); + } + $prefixVar = $compiler->getNewPrefixVariable(); + $assignCompiler = new Smarty_Internal_Compile_Assign(); + $assignAttr = array(); + $assignAttr[][ 'value' ] = $prefixVar; + if (is_array($parameter[ 'if condition' ][ 'var' ])) { + $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ][ 'var' ]; + $_output = ""; + $_output .= $assignCompiler->compile( + $assignAttr, + $compiler, + array('smarty_internal_index' => $parameter[ 'if condition' ][ 'var' ][ 'smarty_internal_index' ]) + ); } else { - $_output = "tpl_vars[".$parameter['if condition']['var']."] = new Smarty_Variable(\$_smarty_tpl->getVariable(".$parameter['if condition']['var'].",null,true,false)->value{$_nocache});"; - $_output .= "while (\$_smarty_tpl->tpl_vars[".$parameter['if condition']['var']."]->value = ".$parameter['if condition']['value']."){?>"; - } + $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ]; + $_output = ""; + $_output .= $assignCompiler->compile($assignAttr, $compiler, array()); + } return $_output; } else { - return ""; - } - } -} + return ""; + } + } +} /** -* Smarty Internal Plugin Compile Whileclose Class -*/ -class Smarty_Internal_Compile_Whileclose extends Smarty_Internal_CompileBase { + * Smarty Internal Plugin Compile Whileclose Class + * + * @package Smarty + * @subpackage Compiler + */ +class Smarty_Internal_Compile_Whileclose extends Smarty_Internal_CompileBase +{ /** - * Compiles code for the {/while} tag - * - * @param array $args array with attributes from parser - * @param object $compiler compiler object - * @return string compiled code - */ - public function compile($args, $compiler) + * Compiles code for the {/while} tag + * + * @param array $args array with attributes from parser + * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object + * + * @return string compiled code + */ + public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) { - $this->compiler = $compiler; + $compiler->loopNesting--; // must endblock be nocache? - if ($this->compiler->nocache) { - $this->compiler->tag_nocache = true; + if ($compiler->nocache) { + $compiler->tag_nocache = true; } - $this->compiler->nocache = $this->_close_tag(array('while')); - return ""; - } -} - -?> \ No newline at end of file + $compiler->nocache = $this->closeTag($compiler, array('while')); + return "\n"; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compilebase.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compilebase.php index 6418acceb..2a32e4373 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compilebase.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compilebase.php @@ -1,150 +1,203 @@ true, 0 => false, 'true' => true, 'false' => false); + + /** + * Mapping array with attributes as key + * + * @var array + */ + public $mapCache = array(); /** * This function checks if the attributes passed are valid - * - * The attributes passed for the tag to compile are checked against the list of required and + * The attributes passed for the tag to compile are checked against the list of required and * optional attributes. Required attributes must be present. Optional attributes are check against - * against the corresponding list. The keyword '_any' specifies that any attribute will be accepted + * the corresponding list. The keyword '_any' specifies that any attribute will be accepted * as valid - * - * @param array $attributes attributes applied to the tag - * @return array of mapped attributes for further processing + * + * @param object $compiler compiler object + * @param array $attributes attributes applied to the tag + * + * @return array of mapped attributes for further processing */ - function _get_attributes ($attributes) + public function getAttributes($compiler, $attributes) { - $_indexed_attr = array(); - // loop over attributes + $_indexed_attr = array(); + if (!isset($this->mapCache[ 'option' ])) { + $this->mapCache[ 'option' ] = array_fill_keys($this->option_flags, true); + } foreach ($attributes as $key => $mixed) { // shorthand ? if (!is_array($mixed)) { // option flag ? - if (in_array(trim($mixed, '\'"'), $this->option_flags)) { - $_indexed_attr[trim($mixed, '\'"')] = true; + if (isset($this->mapCache[ 'option' ][ trim($mixed, '\'"') ])) { + $_indexed_attr[ trim($mixed, '\'"') ] = true; // shorthand attribute ? - } else if (isset($this->shorttag_order[$key])) { - $_indexed_attr[$this->shorttag_order[$key]] = $mixed; + } elseif (isset($this->shorttag_order[ $key ])) { + $_indexed_attr[ $this->shorttag_order[ $key ] ] = $mixed; } else { // too many shorthands - $this->compiler->trigger_template_error('too many shorthand attributes', $this->compiler->lex->taglineno); - } + $compiler->trigger_template_error('too many shorthand attributes', null, true); + } // named attribute } else { - $kv = each($mixed); - // option flag? - if (in_array($kv['key'], $this->option_flags)) { - if (is_bool($kv['value'])) { - $_indexed_attr[$kv['key']] = $kv['value']; - } else if (is_string($kv['value']) && in_array(trim($kv['value'], '\'"'), array('true', 'false'))) { - if (trim($kv['value']) == 'true') { - $_indexed_attr[$kv['key']] = true; - } else { - $_indexed_attr[$kv['key']] = false; - } - } else if (is_numeric($kv['value']) && in_array($kv['value'], array(0, 1))) { - if ($kv['value'] == 1) { - $_indexed_attr[$kv['key']] = true; + foreach ($mixed as $k => $v) { + // option flag? + if (isset($this->mapCache[ 'option' ][ $k ])) { + if (is_bool($v)) { + $_indexed_attr[ $k ] = $v; } else { - $_indexed_attr[$kv['key']] = false; - } + if (is_string($v)) { + $v = trim($v, '\'" '); + } + if (isset($this->optionMap[ $v ])) { + $_indexed_attr[ $k ] = $this->optionMap[ $v ]; + } else { + $compiler->trigger_template_error( + "illegal value '" . var_export($v, true) . + "' for option flag '{$k}'", + null, + true + ); + } + } + // must be named attribute } else { - $this->compiler->trigger_template_error("illegal value of option flag \"{$kv['key']}\"", $this->compiler->lex->taglineno); - } - // must be named attribute - } else { - reset($mixed); - $_indexed_attr[key($mixed)] = $mixed[key($mixed)]; - } - } - } + $_indexed_attr[ $k ] = $v; + } + } + } + } // check if all required attributes present foreach ($this->required_attributes as $attr) { - if (!array_key_exists($attr, $_indexed_attr)) { - $this->compiler->trigger_template_error("missing \"" . $attr . "\" attribute", $this->compiler->lex->taglineno); - } - } - // check for unallowed attributes - if ($this->optional_attributes != array('_any')) { - $tmp_array = array_merge($this->required_attributes, $this->optional_attributes, $this->option_flags); + if (!isset($_indexed_attr[ $attr ])) { + $compiler->trigger_template_error("missing '{$attr}' attribute", null, true); + } + } + // check for not allowed attributes + if ($this->optional_attributes !== array('_any')) { + if (!isset($this->mapCache[ 'all' ])) { + $this->mapCache[ 'all' ] = + array_fill_keys( + array_merge( + $this->required_attributes, + $this->optional_attributes, + $this->option_flags + ), + true + ); + } foreach ($_indexed_attr as $key => $dummy) { - if (!in_array($key, $tmp_array) && $key !== 0) { - $this->compiler->trigger_template_error("unexpected \"" . $key . "\" attribute", $this->compiler->lex->taglineno); - } - } - } + if (!isset($this->mapCache[ 'all' ][ $key ]) && $key !== 0) { + $compiler->trigger_template_error("unexpected '{$key}' attribute", null, true); + } + } + } // default 'false' for all option flags not set foreach ($this->option_flags as $flag) { - if (!isset($_indexed_attr[$flag])) { - $_indexed_attr[$flag] = false; - } - } - + if (!isset($_indexed_attr[ $flag ])) { + $_indexed_attr[ $flag ] = false; + } + } + if (isset($_indexed_attr[ 'nocache' ]) && $_indexed_attr[ 'nocache' ]) { + $compiler->tag_nocache = true; + } return $_indexed_attr; - } + } /** * Push opening tag name on stack - * * Optionally additional data can be saved on stack - * - * @param string $open_tag the opening tag's name - * @param anytype $data optional data which shall be saved on stack + * + * @param object $compiler compiler object + * @param string $openTag the opening tag's name + * @param mixed $data optional data saved */ - function _open_tag($open_tag, $data = null) + public function openTag($compiler, $openTag, $data = null) { - array_push($this->compiler->_tag_stack, array($open_tag, $data)); - } + array_push($compiler->_tag_stack, array($openTag, $data)); + } /** * Pop closing tag - * * Raise an error if this stack-top doesn't match with expected opening tags - * - * @param array $ |string $expected_tag the expected opening tag names - * @return anytype the opening tag's name or saved data + * + * @param object $compiler compiler object + * @param array|string $expectedTag the expected opening tag names + * + * @return mixed any type the opening tag's name or saved data */ - function _close_tag($expected_tag) + public function closeTag($compiler, $expectedTag) { - if (count($this->compiler->_tag_stack) > 0) { + if (count($compiler->_tag_stack) > 0) { // get stacked info - list($_open_tag, $_data) = array_pop($this->compiler->_tag_stack); + list($_openTag, $_data) = array_pop($compiler->_tag_stack); // open tag must match with the expected ones - if (in_array($_open_tag, (array)$expected_tag)) { + if (in_array($_openTag, (array)$expectedTag)) { if (is_null($_data)) { // return opening tag - return $_open_tag; + return $_openTag; } else { // return restored data return $_data; - } - } + } + } // wrong nesting of tags - $this->compiler->trigger_template_error("unclosed {" . $_open_tag . "} tag"); + $compiler->trigger_template_error("unclosed '{$compiler->smarty->left_delimiter}{$_openTag}{$compiler->smarty->right_delimiter}' tag"); return; - } + } // wrong nesting of tags - $this->compiler->trigger_template_error("unexpected closing tag", $this->compiler->lex->taglineno); + $compiler->trigger_template_error('unexpected closing tag', null, true); return; - } -} - -?> \ No newline at end of file + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_config.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_config.php deleted file mode 100644 index 06ae70ba9..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_config.php +++ /dev/null @@ -1,288 +0,0 @@ -data = $data; - $this->smarty = $smarty; - $this->config_resource = $config_resource; - $this->config_resource_type = null; - $this->config_resource_name = null; - $this->config_filepath = null; - $this->config_timestamp = null; - $this->config_source = null; - $this->compiled_config = null; - $this->compiled_filepath = null; - $this->compiled_timestamp = null; - $this->mustCompile = null; - $this->compiler_object = null; - // parse config resource name - if (!$this->parseConfigResourceName ($config_resource)) { - throw new SmartyException ("Unable to parse config resource '{$config_resource}'"); - } - } - - public function getConfigFilepath () - { - return $this->config_filepath === null ? - $this->config_filepath = $this->buildConfigFilepath() : - $this->config_filepath; - } - - public function getTimestamp () - { - return $this->config_timestamp === null ? - $this->config_timestamp = filemtime($this->getConfigFilepath()) : - $this->config_timestamp; - } - - private function parseConfigResourceName($config_resource) - { - if (empty($config_resource)) - return false; - if (strpos($config_resource, ':') === false) { - // no resource given, use default - $this->config_resource_type = $this->smarty->default_config_type; - $this->config_resource_name = $config_resource; - } else { - // get type and name from path - list($this->config_resource_type, $this->config_resource_name) = explode(':', $config_resource, 2); - if (strlen($this->config_resource_type) == 1) { - // 1 char is not resource type, but part of filepath - $this->config_resource_type = $this->smarty->default_config_type; - $this->config_resource_name = $config_resource; - } else { - $this->config_resource_type = strtolower($this->config_resource_type); - } - } - return true; - } - - /* - * get system filepath to config - */ - public function buildConfigFilepath () - { - foreach((array)$this->smarty->config_dir as $_config_dir) { - if (strpos('/\\', substr($_config_dir, -1)) === false) { - $_config_dir .= DS; - } - - $_filepath = $_config_dir . $this->config_resource_name; - if (file_exists($_filepath)) - return $_filepath; - } - // check for absolute path - if (file_exists($this->config_resource_name)) - return $this->config_resource_name; - // no tpl file found - throw new SmartyException("Unable to load config file \"{$this->config_resource_name}\""); - return false; - } - /** - * Read config file source - * - * @return string content of source file - */ - /** - * Returns the template source code - * - * The template source is being read by the actual resource handler - * - * @return string the template source - */ - public function getConfigSource () - { - if ($this->config_source === null) { - if ($this->readConfigSource($this) === false) { - throw new SmartyException("Unable to load config file \"{$this->config_resource_name}\""); - } - } - return $this->config_source; - } - public function readConfigSource() - { - // read source file - if (file_exists($this->getConfigFilepath())) { - $this->config_source = file_get_contents($this->getConfigFilepath()); - return true; - } else { - return false; - } - } - - /** - * Returns the compiled filepath - * - * @return string the compiled filepath - */ - public function getCompiledFilepath () - { - return $this->compiled_filepath === null ? - ($this->compiled_filepath = $this->buildCompiledFilepath()) : - $this->compiled_filepath; - } - public function buildCompiledFilepath() - { - $_compile_id = isset($this->smarty->compile_id) ? preg_replace('![^\w\|]+!', '_', $this->smarty->compile_id) : null; - $_flag = (int)$this->smarty->config_read_hidden + (int)$this->smarty->config_booleanize * 2 + - (int)$this->smarty->config_overwrite * 4; - $_filepath = sha1($this->config_resource_name . $_flag); - // if use_sub_dirs, break file into directories - if ($this->smarty->use_sub_dirs) { - $_filepath = substr($_filepath, 0, 2) . DS - . substr($_filepath, 2, 2) . DS - . substr($_filepath, 4, 2) . DS - . $_filepath; - } - $_compile_dir_sep = $this->smarty->use_sub_dirs ? DS : '^'; - if (isset($_compile_id)) { - $_filepath = $_compile_id . $_compile_dir_sep . $_filepath; - } - $_compile_dir = $this->smarty->compile_dir; - if (substr($_compile_dir, -1) != DS) { - $_compile_dir .= DS; - } - return $_compile_dir . $_filepath . '.' . basename($this->config_resource_name) . '.config' . '.php'; - } - /** - * Returns the timpestamp of the compiled file - * - * @return integer the file timestamp - */ - public function getCompiledTimestamp () - { - return $this->compiled_timestamp === null ? - ($this->compiled_timestamp = (file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false) : - $this->compiled_timestamp; - } - /** - * Returns if the current config file must be compiled - * - * It does compare the timestamps of config source and the compiled config and checks the force compile configuration - * - * @return boolean true if the file must be compiled - */ - public function mustCompile () - { - return $this->mustCompile === null ? - $this->mustCompile = ($this->smarty->force_compile || $this->getCompiledTimestamp () === false || $this->smarty->compile_check && $this->getCompiledTimestamp () < $this->getTimestamp ()): - $this->mustCompile; - } - /** - * Returns the compiled config file - * - * It checks if the config file must be compiled or just read the compiled version - * - * @return string the compiled config file - */ - public function getCompiledConfig () - { - if ($this->compiled_config === null) { - // see if template needs compiling. - if ($this->mustCompile()) { - $this->compileConfigSource(); - } else { - $this->compiled_config = file_get_contents($this->getCompiledFilepath()); - } - } - return $this->compiled_config; - } - - /** - * Compiles the config files - */ - public function compileConfigSource () - { - // compile template - if (!is_object($this->compiler_object)) { - // load compiler - $this->compiler_object = new Smarty_Internal_Config_File_Compiler($this->smarty); - } - // compile locking - if ($this->smarty->compile_locking) { - if ($saved_timestamp = $this->getCompiledTimestamp()) { - touch($this->getCompiledFilepath()); - } - } - // call compiler - try { - $this->compiler_object->compileSource($this); - } - catch (Exception $e) { - // restore old timestamp in case of error - if ($this->smarty->compile_locking && $saved_timestamp) { - touch($this->getCompiledFilepath(), $saved_timestamp); - } - throw $e; - } - // compiling succeded - // write compiled template - Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->getCompiledConfig(), $this->smarty); - } - - /* - * load config variables - * - * @param mixed $sections array of section names, single section or null - * @param object $scope global,parent or local - */ - public function loadConfigVars ($sections = null, $scope = 'local') - { - if ($this->data instanceof Smarty_Internal_Template) { - $this->data->properties['file_dependency'][sha1($this->getConfigFilepath())] = array($this->getConfigFilepath(), $this->getTimestamp(),'file'); - } - if ($this->mustCompile()) { - $this->compileConfigSource(); - } - // pointer to scope - if ($scope == 'local') { - $scope_ptr = $this->data; - } elseif ($scope == 'parent') { - if (isset($this->data->parent)) { - $scope_ptr = $this->data->parent; - } else { - $scope_ptr = $this->data; - } - } elseif ($scope == 'root' || $scope == 'global') { - $scope_ptr = $this->data; - while (isset($scope_ptr->parent)) { - $scope_ptr = $scope_ptr->parent; - } - } - $_config_vars = array(); - include($this->getCompiledFilepath ()); - // copy global config vars - foreach ($_config_vars['vars'] as $variable => $value) { - if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { - $scope_ptr->config_vars[$variable] = $value; - } else { - $scope_ptr->config_vars[$variable] = array_merge((array)$scope_ptr->config_vars[$variable], (array)$value); - } - } - // scan sections - foreach ($_config_vars['sections'] as $this_section => $dummy) { - if ($sections == null || in_array($this_section, (array)$sections)) { - foreach ($_config_vars['sections'][$this_section]['vars'] as $variable => $value) { - if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { - $scope_ptr->config_vars[$variable] = $value; - } else { - $scope_ptr->config_vars[$variable] = array_merge((array)$scope_ptr->config_vars[$variable], (array)$value); - } - } - } - } - } -} -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php index e9dfbdb02..a842fa8f3 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php @@ -1,106 +1,209 @@ smarty = $smarty; + $this->smarty = $smarty; // get required plugins - $this->smarty->loadPlugin('Smarty_Internal_Configfilelexer'); - $this->smarty->loadPlugin('Smarty_Internal_Configfileparser'); - $this->config_data['sections'] = array(); - $this->config_data['vars'] = array(); - } + $this->lexer_class = $lexer_class; + $this->parser_class = $parser_class; + $this->smarty = $smarty; + $this->config_data[ 'sections' ] = array(); + $this->config_data[ 'vars' ] = array(); + } /** - * Methode to compile a Smarty template - * - * @param $template template object to compile + * Method to compile Smarty config source. + * + * @param Smarty_Internal_Template $template + * * @return bool true if compiling succeeded, false if it failed + * @throws \SmartyException */ - public function compileSource($config) + public function compileTemplate(Smarty_Internal_Template $template) { - /* here is where the compiling takes place. Smarty - tags in the templates are replaces with PHP code, - then written to compiled files. */ - $this->config = $config; - // get config file source - $_content = $config->getConfigSource() . "\n"; - // on empty template just return - if ($_content == '') { - return true; - } + $this->template = $template; + $this->template->compiled->file_dependency[ $this->template->source->uid ] = + array( + $this->template->source->filepath, + $this->template->source->getTimeStamp(), + $this->template->source->type + ); + if ($this->smarty->debugging) { + if (!isset($this->smarty->_debug)) { + $this->smarty->_debug = new Smarty_Internal_Debug(); + } + $this->smarty->_debug->start_compile($this->template); + } // init the lexer/parser to compile the config file - $lex = new Smarty_Internal_Configfilelexer($_content, $this->smarty); - $parser = new Smarty_Internal_Configfileparser($lex, $this); - if (isset($this->smarty->_parserdebug)) $parser->PrintTrace(); + /* @var Smarty_Internal_ConfigFileLexer $this ->lex */ + $this->lex = new $this->lexer_class( + str_replace( + array( + "\r\n", + "\r" + ), + "\n", + $template->source->getContent() + ) . "\n", + $this + ); + /* @var Smarty_Internal_ConfigFileParser $this ->parser */ + $this->parser = new $this->parser_class($this->lex, $this); + if (function_exists('mb_internal_encoding') + && function_exists('ini_get') + && ((int)ini_get('mbstring.func_overload')) & 2 + ) { + $mbEncoding = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } else { + $mbEncoding = null; + } + if ($this->smarty->_parserdebug) { + $this->parser->PrintTrace(); + } // get tokens from lexer and parse them - while ($lex->yylex()) { - if (isset($this->smarty->_parserdebug)) echo "
Parsing {$parser->yyTokenName[$lex->token]} Token {$lex->value} Line {$lex->line} \n"; - $parser->doParse($lex->token, $lex->value); - } + while ($this->lex->yylex()) { + if ($this->smarty->_parserdebug) { + echo "
Parsing {$this->parser->yyTokenName[$this->lex->token]} Token {$this->lex->value} Line {$this->lex->line} \n"; + } + $this->parser->doParse($this->lex->token, $this->lex->value); + } // finish parsing process - $parser->doParse(0, 0); - $config->compiled_config = 'config_data, true) . '; ?>'; - } + $this->parser->doParse(0, 0); + if ($mbEncoding) { + mb_internal_encoding($mbEncoding); + } + if ($this->smarty->debugging) { + $this->smarty->_debug->end_compile($this->template); + } + // template header code + $template_header = + "template->source->filepath}' */ ?>\n"; + $code = 'smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' . + var_export($this->config_data, true) . '); ?>'; + return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code); + } + /** * display compiler error messages without dying - * * If parameter $args is empty it is a parser detected syntax error. - * In this case the parser is called to obtain information about exspected tokens. - * + * In this case the parser is called to obtain information about expected tokens. * If parameter $args contains a string this is used as error message - * - * @todo output exact position of parse error in source line - * @param $args string individual error message or null + * + * @param string $args individual error message or null + * + * @throws SmartyCompilerException */ public function trigger_config_file_error($args = null) { - $this->lex = Smarty_Internal_Configfilelexer::instance(); - $this->parser = Smarty_Internal_Configfileparser::instance(); - // get template source line which has error + // get config source line which has error $line = $this->lex->line; if (isset($args)) { // $line--; - } + } $match = preg_split("/\n/", $this->lex->data); - $error_text = "Syntax error in config file '{$this->config->getConfigFilepath()}' on line {$line} '{$match[$line-1]}' "; + $error_text = + "Syntax error in config file '{$this->template->source->filepath}' on line {$line} '{$match[$line - 1]}' "; if (isset($args)) { // individual error message $error_text .= $args; } else { - // exspected token from parser + // expected token from parser foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) { - $exp_token = $this->parser->yyTokenName[$token]; - if (isset($this->lex->smarty_token_names[$exp_token])) { + $exp_token = $this->parser->yyTokenName[ $token ]; + if (isset($this->lex->smarty_token_names[ $exp_token ])) { // token type from lexer - $expect[] = '"' . $this->lex->smarty_token_names[$exp_token] . '"'; + $expect[] = '"' . $this->lex->smarty_token_names[ $exp_token ] . '"'; } else { // otherwise internal token name - $expect[] = $this->parser->yyTokenName[$token]; - } - } + $expect[] = $this->parser->yyTokenName[ $token ]; + } + } // output parser error message $error_text .= ' - Unexpected "' . $this->lex->value . '", expected one of: ' . implode(' , ', $expect); - } + } throw new SmartyCompilerException($error_text); - } -} - -?> \ No newline at end of file + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfilelexer.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfilelexer.php index 9186fe22f..afb3efcb0 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfilelexer.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfilelexer.php @@ -1,111 +1,278 @@ 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE' + ); + + /** + * token names + * + * @var array + */ + public $smarty_token_names = array( // Text for parser error messages + ); + + /** + * compiler object + * + * @var Smarty_Internal_Config_File_Compiler + */ + private $compiler = null; + + /** + * copy of config_booleanize + * + * @var bool + */ + private $configBooleanize = false; + + /** + * storage for assembled token patterns + * + * @var string + */ + private $yy_global_pattern1 = null; + + private $yy_global_pattern2 = null; + + private $yy_global_pattern3 = null; + + private $yy_global_pattern4 = null; + + private $yy_global_pattern5 = null; + + private $yy_global_pattern6 = null; + + private $_yy_state = 1; + + private $_yy_stack = array(); + + /** + * constructor + * + * @param string $data template source + * @param Smarty_Internal_Config_File_Compiler $compiler + */ + public function __construct($data, Smarty_Internal_Config_File_Compiler $compiler) + { $this->data = $data . "\n"; //now all lines are \n-terminated + $this->dataLength = strlen($data); $this->counter = 0; + if (preg_match('/^\xEF\xBB\xBF/', $this->data, $match)) { + $this->counter += strlen($match[ 0 ]); + } $this->line = 1; - $this->smarty = $smarty; - } - public static function &instance($new_instance = null) - { - static $instance = null; - if (isset($new_instance) && is_object($new_instance)) - $instance = $new_instance; - return $instance; - } - + $this->compiler = $compiler; + $this->smarty = $compiler->smarty; + $this->configBooleanize = $this->smarty->config_booleanize; + } + public function replace($input) + { + return $input; + } // end function - private $_yy_state = 1; - private $_yy_stack = array(); + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } - function yylex() + public function yylex() { return $this->{'yylex' . $this->_yy_state}(); } - function yypushstate($state) + public function yypushstate($state) { + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%sState push %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state + ); + } array_push($this->_yy_stack, $this->_yy_state); $this->_yy_state = $state; + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%snew State %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state + ); + } } - function yypopstate() + public function yypopstate() { + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%sState pop %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state + ); + } $this->_yy_state = array_pop($this->_yy_stack); + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%snew State %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state + ); + } } - function yybegin($state) + public function yybegin($state) { $this->_yy_state = $state; + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%sState set %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state + ); + } } - - - - function yylex1() + public function yylex1() { - $tokenMap = array ( - 1 => 0, - 2 => 0, - 3 => 0, - 4 => 0, - 5 => 0, - 6 => 0, - 7 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern1)) { + $this->yy_global_pattern1 = + $this->replace("/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^(#)|^(\\[)|^(\\])|^(=)|^([ \t\r]+)|^(\n)|^([0-9]*[a-zA-Z_]\\w*)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state START'); + ' an empty string. Input "' . substr( + $this->data, + $this->counter, + 5 + ) . '... state START'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r1_' . $this->token}($yysubmatches); + $r = $this->{'yy_r1_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -118,101 +285,94 @@ function yylex1() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { + } + } else { throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const START = 1; - function yy_r1_1($yy_subpatterns) + public function yy_r1_1() { - - $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART; - $this->yypushstate(self::COMMENT); + $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART; + $this->yypushstate(self::COMMENT); } - function yy_r1_2($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_OPENB; - $this->yypushstate(self::SECTION); - } - function yy_r1_3($yy_subpatterns) + public function yy_r1_2() { - - $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB; + $this->token = Smarty_Internal_Configfileparser::TPC_OPENB; + $this->yypushstate(self::SECTION); } - function yy_r1_4($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL; - $this->yypushstate(self::VALUE); - } - function yy_r1_5($yy_subpatterns) + public function yy_r1_3() { - - return false; + $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB; } - function yy_r1_6($yy_subpatterns) + + public function yy_r1_4() { + $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL; + $this->yypushstate(self::VALUE); + } // end function - $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; - } - function yy_r1_7($yy_subpatterns) + public function yy_r1_5() { + return false; + } - $this->token = Smarty_Internal_Configfileparser::TPC_ID; + public function yy_r1_6() + { + $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; } + public function yy_r1_7() + { + $this->token = Smarty_Internal_Configfileparser::TPC_ID; + } + public function yy_r1_8() + { + $this->token = Smarty_Internal_Configfileparser::TPC_OTHER; + } - function yylex2() + public function yylex2() { - $tokenMap = array ( - 1 => 0, - 2 => 0, - 3 => 0, - 4 => 0, - 5 => 0, - 6 => 0, - 7 => 0, - 8 => 0, - 9 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern2)) { + $this->yy_global_pattern2 = + $this->replace("/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^([ \t\r]+)|^(\\d+\\.\\d+(?=[ \t\r]*[\n#]))|^(\\d+(?=[ \t\r]*[\n#]))|^('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#]))|^(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#]))|^(\"\"\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"\"\"(?=[ \t\r]*[\n#]))|^([a-zA-Z]+(?=[ \t\r]*[\n#]))|^([^\n]+?(?=[ \t\r]*\n))|^(\n)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state VALUE'); + ' an empty string. Input "' . substr( + $this->data, + $this->counter, + 5 + ) . '... state VALUE'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r2_' . $this->token}($yysubmatches); + $r = $this->{'yy_r2_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -225,115 +385,111 @@ function yylex2() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { + } + } else { throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const VALUE = 2; - function yy_r2_1($yy_subpatterns) + public function yy_r2_1() { - - return false; + return false; } - function yy_r2_2($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT; - $this->yypopstate(); - } - function yy_r2_3($yy_subpatterns) + public function yy_r2_2() { - - $this->token = Smarty_Internal_Configfileparser::TPC_INT; - $this->yypopstate(); + $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT; + $this->yypopstate(); } - function yy_r2_4($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING; - $this->yypopstate(); - } - function yy_r2_5($yy_subpatterns) + public function yy_r2_3() { - - $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING; - $this->yypopstate(); + $this->token = Smarty_Internal_Configfileparser::TPC_INT; + $this->yypopstate(); } - function yy_r2_6($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_DOUBLE_QUOTED_STRING; - $this->yypopstate(); - } - function yy_r2_7($yy_subpatterns) + public function yy_r2_4() { + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES; + $this->yypushstate(self::TRIPPLE); + } - if (!$this->smarty->config_booleanize || !in_array(strtolower($this->value), Array("true", "false", "on", "off", "yes", "no")) ) { - $this->yypopstate(); - $this->yypushstate(self::NAKED_STRING_VALUE); - return true; //reprocess in new state - } else { - $this->token = Smarty_Internal_Configfileparser::TPC_BOOL; + public function yy_r2_5() + { + $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING; $this->yypopstate(); } - } - function yy_r2_8($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; - $this->yypopstate(); - } - function yy_r2_9($yy_subpatterns) + public function yy_r2_6() { + $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING; + $this->yypopstate(); + } // end function - $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; - $this->value = ""; - $this->yypopstate(); + public function yy_r2_7() + { + if (!$this->configBooleanize || + !in_array(strtolower($this->value), array('true', 'false', 'on', 'off', 'yes', 'no'))) { + $this->yypopstate(); + $this->yypushstate(self::NAKED_STRING_VALUE); + return true; //reprocess in new state + } else { + $this->token = Smarty_Internal_Configfileparser::TPC_BOOL; + $this->yypopstate(); + } } + public function yy_r2_8() + { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->yypopstate(); + } + public function yy_r2_9() + { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->value = ''; + $this->yypopstate(); + } // end function - function yylex3() + public function yylex3() { - $tokenMap = array ( - 1 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern3)) { + $this->yy_global_pattern3 = $this->replace("/\G([^\n]+?(?=[ \t\r]*\n))/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^([^\n]+?(?=[ \t\r]*\n))/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state NAKED_STRING_VALUE'); + ' an empty string. Input "' . substr( + $this->data, + $this->counter, + 5 + ) . '... state NAKED_STRING_VALUE'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r3_' . $this->token}($yysubmatches); + $r = $this->{'yy_r3_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -346,63 +502,56 @@ function yylex3() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { + } + } else { throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const NAKED_STRING_VALUE = 3; - function yy_r3_1($yy_subpatterns) + public function yy_r3_1() { - - $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; - $this->yypopstate(); + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->yypopstate(); } - - - function yylex4() + public function yylex4() { - $tokenMap = array ( - 1 => 0, - 2 => 0, - 3 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern4)) { + $this->yy_global_pattern4 = $this->replace("/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^([ \t\r]+)|^([^\n]+?(?=[ \t\r]*\n))|^(\n)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state COMMENT'); + ' an empty string. Input "' . substr( + $this->data, + $this->counter, + 5 + ) . '... state COMMENT'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r4_' . $this->token}($yysubmatches); + $r = $this->{'yy_r4_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -415,72 +564,66 @@ function yylex4() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { + } + } else { throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const COMMENT = 4; - function yy_r4_1($yy_subpatterns) + public function yy_r4_1() { - - return false; + return false; } - function yy_r4_2($yy_subpatterns) - { - $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; - } - function yy_r4_3($yy_subpatterns) + public function yy_r4_2() { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + } // end function - $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; - $this->yypopstate(); + public function yy_r4_3() + { + $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; + $this->yypopstate(); } - - - function yylex5() + public function yylex5() { - $tokenMap = array ( - 1 => 0, - 2 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern5)) { + $this->yy_global_pattern5 = $this->replace("/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^(\\.)|^(.*?(?=[\.=[\]\r\n]))/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state SECTION'); + ' an empty string. Input "' . substr( + $this->data, + $this->counter, + 5 + ) . '... state SECTION'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r5_' . $this->token}($yysubmatches); + $r = $this->{'yy_r5_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -493,34 +636,104 @@ function yylex5() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { + } + } else { throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const SECTION = 5; - function yy_r5_1($yy_subpatterns) + public function yy_r5_1() { - - $this->token = Smarty_Internal_Configfileparser::TPC_DOT; + $this->token = Smarty_Internal_Configfileparser::TPC_DOT; } - function yy_r5_2($yy_subpatterns) + + public function yy_r5_2() { + $this->token = Smarty_Internal_Configfileparser::TPC_SECTION; + $this->yypopstate(); + } // end function - $this->token = Smarty_Internal_Configfileparser::TPC_SECTION; - $this->yypopstate(); + public function yylex6() + { + if (!isset($this->yy_global_pattern6)) { + $this->yy_global_pattern6 = $this->replace("/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + do { + if (preg_match($this->yy_global_pattern6, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr( + $this->data, + $this->counter, + 5 + ) . '... state TRIPPLE'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r6_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line' . $this->line . + ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); } + public function yy_r6_1() + { + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END; + $this->yypopstate(); + $this->yypushstate(self::START); + } + public function yy_r6_2() + { + $to = strlen($this->data); + preg_match("/\"\"\"[ \t\r]*[\n#;]/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ]; + } else { + $this->compiler->trigger_config_file_error('missing or misspelled literal closing tag'); + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT; + } } -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfileparser.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfileparser.php index 0b5a57343..36fdb76ee 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfileparser.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_configfileparser.php @@ -1,77 +1,4 @@ string = $s->string; - $this->metadata = $s->metadata; - } else { - $this->string = (string) $s; - if ($m instanceof TPC_yyToken) { - $this->metadata = $m->metadata; - } elseif (is_array($m)) { - $this->metadata = $m; - } - } - } - - function __toString() - { - return $this->_string; - } - - function offsetExists($offset) - { - return isset($this->metadata[$offset]); - } - - function offsetGet($offset) - { - return $this->metadata[$offset]; - } - - function offsetSet($offset, $value) - { - if ($offset === null) { - if (isset($value[0])) { - $x = ($value instanceof TPC_yyToken) ? - $value->metadata : $value; - $this->metadata = array_merge($this->metadata, $x); - return; - } - $offset = count($this->metadata); - } - if ($value === null) { - return; - } - if ($value instanceof TPC_yyToken) { - if ($value->metadata) { - $this->metadata[$offset] = $value->metadata; - } - } elseif ($value) { - $this->metadata[$offset] = $value; - } - } - - function offsetUnset($offset) - { - unset($this->metadata[$offset]); - } -} class TPC_yyStackEntry { @@ -80,284 +7,408 @@ class TPC_yyStackEntry ** number for the token at this stack level */ public $minor; /* The user-supplied minor token value. This ** is the value of the token */ -}; +} +// line 12 "../smarty/lexer/smarty_internal_configfileparser.y" -#line 12 "smarty_internal_configfileparser.y" -class Smarty_Internal_Configfileparser#line 79 "smarty_internal_configfileparser.php" +/** + * Smarty Internal Plugin Configfileparse + * + * This is the config file parser. + * It is generated from the smarty_internal_configfileparser.y file + * + * @package Smarty + * @subpackage Compiler + * @author Uwe Tews + */ +class Smarty_Internal_Configfileparser { -#line 14 "smarty_internal_configfileparser.y" + // line 25 "../smarty/lexer/smarty_internal_configfileparser.y" + const TPC_OPENB = 1; + const TPC_SECTION = 2; + const TPC_CLOSEB = 3; + const TPC_DOT = 4; + const TPC_ID = 5; + const TPC_EQUAL = 6; + const TPC_FLOAT = 7; + const TPC_INT = 8; + const TPC_BOOL = 9; + const TPC_SINGLE_QUOTED_STRING = 10; + const TPC_DOUBLE_QUOTED_STRING = 11; + const TPC_TRIPPLE_QUOTES = 12; + const TPC_TRIPPLE_TEXT = 13; + const TPC_TRIPPLE_QUOTES_END = 14; + const TPC_NAKED_STRING = 15; + const TPC_OTHER = 16; + const TPC_NEWLINE = 17; + const TPC_COMMENTSTART = 18; + const YY_NO_ACTION = 60; + const YY_ACCEPT_ACTION = 59; + const YY_ERROR_ACTION = 58; + const YY_SZ_ACTTAB = 38; + const YY_SHIFT_USE_DFLT = -8; + const YY_SHIFT_MAX = 19; + const YY_REDUCE_USE_DFLT = -17; + const YY_REDUCE_MAX = 10; + const YYNOCODE = 29; + const YYSTACKDEPTH = 100; + const YYNSTATE = 36; + const YYNRULE = 22; + const YYERRORSYMBOL = 19; + const YYERRSYMDT = 'yy0'; + const YYFALLBACK = 0; + + public static $yy_action = array( + 32, 31, 30, 29, 35, 13, 19, 3, 24, 26, + 59, 9, 14, 1, 16, 25, 11, 28, 25, 11, + 17, 27, 34, 20, 18, 15, 23, 5, 6, 22, + 10, 8, 4, 12, 2, 33, 7, 21, + ); + + public static $yy_lookahead = array( + 7, 8, 9, 10, 11, 12, 5, 23, 15, 16, + 20, 21, 2, 23, 4, 17, 18, 14, 17, 18, + 13, 14, 25, 26, 15, 2, 17, 3, 3, 17, + 25, 25, 6, 1, 23, 27, 22, 24, + ); + + public static $yy_shift_ofst = array( + -8, 1, 1, 1, -7, -2, -2, 32, -8, -8, + -8, 9, 10, 7, 25, 24, 23, 3, 12, 26, + ); + + public static $yy_reduce_ofst = array( + -10, -3, -3, -3, 8, 6, 5, 13, 11, 14, + -16, + ); + + public static $yyExpectedTokens = array( + array(), + array(5, 17, 18,), + array(5, 17, 18,), + array(5, 17, 18,), + array(7, 8, 9, 10, 11, 12, 15, 16,), + array(17, 18,), + array(17, 18,), + array(1,), + array(), + array(), + array(), + array(15, 17,), + array(2, 4,), + array(13, 14,), + array(3,), + array(3,), + array(2,), + array(14,), + array(17,), + array(6,), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + ); + + public static $yy_default = array( + 44, 37, 41, 40, 58, 58, 58, 36, 44, 39, + 44, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 43, 38, 57, 56, 53, 55, 54, 52, 51, 49, + 48, 47, 46, 45, 42, 50, + ); + + public static $yyFallback = array(); - // states whether the parse was successful or not + public static $yyRuleName = array( + 'start ::= global_vars sections', + 'global_vars ::= var_list', + 'sections ::= sections section', + 'sections ::=', + 'section ::= OPENB SECTION CLOSEB newline var_list', + 'section ::= OPENB DOT SECTION CLOSEB newline var_list', + 'var_list ::= var_list newline', + 'var_list ::= var_list var', + 'var_list ::=', + 'var ::= ID EQUAL value', + 'value ::= FLOAT', + 'value ::= INT', + 'value ::= BOOL', + 'value ::= SINGLE_QUOTED_STRING', + 'value ::= DOUBLE_QUOTED_STRING', + 'value ::= TRIPPLE_QUOTES TRIPPLE_TEXT TRIPPLE_QUOTES_END', + 'value ::= TRIPPLE_QUOTES TRIPPLE_QUOTES_END', + 'value ::= NAKED_STRING', + 'value ::= OTHER', + 'newline ::= NEWLINE', + 'newline ::= COMMENTSTART NEWLINE', + 'newline ::= COMMENTSTART NAKED_STRING NEWLINE', + ); + + public static $yyRuleInfo = array( + array(0 => 20, 1 => 2), + array(0 => 21, 1 => 1), + array(0 => 22, 1 => 2), + array(0 => 22, 1 => 0), + array(0 => 24, 1 => 5), + array(0 => 24, 1 => 6), + array(0 => 23, 1 => 2), + array(0 => 23, 1 => 2), + array(0 => 23, 1 => 0), + array(0 => 26, 1 => 3), + array(0 => 27, 1 => 1), + array(0 => 27, 1 => 1), + array(0 => 27, 1 => 1), + array(0 => 27, 1 => 1), + array(0 => 27, 1 => 1), + array(0 => 27, 1 => 3), + array(0 => 27, 1 => 2), + array(0 => 27, 1 => 1), + array(0 => 27, 1 => 1), + array(0 => 25, 1 => 1), + array(0 => 25, 1 => 2), + array(0 => 25, 1 => 3), + ); + + public static $yyReduceMap = array( + 0 => 0, + 2 => 0, + 3 => 0, + 19 => 0, + 20 => 0, + 21 => 0, + 1 => 1, + 4 => 4, + 5 => 5, + 6 => 6, + 7 => 7, + 8 => 8, + 9 => 9, + 10 => 10, + 11 => 11, + 12 => 12, + 13 => 13, + 14 => 14, + 15 => 15, + 16 => 16, + 17 => 17, + 18 => 17, + ); + + /** + * helper map + * + * @var array + */ + private static $escapes_single = array( + '\\' => '\\', + '\'' => '\'' + ); + + /** + * result status + * + * @var bool + */ public $successful = true; + + /** + * return value + * + * @var mixed + */ public $retvalue = 0; - private $lex; - private $internalError = false; - function __construct($lex, $compiler) { - // set instance object - self::instance($this); - $this->lex = $lex; - $this->smarty = $compiler->smarty; - $this->compiler = $compiler; - } - public static function &instance($new_instance = null) - { - static $instance = null; - if (isset($new_instance) && is_object($new_instance)) - $instance = $new_instance; - return $instance; - } + /** + * @var + */ + public $yymajor; - private function parse_bool($str) { - if (in_array(strtolower($str) ,array('on','yes','true'))) { - $res = true; - } else { - $res = false; - } - return $res; - } + /** + * compiler object + * + * @var Smarty_Internal_Config_File_Compiler + */ + public $compiler = null; - private static $escapes_single = Array('\\' => '\\', - '\'' => '\''); - private static function parse_single_quoted_string($qstr) { - $escaped_string = substr($qstr, 1, strlen($qstr)-2); //remove outer quotes + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; - $ss = preg_split('/(\\\\.)/', $escaped_string, -1, PREG_SPLIT_DELIM_CAPTURE); + public $yyTraceFILE; - $str = ""; - foreach ($ss as $s) { - if (strlen($s) === 2 && $s[0] === '\\') { - if (isset(self::$escapes_single[$s[1]])) { - $s = self::$escapes_single[$s[1]]; - } - } + public $yyTracePrompt; - $str .= $s; - } + public $yyidx; - return $str; - } + public $yyerrcnt; - private static function parse_double_quoted_string($qstr) { - $inner_str = substr($qstr, 1, strlen($qstr)-2); - return stripcslashes($inner_str); - } + public $yystack = array(); - private static function parse_tripple_double_quoted_string($qstr) { - $inner_str = substr($qstr, 3, strlen($qstr)-6); - return stripcslashes($inner_str); - } + public $yyTokenName = array( + '$', 'OPENB', 'SECTION', 'CLOSEB', + 'DOT', 'ID', 'EQUAL', 'FLOAT', + 'INT', 'BOOL', 'SINGLE_QUOTED_STRING', 'DOUBLE_QUOTED_STRING', + 'TRIPPLE_QUOTES', 'TRIPPLE_TEXT', 'TRIPPLE_QUOTES_END', 'NAKED_STRING', + 'OTHER', 'NEWLINE', 'COMMENTSTART', 'error', + 'start', 'global_vars', 'sections', 'var_list', + 'section', 'newline', 'var', 'value', + ); - private function set_var(Array $var, Array &$target_array) { - $key = $var["key"]; - $value = $var["value"]; + /** + * lexer object + * + * @var Smarty_Internal_Configfilelexer + */ + private $lex; - if ($this->smarty->config_overwrite || !isset($target_array['vars'][$key])) { - $target_array['vars'][$key] = $value; - } else { - settype($target_array['vars'][$key], 'array'); - $target_array['vars'][$key][] = $value; - } + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; + + /** + * copy of config_overwrite property + * + * @var bool + */ + private $configOverwrite = false; + + /** + * copy of config_read_hidden property + * + * @var bool + */ + private $configReadHidden = false; + + private $_retvalue; + + /** + * constructor + * + * @param Smarty_Internal_Configfilelexer $lex + * @param Smarty_Internal_Config_File_Compiler $compiler + */ + public function __construct(Smarty_Internal_Configfilelexer $lex, Smarty_Internal_Config_File_Compiler $compiler) + { + $this->lex = $lex; + $this->smarty = $compiler->smarty; + $this->compiler = $compiler; + $this->configOverwrite = $this->smarty->config_overwrite; + $this->configReadHidden = $this->smarty->config_read_hidden; } - private function add_global_vars(Array $vars) { - if (!isset($this->compiler->config_data['vars'])) { - $this->compiler->config_data['vars'] = Array(); - } - foreach ($vars as $var) { - $this->set_var($var, $this->compiler->config_data); + public static function yy_destructor($yymajor, $yypminor) + { + switch ($yymajor) { + default: + break; /* If no destructor action specified: do nothing */ } } - private function add_section_vars($section_name, Array $vars) { - if (!isset($this->compiler->config_data['sections'][$section_name]['vars'])) { - $this->compiler->config_data['sections'][$section_name]['vars'] = Array(); + /** + * parse single quoted string + * remove outer quotes + * unescape inner quotes + * + * @param string $qstr + * + * @return string + */ + private static function parse_single_quoted_string($qstr) + { + $escaped_string = substr($qstr, 1, strlen($qstr) - 2); //remove outer quotes + $ss = preg_split('/(\\\\.)/', $escaped_string, -1, PREG_SPLIT_DELIM_CAPTURE); + $str = ''; + foreach ($ss as $s) { + if (strlen($s) === 2 && $s[ 0 ] === '\\') { + if (isset(self::$escapes_single[ $s[ 1 ] ])) { + $s = self::$escapes_single[ $s[ 1 ] ]; + } + } + $str .= $s; } - foreach ($vars as $var) { - $this->set_var($var, $this->compiler->config_data['sections'][$section_name]); - } - } -#line 174 "smarty_internal_configfileparser.php" - - const TPC_OPENB = 1; - const TPC_SECTION = 2; - const TPC_CLOSEB = 3; - const TPC_DOT = 4; - const TPC_ID = 5; - const TPC_EQUAL = 6; - const TPC_FLOAT = 7; - const TPC_INT = 8; - const TPC_BOOL = 9; - const TPC_SINGLE_QUOTED_STRING = 10; - const TPC_DOUBLE_QUOTED_STRING = 11; - const TPC_TRIPPLE_DOUBLE_QUOTED_STRING = 12; - const TPC_NAKED_STRING = 13; - const TPC_NEWLINE = 14; - const TPC_COMMENTSTART = 15; - const YY_NO_ACTION = 54; - const YY_ACCEPT_ACTION = 53; - const YY_ERROR_ACTION = 52; - - const YY_SZ_ACTTAB = 35; -static public $yy_action = array( - /* 0 */ 26, 27, 21, 30, 29, 28, 31, 16, 53, 8, - /* 10 */ 19, 2, 20, 11, 24, 23, 20, 11, 17, 15, - /* 20 */ 3, 14, 13, 18, 4, 6, 5, 1, 12, 22, - /* 30 */ 9, 47, 10, 25, 7, - ); - static public $yy_lookahead = array( - /* 0 */ 7, 8, 9, 10, 11, 12, 13, 5, 17, 18, - /* 10 */ 14, 20, 14, 15, 22, 23, 14, 15, 2, 2, - /* 20 */ 20, 4, 13, 14, 6, 3, 3, 20, 1, 24, - /* 30 */ 22, 25, 22, 21, 19, -); - const YY_SHIFT_USE_DFLT = -8; - const YY_SHIFT_MAX = 17; - static public $yy_shift_ofst = array( - /* 0 */ -8, 2, 2, 2, -7, -2, -2, 27, -8, -8, - /* 10 */ -8, 9, 17, -4, 16, 23, 18, 22, -); - const YY_REDUCE_USE_DFLT = -10; - const YY_REDUCE_MAX = 10; - static public $yy_reduce_ofst = array( - /* 0 */ -9, -8, -8, -8, 5, 10, 8, 12, 15, 0, - /* 10 */ 7, -); - static public $yyExpectedTokens = array( - /* 0 */ array(), - /* 1 */ array(5, 14, 15, ), - /* 2 */ array(5, 14, 15, ), - /* 3 */ array(5, 14, 15, ), - /* 4 */ array(7, 8, 9, 10, 11, 12, 13, ), - /* 5 */ array(14, 15, ), - /* 6 */ array(14, 15, ), - /* 7 */ array(1, ), - /* 8 */ array(), - /* 9 */ array(), - /* 10 */ array(), - /* 11 */ array(13, 14, ), - /* 12 */ array(2, 4, ), - /* 13 */ array(14, ), - /* 14 */ array(2, ), - /* 15 */ array(3, ), - /* 16 */ array(6, ), - /* 17 */ array(3, ), - /* 18 */ array(), - /* 19 */ array(), - /* 20 */ array(), - /* 21 */ array(), - /* 22 */ array(), - /* 23 */ array(), - /* 24 */ array(), - /* 25 */ array(), - /* 26 */ array(), - /* 27 */ array(), - /* 28 */ array(), - /* 29 */ array(), - /* 30 */ array(), - /* 31 */ array(), -); - static public $yy_default = array( - /* 0 */ 40, 36, 33, 37, 52, 52, 52, 32, 35, 40, - /* 10 */ 40, 52, 52, 52, 52, 52, 52, 52, 50, 51, - /* 20 */ 49, 44, 41, 39, 38, 34, 42, 43, 47, 46, - /* 30 */ 45, 48, -); - const YYNOCODE = 26; - const YYSTACKDEPTH = 100; - const YYNSTATE = 32; - const YYNRULE = 20; - const YYERRORSYMBOL = 16; - const YYERRSYMDT = 'yy0'; - const YYFALLBACK = 0; - static public $yyFallback = array( - ); - static function Trace($TraceFILE, $zTracePrompt) + return $str; + } /* Index of top element in stack */ + /** + * parse double quoted string + * + * @param string $qstr + * + * @return string + */ + private static function parse_double_quoted_string($qstr) + { + $inner_str = substr($qstr, 1, strlen($qstr) - 2); + return stripcslashes($inner_str); + } /* Shifts left before out of the error */ + /** + * parse triple quoted string + * + * @param string $qstr + * + * @return string + */ + private static function parse_tripple_double_quoted_string($qstr) + { + return stripcslashes($qstr); + } /* The parser's stack */ + public function Trace($TraceFILE, $zTracePrompt) { if (!$TraceFILE) { $zTracePrompt = 0; } elseif (!$zTracePrompt) { $TraceFILE = 0; } - self::$yyTraceFILE = $TraceFILE; - self::$yyTracePrompt = $zTracePrompt; + $this->yyTraceFILE = $TraceFILE; + $this->yyTracePrompt = $zTracePrompt; } - static function PrintTrace() + public function PrintTrace() { - self::$yyTraceFILE = fopen('php://output', 'w'); - self::$yyTracePrompt = '
'; + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; } - static public $yyTraceFILE; - static public $yyTracePrompt; - public $yyidx; /* Index of top element in stack */ - public $yyerrcnt; /* Shifts left before out of the error */ - public $yystack = array(); /* The parser's stack */ - - public $yyTokenName = array( - '$', 'OPENB', 'SECTION', 'CLOSEB', - 'DOT', 'ID', 'EQUAL', 'FLOAT', - 'INT', 'BOOL', 'SINGLE_QUOTED_STRING', 'DOUBLE_QUOTED_STRING', - 'TRIPPLE_DOUBLE_QUOTED_STRING', 'NAKED_STRING', 'NEWLINE', 'COMMENTSTART', - 'error', 'start', 'global_vars', 'sections', - 'var_list', 'section', 'newline', 'var', - 'value', - ); - - static public $yyRuleName = array( - /* 0 */ "start ::= global_vars sections", - /* 1 */ "global_vars ::= var_list", - /* 2 */ "sections ::= sections section", - /* 3 */ "sections ::=", - /* 4 */ "section ::= OPENB SECTION CLOSEB newline var_list", - /* 5 */ "section ::= OPENB DOT SECTION CLOSEB newline var_list", - /* 6 */ "var_list ::= var_list newline", - /* 7 */ "var_list ::= var_list var", - /* 8 */ "var_list ::=", - /* 9 */ "var ::= ID EQUAL value", - /* 10 */ "value ::= FLOAT", - /* 11 */ "value ::= INT", - /* 12 */ "value ::= BOOL", - /* 13 */ "value ::= SINGLE_QUOTED_STRING", - /* 14 */ "value ::= DOUBLE_QUOTED_STRING", - /* 15 */ "value ::= TRIPPLE_DOUBLE_QUOTED_STRING", - /* 16 */ "value ::= NAKED_STRING", - /* 17 */ "newline ::= NEWLINE", - /* 18 */ "newline ::= COMMENTSTART NEWLINE", - /* 19 */ "newline ::= COMMENTSTART NAKED_STRING NEWLINE", - ); - - function tokenName($tokenType) + public function tokenName($tokenType) { if ($tokenType === 0) { return 'End of Input'; } if ($tokenType > 0 && $tokenType < count($this->yyTokenName)) { - return $this->yyTokenName[$tokenType]; + return $this->yyTokenName[ $tokenType ]; } else { - return "Unknown"; - } - } - - static function yy_destructor($yymajor, $yypminor) - { - switch ($yymajor) { - default: break; /* If no destructor action specified: do nothing */ + return 'Unknown'; } } - function yy_pop_parser_stack() + public function yy_pop_parser_stack() { - if (!count($this->yystack)) { + if (empty($this->yystack)) { return; } $yytos = array_pop($this->yystack); - if (self::$yyTraceFILE && $this->yyidx >= 0) { - fwrite(self::$yyTraceFILE, - self::$yyTracePrompt . 'Popping ' . $this->yyTokenName[$yytos->major] . - "\n"); + if ($this->yyTraceFILE && $this->yyidx >= 0) { + fwrite( + $this->yyTraceFILE, + $this->yyTracePrompt . 'Popping ' . $this->yyTokenName[ $yytos->major ] . + "\n" + ); } $yymajor = $yytos->major; self::yy_destructor($yymajor, $yytos->minor); @@ -365,22 +416,30 @@ function yy_pop_parser_stack() return $yymajor; } - function __destruct() + public function __destruct() { - while ($this->yystack !== Array()) { + while ($this->yystack !== array()) { $this->yy_pop_parser_stack(); } - if (is_resource(self::$yyTraceFILE)) { - fclose(self::$yyTraceFILE); + if (is_resource($this->yyTraceFILE)) { + fclose($this->yyTraceFILE); } } - function yy_get_expected_tokens($token) + public function yy_get_expected_tokens($token) { - $state = $this->yystack[$this->yyidx]->stateno; - $expected = self::$yyExpectedTokens[$state]; - if (in_array($token, self::$yyExpectedTokens[$state], true)) { - return $expected; + static $res3 = array(); + static $res4 = array(); + $state = $this->yystack[ $this->yyidx ]->stateno; + $expected = self::$yyExpectedTokens[ $state ]; + if (isset($res3[ $state ][ $token ])) { + if ($res3[ $state ][ $token ]) { + return $expected; + } + } else { + if ($res3[ $state ][ $token ] = in_array($token, self::$yyExpectedTokens[ $state ], true)) { + return $expected; + } } $stack = $this->yystack; $yyidx = $this->yyidx; @@ -390,7 +449,7 @@ function yy_get_expected_tokens($token) // reduce action $done = 0; do { - if ($done++ == 100) { + if ($done++ === 100) { $this->yyidx = $yyidx; $this->yystack = $stack; // too much recursion prevents proper detection @@ -398,17 +457,26 @@ function yy_get_expected_tokens($token) return array_unique($expected); } $yyruleno = $yyact - self::YYNSTATE; - $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][ 1 ]; $nextstate = $this->yy_find_reduce_action( - $this->yystack[$this->yyidx]->stateno, - self::$yyRuleInfo[$yyruleno]['lhs']); - if (isset(self::$yyExpectedTokens[$nextstate])) { - $expected = array_merge($expected, self::$yyExpectedTokens[$nextstate]); - if (in_array($token, - self::$yyExpectedTokens[$nextstate], true)) { - $this->yyidx = $yyidx; - $this->yystack = $stack; - return array_unique($expected); + $this->yystack[ $this->yyidx ]->stateno, + self::$yyRuleInfo[ $yyruleno ][ 0 ] + ); + if (isset(self::$yyExpectedTokens[ $nextstate ])) { + $expected = array_merge($expected, self::$yyExpectedTokens[ $nextstate ]); + if (isset($res4[ $nextstate ][ $token ])) { + if ($res4[ $nextstate ][ $token ]) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } else { + if ($res4[ $nextstate ][ $token ] = + in_array($token, self::$yyExpectedTokens[ $nextstate ], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } } } if ($nextstate < self::YYNSTATE) { @@ -416,10 +484,10 @@ function yy_get_expected_tokens($token) $this->yyidx++; $x = new TPC_yyStackEntry; $x->stateno = $nextstate; - $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; - $this->yystack[$this->yyidx] = $x; + $x->major = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $this->yystack[ $this->yyidx ] = $x; continue 2; - } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) { $this->yyidx = $yyidx; $this->yystack = $stack; // the last token was just ignored, we can't accept @@ -438,19 +506,27 @@ function yy_get_expected_tokens($token) } break; } while (true); - $this->yyidx = $yyidx; - $this->yystack = $stack; + $this->yyidx = $yyidx; + $this->yystack = $stack; return array_unique($expected); } - function yy_is_expected_token($token) + public function yy_is_expected_token($token) { + static $res = array(); + static $res2 = array(); if ($token === 0) { return true; // 0 is not part of this } - $state = $this->yystack[$this->yyidx]->stateno; - if (in_array($token, self::$yyExpectedTokens[$state], true)) { - return true; + $state = $this->yystack[ $this->yyidx ]->stateno; + if (isset($res[ $state ][ $token ])) { + if ($res[ $state ][ $token ]) { + return true; + } + } else { + if ($res[ $state ][ $token ] = in_array($token, self::$yyExpectedTokens[ $state ], true)) { + return true; + } } $stack = $this->yystack; $yyidx = $this->yyidx; @@ -460,7 +536,7 @@ function yy_is_expected_token($token) // reduce action $done = 0; do { - if ($done++ == 100) { + if ($done++ === 100) { $this->yyidx = $yyidx; $this->yystack = $stack; // too much recursion prevents proper detection @@ -468,25 +544,35 @@ function yy_is_expected_token($token) return true; } $yyruleno = $yyact - self::YYNSTATE; - $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][ 1 ]; $nextstate = $this->yy_find_reduce_action( - $this->yystack[$this->yyidx]->stateno, - self::$yyRuleInfo[$yyruleno]['lhs']); - if (isset(self::$yyExpectedTokens[$nextstate]) && - in_array($token, self::$yyExpectedTokens[$nextstate], true)) { - $this->yyidx = $yyidx; - $this->yystack = $stack; - return true; + $this->yystack[ $this->yyidx ]->stateno, + self::$yyRuleInfo[ $yyruleno ][ 0 ] + ); + if (isset($res2[ $nextstate ][ $token ])) { + if ($res2[ $nextstate ][ $token ]) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + } else { + if ($res2[ $nextstate ][ $token ] = + (isset(self::$yyExpectedTokens[ $nextstate ]) && + in_array($token, self::$yyExpectedTokens[ $nextstate ], true))) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } } if ($nextstate < self::YYNSTATE) { // we need to shift a non-terminal $this->yyidx++; $x = new TPC_yyStackEntry; $x->stateno = $nextstate; - $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; - $this->yystack[$this->yyidx] = $x; + $x->major = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $this->yystack[ $this->yyidx ] = $x; continue 2; - } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) { $this->yyidx = $yyidx; $this->yystack = $stack; if (!$token) { @@ -514,273 +600,288 @@ function yy_is_expected_token($token) return true; } - function yy_find_shift_action($iLookAhead) + public function yy_find_shift_action($iLookAhead) { - $stateno = $this->yystack[$this->yyidx]->stateno; - + $stateno = $this->yystack[ $this->yyidx ]->stateno; /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ - if (!isset(self::$yy_shift_ofst[$stateno])) { + if (!isset(self::$yy_shift_ofst[ $stateno ])) { // no shift actions - return self::$yy_default[$stateno]; + return self::$yy_default[ $stateno ]; } - $i = self::$yy_shift_ofst[$stateno]; + $i = self::$yy_shift_ofst[ $stateno ]; if ($i === self::YY_SHIFT_USE_DFLT) { - return self::$yy_default[$stateno]; + return self::$yy_default[ $stateno ]; } - if ($iLookAhead == self::YYNOCODE) { + if ($iLookAhead === self::YYNOCODE) { return self::YY_NO_ACTION; } $i += $iLookAhead; if ($i < 0 || $i >= self::YY_SZ_ACTTAB || - self::$yy_lookahead[$i] != $iLookAhead) { + self::$yy_lookahead[ $i ] != $iLookAhead) { if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback) - && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) { - if (self::$yyTraceFILE) { - fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " . - $this->yyTokenName[$iLookAhead] . " => " . - $this->yyTokenName[$iFallback] . "\n"); + && ($iFallback = self::$yyFallback[ $iLookAhead ]) != 0) { + if ($this->yyTraceFILE) { + fwrite($this->yyTraceFILE, $this->yyTracePrompt . 'FALLBACK ' . + $this->yyTokenName[ $iLookAhead ] . ' => ' . + $this->yyTokenName[ $iFallback ] . "\n"); } return $this->yy_find_shift_action($iFallback); } - return self::$yy_default[$stateno]; + return self::$yy_default[ $stateno ]; } else { - return self::$yy_action[$i]; + return self::$yy_action[ $i ]; } } - function yy_find_reduce_action($stateno, $iLookAhead) + public function yy_find_reduce_action($stateno, $iLookAhead) { /* $stateno = $this->yystack[$this->yyidx]->stateno; */ - - if (!isset(self::$yy_reduce_ofst[$stateno])) { - return self::$yy_default[$stateno]; + if (!isset(self::$yy_reduce_ofst[ $stateno ])) { + return self::$yy_default[ $stateno ]; } - $i = self::$yy_reduce_ofst[$stateno]; - if ($i == self::YY_REDUCE_USE_DFLT) { - return self::$yy_default[$stateno]; + $i = self::$yy_reduce_ofst[ $stateno ]; + if ($i === self::YY_REDUCE_USE_DFLT) { + return self::$yy_default[ $stateno ]; } - if ($iLookAhead == self::YYNOCODE) { + if ($iLookAhead === self::YYNOCODE) { return self::YY_NO_ACTION; } $i += $iLookAhead; if ($i < 0 || $i >= self::YY_SZ_ACTTAB || - self::$yy_lookahead[$i] != $iLookAhead) { - return self::$yy_default[$stateno]; + self::$yy_lookahead[ $i ] != $iLookAhead) { + return self::$yy_default[ $stateno ]; } else { - return self::$yy_action[$i]; + return self::$yy_action[ $i ]; } } - function yy_shift($yyNewState, $yyMajor, $yypMinor) + public function yy_shift($yyNewState, $yyMajor, $yypMinor) { $this->yyidx++; if ($this->yyidx >= self::YYSTACKDEPTH) { $this->yyidx--; - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sStack Overflow!\n", $this->yyTracePrompt); } while ($this->yyidx >= 0) { $this->yy_pop_parser_stack(); } -#line 126 "smarty_internal_configfileparser.y" - - $this->internalError = true; - $this->compiler->trigger_config_file_error("Stack overflow in configfile parser"); -#line 585 "smarty_internal_configfileparser.php" + // line 239 "../smarty/lexer/smarty_internal_configfileparser.y" + $this->internalError = true; + $this->compiler->trigger_config_file_error('Stack overflow in configfile parser'); return; } $yytos = new TPC_yyStackEntry; $yytos->stateno = $yyNewState; $yytos->major = $yyMajor; $yytos->minor = $yypMinor; - array_push($this->yystack, $yytos); - if (self::$yyTraceFILE && $this->yyidx > 0) { - fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt, - $yyNewState); - fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt); - for($i = 1; $i <= $this->yyidx; $i++) { - fprintf(self::$yyTraceFILE, " %s", - $this->yyTokenName[$this->yystack[$i]->major]); + $this->yystack[] = $yytos; + if ($this->yyTraceFILE && $this->yyidx > 0) { + fprintf( + $this->yyTraceFILE, + "%sShift %d\n", + $this->yyTracePrompt, + $yyNewState + ); + fprintf($this->yyTraceFILE, "%sStack:", $this->yyTracePrompt); + for ($i = 1; $i <= $this->yyidx; $i++) { + fprintf( + $this->yyTraceFILE, + " %s", + $this->yyTokenName[ $this->yystack[ $i ]->major ] + ); } - fwrite(self::$yyTraceFILE,"\n"); - } - } - - static public $yyRuleInfo = array( - array( 'lhs' => 17, 'rhs' => 2 ), - array( 'lhs' => 18, 'rhs' => 1 ), - array( 'lhs' => 19, 'rhs' => 2 ), - array( 'lhs' => 19, 'rhs' => 0 ), - array( 'lhs' => 21, 'rhs' => 5 ), - array( 'lhs' => 21, 'rhs' => 6 ), - array( 'lhs' => 20, 'rhs' => 2 ), - array( 'lhs' => 20, 'rhs' => 2 ), - array( 'lhs' => 20, 'rhs' => 0 ), - array( 'lhs' => 23, 'rhs' => 3 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 24, 'rhs' => 1 ), - array( 'lhs' => 22, 'rhs' => 1 ), - array( 'lhs' => 22, 'rhs' => 2 ), - array( 'lhs' => 22, 'rhs' => 3 ), - ); + fwrite($this->yyTraceFILE, "\n"); + } + } - static public $yyReduceMap = array( - 0 => 0, - 2 => 0, - 3 => 0, - 17 => 0, - 18 => 0, - 19 => 0, - 1 => 1, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - 13 => 13, - 14 => 14, - 15 => 15, - 16 => 16, - ); -#line 132 "smarty_internal_configfileparser.y" - function yy_r0(){ $this->_retvalue = null; } -#line 652 "smarty_internal_configfileparser.php" -#line 135 "smarty_internal_configfileparser.y" - function yy_r1(){ $this->add_global_vars($this->yystack[$this->yyidx + 0]->minor); $this->_retvalue = null; } -#line 655 "smarty_internal_configfileparser.php" -#line 141 "smarty_internal_configfileparser.y" - function yy_r4(){ $this->add_section_vars($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + 0]->minor); $this->_retvalue = null; } -#line 658 "smarty_internal_configfileparser.php" -#line 142 "smarty_internal_configfileparser.y" - function yy_r5(){ if ($this->smarty->config_read_hidden) { $this->add_section_vars($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + 0]->minor); } $this->_retvalue = null; } -#line 661 "smarty_internal_configfileparser.php" -#line 145 "smarty_internal_configfileparser.y" - function yy_r6(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; } -#line 664 "smarty_internal_configfileparser.php" -#line 146 "smarty_internal_configfileparser.y" - function yy_r7(){ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -1]->minor, Array($this->yystack[$this->yyidx + 0]->minor)); } -#line 667 "smarty_internal_configfileparser.php" -#line 147 "smarty_internal_configfileparser.y" - function yy_r8(){ $this->_retvalue = Array(); } -#line 670 "smarty_internal_configfileparser.php" -#line 151 "smarty_internal_configfileparser.y" - function yy_r9(){ $this->_retvalue = Array("key" => $this->yystack[$this->yyidx + -2]->minor, "value" => $this->yystack[$this->yyidx + 0]->minor); } -#line 673 "smarty_internal_configfileparser.php" -#line 153 "smarty_internal_configfileparser.y" - function yy_r10(){ $this->_retvalue = (float) $this->yystack[$this->yyidx + 0]->minor; } -#line 676 "smarty_internal_configfileparser.php" -#line 154 "smarty_internal_configfileparser.y" - function yy_r11(){ $this->_retvalue = (int) $this->yystack[$this->yyidx + 0]->minor; } -#line 679 "smarty_internal_configfileparser.php" -#line 155 "smarty_internal_configfileparser.y" - function yy_r12(){ $this->_retvalue = $this->parse_bool($this->yystack[$this->yyidx + 0]->minor); } -#line 682 "smarty_internal_configfileparser.php" -#line 156 "smarty_internal_configfileparser.y" - function yy_r13(){ $this->_retvalue = self::parse_single_quoted_string($this->yystack[$this->yyidx + 0]->minor); } -#line 685 "smarty_internal_configfileparser.php" -#line 157 "smarty_internal_configfileparser.y" - function yy_r14(){ $this->_retvalue = self::parse_double_quoted_string($this->yystack[$this->yyidx + 0]->minor); } -#line 688 "smarty_internal_configfileparser.php" -#line 158 "smarty_internal_configfileparser.y" - function yy_r15(){ $this->_retvalue = self::parse_tripple_double_quoted_string($this->yystack[$this->yyidx + 0]->minor); } -#line 691 "smarty_internal_configfileparser.php" -#line 159 "smarty_internal_configfileparser.y" - function yy_r16(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 694 "smarty_internal_configfileparser.php" + public function yy_r0() + { + $this->_retvalue = null; + } - private $_retvalue; + public function yy_r1() + { + $this->add_global_vars($this->yystack[ $this->yyidx + 0 ]->minor); + $this->_retvalue = null; + } + + public function yy_r4() + { + $this->add_section_vars($this->yystack[ $this->yyidx + -3 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor); + $this->_retvalue = null; + } - function yy_reduce($yyruleno) + // line 245 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r5() { - $yymsp = $this->yystack[$this->yyidx]; - if (self::$yyTraceFILE && $yyruleno >= 0 - && $yyruleno < count(self::$yyRuleName)) { - fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n", - self::$yyTracePrompt, $yyruleno, - self::$yyRuleName[$yyruleno]); + if ($this->configReadHidden) { + $this->add_section_vars( + $this->yystack[ $this->yyidx + -3 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor + ); } + $this->_retvalue = null; + } + + // line 250 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r6() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + // line 264 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r7() + { + $this->_retvalue = + array_merge($this->yystack[ $this->yyidx + -1 ]->minor, array($this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 269 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r8() + { + $this->_retvalue = array(); + } + // line 277 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r9() + { + $this->_retvalue = + array( + 'key' => $this->yystack[ $this->yyidx + -2 ]->minor, + 'value' => $this->yystack[ $this->yyidx + 0 ]->minor + ); + } + + // line 281 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r10() + { + $this->_retvalue = (float)$this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 285 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r11() + { + $this->_retvalue = (int)$this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 291 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r12() + { + $this->_retvalue = $this->parse_bool($this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 296 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r13() + { + $this->_retvalue = self::parse_single_quoted_string($this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 300 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r14() + { + $this->_retvalue = self::parse_double_quoted_string($this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 304 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r15() + { + $this->_retvalue = self::parse_tripple_double_quoted_string($this->yystack[ $this->yyidx + -1 ]->minor); + } + + // line 308 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r16() + { + $this->_retvalue = ''; + } + + // line 312 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_r17() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 316 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_reduce($yyruleno) + { + if ($this->yyTraceFILE && $yyruleno >= 0 + && $yyruleno < count(self::$yyRuleName)) { + fprintf( + $this->yyTraceFILE, + "%sReduce (%d) [%s].\n", + $this->yyTracePrompt, + $yyruleno, + self::$yyRuleName[ $yyruleno ] + ); + } $this->_retvalue = $yy_lefthand_side = null; - if (array_key_exists($yyruleno, self::$yyReduceMap)) { + if (isset(self::$yyReduceMap[ $yyruleno ])) { // call the action $this->_retvalue = null; - $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}(); + $this->{'yy_r' . self::$yyReduceMap[ $yyruleno ]}(); $yy_lefthand_side = $this->_retvalue; } - $yygoto = self::$yyRuleInfo[$yyruleno]['lhs']; - $yysize = self::$yyRuleInfo[$yyruleno]['rhs']; + $yygoto = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $yysize = self::$yyRuleInfo[ $yyruleno ][ 1 ]; $this->yyidx -= $yysize; - for($i = $yysize; $i; $i--) { + for ($i = $yysize; $i; $i--) { // pop all of the right-hand side parameters array_pop($this->yystack); } - $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto); + $yyact = $this->yy_find_reduce_action($this->yystack[ $this->yyidx ]->stateno, $yygoto); if ($yyact < self::YYNSTATE) { - if (!self::$yyTraceFILE && $yysize) { + if (!$this->yyTraceFILE && $yysize) { $this->yyidx++; $x = new TPC_yyStackEntry; $x->stateno = $yyact; $x->major = $yygoto; $x->minor = $yy_lefthand_side; - $this->yystack[$this->yyidx] = $x; + $this->yystack[ $this->yyidx ] = $x; } else { $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); } - } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) { + } elseif ($yyact === self::YYNSTATE + self::YYNRULE + 1) { $this->yy_accept(); } } - function yy_parse_failed() + // line 320 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_parse_failed() { - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sFail!\n", $this->yyTracePrompt); } while ($this->yyidx >= 0) { $this->yy_pop_parser_stack(); } } - function yy_syntax_error($yymajor, $TOKEN) + // line 324 "../smarty/lexer/smarty_internal_configfileparser.y" + public function yy_syntax_error($yymajor, $TOKEN) { -#line 119 "smarty_internal_configfileparser.y" - - $this->internalError = true; - $this->yymajor = $yymajor; - $this->compiler->trigger_config_file_error(); -#line 757 "smarty_internal_configfileparser.php" + // line 232 "../smarty/lexer/smarty_internal_configfileparser.y" + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_config_file_error(); } - function yy_accept() + public function yy_accept() { - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sAccept!\n", $this->yyTracePrompt); } while ($this->yyidx >= 0) { - $stack = $this->yy_pop_parser_stack(); + $this->yy_pop_parser_stack(); } -#line 111 "smarty_internal_configfileparser.y" - - $this->successful = !$this->internalError; - $this->internalError = false; - $this->retvalue = $this->_retvalue; - //echo $this->retvalue."\n\n"; -#line 775 "smarty_internal_configfileparser.php" + // line 225 "../smarty/lexer/smarty_internal_configfileparser.y" + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; } - function doParse($yymajor, $yytokenvalue) + public function doParse($yymajor, $yytokenvalue) { $yyerrorhit = 0; /* True if yymajor has invoked an error */ - if ($this->yyidx === null || $this->yyidx < 0) { $this->yyidx = 0; $this->yyerrcnt = -1; @@ -788,19 +889,21 @@ function doParse($yymajor, $yytokenvalue) $x->stateno = 0; $x->major = 0; $this->yystack = array(); - array_push($this->yystack, $x); + $this->yystack[] = $x; } - $yyendofinput = ($yymajor==0); - - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sInput %s\n", - self::$yyTracePrompt, $this->yyTokenName[$yymajor]); + $yyendofinput = ($yymajor == 0); + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%sInput %s\n", + $this->yyTracePrompt, + $this->yyTokenName[ $yymajor ] + ); } - do { $yyact = $this->yy_find_shift_action($yymajor); if ($yymajor < self::YYERRORSYMBOL && - !$this->yy_is_expected_token($yymajor)) { + !$this->yy_is_expected_token($yymajor)) { // force a syntax error $yyact = self::YY_ERROR_ACTION; } @@ -814,35 +917,42 @@ function doParse($yymajor, $yytokenvalue) } } elseif ($yyact < self::YYNSTATE + self::YYNRULE) { $this->yy_reduce($yyact - self::YYNSTATE); - } elseif ($yyact == self::YY_ERROR_ACTION) { - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sSyntax Error!\n", - self::$yyTracePrompt); + } elseif ($yyact === self::YY_ERROR_ACTION) { + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%sSyntax Error!\n", + $this->yyTracePrompt + ); } if (self::YYERRORSYMBOL) { if ($this->yyerrcnt < 0) { $this->yy_syntax_error($yymajor, $yytokenvalue); } - $yymx = $this->yystack[$this->yyidx]->major; - if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){ - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sDiscard input token %s\n", - self::$yyTracePrompt, $this->yyTokenName[$yymajor]); + $yymx = $this->yystack[ $this->yyidx ]->major; + if ($yymx === self::YYERRORSYMBOL || $yyerrorhit) { + if ($this->yyTraceFILE) { + fprintf( + $this->yyTraceFILE, + "%sDiscard input token %s\n", + $this->yyTracePrompt, + $this->yyTokenName[ $yymajor ] + ); } $this->yy_destructor($yymajor, $yytokenvalue); $yymajor = self::YYNOCODE; } else { while ($this->yyidx >= 0 && - $yymx != self::YYERRORSYMBOL && - ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE - ){ + $yymx !== self::YYERRORSYMBOL && + ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE + ) { $this->yy_pop_parser_stack(); } - if ($this->yyidx < 0 || $yymajor==0) { + if ($this->yyidx < 0 || $yymajor == 0) { $this->yy_destructor($yymajor, $yytokenvalue); $this->yy_parse_failed(); $yymajor = self::YYNOCODE; - } elseif ($yymx != self::YYERRORSYMBOL) { + } elseif ($yymx !== self::YYERRORSYMBOL) { $u2 = 0; $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2); } @@ -863,8 +973,74 @@ function doParse($yymajor, $yytokenvalue) } else { $this->yy_accept(); $yymajor = self::YYNOCODE; - } - } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); + } + } while ($yymajor !== self::YYNOCODE && $this->yyidx >= 0); + } + + /** + * parse optional boolean keywords + * + * @param string $str + * + * @return bool + */ + private function parse_bool($str) + { + $str = strtolower($str); + if (in_array($str, array('on', 'yes', 'true'))) { + $res = true; + } else { + $res = false; + } + return $res; + } + + /** + * set a config variable in target array + * + * @param array $var + * @param array $target_array + */ + private function set_var(array $var, array &$target_array) + { + $key = $var[ 'key' ]; + $value = $var[ 'value' ]; + if ($this->configOverwrite || !isset($target_array[ 'vars' ][ $key ])) { + $target_array[ 'vars' ][ $key ] = $value; + } else { + settype($target_array[ 'vars' ][ $key ], 'array'); + $target_array[ 'vars' ][ $key ][] = $value; + } + } + + /** + * add config variable to global vars + * + * @param array $vars + */ + private function add_global_vars(array $vars) + { + if (!isset($this->compiler->config_data[ 'vars' ])) { + $this->compiler->config_data[ 'vars' ] = array(); + } + foreach ($vars as $var) { + $this->set_var($var, $this->compiler->config_data); + } + } + + /** + * add config variable to section + * + * @param string $section_name + * @param array $vars + */ + private function add_section_vars($section_name, array $vars) + { + if (!isset($this->compiler->config_data[ 'sections' ][ $section_name ][ 'vars' ])) { + $this->compiler->config_data[ 'sections' ][ $section_name ][ 'vars' ] = array(); + } + foreach ($vars as $var) { + $this->set_var($var, $this->compiler->config_data[ 'sections' ][ $section_name ]); + } } } -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_data.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_data.php index 609376ecb..98e3e57b3 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_data.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_data.php @@ -1,479 +1,292 @@ $_val) { - if ($_key != '') { - $this->tpl_vars[$_key] = new Smarty_variable($_val, $nocache); - } - } - } else { - if ($tpl_var != '') { - $this->tpl_vars[$tpl_var] = new Smarty_variable($value, $nocache); - } - } - } + public $tpl_vars = array(); + /** - * assigns a global Smarty variable - * - * @param string $varname the global variable name - * @param mixed $value the value to assign - * @param boolean $nocache if true any output of this variable will be not cached + * parent template (if any) + * + * @var Smarty|Smarty_Internal_Template|Smarty_Data */ - public function assignGlobal($varname, $value = null, $nocache = false) - { - if ($varname != '') { - Smarty::$global_tpl_vars[$varname] = new Smarty_variable($value, $nocache); - } - } + public $parent = null; + /** - * assigns values to template variables by reference - * - * @param string $tpl_var the template variable name - * @param mixed $ &$value the referenced value to assign - * @param boolean $nocache if true any output of this variable will be not cached + * configuration settings + * + * @var string[] */ - public function assignByRef($tpl_var, &$value, $nocache = false) - { - if ($tpl_var != '') { - $this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache); - $this->tpl_vars[$tpl_var]->value = &$value; - } - } + public $config_vars = array(); + + /** + * extension handler + * + * @var Smarty_Internal_Extension_Handler + */ + public $ext = null; /** - * wrapper function for Smarty 2 BC - * - * @param string $tpl_var the template variable name - * @param mixed $ &$value the referenced value to assign + * Smarty_Internal_Data constructor. + * + * Install extension handler */ - public function assign_by_ref($tpl_var, &$value) + public function __construct() { - if($this->smarty->deprecation_notices) - trigger_error("function call 'assign_by_ref' is unknown or deprecated, use 'assignByRef'", E_USER_NOTICE); - $this->assignByRef($tpl_var, $value); - } + $this->ext = new Smarty_Internal_Extension_Handler(); + $this->ext->objType = $this->_objType; + } + /** - * appends values to template variables - * - * @param array $ |string $tpl_var the template variable name(s) - * @param mixed $value the value to append - * @param boolean $merge flag if array elements shall be merged - * @param boolean $nocache if true any output of this variable will be not cached + * assigns a Smarty variable + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to assign + * @param boolean $nocache if true any output of this variable will be not cached + * + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ - public function append($tpl_var, $value = null, $merge = false, $nocache = false) + public function assign($tpl_var, $value = null, $nocache = false) { if (is_array($tpl_var)) { - // $tpl_var is an array, ignore $value foreach ($tpl_var as $_key => $_val) { - if ($_key != '') { - if (!isset($this->tpl_vars[$_key])) { - $tpl_var_inst = $this->getVariable($_key, null, true, false); - if ($tpl_var_inst instanceof Undefined_Smarty_Variable) { - $this->tpl_vars[$_key] = new Smarty_variable(null, $nocache); - } else { - $this->tpl_vars[$_key] = clone $tpl_var_inst; - } - } - if (!(is_array($this->tpl_vars[$_key]->value) || $this->tpl_vars[$_key]->value instanceof ArrayAccess)) { - settype($this->tpl_vars[$_key]->value, 'array'); - } - if ($merge && is_array($_val)) { - foreach($_val as $_mkey => $_mval) { - $this->tpl_vars[$_key]->value[$_mkey] = $_mval; - } - } else { - $this->tpl_vars[$_key]->value[] = $_val; - } - } - } + $this->assign($_key, $_val, $nocache); + } } else { - if ($tpl_var != '' && isset($value)) { - if (!isset($this->tpl_vars[$tpl_var])) { - $tpl_var_inst = $this->getVariable($tpl_var, null, true, false); - if ($tpl_var_inst instanceof Undefined_Smarty_Variable) { - $this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache); - } else { - $this->tpl_vars[$tpl_var] = clone $tpl_var_inst; - } - } - if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) { - settype($this->tpl_vars[$tpl_var]->value, 'array'); - } - if ($merge && is_array($value)) { - foreach($value as $_mkey => $_mval) { - $this->tpl_vars[$tpl_var]->value[$_mkey] = $_mval; - } + if ($tpl_var !== '') { + if ($this->_objType === 2) { + /** + * + * + * @var Smarty_Internal_Template $this + */ + $this->_assignInScope($tpl_var, $value, $nocache); } else { - $this->tpl_vars[$tpl_var]->value[] = $value; - } - } - } - } + $this->tpl_vars[ $tpl_var ] = new Smarty_Variable($value, $nocache); + } + } + } + return $this; + } /** - * appends values to template variables by reference - * - * @param string $tpl_var the template variable name - * @param mixed $ &$value the referenced value to append - * @param boolean $merge flag if array elements shall be merged - */ - public function appendByRef($tpl_var, &$value, $merge = false) - { - if ($tpl_var != '' && isset($value)) { - if (!isset($this->tpl_vars[$tpl_var])) { - $this->tpl_vars[$tpl_var] = new Smarty_variable(); - } - if (!@is_array($this->tpl_vars[$tpl_var]->value)) { - settype($this->tpl_vars[$tpl_var]->value, 'array'); - } - if ($merge && is_array($value)) { - foreach($value as $_key => $_val) { - $this->tpl_vars[$tpl_var]->value[$_key] = &$value[$_key]; - } - } else { - $this->tpl_vars[$tpl_var]->value[] = &$value; - } - } - } - - /** - * - * @param string $tpl_var the template variable name - * @param mixed $ &$value the referenced value to append - * @param boolean $merge flag if array elements shall be merged + * appends values to template variables + * + * @api Smarty::append() + * @link http://www.smarty.net/docs/en/api.append.tpl + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to append + * @param bool $merge flag if array elements shall be merged + * @param bool $nocache if true any output of this variable will + * be not cached + * + * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty */ - public function append_by_ref($tpl_var, &$value, $merge = false) + public function append($tpl_var, $value = null, $merge = false, $nocache = false) { - if($this->smarty->deprecation_notices) - trigger_error("function call 'append_by_ref' is unknown or deprecated, use 'appendByRef'", E_USER_NOTICE); - $this->appendByRef($tpl_var, $value, $merge); - } + return $this->ext->append->append($this, $tpl_var, $value, $merge, $nocache); + } + /** - * Returns a single or all template variables - * - * @param string $varname variable name or null - * @return string variable value or or array of variables + * assigns a global Smarty variable + * + * @param string $varName the global variable name + * @param mixed $value the value to assign + * @param boolean $nocache if true any output of this variable will be not cached + * + * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty */ - function getTemplateVars($varname = null, $_ptr = null, $search_parents = true) + public function assignGlobal($varName, $value = null, $nocache = false) { - if (isset($varname)) { - $_var = $this->getVariable($varname, $_ptr, $search_parents, false); - if (is_object($_var)) { - return $_var->value; - } else { - return null; - } - } else { - $_result = array(); - if ($_ptr === null) { - $_ptr = $this; - } while ($_ptr !== null) { - foreach ($_ptr->tpl_vars AS $key => $var) { - if (!array_key_exists($key, $_result)) { - $_result[$key] = $var->value; - } - } - // not found, try at parent - if ($search_parents) { - $_ptr = $_ptr->parent; - } else { - $_ptr = null; - } - } - if ($search_parents && isset(Smarty::$global_tpl_vars)) { - foreach (Smarty::$global_tpl_vars AS $key => $var) { - if (!array_key_exists($key, $_result)) { - $_result[$key] = $var->value; - } - } - } - return $_result; - } - } + return $this->ext->assignGlobal->assignGlobal($this, $varName, $value, $nocache); + } /** - * clear the given assigned template variable. - * - * @param string $ |array $tpl_var the template variable(s) to clear + * appends values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed &$value the referenced value to append + * @param boolean $merge flag if array elements shall be merged + * + * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty */ - public function clearAssign($tpl_var) + public function appendByRef($tpl_var, &$value, $merge = false) { - if (is_array($tpl_var)) { - foreach ($tpl_var as $curr_var) { - unset($this->tpl_vars[$curr_var]); - } - } else { - unset($this->tpl_vars[$tpl_var]); - } - } + return $this->ext->appendByRef->appendByRef($this, $tpl_var, $value, $merge); + } /** - * clear all the assigned template variables. + * assigns values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param $value + * @param boolean $nocache if true any output of this variable will be not cached + * + * @return \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty */ - public function clearAllAssign() + public function assignByRef($tpl_var, &$value, $nocache = false) { - $this->tpl_vars = array(); - } + return $this->ext->assignByRef->assignByRef($this, $tpl_var, $value, $nocache); + } /** - * load a config file, optionally load just selected sections - * - * @param string $config_file filename - * @param mixed $sections array of section names, single section or null + * Returns a single or all template variables + * + * @api Smarty::getTemplateVars() + * @link http://www.smarty.net/docs/en/api.get.template.vars.tpl + * + * @param string $varName variable name or null + * @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $_ptr optional pointer to data object + * @param bool $searchParents include parent templates? + * + * @return mixed variable value or or array of variables */ - public function configLoad($config_file, $sections = null) - { - // load Config class - $config = new Smarty_Internal_Config($config_file, $this->smarty, $this); - $config->loadConfigVars($sections); - } + public function getTemplateVars($varName = null, Smarty_Internal_Data $_ptr = null, $searchParents = true) + { + return $this->ext->getTemplateVars->getTemplateVars($this, $varName, $_ptr, $searchParents); + } /** * gets the object of a Smarty variable - * - * @param string $variable the name of the Smarty variable - * @param object $_ptr optional pointer to data object - * @param boolean $search_parents search also in parent data - * @return object the object of the variable + * + * @param string $variable the name of the Smarty variable + * @param Smarty_Internal_Data $_ptr optional pointer to data object + * @param boolean $searchParents search also in parent data + * @param bool $error_enable + * + * @return Smarty_Variable|Smarty_Undefined_Variable the object of the variable + * @deprecated since 3.1.28 please use Smarty_Internal_Data::getTemplateVars() instead. */ - public function getVariable($_variable, $_ptr = null, $search_parents = true, $error_enable = true) - { - if ($_ptr === null) { - $_ptr = $this; - } while ($_ptr !== null) { - if (isset($_ptr->tpl_vars[$_variable])) { - // found it, return it - return $_ptr->tpl_vars[$_variable]; - } - // not found, try at parent - if ($search_parents) { - $_ptr = $_ptr->parent; - } else { - $_ptr = null; - } - } - if (isset(Smarty::$global_tpl_vars[$_variable])) { - // found it, return it - return Smarty::$global_tpl_vars[$_variable]; - } - if ($this->smarty->error_unassigned && $error_enable) { - throw new SmartyException('Undefined Smarty variable "' . $_variable . '"'); - } else { - if ($error_enable) { - // force a notice - $x = $$_variable; - } - return new Undefined_Smarty_Variable; - } - } + public function getVariable( + $variable = null, + Smarty_Internal_Data $_ptr = null, + $searchParents = true, + $error_enable = true + ) { + return $this->ext->getTemplateVars->_getVariable($this, $variable, $_ptr, $searchParents, $error_enable); + } + /** - * gets a config variable - * - * @param string $variable the name of the config variable - * @return mixed the value of the config variable + * Follow the parent chain an merge template and config variables + * + * @param \Smarty_Internal_Data|null $data */ - public function getConfigVariable($_variable) + public function _mergeVars(Smarty_Internal_Data $data = null) { - $_ptr = $this; - while ($_ptr !== null) { - if (isset($_ptr->config_vars[$_variable])) { - // found it, return it - return $_ptr->config_vars[$_variable]; - } - // not found, try at parent - $_ptr = $_ptr->parent; - } - if ($this->smarty->error_unassigned) { - throw new SmartyException('Undefined config variable "' . $_variable . '"'); + if (isset($data)) { + if (!empty($this->tpl_vars)) { + $data->tpl_vars = array_merge($this->tpl_vars, $data->tpl_vars); + } + if (!empty($this->config_vars)) { + $data->config_vars = array_merge($this->config_vars, $data->config_vars); + } } else { - // force a notice - $x = $$_variable; - return null; - } - } + $data = $this; + } + if (isset($this->parent)) { + $this->parent->_mergeVars($data); + } + } /** - * gets a stream variable - * - * @param string $variable the stream of the variable - * @return mixed the value of the stream variable + * Return true if this instance is a Data obj + * + * @return bool */ - public function getStreamVariable($variable) + public function _isDataObj() { - $_result = ''; - if ($fp = fopen($variable, 'r+')) { - while (!feof($fp)) { - $_result .= fgets($fp); - } - fclose($fp); - return $_result; - } - - if ($this->smarty->error_unassigned) { - throw new SmartyException('Undefined stream variable "' . $variable . '"'); - } else { - return null; - } - } + return $this->_objType === 4; + } /** - * Returns a single or all config variables - * - * @param string $varname variable name or null - * @return string variable value or or array of variables + * Return true if this instance is a template obj + * + * @return bool */ - function getConfigVars($varname = null, $search_parents = true) + public function _isTplObj() { - // var_dump($this); - $_ptr = $this; - $var_array = array(); - while ($_ptr !== null) { - if (isset($varname)) { - if (isset($_ptr->config_vars[$varname])) { - return $_ptr->config_vars[$varname]; - } - } else { - $var_array = array_merge($_ptr->config_vars, $var_array); - } - // not found, try at parent - if ($search_parents) { - $_ptr = $_ptr->parent; - } else { - $_ptr = null; - } - } - if (isset($varname)) { - return ''; - } else { - return $var_array; - } - } + return $this->_objType === 2; + } /** - * Deassigns a single or all config variables - * - * @param string $varname variable name or null + * Return true if this instance is a Smarty obj + * + * @return bool */ - function clearConfig($varname = null) + public function _isSmartyObj() { - if (isset($varname)) { - unset($this->config_vars[$varname]); - return; - } else { - $this->config_vars = array(); - return; - } - } - -} + return $this->_objType === 1; + } -/** - * class for the Smarty data object - * - * The Smarty data object will hold Smarty variables in the current scope - * - * @param object $parent tpl_vars next higher level of Smarty variables - */ -class Smarty_Data extends Smarty_Internal_Data { - // array of variable objects - public $tpl_vars = array(); - // back pointer to parent object - public $parent = null; - // config vars - public $config_vars = array(); - // Smarty object - public $smarty = null; /** - * create Smarty data object + * Get Smarty object + * + * @return Smarty */ - public function __construct ($_parent = null, $smarty = null) + public function _getSmartyObj() { - $this->smarty = $smarty; - if (is_object($_parent)) { - // when object set up back pointer - $this->parent = $_parent; - } elseif (is_array($_parent)) { - // set up variable values - foreach ($_parent as $_key => $_val) { - $this->tpl_vars[$_key] = new Smarty_variable($_val); - } - } elseif ($_parent != null) { - throw new SmartyException("Wrong type for template variables"); - } - } -} -/** - * class for the Smarty variable object - * - * This class defines the Smarty variable object - */ -class Smarty_Variable { - // template variable - public $value; - public $nocache; - public $scope; + return $this->smarty; + } + /** - * create Smarty variable object - * - * @param mixed $value the value to assign - * @param boolean $nocache if true any output of this variable will be not cached - * @param boolean $scope the scope the variable will have (local,parent or root) + * Handle unknown class methods + * + * @param string $name unknown method-name + * @param array $args argument array + * + * @return mixed */ - public function __construct ($value = null, $nocache = false, $scope = Smarty::SCOPE_LOCAL) - { - $this->value = $value; - $this->nocache = $nocache; - $this->scope = $scope; - } - - public function __toString () + public function __call($name, $args) { - return $this->value; - } -} - -/** - * class for undefined variable object - * - * This class defines an object for undefined variable handling - */ -class Undefined_Smarty_Variable { - // return always false - public function __get ($name) - { - if ($name == 'nocache') { - return false; - } else { - return null; - } - } -} - -?> \ No newline at end of file + return $this->ext->_callExternalMethod($this, $name, $args); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_debug.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_debug.php index 0fd22a6a6..24b233e26 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_debug.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_debug.php @@ -1,170 +1,425 @@ smarty; - } - $_assigned_vars = $ptr->tpl_vars; - ksort($_assigned_vars); - $_config_vars = $ptr->config_vars; - ksort($_config_vars); - $ldelim = $smarty->left_delimiter; - $rdelim = $smarty->right_delimiter; - $smarty->left_delimiter = '{'; - $smarty->right_delimiter = '}'; - $_template = new Smarty_Internal_Template ($smarty->debug_tpl, $smarty); - $_template->caching = false; - $_template->force_compile = false; - $_template->disableSecurity(); - $_template->cache_id = null; - $_template->compile_id = null; - if ($obj instanceof Smarty_Internal_Template) { - $_template->assign('template_name',$obj->resource_type.':'.$obj->resource_name); - } - if ($obj instanceof Smarty) { - $_template->assign('template_data', self::$template_data); - } else { - $_template->assign('template_data', null); - } - $_template->assign('assigned_vars', $_assigned_vars); - $_template->assign('config_vars', $_config_vars); - $_template->assign('execution_time', microtime(true) - $smarty->start_time); - echo $_template->getRenderedTemplate(); - $smarty->left_delimiter = $ldelim; - $smarty->right_delimiter = $rdelim; - } - /* - * Recursively gets variables from all template/data scopes - */ - public static function get_debug_vars($obj) - { - $config_vars = $obj->config_vars; - $tpl_vars = array(); - foreach ($obj->tpl_vars as $key => $var) { - $tpl_vars[$key] = clone $var; - if ($obj instanceof Smarty_Internal_Template) { - $tpl_vars[$key]->scope = $obj->resource_type.':'.$obj->resource_name; - } elseif ($obj instanceof Smarty_Data) { - $tpl_vars[$key]->scope = 'Data object'; - } else { - $tpl_vars[$key]->scope = 'Smarty root'; - } - } - - if (isset($obj->parent)) { - $parent = self::get_debug_vars($obj->parent); - $tpl_vars = array_merge($parent->tpl_vars, $tpl_vars); - $config_vars = array_merge($parent->config_vars, $config_vars); - } else { - foreach (Smarty::$global_tpl_vars as $name => $var) { - if (!array_key_exists($name, $tpl_vars)) { - $clone = clone $var; - $clone->scope = 'Global'; - $tpl_vars[$name] = $clone; - } - } - } - return (object) array('tpl_vars' => $tpl_vars, 'config_vars' => $config_vars); - } - - /** - * get_key - */ - static function get_key($template) - { - // calculate Uid if not already done - if ($template->templateUid == '') { - $template->getTemplateFilepath(); - } - $key = $template->templateUid; - if (isset(self::$template_data[$key])) { - return $key; - } else { - self::$template_data[$key]['name'] = $template->getTemplateFilepath(); - self::$template_data[$key]['compile_time'] = 0; - self::$template_data[$key]['render_time'] = 0; - self::$template_data[$key]['cache_time'] = 0; - return $key; - } - } -} + * Smarty Internal Plugin Debug Class + * + * @package Smarty + * @subpackage Debug + */ +class Smarty_Internal_Debug extends Smarty_Internal_Data +{ + /** + * template data + * + * @var array + */ + public $template_data = array(); + + /** + * List of uid's which shall be ignored + * + * @var array + */ + public $ignore_uid = array(); + + /** + * Index of display() and fetch() calls + * + * @var int + */ + public $index = 0; + + /** + * Counter for window offset + * + * @var int + */ + public $offset = 0; + + /** + * Start logging template + * + * @param \Smarty_Internal_Template $template template + * @param null $mode true: display false: fetch null: subtemplate + */ + public function start_template(Smarty_Internal_Template $template, $mode = null) + { + if (isset($mode) && !$template->_isSubTpl()) { + $this->index++; + $this->offset++; + $this->template_data[ $this->index ] = null; + } + $key = $this->get_key($template); + $this->template_data[ $this->index ][ $key ][ 'start_template_time' ] = microtime(true); + } + + /** + * End logging of cache time + * + * @param \Smarty_Internal_Template $template cached template + */ + public function end_template(Smarty_Internal_Template $template) + { + $key = $this->get_key($template); + $this->template_data[ $this->index ][ $key ][ 'total_time' ] += + microtime(true) - $this->template_data[ $this->index ][ $key ][ 'start_template_time' ]; + //$this->template_data[$this->index][$key]['properties'] = $template->properties; + } + + /** + * Start logging of compile time + * + * @param \Smarty_Internal_Template $template + */ + public function start_compile(Smarty_Internal_Template $template) + { + static $_is_stringy = array('string' => true, 'eval' => true); + if (!empty($template->compiler->trace_uid)) { + $key = $template->compiler->trace_uid; + if (!isset($this->template_data[ $this->index ][ $key ])) { + if (isset($_is_stringy[ $template->source->type ])) { + $this->template_data[ $this->index ][ $key ][ 'name' ] = + '\'' . substr($template->source->name, 0, 25) . '...\''; + } else { + $this->template_data[ $this->index ][ $key ][ 'name' ] = $template->source->filepath; + } + $this->template_data[ $this->index ][ $key ][ 'compile_time' ] = 0; + $this->template_data[ $this->index ][ $key ][ 'render_time' ] = 0; + $this->template_data[ $this->index ][ $key ][ 'cache_time' ] = 0; + } + } else { + if (isset($this->ignore_uid[ $template->source->uid ])) { + return; + } + $key = $this->get_key($template); + } + $this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true); + } + + /** + * End logging of compile time + * + * @param \Smarty_Internal_Template $template + */ + public function end_compile(Smarty_Internal_Template $template) + { + if (!empty($template->compiler->trace_uid)) { + $key = $template->compiler->trace_uid; + } else { + if (isset($this->ignore_uid[ $template->source->uid ])) { + return; + } + $key = $this->get_key($template); + } + $this->template_data[ $this->index ][ $key ][ 'compile_time' ] += + microtime(true) - $this->template_data[ $this->index ][ $key ][ 'start_time' ]; + } + + /** + * Start logging of render time + * + * @param \Smarty_Internal_Template $template + */ + public function start_render(Smarty_Internal_Template $template) + { + $key = $this->get_key($template); + $this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true); + } -?> \ No newline at end of file + /** + * End logging of compile time + * + * @param \Smarty_Internal_Template $template + */ + public function end_render(Smarty_Internal_Template $template) + { + $key = $this->get_key($template); + $this->template_data[ $this->index ][ $key ][ 'render_time' ] += + microtime(true) - $this->template_data[ $this->index ][ $key ][ 'start_time' ]; + } + + /** + * Start logging of cache time + * + * @param \Smarty_Internal_Template $template cached template + */ + public function start_cache(Smarty_Internal_Template $template) + { + $key = $this->get_key($template); + $this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true); + } + + /** + * End logging of cache time + * + * @param \Smarty_Internal_Template $template cached template + */ + public function end_cache(Smarty_Internal_Template $template) + { + $key = $this->get_key($template); + $this->template_data[ $this->index ][ $key ][ 'cache_time' ] += + microtime(true) - $this->template_data[ $this->index ][ $key ][ 'start_time' ]; + } + + /** + * Register template object + * + * @param \Smarty_Internal_Template $template cached template + */ + public function register_template(Smarty_Internal_Template $template) + { + } + + /** + * Register data object + * + * @param \Smarty_Data $data data object + */ + public static function register_data(Smarty_Data $data) + { + } + + /** + * Opens a window for the Smarty Debugging Console and display the data + * + * @param Smarty_Internal_Template|Smarty $obj object to debug + * @param bool $full + * + * @throws \Exception + * @throws \SmartyException + */ + public function display_debug($obj, $full = false) + { + if (!$full) { + $this->offset++; + $savedIndex = $this->index; + $this->index = 9999; + } + $smarty = $obj->_getSmartyObj(); + // create fresh instance of smarty for displaying the debug console + // to avoid problems if the application did overload the Smarty class + $debObj = new Smarty(); + // copy the working dirs from application + $debObj->setCompileDir($smarty->getCompileDir()); + // init properties by hand as user may have edited the original Smarty class + $debObj->setPluginsDir(is_dir(dirname(__FILE__) . '/../plugins') ? dirname(__FILE__) . + '/../plugins' : $smarty->getPluginsDir()); + $debObj->force_compile = false; + $debObj->compile_check = Smarty::COMPILECHECK_ON; + $debObj->left_delimiter = '{'; + $debObj->right_delimiter = '}'; + $debObj->security_policy = null; + $debObj->debugging = false; + $debObj->debugging_ctrl = 'NONE'; + $debObj->error_reporting = E_ALL & ~E_NOTICE; + $debObj->debug_tpl = + isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . dirname(__FILE__) . '/../debug.tpl'; + $debObj->registered_plugins = array(); + $debObj->registered_resources = array(); + $debObj->registered_filters = array(); + $debObj->autoload_filters = array(); + $debObj->default_modifiers = array(); + $debObj->escape_html = true; + $debObj->caching = Smarty::CACHING_OFF; + $debObj->compile_id = null; + $debObj->cache_id = null; + // prepare information of assigned variables + $ptr = $this->get_debug_vars($obj); + $_assigned_vars = $ptr->tpl_vars; + ksort($_assigned_vars); + $_config_vars = $ptr->config_vars; + ksort($_config_vars); + $debugging = $smarty->debugging; + $_template = new Smarty_Internal_Template($debObj->debug_tpl, $debObj); + if ($obj->_isTplObj()) { + $_template->assign('template_name', $obj->source->type . ':' . $obj->source->name); + } + if ($obj->_objType === 1 || $full) { + $_template->assign('template_data', $this->template_data[ $this->index ]); + } else { + $_template->assign('template_data', null); + } + $_template->assign('assigned_vars', $_assigned_vars); + $_template->assign('config_vars', $_config_vars); + $_template->assign('execution_time', microtime(true) - $smarty->start_time); + $_template->assign('display_mode', $debugging === 2 || !$full); + $_template->assign('offset', $this->offset * 50); + echo $_template->fetch(); + if (isset($full)) { + $this->index--; + } + if (!$full) { + $this->index = $savedIndex; + } + } + + /** + * Recursively gets variables from all template/data scopes + * + * @param Smarty_Internal_Template|Smarty_Data $obj object to debug + * + * @return StdClass + */ + public function get_debug_vars($obj) + { + $config_vars = array(); + foreach ($obj->config_vars as $key => $var) { + $config_vars[ $key ][ 'value' ] = $var; + if ($obj->_isTplObj()) { + $config_vars[ $key ][ 'scope' ] = $obj->source->type . ':' . $obj->source->name; + } elseif ($obj->_isDataObj()) { + $tpl_vars[ $key ][ 'scope' ] = $obj->dataObjectName; + } else { + $config_vars[ $key ][ 'scope' ] = 'Smarty object'; + } + } + $tpl_vars = array(); + foreach ($obj->tpl_vars as $key => $var) { + foreach ($var as $varkey => $varvalue) { + if ($varkey === 'value') { + $tpl_vars[ $key ][ $varkey ] = $varvalue; + } else { + if ($varkey === 'nocache') { + if ($varvalue === true) { + $tpl_vars[ $key ][ $varkey ] = $varvalue; + } + } else { + if ($varkey !== 'scope' || $varvalue !== 0) { + $tpl_vars[ $key ][ 'attributes' ][ $varkey ] = $varvalue; + } + } + } + } + if ($obj->_isTplObj()) { + $tpl_vars[ $key ][ 'scope' ] = $obj->source->type . ':' . $obj->source->name; + } elseif ($obj->_isDataObj()) { + $tpl_vars[ $key ][ 'scope' ] = $obj->dataObjectName; + } else { + $tpl_vars[ $key ][ 'scope' ] = 'Smarty object'; + } + } + if (isset($obj->parent)) { + $parent = $this->get_debug_vars($obj->parent); + foreach ($parent->tpl_vars as $name => $pvar) { + if (isset($tpl_vars[ $name ]) && $tpl_vars[ $name ][ 'value' ] === $pvar[ 'value' ]) { + $tpl_vars[ $name ][ 'scope' ] = $pvar[ 'scope' ]; + } + } + $tpl_vars = array_merge($parent->tpl_vars, $tpl_vars); + foreach ($parent->config_vars as $name => $pvar) { + if (isset($config_vars[ $name ]) && $config_vars[ $name ][ 'value' ] === $pvar[ 'value' ]) { + $config_vars[ $name ][ 'scope' ] = $pvar[ 'scope' ]; + } + } + $config_vars = array_merge($parent->config_vars, $config_vars); + } else { + foreach (Smarty::$global_tpl_vars as $key => $var) { + if (!array_key_exists($key, $tpl_vars)) { + foreach ($var as $varkey => $varvalue) { + if ($varkey === 'value') { + $tpl_vars[ $key ][ $varkey ] = $varvalue; + } else { + if ($varkey === 'nocache') { + if ($varvalue === true) { + $tpl_vars[ $key ][ $varkey ] = $varvalue; + } + } else { + if ($varkey !== 'scope' || $varvalue !== 0) { + $tpl_vars[ $key ][ 'attributes' ][ $varkey ] = $varvalue; + } + } + } + } + $tpl_vars[ $key ][ 'scope' ] = 'Global'; + } + } + } + return (object)array('tpl_vars' => $tpl_vars, 'config_vars' => $config_vars); + } + + /** + * Return key into $template_data for template + * + * @param \Smarty_Internal_Template $template template object + * + * @return string key into $template_data + */ + private function get_key(Smarty_Internal_Template $template) + { + static $_is_stringy = array('string' => true, 'eval' => true); + // calculate Uid if not already done + if ($template->source->uid === '') { + $template->source->filepath; + } + $key = $template->source->uid; + if (isset($this->template_data[ $this->index ][ $key ])) { + return $key; + } else { + if (isset($_is_stringy[ $template->source->type ])) { + $this->template_data[ $this->index ][ $key ][ 'name' ] = + '\'' . substr($template->source->name, 0, 25) . '...\''; + } else { + $this->template_data[ $this->index ][ $key ][ 'name' ] = $template->source->filepath; + } + $this->template_data[ $this->index ][ $key ][ 'compile_time' ] = 0; + $this->template_data[ $this->index ][ $key ][ 'render_time' ] = 0; + $this->template_data[ $this->index ][ $key ][ 'cache_time' ] = 0; + $this->template_data[ $this->index ][ $key ][ 'total_time' ] = 0; + return $key; + } + } + + /** + * Ignore template + * + * @param \Smarty_Internal_Template $template + */ + public function ignore(Smarty_Internal_Template $template) + { + // calculate Uid if not already done + if ($template->source->uid === '') { + $template->source->filepath; + } + $this->ignore_uid[ $template->source->uid ] = true; + } + + /** + * handle 'URL' debugging mode + * + * @param Smarty $smarty + */ + public function debugUrl(Smarty $smarty) + { + if (isset($_SERVER[ 'QUERY_STRING' ])) { + $_query_string = $_SERVER[ 'QUERY_STRING' ]; + } else { + $_query_string = ''; + } + if (false !== strpos($_query_string, $smarty->smarty_debug_id)) { + if (false !== strpos($_query_string, $smarty->smarty_debug_id . '=on')) { + // enable debugging for this browser session + setcookie('SMARTY_DEBUG', true); + $smarty->debugging = true; + } elseif (false !== strpos($_query_string, $smarty->smarty_debug_id . '=off')) { + // disable debugging for this browser session + setcookie('SMARTY_DEBUG', false); + $smarty->debugging = false; + } else { + // enable debugging for this page + $smarty->debugging = true; + } + } else { + if (isset($_COOKIE[ 'SMARTY_DEBUG' ])) { + $smarty->debugging = true; + } + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php new file mode 100644 index 000000000..0ba00659d --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php @@ -0,0 +1,113 @@ + $smarty_dir, 'length' => strlen($smarty_dir),); + } + } + // walk the muted directories and test against $errfile + foreach (self::$mutedDirectories as $key => &$dir) { + if (!$dir) { + // resolve directory and length for speedy comparisons + $file = realpath($key); + if ($file === false) { + // this directory does not exist, remove and skip it + unset(self::$mutedDirectories[ $key ]); + continue; + } + $dir = array('file' => $file, 'length' => strlen($file),); + } + if (!strncmp($errfile, $dir[ 'file' ], $dir[ 'length' ])) { + $_is_muted_directory = true; + break; + } + } + // pass to next error handler if this error did not occur inside SMARTY_DIR + // or the error was within smarty but masked to be ignored + if (!$_is_muted_directory || ($errno && $errno & error_reporting())) { + if (self::$previousErrorHandler) { + return call_user_func( + self::$previousErrorHandler, + $errno, + $errstr, + $errfile, + $errline, + $errcontext + ); + } else { + return false; + } + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_extension_handler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_extension_handler.php new file mode 100644 index 000000000..b07615526 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_extension_handler.php @@ -0,0 +1,197 @@ + 0, 'DefaultModifiers' => 0, 'ConfigVars' => 0, + 'DebugTemplate' => 0, 'RegisteredObject' => 0, 'StreamVariable' => 0, + 'TemplateVars' => 0, 'Literals' => 'Literals', + );// + + private $resolvedProperties = array(); + + /** + * Call external Method + * + * @param \Smarty_Internal_Data $data + * @param string $name external method names + * @param array $args argument array + * + * @return mixed + */ + public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args) + { + /* @var Smarty $data ->smarty */ + $smarty = isset($data->smarty) ? $data->smarty : $data; + if (!isset($smarty->ext->$name)) { + if (preg_match('/^((set|get)|(.*?))([A-Z].*)$/', $name, $match)) { + $basename = $this->upperCase($match[ 4 ]); + if (!isset($smarty->ext->$basename) && isset($this->_property_info[ $basename ]) + && is_string($this->_property_info[ $basename ]) + ) { + $class = 'Smarty_Internal_Method_' . $this->_property_info[ $basename ]; + if (class_exists($class)) { + $classObj = new $class(); + $methodes = get_class_methods($classObj); + foreach ($methodes as $method) { + $smarty->ext->$method = $classObj; + } + } + } + if (!empty($match[ 2 ]) && !isset($smarty->ext->$name)) { + $class = 'Smarty_Internal_Method_' . $this->upperCase($name); + if (!class_exists($class)) { + $objType = $data->_objType; + $propertyType = false; + if (!isset($this->resolvedProperties[ $match[ 0 ] ][ $objType ])) { + $property = isset($this->resolvedProperties[ 'property' ][ $basename ]) ? + $this->resolvedProperties[ 'property' ][ $basename ] : + $property = $this->resolvedProperties[ 'property' ][ $basename ] = strtolower( + join( + '_', + preg_split( + '/([A-Z][^A-Z]*)/', + $basename, + -1, + PREG_SPLIT_NO_EMPTY | + PREG_SPLIT_DELIM_CAPTURE + ) + ) + ); + if ($property !== false) { + if (property_exists($data, $property)) { + $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ] = 1; + } elseif (property_exists($smarty, $property)) { + $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ] = 2; + } else { + $this->resolvedProperties[ 'property' ][ $basename ] = $property = false; + } + } + } else { + $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ]; + $property = $this->resolvedProperties[ 'property' ][ $basename ]; + } + if ($propertyType) { + $obj = $propertyType === 1 ? $data : $smarty; + if ($match[ 2 ] === 'get') { + return $obj->$property; + } elseif ($match[ 2 ] === 'set') { + return $obj->$property = $args[ 0 ]; + } + } + } + } + } + } + $callback = array($smarty->ext->$name, $name); + array_unshift($args, $data); + if (isset($callback) && $callback[ 0 ]->objMap | $data->_objType) { + return call_user_func_array($callback, $args); + } + return call_user_func_array(array(new Smarty_Internal_Undefined(), $name), $args); + } + + /** + * Make first character of name parts upper case + * + * @param string $name + * + * @return string + */ + public function upperCase($name) + { + $_name = explode('_', $name); + $_name = array_map('ucfirst', $_name); + return implode('_', $_name); + } + + /** + * get extension object + * + * @param string $property_name property name + * + * @return mixed|Smarty_Template_Cached + */ + public function __get($property_name) + { + // object properties of runtime template extensions will start with '_' + if ($property_name[ 0 ] === '_') { + $class = 'Smarty_Internal_Runtime' . $this->upperCase($property_name); + } else { + $class = 'Smarty_Internal_Method_' . $this->upperCase($property_name); + } + if (!class_exists($class)) { + return $this->$property_name = new Smarty_Internal_Undefined($class); + } + return $this->$property_name = new $class(); + } + + /** + * set extension property + * + * @param string $property_name property name + * @param mixed $value value + * + */ + public function __set($property_name, $value) + { + $this->$property_name = $value; + } + + /** + * Call error handler for undefined method + * + * @param string $name unknown method-name + * @param array $args argument array + * + * @return mixed + */ + public function __call($name, $args) + { + return call_user_func_array(array(new Smarty_Internal_Undefined(), $name), array($this)); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_filter.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_filter.php deleted file mode 100644 index 90214ad42..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_filter.php +++ /dev/null @@ -1,89 +0,0 @@ -smarty = $smarty; - } - /** - * Registers a filter function - * - * @param string $type filter type - * @param callback $callback - */ - public function registerFilter($type, $callback) - { - $this->smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback; - } - - /** - * Unregisters a filter function - * - * @param string $type filter type - * @param callback $callback - */ - public function unregisterFilter($type, $callback) - { - $name = $this->_get_filter_name($callback); - if(isset($this->smarty->registered_filters[$type][$name])) { - unset($this->smarty->registered_filters[$type][$name]); - } - } - - - /** - * Return internal filter name - * - * @param callback $function_name - */ - public function _get_filter_name($function_name) - { - if (is_array($function_name)) { - $_class_name = (is_object($function_name[0]) ? - get_class($function_name[0]) : $function_name[0]); - return $_class_name . '_' . $function_name[1]; - } else { - return $function_name; - } - } - - - /** - * load a filter of specified type and name - * - * @param string $type filter type - * @param string $name filter name - * @return bool - */ - function loadFilter($type, $name) - { - $_plugin = "smarty_{$type}filter_{$name}"; - $_filter_name = $_plugin; - if ($this->smarty->loadPlugin($_plugin)) { - if (class_exists($_plugin, false)) { - $_plugin = array($_plugin, 'execute'); - } - if (is_callable($_plugin)) { - return $this->smarty->registered_filters[$type][$_filter_name] = $_plugin; - } - } - throw new SmartyException("{$type}filter \"{$name}\" not callable"); - return false; - } - - -} -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_filter_handler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_filter_handler.php deleted file mode 100644 index fbd884602..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_filter_handler.php +++ /dev/null @@ -1,67 +0,0 @@ -smarty->variable_filter && $flag !== false) || $flag === true) { - // loop over autoload filters of specified type - if (!empty($template->smarty->autoload_filters[$type])) { - foreach ((array)$template->smarty->autoload_filters[$type] as $name) { - $plugin_name = "Smarty_{$type}filter_{$name}"; - if ($template->smarty->loadPlugin($plugin_name)) { - if (function_exists($plugin_name)) { - // use loaded Smarty2 style plugin - $output = $plugin_name($output, $template); - } elseif (class_exists($plugin_name, false)) { - // loaded class of filter plugin - $output = call_user_func(array($plugin_name, 'execute'), $output, $template); - } - } else { - // nothing found, throw exception - throw new SmartyException("Unable to load filter {$plugin_name}"); - } - } - } - // loop over registerd filters of specified type - if (!empty($template->smarty->registered_filters[$type])) { - foreach ($template->smarty->registered_filters[$type] as $key => $name) { - if (is_array($template->smarty->registered_filters[$type][$key])) { - $output = call_user_func($template->smarty->registered_filters[$type][$key], $output, $template); - } else { - $output = $template->smarty->registered_filters[$type][$key]($output, $template); - } - } - } - } - // return filtered output - return $output; - } -} - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_function_call_handler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_function_call_handler.php deleted file mode 100644 index f9860dce3..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_function_call_handler.php +++ /dev/null @@ -1,40 +0,0 @@ -smarty->template_functions[$_name]['called_nocache'] = true; - } else { - $_function = "smarty_template_function_{$_hash}_{$_name}"; - } - if (!is_callable($_function)) { - $_code = "function {$_function}(\$_smarty_tpl,\$params) { - \$saved_tpl_vars = \$_smarty_tpl->tpl_vars; - foreach (\$_smarty_tpl->template_functions['{$_name}']['parameter'] as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(trim(\$value,'\''));}; - foreach (\$params as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);}?>"; - if ($_nocache) { - $_code .= preg_replace(array("!<\?php echo \\'/\*%%SmartyNocache:{$_template->smarty->template_functions[$_name]['nocache_hash']}%%\*/|/\*/%%SmartyNocache:{$_template->smarty->template_functions[$_name]['nocache_hash']}%%\*/\\';\?>!", - "!\\\'!"), array('', "'"), $_template->smarty->template_functions[$_name]['compiled']); - } else { - $_code .= preg_replace("/{$_template->smarty->template_functions[$_name]['nocache_hash']}/", $_template->properties['nocache_hash'], $_template->smarty->template_functions[$_name]['compiled']); - } - $_code .= "tpl_vars = \$saved_tpl_vars;}"; - eval($_code); - } - $_function($_template, $_params); - } -} - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_get_include_path.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_get_include_path.php deleted file mode 100644 index 23c85a2c3..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_get_include_path.php +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_addautoloadfilters.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_addautoloadfilters.php new file mode 100644 index 000000000..a05f55a82 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_addautoloadfilters.php @@ -0,0 +1,53 @@ +_getSmartyObj(); + if ($type !== null) { + $this->_checkFilterType($type); + if (!empty($smarty->autoload_filters[ $type ])) { + $smarty->autoload_filters[ $type ] = array_merge($smarty->autoload_filters[ $type ], (array)$filters); + } else { + $smarty->autoload_filters[ $type ] = (array)$filters; + } + } else { + foreach ((array)$filters as $type => $value) { + $this->_checkFilterType($type); + if (!empty($smarty->autoload_filters[ $type ])) { + $smarty->autoload_filters[ $type ] = + array_merge($smarty->autoload_filters[ $type ], (array)$value); + } else { + $smarty->autoload_filters[ $type ] = (array)$value; + } + } + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_adddefaultmodifiers.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_adddefaultmodifiers.php new file mode 100644 index 000000000..c3feb3d8b --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_adddefaultmodifiers.php @@ -0,0 +1,42 @@ +_getSmartyObj(); + if (is_array($modifiers)) { + $smarty->default_modifiers = array_merge($smarty->default_modifiers, $modifiers); + } else { + $smarty->default_modifiers[] = $modifiers; + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_append.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_append.php new file mode 100644 index 000000000..881375efe --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_append.php @@ -0,0 +1,74 @@ + $_val) { + if ($_key !== '') { + $this->append($data, $_key, $_val, $merge, $nocache); + } + } + } else { + if ($tpl_var !== '' && isset($value)) { + if (!isset($data->tpl_vars[ $tpl_var ])) { + $tpl_var_inst = $data->ext->getTemplateVars->_getVariable($data, $tpl_var, null, true, false); + if ($tpl_var_inst instanceof Smarty_Undefined_Variable) { + $data->tpl_vars[ $tpl_var ] = new Smarty_Variable(null, $nocache); + } else { + $data->tpl_vars[ $tpl_var ] = clone $tpl_var_inst; + } + } + if (!(is_array($data->tpl_vars[ $tpl_var ]->value) + || $data->tpl_vars[ $tpl_var ]->value instanceof ArrayAccess) + ) { + settype($data->tpl_vars[ $tpl_var ]->value, 'array'); + } + if ($merge && is_array($value)) { + foreach ($value as $_mkey => $_mval) { + $data->tpl_vars[ $tpl_var ]->value[ $_mkey ] = $_mval; + } + } else { + $data->tpl_vars[ $tpl_var ]->value[] = $value; + } + } + if ($data->_isTplObj() && $data->scope) { + $data->ext->_updateScope->_updateScope($data, $tpl_var); + } + } + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_appendbyref.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_appendbyref.php new file mode 100644 index 000000000..c95904460 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_appendbyref.php @@ -0,0 +1,49 @@ +tpl_vars[ $tpl_var ])) { + $data->tpl_vars[ $tpl_var ] = new Smarty_Variable(); + } + if (!is_array($data->tpl_vars[ $tpl_var ]->value)) { + settype($data->tpl_vars[ $tpl_var ]->value, 'array'); + } + if ($merge && is_array($value)) { + foreach ($value as $_key => $_val) { + $data->tpl_vars[ $tpl_var ]->value[ $_key ] = &$value[ $_key ]; + } + } else { + $data->tpl_vars[ $tpl_var ]->value[] = &$value; + } + if ($data->_isTplObj() && $data->scope) { + $data->ext->_updateScope->_updateScope($data, $tpl_var); + } + } + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_assignbyref.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_assignbyref.php new file mode 100644 index 000000000..fa705bb80 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_assignbyref.php @@ -0,0 +1,36 @@ +tpl_vars[ $tpl_var ] = new Smarty_Variable(null, $nocache); + $data->tpl_vars[ $tpl_var ]->value = &$value; + if ($data->_isTplObj() && $data->scope) { + $data->ext->_updateScope->_updateScope($data, $tpl_var); + } + } + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_assignglobal.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_assignglobal.php new file mode 100644 index 000000000..08cfa4693 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_assignglobal.php @@ -0,0 +1,44 @@ +_isTplObj()) { + $ptr->tpl_vars[ $varName ] = clone Smarty::$global_tpl_vars[ $varName ]; + $ptr = $ptr->parent; + } + } + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearallassign.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearallassign.php new file mode 100644 index 000000000..29ff2ffb0 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearallassign.php @@ -0,0 +1,36 @@ +tpl_vars = array(); + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearallcache.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearallcache.php new file mode 100644 index 000000000..30d55f7d2 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearallcache.php @@ -0,0 +1,41 @@ +_clearTemplateCache(); + // load cache resource and call clearAll + $_cache_resource = Smarty_CacheResource::load($smarty, $type); + return $_cache_resource->clearAll($smarty, $exp_time); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearassign.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearassign.php new file mode 100644 index 000000000..22bfa2d31 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearassign.php @@ -0,0 +1,43 @@ +tpl_vars[ $curr_var ]); + } + } else { + unset($data->tpl_vars[ $tpl_var ]); + } + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearcache.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearcache.php new file mode 100644 index 000000000..a5dd4e26e --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearcache.php @@ -0,0 +1,50 @@ +_clearTemplateCache(); + // load cache resource and call clear + $_cache_resource = Smarty_CacheResource::load($smarty, $type); + return $_cache_resource->clear($smarty, $template_name, $cache_id, $compile_id, $exp_time); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearcompiledtemplate.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearcompiledtemplate.php new file mode 100644 index 000000000..bf4929807 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearcompiledtemplate.php @@ -0,0 +1,131 @@ +_clearTemplateCache(); + $_compile_dir = $smarty->getCompileDir(); + if ($_compile_dir === '/') { //We should never want to delete this! + return 0; + } + $_compile_id = isset($compile_id) ? preg_replace('![^\w]+!', '_', $compile_id) : null; + $_dir_sep = $smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + if (isset($resource_name)) { + $_save_stat = $smarty->caching; + $smarty->caching = Smarty::CACHING_OFF; + /* @var Smarty_Internal_Template $tpl */ + $tpl = $smarty->createTemplate($resource_name); + $smarty->caching = $_save_stat; + if (!$tpl->source->handler->uncompiled && !$tpl->source->handler->recompiled && $tpl->source->exists) { + $_resource_part_1 = basename(str_replace('^', DIRECTORY_SEPARATOR, $tpl->compiled->filepath)); + $_resource_part_1_length = strlen($_resource_part_1); + } else { + return 0; + } + $_resource_part_2 = str_replace('.php', '.cache.php', $_resource_part_1); + $_resource_part_2_length = strlen($_resource_part_2); + } + $_dir = $_compile_dir; + if ($smarty->use_sub_dirs && isset($_compile_id)) { + $_dir .= $_compile_id . $_dir_sep; + } + if (isset($_compile_id)) { + $_compile_id_part = $_compile_dir . $_compile_id . $_dir_sep; + $_compile_id_part_length = strlen($_compile_id_part); + } + $_count = 0; + try { + $_compileDirs = new RecursiveDirectoryIterator($_dir); + // NOTE: UnexpectedValueException thrown for PHP >= 5.3 + } catch (Exception $e) { + return 0; + } + $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($_compile as $_file) { + if (substr(basename($_file->getPathname()), 0, 1) === '.') { + continue; + } + $_filepath = (string)$_file; + if ($_file->isDir()) { + if (!$_compile->isDot()) { + // delete folder if empty + @rmdir($_file->getPathname()); + } + } else { + // delete only php files + if (substr($_filepath, -4) !== '.php') { + continue; + } + $unlink = false; + if ((!isset($_compile_id) || + (isset($_filepath[ $_compile_id_part_length ]) && + $a = !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length))) + && (!isset($resource_name) || (isset($_filepath[ $_resource_part_1_length ]) + && substr_compare( + $_filepath, + $_resource_part_1, + -$_resource_part_1_length, + $_resource_part_1_length + ) === 0) || (isset($_filepath[ $_resource_part_2_length ]) + && substr_compare( + $_filepath, + $_resource_part_2, + -$_resource_part_2_length, + $_resource_part_2_length + ) === 0)) + ) { + if (isset($exp_time)) { + if (is_file($_filepath) && time() - filemtime($_filepath) >= $exp_time) { + $unlink = true; + } + } else { + $unlink = true; + } + } + if ($unlink && is_file($_filepath) && @unlink($_filepath)) { + $_count++; + if (function_exists('opcache_invalidate') + && (!function_exists('ini_get') || strlen(ini_get('opcache.restrict_api')) < 1) + ) { + opcache_invalidate($_filepath, true); + } elseif (function_exists('apc_delete_file')) { + apc_delete_file($_filepath); + } + } + } + } + return $_count; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearconfig.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearconfig.php new file mode 100644 index 000000000..15bf492a1 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_clearconfig.php @@ -0,0 +1,41 @@ +config_vars[ $name ]); + } else { + $data->config_vars = array(); + } + return $data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_compileallconfig.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_compileallconfig.php new file mode 100644 index 000000000..3934ca042 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_compileallconfig.php @@ -0,0 +1,36 @@ +compileAll($smarty, $extension, $force_compile, $time_limit, $max_errors, true); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_compilealltemplates.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_compilealltemplates.php new file mode 100644 index 000000000..5c046da40 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_compilealltemplates.php @@ -0,0 +1,130 @@ +compileAll($smarty, $extension, $force_compile, $time_limit, $max_errors); + } + + /** + * Compile all template or config files + * + * @param \Smarty $smarty + * @param string $extension template file name extension + * @param bool $force_compile force all to recompile + * @param int $time_limit set maximum execution time + * @param int $max_errors set maximum allowed errors + * @param bool $isConfig flag true if called for config files + * + * @return int number of template files compiled + */ + protected function compileAll( + Smarty $smarty, + $extension, + $force_compile, + $time_limit, + $max_errors, + $isConfig = false + ) { + // switch off time limit + if (function_exists('set_time_limit')) { + @set_time_limit($time_limit); + } + $_count = 0; + $_error_count = 0; + $sourceDir = $isConfig ? $smarty->getConfigDir() : $smarty->getTemplateDir(); + // loop over array of source directories + foreach ($sourceDir as $_dir) { + $_dir_1 = new RecursiveDirectoryIterator( + $_dir, + defined('FilesystemIterator::FOLLOW_SYMLINKS') ? + FilesystemIterator::FOLLOW_SYMLINKS : 0 + ); + $_dir_2 = new RecursiveIteratorIterator($_dir_1); + foreach ($_dir_2 as $_fileinfo) { + $_file = $_fileinfo->getFilename(); + if (substr(basename($_fileinfo->getPathname()), 0, 1) === '.' || strpos($_file, '.svn') !== false) { + continue; + } + if (substr_compare($_file, $extension, -strlen($extension)) !== 0) { + continue; + } + if ($_fileinfo->getPath() !== substr($_dir, 0, -1)) { + $_file = substr($_fileinfo->getPath(), strlen($_dir)) . DIRECTORY_SEPARATOR . $_file; + } + echo "\n
", $_dir, '---', $_file; + flush(); + $_start_time = microtime(true); + $_smarty = clone $smarty; + // + $_smarty->_cache = array(); + $_smarty->ext = new Smarty_Internal_Extension_Handler(); + $_smarty->ext->objType = $_smarty->_objType; + $_smarty->force_compile = $force_compile; + try { + /* @var Smarty_Internal_Template $_tpl */ + $_tpl = new $smarty->template_class($_file, $_smarty); + $_tpl->caching = Smarty::CACHING_OFF; + $_tpl->source = + $isConfig ? Smarty_Template_Config::load($_tpl) : Smarty_Template_Source::load($_tpl); + if ($_tpl->mustCompile()) { + $_tpl->compileTemplateSource(); + $_count++; + echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; + flush(); + } else { + echo ' is up to date'; + flush(); + } + } catch (Exception $e) { + echo "\n
------>Error: ", $e->getMessage(), "

\n"; + $_error_count++; + } + // free memory + unset($_tpl); + $_smarty->_clearTemplateCache(); + if ($max_errors !== null && $_error_count === $max_errors) { + echo "\n

too many errors\n"; + exit(1); + } + } + } + echo "\n
"; + return $_count; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_configload.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_configload.php new file mode 100644 index 000000000..2e6254880 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_configload.php @@ -0,0 +1,182 @@ +_loadConfigFile($data, $config_file, $sections, null); + return $data; + } + + /** + * load a config file, optionally load just selected sections + * + * @api Smarty::configLoad() + * @link http://www.smarty.net/docs/en/api.config.load.tpl + * + * @param \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template $data + * @param string $config_file filename + * @param mixed $sections array of section names, single + * section or null + * @param int $scope scope into which config variables + * shall be loaded + * + * @throws \Exception + */ + public function _loadConfigFile(Smarty_Internal_Data $data, $config_file, $sections = null, $scope = 0) + { + /* @var \Smarty $smarty */ + $smarty = $data->_getSmartyObj(); + /* @var \Smarty_Internal_Template $confObj */ + $confObj = new Smarty_Internal_Template($config_file, $smarty, $data, null, null, null, null, true); + $confObj->caching = Smarty::CACHING_OFF; + $confObj->source->config_sections = $sections; + $confObj->source->scope = $scope; + $confObj->compiled = Smarty_Template_Compiled::load($confObj); + $confObj->compiled->render($confObj); + if ($data->_isTplObj()) { + $data->compiled->file_dependency[ $confObj->source->uid ] = + array($confObj->source->filepath, $confObj->source->getTimeStamp(), $confObj->source->type); + } + } + + /** + * load config variables into template object + * + * @param \Smarty_Internal_Template $tpl + * @param array $new_config_vars + */ + public function _loadConfigVars(Smarty_Internal_Template $tpl, $new_config_vars) + { + $this->_assignConfigVars($tpl->parent->config_vars, $tpl, $new_config_vars); + $tagScope = $tpl->source->scope; + if ($tagScope >= 0) { + if ($tagScope === Smarty::SCOPE_LOCAL) { + $this->_updateVarStack($tpl, $new_config_vars); + $tagScope = 0; + if (!$tpl->scope) { + return; + } + } + if ($tpl->parent->_isTplObj() && ($tagScope || $tpl->parent->scope)) { + $mergedScope = $tagScope | $tpl->scope; + if ($mergedScope) { + // update scopes + /* @var \Smarty_Internal_Template|\Smarty|\Smarty_Internal_Data $ptr */ + foreach ($tpl->smarty->ext->_updateScope->_getAffectedScopes($tpl->parent, $mergedScope) as $ptr) { + $this->_assignConfigVars($ptr->config_vars, $tpl, $new_config_vars); + if ($tagScope && $ptr->_isTplObj() && isset($tpl->_cache[ 'varStack' ])) { + $this->_updateVarStack($tpl, $new_config_vars); + } + } + } + } + } + } + + /** + * Assign all config variables in given scope + * + * @param array $config_vars config variables in scope + * @param \Smarty_Internal_Template $tpl + * @param array $new_config_vars loaded config variables + */ + public function _assignConfigVars(&$config_vars, Smarty_Internal_Template $tpl, $new_config_vars) + { + // copy global config vars + foreach ($new_config_vars[ 'vars' ] as $variable => $value) { + if ($tpl->smarty->config_overwrite || !isset($config_vars[ $variable ])) { + $config_vars[ $variable ] = $value; + } else { + $config_vars[ $variable ] = array_merge((array)$config_vars[ $variable ], (array)$value); + } + } + // scan sections + $sections = $tpl->source->config_sections; + if (!empty($sections)) { + foreach ((array)$sections as $tpl_section) { + if (isset($new_config_vars[ 'sections' ][ $tpl_section ])) { + foreach ($new_config_vars[ 'sections' ][ $tpl_section ][ 'vars' ] as $variable => $value) { + if ($tpl->smarty->config_overwrite || !isset($config_vars[ $variable ])) { + $config_vars[ $variable ] = $value; + } else { + $config_vars[ $variable ] = array_merge((array)$config_vars[ $variable ], (array)$value); + } + } + } + } + } + } + + /** + * Update config variables in template local variable stack + * + * @param \Smarty_Internal_Template $tpl + * @param array $config_vars + */ + public function _updateVarStack(Smarty_Internal_Template $tpl, $config_vars) + { + $i = 0; + while (isset($tpl->_cache[ 'varStack' ][ $i ])) { + $this->_assignConfigVars($tpl->_cache[ 'varStack' ][ $i ][ 'config' ], $tpl, $config_vars); + $i++; + } + } + + /** + * gets a config variable value + * + * @param \Smarty|\Smarty_Internal_Data|\Smarty_Internal_Template $data + * @param string $varName the name of the config variable + * @param bool $errorEnable + * + * @return null|string the value of the config variable + */ + public function _getConfigVariable(Smarty_Internal_Data $data, $varName, $errorEnable = true) + { + $_ptr = $data; + while ($_ptr !== null) { + if (isset($_ptr->config_vars[ $varName ])) { + // found it, return it + return $_ptr->config_vars[ $varName ]; + } + // not found, try at parent + $_ptr = $_ptr->parent; + } + if ($data->smarty->error_unassigned && $errorEnable) { + // force a notice + $x = $$varName; + } + return null; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_createdata.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_createdata.php new file mode 100644 index 000000000..f95097519 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_createdata.php @@ -0,0 +1,44 @@ +_getSmartyObj(); + $dataObj = new Smarty_Data($parent, $smarty, $name); + if ($smarty->debugging) { + Smarty_Internal_Debug::register_data($dataObj); + } + return $dataObj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getautoloadfilters.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getautoloadfilters.php new file mode 100644 index 000000000..4145db10b --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getautoloadfilters.php @@ -0,0 +1,37 @@ + array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type + * was specified + * @throws \SmartyException + */ + public function getAutoloadFilters(Smarty_Internal_TemplateBase $obj, $type = null) + { + $smarty = $obj->_getSmartyObj(); + if ($type !== null) { + $this->_checkFilterType($type); + return isset($smarty->autoload_filters[ $type ]) ? $smarty->autoload_filters[ $type ] : array(); + } + return $smarty->autoload_filters; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getconfigvariable.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getconfigvariable.php new file mode 100644 index 000000000..b54815123 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getconfigvariable.php @@ -0,0 +1,34 @@ +ext->configLoad->_getConfigVariable($data, $varName, $errorEnable); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getconfigvars.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getconfigvars.php new file mode 100644 index 000000000..1d11e44c1 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getconfigvars.php @@ -0,0 +1,58 @@ +config_vars[ $varname ])) { + return $_ptr->config_vars[ $varname ]; + } + } else { + $var_array = array_merge($_ptr->config_vars, $var_array); + } + // not found, try at parent + if ($search_parents) { + $_ptr = $_ptr->parent; + } else { + $_ptr = null; + } + } + if (isset($varname)) { + return ''; + } else { + return $var_array; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getdebugtemplate.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getdebugtemplate.php new file mode 100644 index 000000000..77d908c15 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getdebugtemplate.php @@ -0,0 +1,35 @@ +_getSmartyObj(); + return $smarty->debug_tpl; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getdefaultmodifiers.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getdefaultmodifiers.php new file mode 100644 index 000000000..57da85c49 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getdefaultmodifiers.php @@ -0,0 +1,35 @@ +_getSmartyObj(); + return $smarty->default_modifiers; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getglobal.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getglobal.php new file mode 100644 index 000000000..2be11d7e8 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getglobal.php @@ -0,0 +1,47 @@ +value; + } else { + return ''; + } + } else { + $_result = array(); + foreach (Smarty::$global_tpl_vars as $key => $var) { + $_result[ $key ] = $var->value; + } + return $_result; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getregisteredobject.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getregisteredobject.php new file mode 100644 index 000000000..df6ede130 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getregisteredobject.php @@ -0,0 +1,44 @@ +_getSmartyObj(); + if (!isset($smarty->registered_objects[ $object_name ])) { + throw new SmartyException("'$object_name' is not a registered object"); + } + if (!is_object($smarty->registered_objects[ $object_name ][ 0 ])) { + throw new SmartyException("registered '$object_name' is not an object"); + } + return $smarty->registered_objects[ $object_name ][ 0 ]; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getstreamvariable.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getstreamvariable.php new file mode 100644 index 000000000..8db39c525 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_getstreamvariable.php @@ -0,0 +1,50 @@ +smarty) ? $data->smarty : $data; + if ($smarty->error_unassigned) { + throw new SmartyException('Undefined stream variable "' . $variable . '"'); + } else { + return null; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_gettags.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_gettags.php new file mode 100644 index 000000000..c07ae07ec --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_gettags.php @@ -0,0 +1,63 @@ +_getSmartyObj(); + if ($obj->_isTplObj() && !isset($template)) { + $tpl = clone $obj; + } elseif (isset($template) && $template->_isTplObj()) { + $tpl = clone $template; + } elseif (isset($template) && is_string($template)) { + /* @var Smarty_Internal_Template $tpl */ + $tpl = new $smarty->template_class($template, $smarty); + // checks if template exists + if (!$tpl->source->exists) { + throw new SmartyException("Unable to load template {$tpl->source->type} '{$tpl->source->name}'"); + } + } + if (isset($tpl)) { + $tpl->smarty = clone $tpl->smarty; + $tpl->smarty->_cache[ 'get_used_tags' ] = true; + $tpl->_cache[ 'used_tags' ] = array(); + $tpl->smarty->merge_compiled_includes = false; + $tpl->smarty->disableSecurity(); + $tpl->caching = Smarty::CACHING_OFF; + $tpl->loadCompiler(); + $tpl->compiler->compileTemplate($tpl); + return $tpl->_cache[ 'used_tags' ]; + } + throw new SmartyException('Missing template specification'); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_gettemplatevars.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_gettemplatevars.php new file mode 100644 index 000000000..9ef7d46bb --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_gettemplatevars.php @@ -0,0 +1,119 @@ +_getVariable($data, $varName, $_ptr, $searchParents, false); + if (is_object($_var)) { + return $_var->value; + } else { + return null; + } + } else { + $_result = array(); + if ($_ptr === null) { + $_ptr = $data; + } + while ($_ptr !== null) { + foreach ($_ptr->tpl_vars as $key => $var) { + if (!array_key_exists($key, $_result)) { + $_result[ $key ] = $var->value; + } + } + // not found, try at parent + if ($searchParents && isset($_ptr->parent)) { + $_ptr = $_ptr->parent; + } else { + $_ptr = null; + } + } + if ($searchParents && isset(Smarty::$global_tpl_vars)) { + foreach (Smarty::$global_tpl_vars as $key => $var) { + if (!array_key_exists($key, $_result)) { + $_result[ $key ] = $var->value; + } + } + } + return $_result; + } + } + + /** + * gets the object of a Smarty variable + * + * @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $data + * @param string $varName the name of the Smarty variable + * @param \Smarty_Internal_Data|\Smarty_Internal_Template|\Smarty $_ptr optional pointer to data object + * @param bool $searchParents search also in parent data + * @param bool $errorEnable + * + * @return \Smarty_Variable + */ + public function _getVariable( + Smarty_Internal_Data $data, + $varName, + Smarty_Internal_Data $_ptr = null, + $searchParents = true, + $errorEnable = true + ) { + if ($_ptr === null) { + $_ptr = $data; + } + while ($_ptr !== null) { + if (isset($_ptr->tpl_vars[ $varName ])) { + // found it, return it + return $_ptr->tpl_vars[ $varName ]; + } + // not found, try at parent + if ($searchParents && isset($_ptr->parent)) { + $_ptr = $_ptr->parent; + } else { + $_ptr = null; + } + } + if (isset(Smarty::$global_tpl_vars[ $varName ])) { + // found it, return it + return Smarty::$global_tpl_vars[ $varName ]; + } + if ($errorEnable && $data->_getSmartyObj()->error_unassigned) { + // force a notice + $x = $$varName; + } + return new Smarty_Undefined_Variable; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_literals.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_literals.php new file mode 100644 index 000000000..bfa3f58ec --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_literals.php @@ -0,0 +1,100 @@ +_getSmartyObj(); + return (array)$smarty->literals; + } + + /** + * Add literals + * + * @api Smarty::addLiterals() + * + * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj + * @param array|string $literals literal or list of literals + * to addto add + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function addLiterals(Smarty_Internal_TemplateBase $obj, $literals = null) + { + if (isset($literals)) { + $this->set($obj->_getSmartyObj(), (array)$literals); + } + return $obj; + } + + /** + * Set literals + * + * @api Smarty::setLiterals() + * + * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj + * @param array|string $literals literal or list of literals + * to setto set + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function setLiterals(Smarty_Internal_TemplateBase $obj, $literals = null) + { + $smarty = $obj->_getSmartyObj(); + $smarty->literals = array(); + if (!empty($literals)) { + $this->set($smarty, (array)$literals); + } + return $obj; + } + + /** + * common setter for literals for easier handling of duplicates the + * Smarty::$literals array gets filled with identical key values + * + * @param \Smarty $smarty + * @param array $literals + * + * @throws \SmartyException + */ + private function set(Smarty $smarty, $literals) + { + $literals = array_combine($literals, $literals); + $error = isset($literals[ $smarty->left_delimiter ]) ? array($smarty->left_delimiter) : array(); + $error = isset($literals[ $smarty->right_delimiter ]) ? $error[] = $smarty->right_delimiter : $error; + if (!empty($error)) { + throw new SmartyException( + 'User defined literal(s) "' . $error . + '" may not be identical with left or right delimiter' + ); + } + $smarty->literals = array_merge((array)$smarty->literals, (array)$literals); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_loadfilter.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_loadfilter.php new file mode 100644 index 000000000..66d80d474 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_loadfilter.php @@ -0,0 +1,77 @@ + true, 'post' => true, 'output' => true, 'variable' => true); + + /** + * load a filter of specified type and name + * + * @api Smarty::loadFilter() + * + * @link http://www.smarty.net/docs/en/api.load.filter.tpl + * + * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj + * @param string $type filter type + * @param string $name filter name + * + * @return bool + * @throws SmartyException if filter could not be loaded + */ + public function loadFilter(Smarty_Internal_TemplateBase $obj, $type, $name) + { + $smarty = $obj->_getSmartyObj(); + $this->_checkFilterType($type); + $_plugin = "smarty_{$type}filter_{$name}"; + $_filter_name = $_plugin; + if (is_callable($_plugin)) { + $smarty->registered_filters[ $type ][ $_filter_name ] = $_plugin; + return true; + } + if ($smarty->loadPlugin($_plugin)) { + if (class_exists($_plugin, false)) { + $_plugin = array($_plugin, 'execute'); + } + if (is_callable($_plugin)) { + $smarty->registered_filters[ $type ][ $_filter_name ] = $_plugin; + return true; + } + } + throw new SmartyException("{$type}filter '{$name}' not found or callable"); + } + + /** + * Check if filter type is valid + * + * @param string $type + * + * @throws \SmartyException + */ + public function _checkFilterType($type) + { + if (!isset($this->filterTypes[ $type ])) { + throw new SmartyException("Illegal filter type '{$type}'"); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_loadplugin.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_loadplugin.php new file mode 100644 index 000000000..3bd659cb8 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_loadplugin.php @@ -0,0 +1,111 @@ +loadPlugin() method + * + * @package Smarty + * @subpackage PluginsInternal + * @author Uwe Tews + */ +class Smarty_Internal_Method_LoadPlugin +{ + /** + * Cache of searched plugin files + * + * @var array + */ + public $plugin_files = array(); + + /** + * Takes unknown classes and loads plugin files for them + * class name format: Smarty_PluginType_PluginName + * plugin filename format: plugintype.pluginname.php + * + * @param \Smarty $smarty + * @param string $plugin_name class plugin name to load + * @param bool $check check if already loaded + * + * @return bool|string + * @throws \SmartyException + */ + public function loadPlugin(Smarty $smarty, $plugin_name, $check) + { + // if function or class exists, exit silently (already loaded) + if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) { + return true; + } + if (!preg_match('#^smarty_((internal)|([^_]+))_(.+)$#i', $plugin_name, $match)) { + throw new SmartyException("plugin {$plugin_name} is not a valid name format"); + } + if (!empty($match[ 2 ])) { + $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; + if (isset($this->plugin_files[ $file ])) { + if ($this->plugin_files[ $file ] !== false) { + return $this->plugin_files[ $file ]; + } else { + return false; + } + } else { + if (is_file($file)) { + $this->plugin_files[ $file ] = $file; + include_once $file; + return $file; + } else { + $this->plugin_files[ $file ] = false; + return false; + } + } + } + // plugin filename is expected to be: [type].[name].php + $_plugin_filename = "{$match[1]}.{$match[4]}.php"; + $_lower_filename = strtolower($_plugin_filename); + if (isset($this->plugin_files)) { + if (isset($this->plugin_files[ 'plugins_dir' ][ $_lower_filename ])) { + if (!$smarty->use_include_path || $this->plugin_files[ 'plugins_dir' ][ $_lower_filename ] !== false) { + return $this->plugin_files[ 'plugins_dir' ][ $_lower_filename ]; + } + } + if (!$smarty->use_include_path || $smarty->ext->_getIncludePath->isNewIncludePath($smarty)) { + unset($this->plugin_files[ 'include_path' ]); + } else { + if (isset($this->plugin_files[ 'include_path' ][ $_lower_filename ])) { + return $this->plugin_files[ 'include_path' ][ $_lower_filename ]; + } + } + } + $_file_names = array($_plugin_filename); + if ($_lower_filename !== $_plugin_filename) { + $_file_names[] = $_lower_filename; + } + $_p_dirs = $smarty->getPluginsDir(); + if (!isset($this->plugin_files[ 'plugins_dir' ][ $_lower_filename ])) { + // loop through plugin dirs and find the plugin + foreach ($_p_dirs as $_plugin_dir) { + foreach ($_file_names as $name) { + $file = $_plugin_dir . $name; + if (is_file($file)) { + $this->plugin_files[ 'plugins_dir' ][ $_lower_filename ] = $file; + include_once $file; + return $file; + } + $this->plugin_files[ 'plugins_dir' ][ $_lower_filename ] = false; + } + } + } + if ($smarty->use_include_path) { + foreach ($_file_names as $_file_name) { + // try PHP include_path + $file = $smarty->ext->_getIncludePath->getIncludePath($_p_dirs, $_file_name, $smarty); + $this->plugin_files[ 'include_path' ][ $_lower_filename ] = $file; + if ($file !== false) { + include_once $file; + return $file; + } + } + } + // no plugin loaded + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_mustcompile.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_mustcompile.php new file mode 100644 index 000000000..39318838e --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_mustcompile.php @@ -0,0 +1,50 @@ +source->exists) { + if ($_template->_isSubTpl()) { + $parent_resource = " in '$_template->parent->template_resource}'"; + } else { + $parent_resource = ''; + } + throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}"); + } + if ($_template->mustCompile === null) { + $_template->mustCompile = (!$_template->source->handler->uncompiled && + ($_template->smarty->force_compile || $_template->source->handler->recompiled || + !$_template->compiled->exists || ($_template->compile_check && + $_template->compiled->getTimeStamp() < + $_template->source->getTimeStamp()))); + } + return $_template->mustCompile; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registercacheresource.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registercacheresource.php new file mode 100644 index 000000000..648365619 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registercacheresource.php @@ -0,0 +1,42 @@ +_getSmartyObj(); + $smarty->registered_cache_resources[ $name ] = $resource_handler; + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerclass.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerclass.php new file mode 100644 index 000000000..8d18547e2 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerclass.php @@ -0,0 +1,46 @@ +_getSmartyObj(); + // test if exists + if (!class_exists($class_impl)) { + throw new SmartyException("Undefined class '$class_impl' in register template class"); + } + // register the class + $smarty->registered_classes[ $class_name ] = $class_impl; + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaultconfighandler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaultconfighandler.php new file mode 100644 index 000000000..b340f178d --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaultconfighandler.php @@ -0,0 +1,42 @@ +_getSmartyObj(); + if (is_callable($callback)) { + $smarty->default_config_handler_func = $callback; + } else { + throw new SmartyException('Default config handler not callable'); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaultpluginhandler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaultpluginhandler.php new file mode 100644 index 000000000..a9fb78dc6 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaultpluginhandler.php @@ -0,0 +1,43 @@ +_getSmartyObj(); + if (is_callable($callback)) { + $smarty->default_plugin_handler_func = $callback; + } else { + throw new SmartyException("Default plugin handler '$callback' not callable"); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaulttemplatehandler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaulttemplatehandler.php new file mode 100644 index 000000000..cbc133ccd --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerdefaulttemplatehandler.php @@ -0,0 +1,88 @@ +_getSmartyObj(); + if (is_callable($callback)) { + $smarty->default_template_handler_func = $callback; + } else { + throw new SmartyException('Default template handler not callable'); + } + return $obj; + } + + /** + * get default content from template or config resource handler + * + * @param Smarty_Template_Source $source + * + * @throws \SmartyException + */ + public static function _getDefaultTemplate(Smarty_Template_Source $source) + { + if ($source->isConfig) { + $default_handler = $source->smarty->default_config_handler_func; + } else { + $default_handler = $source->smarty->default_template_handler_func; + } + $_content = $_timestamp = null; + $_return = call_user_func_array( + $default_handler, + array($source->type, $source->name, &$_content, &$_timestamp, $source->smarty) + ); + if (is_string($_return)) { + $source->exists = is_file($_return); + if ($source->exists) { + $source->timestamp = filemtime($_return); + } else { + throw new SmartyException( + 'Default handler: Unable to load ' . + ($source->isConfig ? 'config' : 'template') . + " default file '{$_return}' for '{$source->type}:{$source->name}'" + ); + } + $source->name = $source->filepath = $_return; + $source->uid = sha1($source->filepath); + } elseif ($_return === true) { + $source->content = $_content; + $source->exists = true; + $source->uid = $source->name = sha1($_content); + $source->handler = Smarty_Resource::load($source->smarty, 'eval'); + } else { + $source->exists = false; + throw new SmartyException( + 'Default handler: No ' . ($source->isConfig ? 'config' : 'template') . + " default content for '{$source->type}:{$source->name}'" + ); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerfilter.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerfilter.php new file mode 100644 index 000000000..c0f9fff10 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerfilter.php @@ -0,0 +1,87 @@ + true, 'post' => true, 'output' => true, 'variable' => true); + + /** + * Registers a filter function + * + * @api Smarty::registerFilter() + * + * @link http://www.smarty.net/docs/en/api.register.filter.tpl + * + * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj + * @param string $type filter type + * @param callback $callback + * @param string|null $name optional filter name + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function registerFilter(Smarty_Internal_TemplateBase $obj, $type, $callback, $name = null) + { + $smarty = $obj->_getSmartyObj(); + $this->_checkFilterType($type); + $name = isset($name) ? $name : $this->_getFilterName($callback); + if (!is_callable($callback)) { + throw new SmartyException("{$type}filter '{$name}' not callable"); + } + $smarty->registered_filters[ $type ][ $name ] = $callback; + return $obj; + } + + /** + * Return internal filter name + * + * @param callback $function_name + * + * @return string internal filter name + */ + public function _getFilterName($function_name) + { + if (is_array($function_name)) { + $_class_name = (is_object($function_name[ 0 ]) ? get_class($function_name[ 0 ]) : $function_name[ 0 ]); + return $_class_name . '_' . $function_name[ 1 ]; + } elseif (is_string($function_name)) { + return $function_name; + } else { + return 'closure'; + } + } + + /** + * Check if filter type is valid + * + * @param string $type + * + * @throws \SmartyException + */ + public function _checkFilterType($type) + { + if (!isset($this->filterTypes[ $type ])) { + throw new SmartyException("Illegal filter type '{$type}'"); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerobject.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerobject.php new file mode 100644 index 000000000..4646e4f22 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerobject.php @@ -0,0 +1,84 @@ +_getSmartyObj(); + // test if allowed methods callable + if (!empty($allowed_methods_properties)) { + foreach ((array)$allowed_methods_properties as $method) { + if (!is_callable(array($object, $method)) && !property_exists($object, $method)) { + throw new SmartyException("Undefined method or property '$method' in registered object"); + } + } + } + // test if block methods callable + if (!empty($block_methods)) { + foreach ((array)$block_methods as $method) { + if (!is_callable(array($object, $method))) { + throw new SmartyException("Undefined method '$method' in registered object"); + } + } + } + // register the object + $smarty->registered_objects[ $object_name ] = + array($object, (array)$allowed_methods_properties, (boolean)$format, (array)$block_methods); + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerplugin.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerplugin.php new file mode 100644 index 000000000..ed18d84bb --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerplugin.php @@ -0,0 +1,58 @@ +_getSmartyObj(); + if (isset($smarty->registered_plugins[ $type ][ $name ])) { + throw new SmartyException("Plugin tag '{$name}' already registered"); + } elseif (!is_callable($callback)) { + throw new SmartyException("Plugin '{$name}' not callable"); + } elseif ($cacheable && $cache_attr) { + throw new SmartyException("Cannot set caching attributes for plugin '{$name}' when it is cacheable."); + } else { + $smarty->registered_plugins[ $type ][ $name ] = array($callback, (bool)$cacheable, (array)$cache_attr); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerresource.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerresource.php new file mode 100644 index 000000000..7c7d0f78a --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_registerresource.php @@ -0,0 +1,46 @@ +_getSmartyObj(); + $smarty->registered_resources[ $name ] = + $resource_handler instanceof Smarty_Resource ? $resource_handler : array($resource_handler, false); + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setautoloadfilters.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setautoloadfilters.php new file mode 100644 index 000000000..2972f3ce1 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setautoloadfilters.php @@ -0,0 +1,72 @@ + true, 'post' => true, 'output' => true, 'variable' => true); + + /** + * Set autoload filters + * + * @api Smarty::setAutoloadFilters() + * + * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj + * @param array $filters filters to load automatically + * @param string $type "pre", "output", … specify + * the filter type to set. + * Defaults to none treating + * $filters' keys as the + * appropriate types + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function setAutoloadFilters(Smarty_Internal_TemplateBase $obj, $filters, $type = null) + { + $smarty = $obj->_getSmartyObj(); + if ($type !== null) { + $this->_checkFilterType($type); + $smarty->autoload_filters[ $type ] = (array)$filters; + } else { + foreach ((array)$filters as $type => $value) { + $this->_checkFilterType($type); + } + $smarty->autoload_filters = (array)$filters; + } + return $obj; + } + + /** + * Check if filter type is valid + * + * @param string $type + * + * @throws \SmartyException + */ + public function _checkFilterType($type) + { + if (!isset($this->filterTypes[ $type ])) { + throw new SmartyException("Illegal filter type '{$type}'"); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setdebugtemplate.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setdebugtemplate.php new file mode 100644 index 000000000..cc9d23e2a --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setdebugtemplate.php @@ -0,0 +1,41 @@ +_getSmartyObj(); + if (!is_readable($tpl_name)) { + throw new SmartyException("Unknown file '{$tpl_name}'"); + } + $smarty->debug_tpl = $tpl_name; + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setdefaultmodifiers.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setdefaultmodifiers.php new file mode 100644 index 000000000..eadc2de1b --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_setdefaultmodifiers.php @@ -0,0 +1,38 @@ +_getSmartyObj(); + $smarty->default_modifiers = (array)$modifiers; + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unloadfilter.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unloadfilter.php new file mode 100644 index 000000000..55e1596be --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unloadfilter.php @@ -0,0 +1,43 @@ +_getSmartyObj(); + $this->_checkFilterType($type); + if (isset($smarty->registered_filters[ $type ])) { + $_filter_name = "smarty_{$type}filter_{$name}"; + if (isset($smarty->registered_filters[ $type ][ $_filter_name ])) { + unset($smarty->registered_filters[ $type ][ $_filter_name ]); + if (empty($smarty->registered_filters[ $type ])) { + unset($smarty->registered_filters[ $type ]); + } + } + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregistercacheresource.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregistercacheresource.php new file mode 100644 index 000000000..b99903867 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregistercacheresource.php @@ -0,0 +1,40 @@ +_getSmartyObj(); + if (isset($smarty->registered_cache_resources[ $name ])) { + unset($smarty->registered_cache_resources[ $name ]); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterfilter.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterfilter.php new file mode 100644 index 000000000..9cb494a52 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterfilter.php @@ -0,0 +1,43 @@ +_getSmartyObj(); + $this->_checkFilterType($type); + if (isset($smarty->registered_filters[ $type ])) { + $name = is_string($callback) ? $callback : $this->_getFilterName($callback); + if (isset($smarty->registered_filters[ $type ][ $name ])) { + unset($smarty->registered_filters[ $type ][ $name ]); + if (empty($smarty->registered_filters[ $type ])) { + unset($smarty->registered_filters[ $type ]); + } + } + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterobject.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterobject.php new file mode 100644 index 000000000..1e592b339 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterobject.php @@ -0,0 +1,40 @@ +_getSmartyObj(); + if (isset($smarty->registered_objects[ $object_name ])) { + unset($smarty->registered_objects[ $object_name ]); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterplugin.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterplugin.php new file mode 100644 index 000000000..f39e31678 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterplugin.php @@ -0,0 +1,41 @@ +_getSmartyObj(); + if (isset($smarty->registered_plugins[ $type ][ $name ])) { + unset($smarty->registered_plugins[ $type ][ $name ]); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterresource.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterresource.php new file mode 100644 index 000000000..a79db4299 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_method_unregisterresource.php @@ -0,0 +1,40 @@ +_getSmartyObj(); + if (isset($smarty->registered_resources[ $type ])) { + unset($smarty->registered_resources[ $type ]); + } + return $obj; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_nocache_insert.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_nocache_insert.php index 1b25e8071..88694dcfd 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_nocache_insert.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_nocache_insert.php @@ -1,49 +1,51 @@ assign('{$_assign}' , {$_function} (" . var_export($_attr, true) . ",\$_smarty_tpl), true);?>"; + $_output .= "\$_smarty_tpl->assign('{$_assign}' , {$_function} (" . var_export($_attr, true) . + ',\$_smarty_tpl), true);?>'; } else { - $_output .= "echo {$_function}(" . var_export($_attr, true) . ",\$_smarty_tpl);?>"; - } + $_output .= "echo {$_function}(" . var_export($_attr, true) . ',$_smarty_tpl);?>'; + } $_tpl = $_template; - while ($_tpl->parent instanceof Smarty_Internal_Template) { + while ($_tpl->_isSubTpl()) { $_tpl = $_tpl->parent; - } - return "/*%%SmartyNocache:{$_tpl->properties['nocache_hash']}%%*/" . $_output . "/*/%%SmartyNocache:{$_tpl->properties['nocache_hash']}%%*/"; - } -} - -?> \ No newline at end of file + } + return "/*%%SmartyNocache:{$_tpl->compiled->nocache_hash}%%*/{$_output}/*/%%SmartyNocache:{$_tpl->compiled->nocache_hash}%%*/"; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree.php index 9eba5944c..9f7678526 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree.php @@ -1,236 +1,50 @@ parser = $parser; - $this->data = $data; - $this->saved_block_nesting = $parser->block_nesting_level; - } - - public function to_smarty_php() - { - return $this->data; - } - - public function assign_to_var() - { - $var = sprintf('$_tmp%d', ++$this->parser->prefix_number); - $this->parser->compiler->prefix_code[] = sprintf('%s', - $this->data, $var); - return $var; - } -} - -/** - * Code fragment inside a tag. - */ -class _smarty_code extends _smarty_parsetree { - public $parser; + /** + * Buffer content + * + * @var mixed + */ public $data; - function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - public function to_smarty_php() - { - return sprintf("(%s)", $this->data); - } -} -/** - * Double quoted string inside a tag. - */ -class _smarty_doublequoted extends _smarty_parsetree { - public $parser; - public $subtrees = Array(); - function __construct($parser, _smarty_parsetree $subtree) - { - $this->parser = $parser; - $this->subtrees[] = $subtree; - if ($subtree instanceof _smarty_tag) { - $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack); - } - } - - function append_subtree(_smarty_parsetree $subtree) - { - $last_subtree = count($this->subtrees)-1; - if ($last_subtree >= 0 && $this->subtrees[$last_subtree] instanceof _smarty_tag && $this->subtrees[$last_subtree]->saved_block_nesting < $this->parser->block_nesting_level) { - if ($subtree instanceof _smarty_code) { - $this->subtrees[$last_subtree]->data .= 'data . ';?>'; - } elseif ($subtree instanceof _smarty_dq_content) { - $this->subtrees[$last_subtree]->data .= 'data . '";?>'; - } else { - $this->subtrees[$last_subtree]->data .= $subtree->data; - } - } else { - $this->subtrees[] = $subtree; - } - if ($subtree instanceof _smarty_tag) { - $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack); - } - } - - public function to_smarty_php() - { - $code = ''; - foreach ($this->subtrees as $subtree) { - if ($code !== "") { - $code .= "."; - } - if ($subtree instanceof _smarty_tag) { - $more_php = $subtree->assign_to_var(); - } else { - $more_php = $subtree->to_smarty_php(); - } - - $code .= $more_php; - - if (!$subtree instanceof _smarty_dq_content) { - $this->parser->compiler->has_variable_string = true; - } - } - return $code; - } -} - -/** - * Raw chars as part of a double quoted string. - */ -class _smarty_dq_content extends _smarty_parsetree { - public $data; - function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - public function to_smarty_php() - { - return '"' . $this->data . '"'; - } -} - -/** - * Template element - */ -class _smarty_template_buffer extends _smarty_parsetree { - public $subtrees = Array(); - function __construct($parser) - { - $this->parser = $parser; - } - - function append_subtree(_smarty_parsetree $subtree) - { - $this->subtrees[] = $subtree; - } - - public function to_smarty_php() - { - $code = ''; - for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) { - if ($key + 2 < $cnt) { - if ($this->subtrees[$key] instanceof _smarty_linebreak && $this->subtrees[$key + 1] instanceof _smarty_tag && $this->subtrees[$key + 1]->data == '' && $this->subtrees[$key + 2] instanceof _smarty_linebreak) { - $key = $key + 1; - continue; - } - if (substr($this->subtrees[$key]->data, -1) == '<' && $this->subtrees[$key + 1]->data == '' && substr($this->subtrees[$key + 2]->data, -1) == '?') { - $key = $key + 2; - continue; - } - } - if (substr($code, -1) == '<') { - $subtree = $this->subtrees[$key]->to_smarty_php(); - if (substr($subtree, 0, 1) == '?') { - $code = substr($code, 0, strlen($code)-1) . '<?' . substr($subtree, 1); - } elseif ($this->parser->asp_tags && substr($subtree, 0, 1) == '%') { - $code = substr($code, 0, strlen($code)-1) . '<%' . substr($subtree, 1); - } else { - $code .= $subtree; - } - continue; - } - if ($this->parser->asp_tags && substr($code, -1) == '%') { - $subtree = $this->subtrees[$key]->to_smarty_php(); - if (substr($subtree, 0, 1) == '>') { - $code = substr($code, 0, strlen($code)-1) . '%>' . substr($subtree, 1); - } else { - $code .= $subtree; - } - continue; - } - if (substr($code, -1) == '?') { - $subtree = $this->subtrees[$key]->to_smarty_php(); - if (substr($subtree, 0, 1) == '>') { - $code = substr($code, 0, strlen($code)-1) . '?>' . substr($subtree, 1); - } else { - $code .= $subtree; - } - continue; - } - $code .= $this->subtrees[$key]->to_smarty_php(); - } - return $code; - } + /** + * Subtree array + * + * @var array + */ + public $subtrees = array(); + + /** + * Return buffer + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string buffer content + */ + abstract public function to_smarty_php(Smarty_Internal_Templateparser $parser); + + /** + * Template data object destructor + */ + public function __destruct() + { + $this->data = null; + $this->subtrees = null; + } } - -/** - * template text - */ -class _smarty_text extends _smarty_parsetree { - public $data; - function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - public function to_smarty_php() - { - return $this->data; - } -} - -/** - * template linebreaks - */ -class _smarty_linebreak extends _smarty_parsetree { - public $data; - function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - public function to_smarty_php() - { - return $this->data; - } -} - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_code.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_code.php new file mode 100644 index 000000000..7bd0bc45c --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_code.php @@ -0,0 +1,42 @@ +data = $data; + } + + /** + * Return buffer content in parentheses + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string content + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return sprintf('(%s)', $this->data); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_dq.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_dq.php new file mode 100644 index 000000000..8655f5869 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_dq.php @@ -0,0 +1,95 @@ +subtrees[] = $subtree; + if ($subtree instanceof Smarty_Internal_ParseTree_Tag) { + $parser->block_nesting_level = count($parser->compiler->_tag_stack); + } + } + + /** + * Append buffer to subtree + * + * @param \Smarty_Internal_Templateparser $parser + * @param Smarty_Internal_ParseTree $subtree parse tree buffer + */ + public function append_subtree(Smarty_Internal_Templateparser $parser, Smarty_Internal_ParseTree $subtree) + { + $last_subtree = count($this->subtrees) - 1; + if ($last_subtree >= 0 && $this->subtrees[ $last_subtree ] instanceof Smarty_Internal_ParseTree_Tag + && $this->subtrees[ $last_subtree ]->saved_block_nesting < $parser->block_nesting_level + ) { + if ($subtree instanceof Smarty_Internal_ParseTree_Code) { + $this->subtrees[ $last_subtree ]->data = + $parser->compiler->appendCode( + $this->subtrees[ $last_subtree ]->data, + 'data . ';?>' + ); + } elseif ($subtree instanceof Smarty_Internal_ParseTree_DqContent) { + $this->subtrees[ $last_subtree ]->data = + $parser->compiler->appendCode( + $this->subtrees[ $last_subtree ]->data, + 'data . '";?>' + ); + } else { + $this->subtrees[ $last_subtree ]->data = + $parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, $subtree->data); + } + } else { + $this->subtrees[] = $subtree; + } + if ($subtree instanceof Smarty_Internal_ParseTree_Tag) { + $parser->block_nesting_level = count($parser->compiler->_tag_stack); + } + } + + /** + * Merge subtree buffer content together + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string compiled template code + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + $code = ''; + foreach ($this->subtrees as $subtree) { + if ($code !== '') { + $code .= '.'; + } + if ($subtree instanceof Smarty_Internal_ParseTree_Tag) { + $more_php = $subtree->assign_to_var($parser); + } else { + $more_php = $subtree->to_smarty_php($parser); + } + $code .= $more_php; + if (!$subtree instanceof Smarty_Internal_ParseTree_DqContent) { + $parser->compiler->has_variable_string = true; + } + } + return $code; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_dqcontent.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_dqcontent.php new file mode 100644 index 000000000..a8ca389d9 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_dqcontent.php @@ -0,0 +1,42 @@ +data = $data; + } + + /** + * Return content as double quoted string + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string doubled quoted string + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return '"' . $this->data . '"'; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_tag.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_tag.php new file mode 100644 index 000000000..e6c755604 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_tag.php @@ -0,0 +1,67 @@ +data = $data; + $this->saved_block_nesting = $parser->block_nesting_level; + } + + /** + * Return buffer content + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string content + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return $this->data; + } + + /** + * Return complied code that loads the evaluated output of buffer content into a temporary variable + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string template code + */ + public function assign_to_var(Smarty_Internal_Templateparser $parser) + { + $var = $parser->compiler->getNewPrefixVariable(); + $tmp = $parser->compiler->appendCode('', $this->data); + $tmp = $parser->compiler->appendCode($tmp, ""); + $parser->compiler->prefix_code[] = sprintf('%s', $tmp); + return $var; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php new file mode 100644 index 000000000..477232ef8 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php @@ -0,0 +1,169 @@ +subtrees)) { + $this->subtrees = array_merge($this->subtrees, $subtree->subtrees); + } else { + if ($subtree->data !== '') { + $this->subtrees[] = $subtree; + } + } + } + + /** + * Append array to subtree + * + * @param \Smarty_Internal_Templateparser $parser + * @param \Smarty_Internal_ParseTree[] $array + */ + public function append_array(Smarty_Internal_Templateparser $parser, $array = array()) + { + if (!empty($array)) { + $this->subtrees = array_merge($this->subtrees, (array)$array); + } + } + + /** + * Prepend array to subtree + * + * @param \Smarty_Internal_Templateparser $parser + * @param \Smarty_Internal_ParseTree[] $array + */ + public function prepend_array(Smarty_Internal_Templateparser $parser, $array = array()) + { + if (!empty($array)) { + $this->subtrees = array_merge((array)$array, $this->subtrees); + } + } + + /** + * Sanitize and merge subtree buffers together + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string template code content + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + $code = ''; + + foreach ($this->getChunkedSubtrees() as $chunk) { + $text = ''; + switch ($chunk['mode']) { + case 'textstripped': + foreach ($chunk['subtrees'] as $subtree) { + $text .= $subtree->to_smarty_php($parser); + } + $code .= preg_replace( + '/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/', + "\n", + $parser->compiler->processText($text) + ); + break; + case 'text': + foreach ($chunk['subtrees'] as $subtree) { + $text .= $subtree->to_smarty_php($parser); + } + $code .= preg_replace( + '/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/', + "\n", + $text + ); + break; + case 'tag': + foreach ($chunk['subtrees'] as $subtree) { + $text = $parser->compiler->appendCode($text, $subtree->to_smarty_php($parser)); + } + $code .= $text; + break; + default: + foreach ($chunk['subtrees'] as $subtree) { + $text = $subtree->to_smarty_php($parser); + } + $code .= $text; + + } + } + return $code; + } + + private function getChunkedSubtrees() { + $chunks = []; + $currentMode = null; + $currentChunk = []; + for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) { + + if ($this->subtrees[ $key ]->data === '' && in_array($currentMode, ['textstripped', 'text', 'tag'])) { + continue; + } + + if ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Text + && $this->subtrees[ $key ]->isToBeStripped()) { + $newMode = 'textstripped'; + } elseif ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Text) { + $newMode = 'text'; + } elseif ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Tag) { + $newMode = 'tag'; + } else { + $newMode = 'other'; + } + + if ($newMode == $currentMode) { + $currentChunk[] = $this->subtrees[ $key ]; + } else { + $chunks[] = [ + 'mode' => $currentMode, + 'subtrees' => $currentChunk + ]; + $currentMode = $newMode; + $currentChunk = [$this->subtrees[ $key ]]; + } + } + if ($currentMode && $currentChunk) { + $chunks[] = [ + 'mode' => $currentMode, + 'subtrees' => $currentChunk + ]; + } + return $chunks; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_text.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_text.php new file mode 100644 index 000000000..399e84941 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_text.php @@ -0,0 +1,57 @@ +data = $data; + $this->toBeStripped = $toBeStripped; + } + + /** + * Wether this section should be stripped on output to smarty php + * @return bool + */ + public function isToBeStripped() { + return $this->toBeStripped; + } + + /** + * Return buffer content + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string text + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return $this->data; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_register.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_register.php deleted file mode 100644 index edaa7ff13..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_register.php +++ /dev/null @@ -1,156 +0,0 @@ -smarty = $smarty; - } - /** - * Registers plugin to be used in templates - * - * @param string $type plugin type - * @param string $tag name of template tag - * @param callback $callback PHP callback to register - * @param boolean $cacheable if true (default) this fuction is cachable - * @param array $cache_attr caching attributes if any - */ - - public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null) - { - if (isset($this->smarty->registered_plugins[$type][$tag])) { - throw new Exception("Plugin tag \"{$tag}\" already registered"); - } elseif (!is_callable($callback)) { - throw new Exception("Plugin \"{$tag}\" not callable"); - } else { - $this->smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr); - } - } - - /** - * Unregister Plugin - * - * @param string $type of plugin - * @param string $tag name of plugin - */ - function unregisterPlugin($type, $tag) - { - if (isset($this->smarty->registered_plugins[$type][$tag])) { - unset($this->smarty->registered_plugins[$type][$tag]); - } - } - - /** - * Registers a resource to fetch a template - * - * @param string $type name of resource type - * @param array $callback array of callbacks to handle resource - */ - public function registerResource($type, $callback) - { - $this->smarty->registered_resources[$type] = array($callback, false); - } - - /** - * Unregisters a resource - * - * @param string $type name of resource type - */ - function unregisterResource($type) - { - if (isset($this->smarty->registered_resources[$type])) { - unset($this->smarty->registered_resources[$type]); - } - } - - - /** - * Registers object to be used in templates - * - * @param string $object name of template object - * @param object $ &$object_impl the referenced PHP object to register - * @param mixed $ null | array $allowed list of allowed methods (empty = all) - * @param boolean $smarty_args smarty argument format, else traditional - * @param mixed $ null | array $block_functs list of methods that are block format - */ - function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) - { - // test if allowed methodes callable - if (!empty($allowed)) { - foreach ((array)$allowed as $method) { - if (!is_callable(array($object_impl, $method))) { - throw new SmartyException("Undefined method '$method' in registered object"); - } - } - } - // test if block methodes callable - if (!empty($block_methods)) { - foreach ((array)$block_methods as $method) { - if (!is_callable(array($object_impl, $method))) { - throw new SmartyException("Undefined method '$method' in registered object"); - } - } - } - // register the object - $this->smarty->registered_objects[$object_name] = - array($object_impl, (array)$allowed, (boolean)$smarty_args, (array)$block_methods); - } - - /** - * Registers static classes to be used in templates - * - * @param string $class name of template class - * @param string $class_impl the referenced PHP class to register - */ - function registerClass($class_name, $class_impl) - { - // test if exists - if (!class_exists($class_impl)) { - throw new SmartyException("Undefined class '$class_impl' in register template class"); - } - // register the class - $this->smarty->registered_classes[$class_name] = $class_impl; - } - - /** - * Registers a default plugin handler - * - * @param $callback mixed string | array $plugin class/methode name - */ - function registerDefaultPluginHandler($callback) - { - if (is_callable($callback)) { - $this->smarty->default_plugin_handler_func = $callback; - } else { - throw new SmartyException("Default plugin handler '$callback' not callable"); - } - } - - /** - * Registers a default template handler - * - * @param $callback mixed string | array class/method name - */ - function registerDefaultTemplateHandler($callback) - { - if (is_callable($callback)) { - $this->smarty->default_template_handler_func = $callback; - } else { - throw new SmartyException("Default template handler '$callback' not callable"); - } - } - -} -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_eval.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_eval.php index a3acf71d0..3b552a589 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_eval.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_eval.php @@ -1,89 +1,94 @@ smarty = $smarty; - } - // classes used for compiling Smarty templates from file resource - public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; - public $template_lexer_class = 'Smarty_Internal_Templatelexer'; - public $template_parser_class = 'Smarty_Internal_Templateparser'; - // properties - public $usesCompiler = true; - public $isEvaluated = true; - +class Smarty_Internal_Resource_Eval extends Smarty_Resource_Recompiled +{ /** - * Return flag if template source is existing - * - * @return boolean true + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return void */ - public function isExisting($template) + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - return true; - } + $source->uid = $source->filepath = sha1($source->name); + $source->timestamp = $source->exists = true; + } /** - * Get filepath to template source - * - * @param object $_template template object - * @return string return 'string' as template source is not a file + * Load template's source from $resource_name into current template object + * + * @uses decode() to decode base64 and urlencoded template_resources + * + * @param Smarty_Template_Source $source source object + * + * @return string template source */ - public function getTemplateFilepath($_template) - { - // no filepath for evaluated strings - // return "string" for compiler error messages - return 'eval:'; - } + public function getContent(Smarty_Template_Source $source) + { + return $this->decode($source->name); + } /** - * Get timestamp to template source - * - * @param object $_template template object - * @return boolean false as string resources have no timestamp + * decode base64 and urlencode + * + * @param string $string template_resource to decode + * + * @return string decoded template_resource */ - public function getTemplateTimestamp($_template) - { - // evaluated strings must always be compiled and have no timestamp - return false; - } + protected function decode($string) + { + // decode if specified + if (($pos = strpos($string, ':')) !== false) { + if (!strncmp($string, 'base64', 6)) { + return base64_decode(substr($string, 7)); + } elseif (!strncmp($string, 'urlencode', 9)) { + return urldecode(substr($string, 10)); + } + } + return $string; + } /** - * Retuen template source from resource name - * - * @param object $_template template object - * @return string content of template source + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name */ - public function getTemplateSource($_template) - { - // return template string - $_template->template_source = $_template->resource_name; - return true; - } + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + return get_class($this) . '#' . $this->decode($resource_name); + } /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return boolean return false as compiled template is not stored + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename */ - public function getCompiledFilepath($_template) - { - // no filepath for strings - return false; - } -} -?> \ No newline at end of file + public function getBasename(Smarty_Template_Source $source) + { + return ''; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_extends.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_extends.php index 74dc0f9b6..80946932e 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_extends.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_extends.php @@ -1,176 +1,126 @@ smarty = $smarty; - $this->_rdl = preg_quote($smarty->right_delimiter); - $this->_ldl = preg_quote($smarty->left_delimiter); - } - // classes used for compiling Smarty templates from file resource - public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; - public $template_lexer_class = 'Smarty_Internal_Templatelexer'; - public $template_parser_class = 'Smarty_Internal_Templateparser'; - // properties - public $usesCompiler = true; - public $isEvaluated = false; - public $allFilepaths = array(); +class Smarty_Internal_Resource_Extends extends Smarty_Resource +{ + /** + * mbstring.overload flag + * + * @var int + */ + public $mbstring_overload = 0; /** - * Return flag if template source is existing - * - * @param object $_template template object - * @return boolean result + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @throws SmartyException */ - public function isExisting($_template) + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - $_template->getTemplateFilepath(); - foreach ($this->allFilepaths as $_filepath) { - if ($_filepath === false) { - return false; - } + $uid = ''; + $sources = array(); + $components = explode('|', $source->name); + $smarty = &$source->smarty; + $exists = true; + foreach ($components as $component) { + /* @var \Smarty_Template_Source $_s */ + $_s = Smarty_Template_Source::load(null, $smarty, $component); + if ($_s->type === 'php') { + throw new SmartyException("Resource type {$_s->type} cannot be used with the extends resource type"); + } + $sources[ $_s->uid ] = $_s; + $uid .= $_s->filepath; + if ($_template) { + $exists = $exists && $_s->exists; + } + } + $source->components = $sources; + $source->filepath = $_s->filepath; + $source->uid = sha1($uid . $source->smarty->_joined_template_dir); + $source->exists = $exists; + if ($_template) { + $source->timestamp = $_s->timestamp; } - return true; - } + } + /** - * Get filepath to template source - * - * @param object $_template template object - * @return string filepath to template source file + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object */ - public function getTemplateFilepath($_template) + public function populateTimestamp(Smarty_Template_Source $source) { - $sha1String = ''; - $_files = explode('|', $_template->resource_name); - foreach ($_files as $_file) { - $_filepath = $_template->buildTemplateFilepath ($_file); - if ($_filepath !== false) { - if (is_object($_template->smarty->security_policy)) { - $_template->smarty->security_policy->isTrustedResourceDir($_filepath); - } - } - $sha1String .= $_filepath; - $this->allFilepaths[$_file] = $_filepath; - } - $_template->templateUid = sha1($sha1String); - return $_filepath; - } + $source->exists = true; + /* @var \Smarty_Template_Source $_s */ + foreach ($source->components as $_s) { + $source->exists = $source->exists && $_s->exists; + } + $source->timestamp = $source->exists ? $_s->getTimeStamp() : false; + } /** - * Get timestamp to template source - * - * @param object $_template template object - * @return integer timestamp of template source file + * Load template's source from files into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded */ - public function getTemplateTimestamp($_template) + public function getContent(Smarty_Template_Source $source) { - return filemtime($_template->getTemplateFilepath()); - } + if (!$source->exists) { + throw new SmartyException("Unable to load template '{$source->type}:{$source->name}'"); + } + $_components = array_reverse($source->components); + $_content = ''; + /* @var \Smarty_Template_Source $_s */ + foreach ($_components as $_s) { + // read content + $_content .= $_s->getContent(); + } + return $_content; + } /** - * Read template source from file - * - * @param object $_template template object - * @return string content of template source file + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename */ - public function getTemplateSource($_template) + public function getBasename(Smarty_Template_Source $source) { - $this->template = $_template; - $_files = array_reverse($this->allFilepaths); - $_first = reset($_files); - $_last = end($_files); - foreach ($_files as $_file => $_filepath) { - if ($_filepath === false) { - throw new SmartyException("Unable to load template 'file : {$_file}'"); - } - // read template file - if ($_filepath != $_first) { - $_template->properties['file_dependency'][sha1($_filepath)] = array($_filepath, filemtime($_filepath),'file'); - } - $_template->template_filepath = $_filepath; - $_content = file_get_contents($_filepath); - if ($_filepath != $_last) { - if (preg_match_all("!({$this->_ldl}block\s(.+?){$this->_rdl})!", $_content, $_open) != - preg_match_all("!({$this->_ldl}/block{$this->_rdl})!", $_content, $_close)) { - $this->smarty->triggerError("unmatched {block} {/block} pairs in file '$_filepath'"); - } - preg_match_all("!{$this->_ldl}block\s(.+?){$this->_rdl}|{$this->_ldl}/block{$this->_rdl}!", $_content, $_result, PREG_OFFSET_CAPTURE); - $_result_count = count($_result[0]); - $_start = 0; - while ($_start < $_result_count) { - $_end = 0; - $_level = 1; - while ($_level != 0) { - $_end++; - if (!strpos($_result[0][$_start + $_end][0], '/')) { - $_level++; - } else { - $_level--; - } - } - $_block_content = str_replace($this->smarty->left_delimiter . '$smarty.block.parent' . $this->smarty->right_delimiter, '%%%%SMARTY_PARENT%%%%', - substr($_content, $_result[0][$_start][1] + strlen($_result[0][$_start][0]), $_result[0][$_start + $_end][1] - $_result[0][$_start][1] - + strlen($_result[0][$_start][0]))); - Smarty_Internal_Compile_Block::saveBlockData($_block_content, $_result[0][$_start][0], $_template, $_filepath); - $_start = $_start + $_end + 1; - } - } else { - $_template->template_source = $_content; - return true; - } - } + return str_replace(':', '.', basename($source->filepath)); } - + /* + * Disable timestamp checks for extends resource. + * The individual source components will be checked. + * + * @return bool + */ /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return string return path to compiled template + * @return bool */ - public function getCompiledFilepath($_template) + public function checkTimestamps() { - $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; - $_files = explode('|', $_template->resource_name); - // calculate Uid if not already done - if ($_template->templateUid == '') { - $_template->getTemplateFilepath(); - } - $_filepath = $_template->templateUid; - // if use_sub_dirs, break file into directories - if ($_template->smarty->use_sub_dirs) { - $_filepath = substr($_filepath, 0, 2) . DS - . substr($_filepath, 2, 2) . DS - . substr($_filepath, 4, 2) . DS - . $_filepath; - } - $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; - if (isset($_compile_id)) { - $_filepath = $_compile_id . $_compile_dir_sep . $_filepath; - } - if ($_template->caching) { - $_cache = '.cache'; - } else { - $_cache = ''; - } - $_compile_dir = $_template->smarty->compile_dir; - if (substr($_compile_dir, -1) != DS) { - $_compile_dir .= DS; - } - return $_compile_dir . $_filepath . '.' . $_template->resource_type . '.' . basename($_files[count($_files)-1]) . $_cache . '.php'; - } -} - -?> \ No newline at end of file + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_file.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_file.php index 79decc599..ae2060673 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_file.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_file.php @@ -1,128 +1,180 @@ smarty = $smarty; - } - // classes used for compiling Smarty templates from file resource - public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; - public $template_lexer_class = 'Smarty_Internal_Templatelexer'; - public $template_parser_class = 'Smarty_Internal_Templateparser'; - // properties - public $usesCompiler = true; - public $isEvaluated = false; - +class Smarty_Internal_Resource_File extends Smarty_Resource +{ /** - * Return flag if template source is existing - * - * @return boolean true + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @throws \SmartyException */ - public function isExisting($template) + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - if ($template->getTemplateFilepath() === false) { - return false; + $source->filepath = $this->buildFilepath($source, $_template); + if ($source->filepath !== false) { + if (isset($source->smarty->security_policy) && is_object($source->smarty->security_policy)) { + $source->smarty->security_policy->isTrustedResourceDir($source->filepath, $source->isConfig); + } + $source->exists = true; + $source->uid = sha1( + $source->filepath . ($source->isConfig ? $source->smarty->_joined_config_dir : + $source->smarty->_joined_template_dir) + ); + $source->timestamp = filemtime($source->filepath); } else { - return true; - } - } + $source->timestamp = $source->exists = false; + } + } /** - * Get filepath to template source - * - * @param object $_template template object - * @return string filepath to template source file + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object */ - public function getTemplateFilepath($_template) + public function populateTimestamp(Smarty_Template_Source $source) { - $_filepath = $_template->buildTemplateFilepath (); - - if ($_filepath !== false) { - if (is_object($_template->smarty->security_policy)) { - $_template->smarty->security_policy->isTrustedResourceDir($_filepath); - } - } - $_template->templateUid = sha1($_filepath); - return $_filepath; - } + if (!$source->exists) { + $source->timestamp = $source->exists = is_file($source->filepath); + } + if ($source->exists) { + $source->timestamp = filemtime($source->filepath); + } + } /** - * Get timestamp to template source - * - * @param object $_template template object - * @return integer timestamp of template source file + * Load template's source from file into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded */ - public function getTemplateTimestamp($_template) + public function getContent(Smarty_Template_Source $source) { - return filemtime($_template->getTemplateFilepath()); - } + if ($source->exists) { + return file_get_contents($source->filepath); + } + throw new SmartyException( + 'Unable to read ' . ($source->isConfig ? 'config' : 'template') . + " {$source->type} '{$source->name}'" + ); + } /** - * Read template source from file - * - * @param object $_template template object - * @return string content of template source file + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename */ - public function getTemplateSource($_template) - { - // read template file - if (file_exists($_tfp = $_template->getTemplateFilepath())) { - $_template->template_source = file_get_contents($_tfp); - return true; - } else { - return false; - } - } + public function getBasename(Smarty_Template_Source $source) + { + return basename($source->filepath); + } /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return string return path to compiled template + * build template filepath by traversing the template_dir array + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return string fully qualified filepath + * @throws SmartyException */ - public function getCompiledFilepath($_template) + protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; - // calculate Uid if not already done - if ($_template->templateUid == '') { - $_template->getTemplateFilepath(); - } - $_filepath = $_template->templateUid; - // if use_sub_dirs, break file into directories - if ($_template->smarty->use_sub_dirs) { - $_filepath = substr($_filepath, 0, 2) . DS - . substr($_filepath, 2, 2) . DS - . substr($_filepath, 4, 2) . DS - . $_filepath; - } - $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; - if (isset($_compile_id)) { - $_filepath = $_compile_id . $_compile_dir_sep . $_filepath; - } - if ($_template->caching) { - $_cache = '.cache'; - } else { - $_cache = ''; - } - $_compile_dir = $_template->smarty->compile_dir; - if (strpos('/\\', substr($_compile_dir, -1)) === false) { - $_compile_dir .= DS; - } - return $_compile_dir . $_filepath . '.' . $_template->resource_type . '.' . basename($_template->resource_name) . $_cache . '.php'; - } -} - -?> \ No newline at end of file + $file = $source->name; + // absolute file ? + if ($file[ 0 ] === '/' || $file[ 1 ] === ':') { + $file = $source->smarty->_realpath($file, true); + return is_file($file) ? $file : false; + } + // go relative to a given template? + if ($file[ 0 ] === '.' && $_template && $_template->_isSubTpl() + && preg_match('#^[.]{1,2}[\\\/]#', $file) + ) { + if ($_template->parent->source->type !== 'file' && $_template->parent->source->type !== 'extends' + && !isset($_template->parent->_cache[ 'allow_relative_path' ]) + ) { + throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'"); + } + // normalize path + $path = + $source->smarty->_realpath(dirname($_template->parent->source->filepath) . DIRECTORY_SEPARATOR . $file); + // files relative to a template only get one shot + return is_file($path) ? $path : false; + } + // normalize DIRECTORY_SEPARATOR + if (strpos($file, DIRECTORY_SEPARATOR === '/' ? '\\' : '/') !== false) { + $file = str_replace(DIRECTORY_SEPARATOR === '/' ? '\\' : '/', DIRECTORY_SEPARATOR, $file); + } + $_directories = $source->smarty->getTemplateDir(null, $source->isConfig); + // template_dir index? + if ($file[ 0 ] === '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) { + $file = $fileMatch[ 2 ]; + $_indices = explode(',', $fileMatch[ 1 ]); + $_index_dirs = array(); + foreach ($_indices as $index) { + $index = trim($index); + // try string indexes + if (isset($_directories[ $index ])) { + $_index_dirs[] = $_directories[ $index ]; + } elseif (is_numeric($index)) { + // try numeric index + $index = (int)$index; + if (isset($_directories[ $index ])) { + $_index_dirs[] = $_directories[ $index ]; + } else { + // try at location index + $keys = array_keys($_directories); + if (isset($_directories[ $keys[ $index ] ])) { + $_index_dirs[] = $_directories[ $keys[ $index ] ]; + } + } + } + } + if (empty($_index_dirs)) { + // index not found + return false; + } else { + $_directories = $_index_dirs; + } + } + // relative file name? + foreach ($_directories as $_directory) { + $path = $_directory . $file; + if (is_file($path)) { + return (strpos($path, '.' . DIRECTORY_SEPARATOR) !== false) ? $source->smarty->_realpath($path) : $path; + } + } + if (!isset($_index_dirs)) { + // Could be relative to cwd + $path = $source->smarty->_realpath($file, true); + if (is_file($path)) { + return $path; + } + } + // Use include path ? + if ($source->smarty->use_include_path) { + return $source->smarty->ext->_getIncludePath->getIncludePath($_directories, $file, $source->smarty); + } + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_php.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_php.php index 16c77446e..9d98ae181 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_php.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_php.php @@ -2,126 +2,115 @@ /** * Smarty Internal Plugin Resource PHP - * * Implements the file system as resource for PHP templates - * - * @package Smarty + * + * @package Smarty * @subpackage TemplateResources - * @author Uwe Tews + * @author Uwe Tews + * @author Rodney Rehm */ - -/** - * Smarty Internal Plugin Resource PHP - */ -class Smarty_Internal_Resource_PHP { +class Smarty_Internal_Resource_Php extends Smarty_Internal_Resource_File +{ /** - * Class constructor, enable short open tags + * Flag that it's an uncompiled resource + * + * @var bool */ - public function __construct($smarty) - { - $this->smarty = $smarty; - ini_set('short_open_tag', '1'); - } - // properties - public $usesCompiler = false; - public $isEvaluated = false; + public $uncompiled = true; /** - * Return flag if template source is existing - * - * @return boolean true + * Resource does implement populateCompiledFilepath() method + * + * @var bool */ - public function isExisting($template) - { - if ($template->getTemplateFilepath() === false) { - return false; - } else { - return true; - } - } + public $hasCompiledHandler = true; /** - * Get filepath to template source - * - * @param object $_template template object - * @return string filepath to template source file + * container for short_open_tag directive's value before executing PHP templates + * + * @var string */ - public function getTemplateFilepath($_template) - { - $_filepath = $_template->buildTemplateFilepath (); - - if (is_object($_template->smarty->security_policy)) { - $_template->smarty->security_policy->isTrustedResourceDir($_filepath); - } - $_template->templateUid = sha1($_filepath); - return $_filepath; - } + protected $short_open_tag; /** - * Get timestamp to template source - * - * @param object $_template template object - * @return integer timestamp of template source file + * Create a new PHP Resource */ - public function getTemplateTimestamp($_template) + public function __construct() { - return filemtime($_template->getTemplateFilepath()); - } + $this->short_open_tag = function_exists('ini_get') ? ini_get('short_open_tag') : 1; + } /** - * Read template source from file - * - * @param object $_template template object - * @return string content of template source file + * Load template's source from file into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded */ - public function getTemplateSource($_template) + public function getContent(Smarty_Template_Source $source) { - if (file_exists($_tfp = $_template->getTemplateFilepath())) { - $_template->template_source = file_get_contents($_tfp); - return true; - } else { - return false; - } - } + if ($source->exists) { + return ''; + } + throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); + } /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return boolean return false as compiled template is not stored + * populate compiled object with compiled filepath + * + * @param Smarty_Template_Compiled $compiled compiled object + * @param Smarty_Internal_Template $_template template object (is ignored) */ - public function getCompiledFilepath($_template) - { - // no filepath for PHP templates - return false; - } + public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template) + { + $compiled->filepath = $_template->source->filepath; + $compiled->timestamp = $_template->source->timestamp; + $compiled->exists = $_template->source->exists; + $compiled->file_dependency[ $_template->source->uid ] = + array( + $compiled->filepath, + $compiled->timestamp, + $_template->source->type, + ); + } /** - * renders the PHP template + * Render and output the template (without using the compiler) + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return void + * @throws SmartyException if template cannot be loaded or allow_php_templates is disabled */ - public function renderUncompiled($_smarty_template) + public function renderUncompiled(Smarty_Template_Source $source, Smarty_Internal_Template $_template) { - if (!$this->smarty->allow_php_templates) { - throw new SmartyException("PHP templates are disabled"); - } - if ($this->getTemplateFilepath($_smarty_template) === false) { - throw new SmartyException("Unable to load template \"{$_smarty_template->resource_type} : {$_smarty_template->resource_name}\""); - } + if (!$source->smarty->allow_php_templates) { + throw new SmartyException('PHP templates are disabled'); + } + if (!$source->exists) { + throw new SmartyException( + "Unable to load template '{$source->type}:{$source->name}'" . + ($_template->_isSubTpl() ? " in '{$_template->parent->template_resource}'" : '') + ); + } // prepare variables - $_smarty_ptr = $_smarty_template; - do { - foreach ($_smarty_ptr->tpl_vars as $_smarty_var => $_smarty_var_object) { - if (isset($_smarty_var_object->value)) { - $$_smarty_var = $_smarty_var_object->value; - } - } - $_smarty_ptr = $_smarty_ptr->parent; - } while ($_smarty_ptr != null); - unset ($_smarty_var, $_smarty_var_object, $_smarty_ptr); - // include PHP template - include($this->getTemplateFilepath($_smarty_template)); - return; - } -} - -?> \ No newline at end of file + extract($_template->getTemplateVars()); + // include PHP template with short open tags enabled + if (function_exists('ini_set')) { + ini_set('short_open_tag', '1'); + } + /** + * + * + * @var Smarty_Internal_Template $_smarty_template + * used in included file + */ + $_smarty_template = $_template; + include $source->filepath; + if (function_exists('ini_set')) { + ini_set('short_open_tag', $this->short_open_tag); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_registered.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_registered.php index 467da11a8..df526101f 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_registered.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_registered.php @@ -1,143 +1,101 @@ smarty = $template->smarty; - if (isset($resource_type)) { - $template->smarty->registerResource($resource_type, - array("smarty_resource_{$resource_type}_source", - "smarty_resource_{$resource_type}_timestamp", - "smarty_resource_{$resource_type}_secure", - "smarty_resource_{$resource_type}_trusted")); - } - } - // classes used for compiling Smarty templates from file resource - public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; - public $template_lexer_class = 'Smarty_Internal_Templatelexer'; - public $template_parser_class = 'Smarty_Internal_Templateparser'; - // properties - public $usesCompiler = true; - public $isEvaluated = false; - +class Smarty_Internal_Resource_Registered extends Smarty_Resource +{ /** - * Return flag if template source is existing - * - * @return boolean true + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return void */ - public function isExisting($_template) + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - if (is_integer($_template->getTemplateTimestamp())) { - return true; - } else { - return false; - } - } - /** - * Get filepath to template source - * - * @param object $_template template object - * @return string return 'string' as template source is not a file - */ - public function getTemplateFilepath($_template) - { - $_filepath = $_template->resource_type .':'.$_template->resource_name; - $_template->templateUid = sha1($_filepath); - return $_filepath; - } + $source->filepath = $source->type . ':' . $source->name; + $source->uid = sha1($source->filepath . $source->smarty->_joined_template_dir); + $source->timestamp = $this->getTemplateTimestamp($source); + $source->exists = !!$source->timestamp; + } /** - * Get timestamp of template source - * - * @param object $_template template object - * @return int timestamp + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + * + * @return void */ - public function getTemplateTimestamp($_template) - { - // return timestamp - $time_stamp = false; - call_user_func_array($this->smarty->registered_resources[$_template->resource_type][0][1], - array($_template->resource_name, &$time_stamp, $this->smarty)); - return is_numeric($time_stamp) ? (int)$time_stamp : $time_stamp; + public function populateTimestamp(Smarty_Template_Source $source) + { + $source->timestamp = $this->getTemplateTimestamp($source); + $source->exists = !!$source->timestamp; } - + /** - * Get timestamp of template source by type and name - * - * @param object $_template template object - * @return int timestamp + * Get timestamp (epoch) the template source was modified + * + * @param Smarty_Template_Source $source source object + * + * @return integer|boolean timestamp (epoch) the template was modified, false if resources has no timestamp */ - public function getTemplateTimestampTypeName($_resource_type, $_resource_name) - { + public function getTemplateTimestamp(Smarty_Template_Source $source) + { // return timestamp $time_stamp = false; - call_user_func_array($this->smarty->registered_resources[$_resource_type][0][1], - array($_resource_name, &$time_stamp, $this->smarty)); + call_user_func_array( + $source->smarty->registered_resources[ $source->type ][ 0 ][ 1 ], + array($source->name, &$time_stamp, $source->smarty) + ); return is_numeric($time_stamp) ? (int)$time_stamp : $time_stamp; - } + } /** - * Retuen template source from resource name - * - * @param object $_template template object - * @return string content of template source + * Load template's source by invoking the registered callback into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded */ - public function getTemplateSource($_template) - { + public function getContent(Smarty_Template_Source $source) + { // return template string - return call_user_func_array($this->smarty->registered_resources[$_template->resource_type][0][0], - array($_template->resource_name, &$_template->template_source, $this->smarty)); - } + $content = null; + $t = call_user_func_array( + $source->smarty->registered_resources[ $source->type ][ 0 ][ 0 ], + array($source->name, &$content, $source->smarty) + ); + if (is_bool($t) && !$t) { + throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); + } + return $content; + } /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return boolean return false as compiled template is not stored + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename */ - public function getCompiledFilepath($_template) - { - $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!','_',$_template->compile_id) : null; - // calculate Uid if not already done - if ($_template->templateUid == '') { - $_template->getTemplateFilepath(); - } - $_filepath = $_template->templateUid; - // if use_sub_dirs, break file into directories - if ($_template->smarty->use_sub_dirs) { - $_filepath = substr($_filepath, 0, 2) . DS - . substr($_filepath, 2, 2) . DS - . substr($_filepath, 4, 2) . DS - . $_filepath; - } - $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; - if (isset($_compile_id)) { - $_filepath = $_compile_id . $_compile_dir_sep . $_filepath; - } - if ($_template->caching) { - $_cache = '.cache'; - } else { - $_cache = ''; - } - $_compile_dir = $_template->smarty->compile_dir; - if (strpos('/\\', substr($_compile_dir, -1)) === false) { - $_compile_dir .= DS; - } - return $_compile_dir . $_filepath . '.' . $_template->resource_type . '.' . basename($_template->resource_name) . $_cache . '.php'; - } -} - -?> \ No newline at end of file + public function getBasename(Smarty_Template_Source $source) + { + return basename($source->name); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_stream.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_stream.php index de2996e93..9956bd073 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_stream.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_stream.php @@ -1,99 +1,78 @@ smarty = $smarty; - } - // classes used for compiling Smarty templates from file resource - public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; - public $template_lexer_class = 'Smarty_Internal_Templatelexer'; - public $template_parser_class = 'Smarty_Internal_Templateparser'; - // properties - public $usesCompiler = true; - public $isEvaluated = true; - +class Smarty_Internal_Resource_Stream extends Smarty_Resource_Recompiled +{ /** - * Return flag if template source is existing - * - * @return boolean true + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return void */ - public function isExisting($template) + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - if ($template->getTemplateSource() == '') { - return false; + if (strpos($source->resource, '://') !== false) { + $source->filepath = $source->resource; } else { - return true; - } - } - /** - * Get filepath to template source - * - * @param object $_template template object - * @return string return 'string' as template source is not a file - */ - public function getTemplateFilepath($_template) - { - // no filepath for strings - // return resource name for compiler error messages - return str_replace(':', '://', $_template->template_resource); - } + $source->filepath = str_replace(':', '://', $source->resource); + } + $source->uid = false; + $source->content = $this->getContent($source); + $source->timestamp = $source->exists = !!$source->content; + } /** - * Get timestamp to template source - * - * @param object $_template template object - * @return boolean false as string resources have no timestamp + * Load template's source from stream into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source */ - public function getTemplateTimestamp($_template) - { - // strings must always be compiled and have no timestamp - return false; - } - - /** - * Retuen template source from resource name - * - * @param object $_template template object - * @return string content of template source - */ - public function getTemplateSource($_template) - { - // return template string - $_template->template_source = ''; - $fp = fopen(str_replace(':', '://', $_template->template_resource),'r+'); - while (!feof($fp)) { - $_template->template_source .= fgets($fp); - } - fclose($fp); - - return true; - } + public function getContent(Smarty_Template_Source $source) + { + $t = ''; + // the availability of the stream has already been checked in Smarty_Resource::fetch() + $fp = fopen($source->filepath, 'r+'); + if ($fp) { + while (!feof($fp) && ($current_line = fgets($fp)) !== false) { + $t .= $current_line; + } + fclose($fp); + return $t; + } else { + return false; + } + } /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return boolean return false as compiled template is not stored + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name */ - public function getCompiledFilepath($_template) - { - // no filepath for strings - return false; - } -} - -?> \ No newline at end of file + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + return get_class($this) . '#' . $resource_name; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_string.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_string.php index 9368f0406..3fecbb7ef 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_string.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_resource_string.php @@ -1,133 +1,108 @@ smarty = $smarty; - } - // classes used for compiling Smarty templates from file resource - public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; - public $template_lexer_class = 'Smarty_Internal_Templatelexer'; - public $template_parser_class = 'Smarty_Internal_Templateparser'; - // properties - public $usesCompiler = true; - public $isEvaluated = false; - +class Smarty_Internal_Resource_String extends Smarty_Resource +{ /** - * Return flag if template source is existing - * - * @return boolean true + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return void */ - public function isExisting($template) + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - return true; - } + $source->uid = $source->filepath = sha1($source->name . $source->smarty->_joined_template_dir); + $source->timestamp = $source->exists = true; + } /** - * Get filepath to template source - * - * @param object $_template template object - * @return string return 'string' as template source is not a file + * Load template's source from $resource_name into current template object + * + * @uses decode() to decode base64 and urlencoded template_resources + * + * @param Smarty_Template_Source $source source object + * + * @return string template source */ - public function getTemplateFilepath($_template) - { - $_template->templateUid = sha1($_template->resource_name); - // no filepath for strings - // return "string" for compiler error messages - return 'string:'; - } + public function getContent(Smarty_Template_Source $source) + { + return $this->decode($source->name); + } /** - * Get timestamp to template source - * - * @param object $_template template object - * @return boolean false as string resources have no timestamp + * decode base64 and urlencode + * + * @param string $string template_resource to decode + * + * @return string decoded template_resource */ - public function getTemplateTimestamp($_template) - { - if ($this->isEvaluated) { - //must always be compiled and have no timestamp - return false; - } else { - return 0; + protected function decode($string) + { + // decode if specified + if (($pos = strpos($string, ':')) !== false) { + if (!strncmp($string, 'base64', 6)) { + return base64_decode(substr($string, 7)); + } elseif (!strncmp($string, 'urlencode', 9)) { + return urldecode(substr($string, 10)); + } } - } + return $string; + } /** - * Get timestamp of template source by type and name - * - * @param object $_template template object - * @return int timestamp (always 0) + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name */ - public function getTemplateTimestampTypeName($_resource_type, $_resource_name) - { - // return timestamp 0 - return 0; - } - + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + return get_class($this) . '#' . $this->decode($resource_name); + } /** - * Retuen template source from resource name - * - * @param object $_template template object - * @return string content of template source + * Determine basename for compiled filename + * Always returns an empty string. + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename */ - public function getTemplateSource($_template) - { - // return template string - $_template->template_source = $_template->resource_name; - return true; - } + public function getBasename(Smarty_Template_Source $source) + { + return ''; + } + /* + * Disable timestamp checks for string resource. + * + * @return bool + */ /** - * Get filepath to compiled template - * - * @param object $_template template object - * @return boolean return false as compiled template is not stored + * @return bool */ - public function getCompiledFilepath($_template) + public function checkTimestamps() { - $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; - // calculate Uid if not already done - if ($_template->templateUid == '') { - $_template->getTemplateFilepath(); - } - $_filepath = $_template->templateUid; - // if use_sub_dirs, break file into directories - if ($_template->smarty->use_sub_dirs) { - $_filepath = substr($_filepath, 0, 2) . DS - . substr($_filepath, 2, 2) . DS - . substr($_filepath, 4, 2) . DS - . $_filepath; - } - $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; - if (isset($_compile_id)) { - $_filepath = $_compile_id . $_compile_dir_sep . $_filepath; - } - if ($_template->caching) { - $_cache = '.cache'; - } else { - $_cache = ''; - } - $_compile_dir = $_template->smarty->compile_dir; - if (strpos('/\\', substr($_compile_dir, -1)) === false) { - $_compile_dir .= DS; - } - return $_compile_dir . $_filepath . '.' . $_template->resource_type . $_cache . '.php'; - } -} - -?> \ No newline at end of file + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_cachemodify.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_cachemodify.php new file mode 100644 index 000000000..6e12d2ae1 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_cachemodify.php @@ -0,0 +1,68 @@ +isCached() && !$_template->compiled->has_nocache_code; + $_last_modified_date = + @substr($_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ], 0, strpos($_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ], 'GMT') + 3); + if ($_isCached && $cached->timestamp <= strtotime($_last_modified_date)) { + switch (PHP_SAPI) { + case 'cgi': // php-cgi < 5.3 + case 'cgi-fcgi': // php-cgi >= 5.3 + case 'fpm-fcgi': // php-fpm >= 5.3.3 + header('Status: 304 Not Modified'); + break; + case 'cli': + if (/* ^phpunit */ + !empty($_SERVER[ 'SMARTY_PHPUNIT_DISABLE_HEADERS' ]) /* phpunit$ */ + ) { + $_SERVER[ 'SMARTY_PHPUNIT_HEADERS' ][] = '304 Not Modified'; + } + break; + default: + if (/* ^phpunit */ + !empty($_SERVER[ 'SMARTY_PHPUNIT_DISABLE_HEADERS' ]) /* phpunit$ */ + ) { + $_SERVER[ 'SMARTY_PHPUNIT_HEADERS' ][] = '304 Not Modified'; + } else { + header($_SERVER[ 'SERVER_PROTOCOL' ] . ' 304 Not Modified'); + } + break; + } + } else { + switch (PHP_SAPI) { + case 'cli': + if (/* ^phpunit */ + !empty($_SERVER[ 'SMARTY_PHPUNIT_DISABLE_HEADERS' ]) /* phpunit$ */ + ) { + $_SERVER[ 'SMARTY_PHPUNIT_HEADERS' ][] = + 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $cached->timestamp) . ' GMT'; + } + break; + default: + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $cached->timestamp) . ' GMT'); + break; + } + echo $content; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_cacheresourcefile.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_cacheresourcefile.php new file mode 100644 index 000000000..287096438 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_cacheresourcefile.php @@ -0,0 +1,139 @@ +use_sub_dirs ? '/' : '^'; + $_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0; + $_dir = $smarty->getCacheDir(); + if ($_dir === '/') { //We should never want to delete this! + return 0; + } + $_dir_length = strlen($_dir); + if (isset($_cache_id)) { + $_cache_id_parts = explode('|', $_cache_id); + $_cache_id_parts_count = count($_cache_id_parts); + if ($smarty->use_sub_dirs) { + foreach ($_cache_id_parts as $id_part) { + $_dir .= $id_part . '/'; + } + } + } + if (isset($resource_name)) { + $_save_stat = $smarty->caching; + $smarty->caching = Smarty::CACHING_LIFETIME_CURRENT; + $tpl = new $smarty->template_class($resource_name, $smarty); + $smarty->caching = $_save_stat; + // remove from template cache + $tpl->source; // have the template registered before unset() + if ($tpl->source->exists) { + $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath)); + } else { + return 0; + } + } + $_count = 0; + $_time = time(); + if (file_exists($_dir)) { + $_cacheDirs = new RecursiveDirectoryIterator($_dir); + $_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($_cache as $_file) { + if (substr(basename($_file->getPathname()), 0, 1) === '.') { + continue; + } + $_filepath = (string)$_file; + // directory ? + if ($_file->isDir()) { + if (!$_cache->isDot()) { + // delete folder if empty + @rmdir($_file->getPathname()); + } + } else { + // delete only php files + if (substr($_filepath, -4) !== '.php') { + continue; + } + $_parts = explode($_dir_sep, str_replace('\\', '/', substr($_filepath, $_dir_length))); + $_parts_count = count($_parts); + // check name + if (isset($resource_name)) { + if ($_parts[ $_parts_count - 1 ] !== $_resourcename_parts) { + continue; + } + } + // check compile id + if (isset($_compile_id) && (!isset($_parts[ $_parts_count - 2 - $_compile_id_offset ]) + || $_parts[ $_parts_count - 2 - $_compile_id_offset ] !== $_compile_id) + ) { + continue; + } + // check cache id + if (isset($_cache_id)) { + // count of cache id parts + $_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset : + $_parts_count - 1 - $_compile_id_offset; + if ($_parts_count < $_cache_id_parts_count) { + continue; + } + for ($i = 0; $i < $_cache_id_parts_count; $i++) { + if ($_parts[ $i ] !== $_cache_id_parts[ $i ]) { + continue 2; + } + } + } + if (is_file($_filepath)) { + // expired ? + if (isset($exp_time)) { + if ($exp_time < 0) { + preg_match('#\'cache_lifetime\' =>\s*(\d*)#', file_get_contents($_filepath), $match); + if ($_time < (filemtime($_filepath) + $match[ 1 ])) { + continue; + } + } else { + if ($_time - filemtime($_filepath) < $exp_time) { + continue; + } + } + } + $_count += @unlink($_filepath) ? 1 : 0; + if (function_exists('opcache_invalidate') + && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) + ) { + opcache_invalidate($_filepath, true); + } elseif (function_exists('apc_delete_file')) { + apc_delete_file($_filepath); + } + } + } + } + } + return $_count; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_capture.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_capture.php new file mode 100644 index 000000000..c9dca83d9 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_capture.php @@ -0,0 +1,174 @@ +isRegistered) { + $this->register($_template); + } + $this->captureStack[] = array( + $buffer, + $assign, + $append + ); + $this->captureCount++; + ob_start(); + } + + /** + * Register callbacks in template class + * + * @param \Smarty_Internal_Template $_template + */ + private function register(Smarty_Internal_Template $_template) + { + $_template->startRenderCallbacks[] = array( + $this, + 'startRender' + ); + $_template->endRenderCallbacks[] = array( + $this, + 'endRender' + ); + $this->startRender($_template); + $this->isRegistered = true; + } + + /** + * Start render callback + * + * @param \Smarty_Internal_Template $_template + */ + public function startRender(Smarty_Internal_Template $_template) + { + $this->countStack[] = $this->captureCount; + $this->captureCount = 0; + } + + /** + * Close capture section + * + * @param \Smarty_Internal_Template $_template + * + * @throws \SmartyException + */ + public function close(Smarty_Internal_Template $_template) + { + if ($this->captureCount) { + list($buffer, $assign, $append) = array_pop($this->captureStack); + $this->captureCount--; + if (isset($assign)) { + $_template->assign($assign, ob_get_contents()); + } + if (isset($append)) { + $_template->append($append, ob_get_contents()); + } + $this->namedBuffer[ $buffer ] = ob_get_clean(); + } else { + $this->error($_template); + } + } + + /** + * Error exception on not matching {capture}{/capture} + * + * @param \Smarty_Internal_Template $_template + * + * @throws \SmartyException + */ + public function error(Smarty_Internal_Template $_template) + { + throw new SmartyException("Not matching {capture}{/capture} in '{$_template->template_resource}'"); + } + + /** + * Return content of named capture buffer by key or as array + * + * @param \Smarty_Internal_Template $_template + * @param string|null $name + * + * @return string|string[]|null + */ + public function getBuffer(Smarty_Internal_Template $_template, $name = null) + { + if (isset($name)) { + return isset($this->namedBuffer[ $name ]) ? $this->namedBuffer[ $name ] : null; + } else { + return $this->namedBuffer; + } + } + + /** + * End render callback + * + * @param \Smarty_Internal_Template $_template + * + * @throws \SmartyException + */ + public function endRender(Smarty_Internal_Template $_template) + { + if ($this->captureCount) { + $this->error($_template); + } else { + $this->captureCount = array_pop($this->countStack); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_codeframe.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_codeframe.php new file mode 100644 index 000000000..983ca6180 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_codeframe.php @@ -0,0 +1,100 @@ +compiled->has_nocache_code; + $properties[ 'file_dependency' ] = $_template->compiled->file_dependency; + $properties[ 'includes' ] = $_template->compiled->includes; + } else { + $properties[ 'has_nocache_code' ] = $_template->cached->has_nocache_code; + $properties[ 'file_dependency' ] = $_template->cached->file_dependency; + $properties[ 'cache_lifetime' ] = $_template->cache_lifetime; + } + $output = "source->filepath) . "' */\n\n"; + $output .= "/* @var Smarty_Internal_Template \$_smarty_tpl */\n"; + $dec = "\$_smarty_tpl->_decodeProperties(\$_smarty_tpl, " . var_export($properties, true) . ',' . + ($cache ? 'true' : 'false') . ')'; + $output .= "if ({$dec}) {\n"; + $output .= "function {$properties['unifunc']} (Smarty_Internal_Template \$_smarty_tpl) {\n"; + if (!$cache && !empty($compiler->tpl_function)) { + $output .= '$_smarty_tpl->smarty->ext->_tplFunction->registerTplFunctions($_smarty_tpl, '; + $output .= var_export($compiler->tpl_function, true); + $output .= ");\n"; + } + if ($cache && isset($_template->smarty->ext->_tplFunction)) { + $output .= "\$_smarty_tpl->smarty->ext->_tplFunction->registerTplFunctions(\$_smarty_tpl, " . + var_export($_template->smarty->ext->_tplFunction->getTplFunction($_template), true) . ");\n"; + } + $output .= "?>"; + $output .= $content; + $output .= ""; + $output .= $functions; + $output .= "[\n]?<\?php\s*/', $output)) { + $curr_split = preg_split( + '/\s*\?>[\n]?<\?php\s*/', + $output + ); + preg_match_all( + '/\s*\?>[\n]?<\?php\s*/', + $output, + $curr_parts + ); + $output = ''; + foreach ($curr_split as $idx => $curr_output) { + $output .= $curr_output; + if (isset($curr_parts[ 0 ][ $idx ])) { + $output .= "\n"; + } + } + } + if (preg_match('/\?>\s*$/', $output)) { + $curr_split = preg_split( + '/\?>\s*$/', + $output + ); + $output = ''; + foreach ($curr_split as $idx => $curr_output) { + $output .= $curr_output; + } + } + return $output; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_filterhandler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_filterhandler.php new file mode 100644 index 000000000..9f868e1a4 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_filterhandler.php @@ -0,0 +1,69 @@ +smarty->autoload_filters[ $type ])) { + foreach ((array)$template->smarty->autoload_filters[ $type ] as $name) { + $plugin_name = "Smarty_{$type}filter_{$name}"; + if (function_exists($plugin_name)) { + $callback = $plugin_name; + } elseif (class_exists($plugin_name, false) && is_callable(array($plugin_name, 'execute'))) { + $callback = array($plugin_name, 'execute'); + } elseif ($template->smarty->loadPlugin($plugin_name, false)) { + if (function_exists($plugin_name)) { + // use loaded Smarty2 style plugin + $callback = $plugin_name; + } elseif (class_exists($plugin_name, false) && is_callable(array($plugin_name, 'execute'))) { + // loaded class of filter plugin + $callback = array($plugin_name, 'execute'); + } else { + throw new SmartyException("Auto load {$type}-filter plugin method '{$plugin_name}::execute' not callable"); + } + } else { + // nothing found, throw exception + throw new SmartyException("Unable to auto load {$type}-filter plugin '{$plugin_name}'"); + } + $content = call_user_func($callback, $content, $template); + } + } + // loop over registered filters of specified type + if (!empty($template->smarty->registered_filters[ $type ])) { + foreach ($template->smarty->registered_filters[ $type ] as $key => $name) { + $content = call_user_func($template->smarty->registered_filters[ $type ][ $key ], $content, $template); + } + } + // return filtered output + return $content; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_foreach.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_foreach.php new file mode 100644 index 000000000..badead165 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_foreach.php @@ -0,0 +1,162 @@ +count($from); + } + } else { + settype($from, 'array'); + } + } + if (!isset($total)) { + $total = empty($from) ? 0 : ($needTotal ? count($from) : 1); + } + if (isset($tpl->tpl_vars[ $item ])) { + $saveVars[ 'item' ] = array( + $item, + $tpl->tpl_vars[ $item ] + ); + } + $tpl->tpl_vars[ $item ] = new Smarty_Variable(null, $tpl->isRenderingCache); + if ($total === 0) { + $from = null; + } else { + if ($key) { + if (isset($tpl->tpl_vars[ $key ])) { + $saveVars[ 'key' ] = array( + $key, + $tpl->tpl_vars[ $key ] + ); + } + $tpl->tpl_vars[ $key ] = new Smarty_Variable(null, $tpl->isRenderingCache); + } + } + if ($needTotal) { + $tpl->tpl_vars[ $item ]->total = $total; + } + if ($name) { + $namedVar = "__smarty_foreach_{$name}"; + if (isset($tpl->tpl_vars[ $namedVar ])) { + $saveVars[ 'named' ] = array( + $namedVar, + $tpl->tpl_vars[ $namedVar ] + ); + } + $namedProp = array(); + if (isset($properties[ 'total' ])) { + $namedProp[ 'total' ] = $total; + } + if (isset($properties[ 'iteration' ])) { + $namedProp[ 'iteration' ] = 0; + } + if (isset($properties[ 'index' ])) { + $namedProp[ 'index' ] = -1; + } + if (isset($properties[ 'show' ])) { + $namedProp[ 'show' ] = ($total > 0); + } + $tpl->tpl_vars[ $namedVar ] = new Smarty_Variable($namedProp); + } + $this->stack[] = $saveVars; + return $from; + } + + /** + * [util function] counts an array, arrayAccess/traversable or PDOStatement object + * + * @param mixed $value + * + * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 + * for empty elements + */ + public function count($value) + { + if ($value instanceof IteratorAggregate) { + // Note: getIterator() returns a Traversable, not an Iterator + // thus rewind() and valid() methods may not be present + return iterator_count($value->getIterator()); + } elseif ($value instanceof Iterator) { + return $value instanceof Generator ? 1 : iterator_count($value); + } elseif ($value instanceof Countable) { + return count($value); + } elseif ($value instanceof PDOStatement) { + return $value->rowCount(); + } elseif ($value instanceof Traversable) { + return iterator_count($value); + } + return count((array)$value); + } + + /** + * Restore saved variables + * + * will be called by {break n} or {continue n} for the required number of levels + * + * @param \Smarty_Internal_Template $tpl + * @param int $levels number of levels + */ + public function restore(Smarty_Internal_Template $tpl, $levels = 1) + { + while ($levels) { + $saveVars = array_pop($this->stack); + if (!empty($saveVars)) { + if (isset($saveVars[ 'item' ])) { + $item = &$saveVars[ 'item' ]; + $tpl->tpl_vars[ $item[ 0 ] ]->value = $item[ 1 ]->value; + } + if (isset($saveVars[ 'key' ])) { + $tpl->tpl_vars[ $saveVars[ 'key' ][ 0 ] ] = $saveVars[ 'key' ][ 1 ]; + } + if (isset($saveVars[ 'named' ])) { + $tpl->tpl_vars[ $saveVars[ 'named' ][ 0 ] ] = $saveVars[ 'named' ][ 1 ]; + } + } + $levels--; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_getincludepath.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_getincludepath.php new file mode 100644 index 000000000..5ae98304e --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_getincludepath.php @@ -0,0 +1,181 @@ +_include_path !== $_i_path) { + $this->_include_dirs = array(); + $this->_include_path = $_i_path; + $_dirs = (array)explode(PATH_SEPARATOR, $_i_path); + foreach ($_dirs as $_path) { + if (is_dir($_path)) { + $this->_include_dirs[] = $smarty->_realpath($_path . DIRECTORY_SEPARATOR, true); + } + } + return true; + } + return false; + } + + /** + * return array with include path directories + * + * @param \Smarty $smarty + * + * @return array + */ + public function getIncludePathDirs(Smarty $smarty) + { + $this->isNewIncludePath($smarty); + return $this->_include_dirs; + } + + /** + * Return full file path from PHP include_path + * + * @param string[] $dirs + * @param string $file + * @param \Smarty $smarty + * + * @return bool|string full filepath or false + */ + public function getIncludePath($dirs, $file, Smarty $smarty) + { + //if (!(isset($this->_has_stream_include) ? $this->_has_stream_include : $this->_has_stream_include = false)) { + if (!(isset($this->_has_stream_include) ? $this->_has_stream_include : + $this->_has_stream_include = function_exists('stream_resolve_include_path')) + ) { + $this->isNewIncludePath($smarty); + } + // try PHP include_path + foreach ($dirs as $dir) { + $dir_n = isset($this->number[ $dir ]) ? $this->number[ $dir ] : $this->number[ $dir ] = $this->counter++; + if (isset($this->isFile[ $dir_n ][ $file ])) { + if ($this->isFile[ $dir_n ][ $file ]) { + return $this->isFile[ $dir_n ][ $file ]; + } else { + continue; + } + } + if (isset($this->_user_dirs[ $dir_n ])) { + if (false === $this->_user_dirs[ $dir_n ]) { + continue; + } else { + $dir = $this->_user_dirs[ $dir_n ]; + } + } else { + if ($dir[ 0 ] === '/' || $dir[ 1 ] === ':') { + $dir = str_ireplace(getcwd(), '.', $dir); + if ($dir[ 0 ] === '/' || $dir[ 1 ] === ':') { + $this->_user_dirs[ $dir_n ] = false; + continue; + } + } + $dir = substr($dir, 2); + $this->_user_dirs[ $dir_n ] = $dir; + } + if ($this->_has_stream_include) { + $path = stream_resolve_include_path($dir . (isset($file) ? $file : '')); + if ($path) { + return $this->isFile[ $dir_n ][ $file ] = $path; + } + } else { + foreach ($this->_include_dirs as $key => $_i_path) { + $path = isset($this->isPath[ $key ][ $dir_n ]) ? $this->isPath[ $key ][ $dir_n ] : + $this->isPath[ $key ][ $dir_n ] = is_dir($_dir_path = $_i_path . $dir) ? $_dir_path : false; + if ($path === false) { + continue; + } + if (isset($file)) { + $_file = $this->isFile[ $dir_n ][ $file ] = (is_file($path . $file)) ? $path . $file : false; + if ($_file) { + return $_file; + } + } else { + // no file was given return directory path + return $path; + } + } + } + } + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_inheritance.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_inheritance.php new file mode 100644 index 000000000..8f7f02d59 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_inheritance.php @@ -0,0 +1,251 @@ +state === 3 && (strpos($tpl->template_resource, 'extendsall') === false)) { + $tpl->inheritance = new Smarty_Internal_Runtime_Inheritance(); + $tpl->inheritance->init($tpl, $initChild, $blockNames); + return; + } + ++$this->tplIndex; + $this->sources[ $this->tplIndex ] = $tpl->source; + // start of child sub template(s) + if ($initChild) { + $this->state = 1; + if (!$this->inheritanceLevel) { + //grab any output of child templates + ob_start(); + } + ++$this->inheritanceLevel; + // $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart'); + // $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd'); + } + // if state was waiting for parent change state to parent + if ($this->state === 2) { + $this->state = 3; + } + } + + /** + * End of child template(s) + * - if outer level is reached flush output buffer and switch to wait for parent template state + * + * @param \Smarty_Internal_Template $tpl + * @param null|string $template optional name of inheritance parent template + * @param null|string $uid uid of inline template + * @param null|string $func function call name of inline template + * + * @throws \Exception + * @throws \SmartyException + */ + public function endChild(Smarty_Internal_Template $tpl, $template = null, $uid = null, $func = null) + { + --$this->inheritanceLevel; + if (!$this->inheritanceLevel) { + ob_end_clean(); + $this->state = 2; + } + if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends') + || $tpl->smarty->extends_recursion) + ) { + $tpl->_subTemplateRender( + $template, + $tpl->cache_id, + $tpl->compile_id, + $tpl->caching ? 9999 : 0, + $tpl->cache_lifetime, + array(), + 2, + false, + $uid, + $func + ); + } + } + + /** + * Smarty_Internal_Block constructor. + * - if outer level {block} of child template ($state === 1) save it as child root block + * - otherwise process inheritance and render + * + * @param \Smarty_Internal_Template $tpl + * @param $className + * @param string $name + * @param int|null $tplIndex index of outer level {block} if nested + * + * @throws \SmartyException + */ + public function instanceBlock(Smarty_Internal_Template $tpl, $className, $name, $tplIndex = null) + { + $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex); + if (isset($this->childRoot[ $name ])) { + $block->child = $this->childRoot[ $name ]; + } + if ($this->state === 1) { + $this->childRoot[ $name ] = $block; + return; + } + // make sure we got child block of child template of current block + while ($block->child && $block->child->child && $block->tplIndex <= $block->child->tplIndex) { + $block->child = $block->child->child; + } + $this->process($tpl, $block); + } + + /** + * Goto child block or render this + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * @param \Smarty_Internal_Block|null $parent + * + * @throws \SmartyException + */ + public function process( + Smarty_Internal_Template $tpl, + Smarty_Internal_Block $block, + Smarty_Internal_Block $parent = null + ) { + if ($block->hide && !isset($block->child)) { + return; + } + if (isset($block->child) && $block->child->hide && !isset($block->child->child)) { + $block->child = null; + } + $block->parent = $parent; + if ($block->append && !$block->prepend && isset($parent)) { + $this->callParent($tpl, $block, '\'{block append}\''); + } + if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) { + $this->callBlock($block, $tpl); + } else { + $this->process($tpl, $block->child, $block); + } + if ($block->prepend && isset($parent)) { + $this->callParent($tpl, $block, '{block prepend}'); + if ($block->append) { + if ($block->callsChild || !isset($block->child) + || ($block->child->hide && !isset($block->child->child)) + ) { + $this->callBlock($block, $tpl); + } else { + $this->process($tpl, $block->child, $block); + } + } + } + $block->parent = null; + } + + /** + * Render child on \$smarty.block.child + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * + * @return null|string block content + * @throws \SmartyException + */ + public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block) + { + if (isset($block->child)) { + $this->process($tpl, $block->child, $block); + } + } + + /** + * Render parent block on \$smarty.block.parent or {block append/prepend} + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * @param string $tag + * + * @return null|string block content + * @throws \SmartyException + */ + public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $tag) + { + if (isset($block->parent)) { + $this->callBlock($block->parent, $tpl); + } else { + throw new SmartyException("inheritance: illegal '{$tag}' used in child template '{$tpl->inheritance->sources[$block->tplIndex]->filepath}' block '{$block->name}'"); + } + } + + /** + * render block + * + * @param \Smarty_Internal_Block $block + * @param \Smarty_Internal_Template $tpl + */ + public function callBlock(Smarty_Internal_Block $block, Smarty_Internal_Template $tpl) + { + $this->sourceStack[] = $tpl->source; + $tpl->source = $this->sources[ $block->tplIndex ]; + $block->callBlock($tpl); + $tpl->source = array_pop($this->sourceStack); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_make_nocache.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_make_nocache.php new file mode 100644 index 000000000..53069148d --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_make_nocache.php @@ -0,0 +1,54 @@ +tpl_vars[ $var ])) { + $export = + preg_replace('/^Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true)); + if (preg_match('/(\w+)::__set_state/', $export, $match)) { + throw new SmartyException("{make_nocache \${$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'"); + } + echo "/*%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/smarty->ext->_make_nocache->store(\$_smarty_tpl, '{$var}', ", '\\') . + $export . ");?>\n/*/%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/"; + } + } + + /** + * Store variable value saved while rendering compiled template in cached template context + * + * @param \Smarty_Internal_Template $tpl + * @param string $var variable name + * @param array $properties + */ + public function store(Smarty_Internal_Template $tpl, $var, $properties) + { + // do not overwrite existing nocache variables + if (!isset($tpl->tpl_vars[ $var ]) || !$tpl->tpl_vars[ $var ]->nocache) { + $newVar = new Smarty_Variable(); + unset($properties[ 'nocache' ]); + foreach ($properties as $k => $v) { + $newVar->$k = $v; + } + $tpl->tpl_vars[ $var ] = $newVar; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_tplfunction.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_tplfunction.php new file mode 100644 index 000000000..e5f8e48f7 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_tplfunction.php @@ -0,0 +1,177 @@ +tplFunctions[ $name ]) ? $tpl->tplFunctions[ $name ] : + (isset($tpl->smarty->tplFunctions[ $name ]) ? $tpl->smarty->tplFunctions[ $name ] : null); + if (isset($funcParam)) { + if (!$tpl->caching || ($tpl->caching && $nocache)) { + $function = $funcParam[ 'call_name' ]; + } else { + if (isset($funcParam[ 'call_name_caching' ])) { + $function = $funcParam[ 'call_name_caching' ]; + } else { + $function = $funcParam[ 'call_name' ]; + } + } + if (function_exists($function)) { + $this->saveTemplateVariables($tpl, $name); + $function($tpl, $params); + $this->restoreTemplateVariables($tpl, $name); + return; + } + // try to load template function dynamically + if ($this->addTplFuncToCache($tpl, $name, $function)) { + $this->saveTemplateVariables($tpl, $name); + $function($tpl, $params); + $this->restoreTemplateVariables($tpl, $name); + return; + } + } + throw new SmartyException("Unable to find template function '{$name}'"); + } + + /** + * Register template functions defined by template + * + * @param \Smarty|\Smarty_Internal_Template|\Smarty_Internal_TemplateBase $obj + * @param array $tplFunctions source information array of + * template functions defined + * in template + * @param bool $override if true replace existing + * functions with same name + */ + public function registerTplFunctions(Smarty_Internal_TemplateBase $obj, $tplFunctions, $override = true) + { + $obj->tplFunctions = + $override ? array_merge($obj->tplFunctions, $tplFunctions) : array_merge($tplFunctions, $obj->tplFunctions); + // make sure that the template functions are known in parent templates + if ($obj->_isSubTpl()) { + $obj->smarty->ext->_tplFunction->registerTplFunctions($obj->parent, $tplFunctions, false); + } else { + $obj->smarty->tplFunctions = $override ? array_merge($obj->smarty->tplFunctions, $tplFunctions) : + array_merge($tplFunctions, $obj->smarty->tplFunctions); + } + } + + /** + * Return source parameter array for single or all template functions + * + * @param \Smarty_Internal_Template $tpl template object + * @param null|string $name template function name + * + * @return array|bool|mixed + */ + public function getTplFunction(Smarty_Internal_Template $tpl, $name = null) + { + if (isset($name)) { + return isset($tpl->tplFunctions[ $name ]) ? $tpl->tplFunctions[ $name ] : + (isset($tpl->smarty->tplFunctions[ $name ]) ? $tpl->smarty->tplFunctions[ $name ] : false); + } else { + return empty($tpl->tplFunctions) ? $tpl->smarty->tplFunctions : $tpl->tplFunctions; + } + } + + /** + * Add template function to cache file for nocache calls + * + * @param Smarty_Internal_Template $tpl + * @param string $_name template function name + * @param string $_function PHP function name + * + * @return bool + */ + public function addTplFuncToCache(Smarty_Internal_Template $tpl, $_name, $_function) + { + $funcParam = $tpl->tplFunctions[ $_name ]; + if (is_file($funcParam[ 'compiled_filepath' ])) { + // read compiled file + $code = file_get_contents($funcParam[ 'compiled_filepath' ]); + // grab template function + if (preg_match("/\/\* {$_function} \*\/([\S\s]*?)\/\*\/ {$_function} \*\//", $code, $match)) { + // grab source info from file dependency + preg_match("/\s*'{$funcParam['uid']}'([\S\s]*?)\),/", $code, $match1); + unset($code); + // make PHP function known + eval($match[ 0 ]); + if (function_exists($_function)) { + // search cache file template + $tplPtr = $tpl; + while (!isset($tplPtr->cached) && isset($tplPtr->parent)) { + $tplPtr = $tplPtr->parent; + } + // add template function code to cache file + if (isset($tplPtr->cached)) { + $content = $tplPtr->cached->read($tplPtr); + if ($content) { + // check if we must update file dependency + if (!preg_match("/'{$funcParam['uid']}'(.*?)'nocache_hash'/", $content, $match2)) { + $content = preg_replace("/('file_dependency'(.*?)\()/", "\\1{$match1[0]}", $content); + } + $tplPtr->smarty->ext->_updateCache->write( + $tplPtr, + preg_replace('/\s*\?>\s*$/', "\n", $content) . + "\n" . preg_replace( + array( + '/^\s*<\?php\s+/', + '/\s*\?>\s*$/', + ), + "\n", + $match[ 0 ] + ) + ); + } + } + return true; + } + } + } + return false; + } + + /** + * Save current template variables on stack + * + * @param \Smarty_Internal_Template $tpl + * @param string $name stack name + */ + public function saveTemplateVariables(Smarty_Internal_Template $tpl, $name) + { + $tpl->_cache[ 'varStack' ][] = + array('tpl' => $tpl->tpl_vars, 'config' => $tpl->config_vars, 'name' => "_tplFunction_{$name}"); + } + + /** + * Restore saved variables into template objects + * + * @param \Smarty_Internal_Template $tpl + * @param string $name stack name + */ + public function restoreTemplateVariables(Smarty_Internal_Template $tpl, $name) + { + if (isset($tpl->_cache[ 'varStack' ])) { + $vars = array_pop($tpl->_cache[ 'varStack' ]); + $tpl->tpl_vars = $vars[ 'tpl' ]; + $tpl->config_vars = $vars[ 'config' ]; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_updatecache.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_updatecache.php new file mode 100644 index 000000000..c1abbb321 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_updatecache.php @@ -0,0 +1,183 @@ +compiled)) { + $_template->loadCompiled(); + } + $_template->compiled->render($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_cache($_template); + } + $this->removeNoCacheHash($cached, $_template, $no_output_filter); + $compile_check = (int)$_template->compile_check; + $_template->compile_check = Smarty::COMPILECHECK_OFF; + if ($_template->_isSubTpl()) { + $_template->compiled->unifunc = $_template->parent->compiled->unifunc; + } + if (!$_template->cached->processed) { + $_template->cached->process($_template, true); + } + $_template->compile_check = $compile_check; + $cached->getRenderedTemplateCode($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + } + + /** + * Sanitize content and write it to cache resource + * + * @param \Smarty_Template_Cached $cached + * @param Smarty_Internal_Template $_template + * @param bool $no_output_filter + * + * @throws \SmartyException + */ + public function removeNoCacheHash( + Smarty_Template_Cached $cached, + Smarty_Internal_Template $_template, + $no_output_filter + ) { + $php_pattern = '/(<%|%>|<\?php|<\?|\?>|)/'; + $content = ob_get_clean(); + $hash_array = $cached->hashes; + $hash_array[ $_template->compiled->nocache_hash ] = true; + $hash_array = array_keys($hash_array); + $nocache_hash = '(' . implode('|', $hash_array) . ')'; + $_template->cached->has_nocache_code = false; + // get text between non-cached items + $cache_split = + preg_split( + "!/\*%%SmartyNocache:{$nocache_hash}%%\*\/(.+?)/\*/%%SmartyNocache:{$nocache_hash}%%\*/!s", + $content + ); + // get non-cached items + preg_match_all( + "!/\*%%SmartyNocache:{$nocache_hash}%%\*\/(.+?)/\*/%%SmartyNocache:{$nocache_hash}%%\*/!s", + $content, + $cache_parts + ); + $content = ''; + // loop over items, stitch back together + foreach ($cache_split as $curr_idx => $curr_split) { + if (preg_match($php_pattern, $curr_split)) { + // escape PHP tags in template content + $php_split = preg_split( + $php_pattern, + $curr_split + ); + preg_match_all( + $php_pattern, + $curr_split, + $php_parts + ); + foreach ($php_split as $idx_php => $curr_php) { + $content .= $curr_php; + if (isset($php_parts[ 0 ][ $idx_php ])) { + $content .= "\n"; + } + } + } else { + $content .= $curr_split; + } + if (isset($cache_parts[ 0 ][ $curr_idx ])) { + $_template->cached->has_nocache_code = true; + $content .= $cache_parts[ 2 ][ $curr_idx ]; + } + } + if (!$no_output_filter && !$_template->cached->has_nocache_code + && (isset($_template->smarty->autoload_filters[ 'output' ]) + || isset($_template->smarty->registered_filters[ 'output' ])) + ) { + $content = $_template->smarty->ext->_filterHandler->runFilter('output', $content, $_template); + } + // write cache file content + $this->writeCachedContent($_template, $content); + } + + /** + * Writes the content to cache resource + * + * @param Smarty_Internal_Template $_template + * @param string $content + * + * @return bool + */ + public function writeCachedContent(Smarty_Internal_Template $_template, $content) + { + if ($_template->source->handler->recompiled || !$_template->caching + ) { + // don't write cache file + return false; + } + if (!isset($_template->cached)) { + $_template->loadCached(); + } + $content = $_template->smarty->ext->_codeFrame->create($_template, $content, '', true); + return $this->write($_template, $content); + } + + /** + * Write this cache object to handler + * + * @param Smarty_Internal_Template $_template template object + * @param string $content content to cache + * + * @return bool success + */ + public function write(Smarty_Internal_Template $_template, $content) + { + if (!$_template->source->handler->recompiled) { + $cached = $_template->cached; + if ($cached->handler->writeCachedContent($_template, $content)) { + $cached->content = null; + $cached->timestamp = time(); + $cached->exists = true; + $cached->valid = true; + $cached->cache_lifetime = $_template->cache_lifetime; + $cached->processed = false; + if ($_template->smarty->cache_locking) { + $cached->handler->releaseLock($_template->smarty, $cached); + } + return true; + } + $cached->content = null; + $cached->timestamp = false; + $cached->exists = false; + $cached->valid = false; + $cached->processed = false; + } + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_updatescope.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_updatescope.php new file mode 100644 index 000000000..2240f97ca --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_updatescope.php @@ -0,0 +1,115 @@ +_updateVarStack($tpl, $varName); + $tagScope = $tagScope & ~Smarty::SCOPE_LOCAL; + if (!$tpl->scope && !$tagScope) { + return; + } + } + $mergedScope = $tagScope | $tpl->scope; + if ($mergedScope) { + if ($mergedScope & Smarty::SCOPE_GLOBAL && $varName) { + Smarty::$global_tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; + } + // update scopes + foreach ($this->_getAffectedScopes($tpl, $mergedScope) as $ptr) { + $this->_updateVariableInOtherScope($ptr->tpl_vars, $tpl, $varName); + if ($tagScope && $ptr->_isTplObj() && isset($tpl->_cache[ 'varStack' ])) { + $this->_updateVarStack($ptr, $varName); + } + } + } + } + + /** + * Get array of objects which needs to be updated by given scope value + * + * @param Smarty_Internal_Template $tpl + * @param int $mergedScope merged tag and template scope to which bubble up variable value + * + * @return array + */ + public function _getAffectedScopes(Smarty_Internal_Template $tpl, $mergedScope) + { + $_stack = array(); + $ptr = $tpl->parent; + if ($mergedScope && isset($ptr) && $ptr->_isTplObj()) { + $_stack[] = $ptr; + $mergedScope = $mergedScope & ~Smarty::SCOPE_PARENT; + if (!$mergedScope) { + // only parent was set, we are done + return $_stack; + } + $ptr = $ptr->parent; + } + while (isset($ptr) && $ptr->_isTplObj()) { + $_stack[] = $ptr; + $ptr = $ptr->parent; + } + if ($mergedScope & Smarty::SCOPE_SMARTY) { + if (isset($tpl->smarty)) { + $_stack[] = $tpl->smarty; + } + } elseif ($mergedScope & Smarty::SCOPE_ROOT) { + while (isset($ptr)) { + if (!$ptr->_isTplObj()) { + $_stack[] = $ptr; + break; + } + $ptr = $ptr->parent; + } + } + return $_stack; + } + + /** + * Update variable in other scope + * + * @param array $tpl_vars template variable array + * @param \Smarty_Internal_Template $from + * @param string $varName variable name + */ + public function _updateVariableInOtherScope(&$tpl_vars, Smarty_Internal_Template $from, $varName) + { + if (!isset($tpl_vars[ $varName ])) { + $tpl_vars[ $varName ] = clone $from->tpl_vars[ $varName ]; + } else { + $tpl_vars[ $varName ] = clone $tpl_vars[ $varName ]; + $tpl_vars[ $varName ]->value = $from->tpl_vars[ $varName ]->value; + } + } + + /** + * Update variable in template local variable stack + * + * @param \Smarty_Internal_Template $tpl + * @param string|null $varName variable name or null for config variables + */ + public function _updateVarStack(Smarty_Internal_Template $tpl, $varName) + { + $i = 0; + while (isset($tpl->_cache[ 'varStack' ][ $i ])) { + $this->_updateVariableInOtherScope($tpl->_cache[ 'varStack' ][ $i ][ 'tpl' ], $tpl, $varName); + $i++; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_writefile.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_writefile.php new file mode 100644 index 000000000..4383e6f38 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_runtime_writefile.php @@ -0,0 +1,100 @@ +_file_perms : 0644; + $_dir_perms = + property_exists($smarty, '_dir_perms') ? (isset($smarty->_dir_perms) ? $smarty->_dir_perms : 0777) : 0771; + if ($_file_perms !== null) { + $old_umask = umask(0); + } + $_dirpath = dirname($_filepath); + // if subdirs, create dir structure + if ($_dirpath !== '.') { + $i = 0; + // loop if concurrency problem occurs + // see https://bugs.php.net/bug.php?id=35326 + while (!is_dir($_dirpath)) { + if (@mkdir($_dirpath, $_dir_perms, true)) { + break; + } + clearstatcache(); + if (++$i === 3) { + error_reporting($_error_reporting); + throw new SmartyException("unable to create directory {$_dirpath}"); + } + sleep(1); + } + } + // write to tmp file, then move to overt file lock race condition + $_tmp_file = $_dirpath . DIRECTORY_SEPARATOR . str_replace(array('.', ','), '_', uniqid('wrt', true)); + if (!file_put_contents($_tmp_file, $_contents)) { + error_reporting($_error_reporting); + throw new SmartyException("unable to write file {$_tmp_file}"); + } + /* + * Windows' rename() fails if the destination exists, + * Linux' rename() properly handles the overwrite. + * Simply unlink()ing a file might cause other processes + * currently reading that file to fail, but linux' rename() + * seems to be smart enough to handle that for us. + */ + if (Smarty::$_IS_WINDOWS) { + // remove original file + if (is_file($_filepath)) { + @unlink($_filepath); + } + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + } else { + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + if (!$success) { + // remove original file + if (is_file($_filepath)) { + @unlink($_filepath); + } + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + } + } + if (!$success) { + error_reporting($_error_reporting); + throw new SmartyException("unable to write file {$_filepath}"); + } + if ($_file_perms !== null) { + // set file permissions + chmod($_filepath, $_file_perms); + umask($old_umask); + } + error_reporting($_error_reporting); + return true; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_smartytemplatecompiler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_smartytemplatecompiler.php index dcc89c673..21f4e3fdd 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_smartytemplatecompiler.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_smartytemplatecompiler.php @@ -1,72 +1,184 @@ smarty = $smarty; - parent::__construct(); + parent::__construct($smarty); // get required plugins $this->lexer_class = $lexer_class; $this->parser_class = $parser_class; - } + } /** - * Methode to compile a Smarty template - * - * @param $_content template source + * method to compile a Smarty template + * + * @param mixed $_content template source + * @param bool $isTemplateSource + * * @return bool true if compiling succeeded, false if it failed + * @throws \SmartyCompilerException */ - protected function doCompile($_content) + protected function doCompile($_content, $isTemplateSource = false) { /* here is where the compiling takes place. Smarty - tags in the templates are replaces with PHP code, - then written to compiled files. */ + tags in the templates are replaces with PHP code, + then written to compiled files. */ // init the lexer/parser to compile the template - $this->lex = new $this->lexer_class($_content, $this); - $this->parser = new $this->parser_class($this->lex, $this); - if (isset($this->smarty->_parserdebug)) $this->parser->PrintTrace(); + $this->parser = + new $this->parser_class( + new $this->lexer_class( + str_replace( + array( + "\r\n", + "\r" + ), + "\n", + $_content + ), + $this + ), + $this + ); + if ($isTemplateSource && $this->template->caching) { + $this->parser->insertPhpCode("compiled->nocache_hash = '{$this->nocache_hash}';\n?>\n"); + } + if (function_exists('mb_internal_encoding') + && function_exists('ini_get') + && ((int)ini_get('mbstring.func_overload')) & 2 + ) { + $mbEncoding = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } else { + $mbEncoding = null; + } + if ($this->smarty->_parserdebug) { + $this->parser->PrintTrace(); + $this->parser->lex->PrintTrace(); + } // get tokens from lexer and parse them - while ($this->lex->yylex() && !$this->abort_and_recompile) { - if (isset($this->smarty->_parserdebug)) echo "
Line {$this->lex->line} Parsing  {$this->parser->yyTokenName[$this->lex->token]} Token " . htmlentities($this->lex->value) . "
"; - $this->parser->doParse($this->lex->token, $this->lex->value); - } - - if ($this->abort_and_recompile) { - // exit here on abort - return false; - } + while ($this->parser->lex->yylex()) { + if ($this->smarty->_parserdebug) { + echo "
Line {$this->parser->lex->line} Parsing  {$this->parser->yyTokenName[$this->parser->lex->token]} Token " .
+                     htmlentities($this->parser->lex->value) . "
"; + } + $this->parser->doParse($this->parser->lex->token, $this->parser->lex->value); + } // finish parsing process - $this->parser->doParse(0, 0); + $this->parser->doParse(0, 0); + if ($mbEncoding) { + mb_internal_encoding($mbEncoding); + } // check for unclosed tags if (count($this->_tag_stack) > 0) { // get stacked info - list($_open_tag, $_data) = array_pop($this->_tag_stack); - $this->trigger_template_error("unclosed {" . $_open_tag . "} tag"); - } + list($openTag, $_data) = array_pop($this->_tag_stack); + $this->trigger_template_error( + "unclosed {$this->smarty->left_delimiter}" . $openTag . + "{$this->smarty->right_delimiter} tag" + ); + } + // call post compile callbacks + foreach ($this->postCompileCallbacks as $cb) { + $parameter = $cb; + $parameter[ 0 ] = $this; + call_user_func_array($cb[ 0 ], $parameter); + } // return compiled code - // return str_replace(array("? >\nparser->retvalue); - return $this->parser->retvalue; - } -} + return $this->prefixCompiledCode . $this->parser->retvalue . $this->postfixCompiledCode; + } -?> \ No newline at end of file + /** + * Register a post compile callback + * - when the callback is called after template compiling the compiler object will be inserted as first parameter + * + * @param callback $callback + * @param array $parameter optional parameter array + * @param string $key optional key for callback + * @param bool $replace if true replace existing keyed callback + */ + public function registerPostCompileCallback($callback, $parameter = array(), $key = null, $replace = false) + { + array_unshift($parameter, $callback); + if (isset($key)) { + if ($replace || !isset($this->postCompileCallbacks[ $key ])) { + $this->postCompileCallbacks[ $key ] = $parameter; + } + } else { + $this->postCompileCallbacks[] = $parameter; + } + } + + /** + * Remove a post compile callback + * + * @param string $key callback key + */ + public function unregisterPostCompileCallback($key) + { + unset($this->postCompileCallbacks[ $key ]); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php index 070fb840d..bae22a7d5 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php @@ -1,998 +1,740 @@ array(), - 'nocache_hash' => '', - 'function' => array()); - // required plugins - public $required_plugins = array('compiled' => array(), 'nocache' => array()); - public $saved_modifier = null; - public $smarty = null; - // blocks for template inheritance - public $block_data = array(); - public $wrapper = null; + + /** + * Template Id + * + * @var null|string + */ + public $templateId = null; + + /** + * Scope in which variables shall be assigned + * + * @var int + */ + public $scope = 0; + + /** + * Flag which is set while rending a cache file + * + * @var bool + */ + public $isRenderingCache = false; + + /** + * Callbacks called before rendering template + * + * @var callback[] + */ + public $startRenderCallbacks = array(); + + /** + * Callbacks called after rendering template + * + * @var callback[] + */ + public $endRenderCallbacks = array(); + /** * Create template data object - * * Some of the global Smarty settings copied to template scope - * It load the required template resources and cacher plugins - * - * @param string $template_resource template resource string - * @param object $_parent back pointer to parent object with variables or null - * @param mixed $_cache_id cache id or null - * @param mixed $_compile_id compile id or null - */ - public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null) - { - $this->smarty = &$smarty; + * It load the required template resources and caching plugins + * + * @param string $template_resource template resource string + * @param Smarty $smarty Smarty instance + * @param null|\Smarty_Internal_Template|\Smarty|\Smarty_Internal_Data $_parent back pointer to parent + * object with variables or + * null + * @param mixed $_cache_id cache id or null + * @param mixed $_compile_id compile id or null + * @param bool|int|null $_caching use caching? + * @param int|null $_cache_lifetime cache life-time in + * seconds + * @param bool $_isConfig + * + * @throws \SmartyException + */ + public function __construct( + $template_resource, + Smarty $smarty, + Smarty_Internal_Data $_parent = null, + $_cache_id = null, + $_compile_id = null, + $_caching = null, + $_cache_lifetime = null, + $_isConfig = false + ) { + $this->smarty = $smarty; // Smarty parameter $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id; $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id; - $this->caching = $_caching === null ? $this->smarty->caching : $_caching; - if ($this->caching === true) $this->caching = Smarty::CACHING_LIFETIME_CURRENT; - $this->cache_lifetime = $_cache_lifetime === null ?$this->smarty->cache_lifetime : $_cache_lifetime; - $this->parent = $_parent; - // dummy local smarty variable - $this->tpl_vars['smarty'] = new Smarty_Variable; + $this->caching = (int)($_caching === null ? $this->smarty->caching : $_caching); + $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime; + $this->compile_check = (int)$smarty->compile_check; + $this->parent = $_parent; // Template resource - $this->template_resource = $template_resource; - // copy block data of template inheritance - if ($this->parent instanceof Smarty_Internal_Template) { - $this->block_data = $this->parent->block_data; + $this->template_resource = $template_resource; + $this->source = $_isConfig ? Smarty_Template_Config::load($this) : Smarty_Template_Source::load($this); + parent::__construct(); + if ($smarty->security_policy && method_exists($smarty->security_policy, 'registerCallBacks')) { + $smarty->security_policy->registerCallBacks($this); } - - } + } /** - * Returns the template filepath - * - * The template filepath is determined by the actual resource handler - * - * @return string the template filepath + * render template + * + * @param bool $no_output_filter if true do not run output filter + * @param null|bool $display true: display, false: fetch null: sub-template + * + * @return string + * @throws \Exception + * @throws \SmartyException */ - public function getTemplateFilepath () + public function render($no_output_filter = true, $display = null) { - return $this->template_filepath === null ? - $this->template_filepath = $this->resource_object->getTemplateFilepath($this) : - $this->template_filepath; - } + if ($this->smarty->debugging) { + if (!isset($this->smarty->_debug)) { + $this->smarty->_debug = new Smarty_Internal_Debug(); + } + $this->smarty->_debug->start_template($this, $display); + } + // checks if template exists + if (!$this->source->exists) { + throw new SmartyException( + "Unable to load template '{$this->source->type}:{$this->source->name}'" . + ($this->_isSubTpl() ? " in '{$this->parent->template_resource}'" : '') + ); + } + // disable caching for evaluated code + if ($this->source->handler->recompiled) { + $this->caching = Smarty::CACHING_OFF; + } + // read from cache or render + if ($this->caching === Smarty::CACHING_LIFETIME_CURRENT || $this->caching === Smarty::CACHING_LIFETIME_SAVED) { + if (!isset($this->cached) || $this->cached->cache_id !== $this->cache_id + || $this->cached->compile_id !== $this->compile_id + ) { + $this->loadCached(true); + } + $this->cached->render($this, $no_output_filter); + } else { + if (!isset($this->compiled) || $this->compiled->compile_id !== $this->compile_id) { + $this->loadCompiled(true); + } + $this->compiled->render($this); + } + // display or fetch + if ($display) { + if ($this->caching && $this->smarty->cache_modified_check) { + $this->smarty->ext->_cacheModify->cacheModifiedCheck( + $this->cached, + $this, + isset($content) ? $content : ob_get_clean() + ); + } else { + if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) + && !$no_output_filter && (isset($this->smarty->autoload_filters[ 'output' ]) + || isset($this->smarty->registered_filters[ 'output' ])) + ) { + echo $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this); + } else { + echo ob_get_clean(); + } + } + if ($this->smarty->debugging) { + $this->smarty->_debug->end_template($this); + // debug output + $this->smarty->_debug->display_debug($this, true); + } + return ''; + } else { + if ($this->smarty->debugging) { + $this->smarty->_debug->end_template($this); + if ($this->smarty->debugging === 2 && $display === false) { + $this->smarty->_debug->display_debug($this, true); + } + } + if (!$no_output_filter + && (!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) + && (isset($this->smarty->autoload_filters[ 'output' ]) + || isset($this->smarty->registered_filters[ 'output' ])) + ) { + return $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this); + } + // return cache content + return null; + } + } /** - * Returns the timpestamp of the template source - * - * The template timestamp is determined by the actual resource handler - * - * @return integer the template timestamp + * Runtime function to render sub-template + * + * @param string $template template name + * @param mixed $cache_id cache id + * @param mixed $compile_id compile id + * @param integer $caching cache mode + * @param integer $cache_lifetime life time of cache data + * @param array $data passed parameter template variables + * @param int $scope scope in which {include} should execute + * @param bool $forceTplCache cache template object + * @param string $uid file dependency uid + * @param string $content_func function name + * + * @throws \Exception + * @throws \SmartyException */ - public function getTemplateTimestamp () - { - return $this->template_timestamp === null ? - $this->template_timestamp = $this->resource_object->getTemplateTimestamp($this) : - $this->template_timestamp; - } + public function _subTemplateRender( + $template, + $cache_id, + $compile_id, + $caching, + $cache_lifetime, + $data, + $scope, + $forceTplCache, + $uid = null, + $content_func = null + ) { + $tpl = clone $this; + $tpl->parent = $this; + $smarty = &$this->smarty; + $_templateId = $smarty->_getTemplateId($template, $cache_id, $compile_id, $caching, $tpl); + // recursive call ? + if (isset($tpl->templateId) ? $tpl->templateId : $tpl->_getTemplateId() !== $_templateId) { + // already in template cache? + if (isset(self::$tplObjCache[ $_templateId ])) { + // copy data from cached object + $cachedTpl = &self::$tplObjCache[ $_templateId ]; + $tpl->templateId = $cachedTpl->templateId; + $tpl->template_resource = $cachedTpl->template_resource; + $tpl->cache_id = $cachedTpl->cache_id; + $tpl->compile_id = $cachedTpl->compile_id; + $tpl->source = $cachedTpl->source; + if (isset($cachedTpl->compiled)) { + $tpl->compiled = $cachedTpl->compiled; + } else { + unset($tpl->compiled); + } + if ($caching !== 9999 && isset($cachedTpl->cached)) { + $tpl->cached = $cachedTpl->cached; + } else { + unset($tpl->cached); + } + } else { + $tpl->templateId = $_templateId; + $tpl->template_resource = $template; + $tpl->cache_id = $cache_id; + $tpl->compile_id = $compile_id; + if (isset($uid)) { + // for inline templates we can get all resource information from file dependency + list($filepath, $timestamp, $type) = $tpl->compiled->file_dependency[ $uid ]; + $tpl->source = new Smarty_Template_Source($smarty, $filepath, $type, $filepath); + $tpl->source->filepath = $filepath; + $tpl->source->timestamp = $timestamp; + $tpl->source->exists = true; + $tpl->source->uid = $uid; + } else { + $tpl->source = Smarty_Template_Source::load($tpl); + unset($tpl->compiled); + } + if ($caching !== 9999) { + unset($tpl->cached); + } + } + } else { + // on recursive calls force caching + $forceTplCache = true; + } + $tpl->caching = $caching; + $tpl->cache_lifetime = $cache_lifetime; + // set template scope + $tpl->scope = $scope; + if (!isset(self::$tplObjCache[ $tpl->templateId ]) && !$tpl->source->handler->recompiled) { + // check if template object should be cached + if ($forceTplCache || (isset(self::$subTplInfo[ $tpl->template_resource ]) + && self::$subTplInfo[ $tpl->template_resource ] > 1) + || ($tpl->_isSubTpl() && isset(self::$tplObjCache[ $tpl->parent->templateId ])) + ) { + self::$tplObjCache[ $tpl->templateId ] = $tpl; + } + } + if (!empty($data)) { + // set up variable values + foreach ($data as $_key => $_val) { + $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val, $this->isRenderingCache); + } + } + if ($tpl->caching === 9999) { + if (!isset($tpl->compiled)) { + $this->loadCompiled(true); + } + if ($tpl->compiled->has_nocache_code) { + $this->cached->hashes[ $tpl->compiled->nocache_hash ] = true; + } + } + $tpl->_cache = array(); + if (isset($uid)) { + if ($smarty->debugging) { + if (!isset($smarty->_debug)) { + $smarty->_debug = new Smarty_Internal_Debug(); + } + $smarty->_debug->start_template($tpl); + $smarty->_debug->start_render($tpl); + } + $tpl->compiled->getRenderedTemplateCode($tpl, $content_func); + if ($smarty->debugging) { + $smarty->_debug->end_template($tpl); + $smarty->_debug->end_render($tpl); + } + } else { + if (isset($tpl->compiled)) { + $tpl->compiled->render($tpl); + } else { + $tpl->render(); + } + } + } /** - * Returns the template source code - * - * The template source is being read by the actual resource handler - * - * @return string the template source + * Get called sub-templates and save call count */ - public function getTemplateSource () - { - if ($this->template_source === null) { - if (!$this->resource_object->getTemplateSource($this)) { - throw new SmartyException("Unable to read template {$this->resource_type} '{$this->resource_name}'"); - } - } - return $this->template_source; - } - - /** - * Returns if the template is existing - * - * The status is determined by the actual resource handler - * - * @return boolean true if the template exists - */ - public function isExisting ($error = false) + public function _subTemplateRegister() { - if ($this->isExisting === null) { - $this->isExisting = $this->resource_object->isExisting($this); - } - if (!$this->isExisting && $error) { - throw new SmartyException("Unable to load template {$this->resource_type} '{$this->resource_name}'"); - } - return $this->isExisting; - } - - /** - * Returns if the current template must be compiled by the Smarty compiler - * - * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration - * - * @return boolean true if the template must be compiled - */ - public function mustCompile () + foreach ($this->compiled->includes as $name => $count) { + if (isset(self::$subTplInfo[ $name ])) { + self::$subTplInfo[ $name ] += $count; + } else { + self::$subTplInfo[ $name ] = $count; + } + } + } + + /** + * Check if this is a sub template + * + * @return bool true is sub template + */ + public function _isSubTpl() { - $this->isExisting(true); - if ($this->mustCompile === null) { - $this->mustCompile = ($this->resource_object->usesCompiler && ($this->smarty->force_compile || $this->resource_object->isEvaluated || $this->getCompiledTimestamp () === false || - // ($this->smarty->compile_check && $this->getCompiledTimestamp () !== $this->getTemplateTimestamp ()))); - ($this->smarty->compile_check && $this->getCompiledTimestamp () < $this->getTemplateTimestamp ()))); - } - return $this->mustCompile; - } + return isset($this->parent) && $this->parent->_isTplObj(); + } /** - * Returns the compiled template filepath - * - * @return string the template filepath + * Assign variable in scope + * + * @param string $varName variable name + * @param mixed $value value + * @param bool $nocache nocache flag + * @param int $scope scope into which variable shall be assigned */ - public function getCompiledFilepath () + public function _assignInScope($varName, $value, $nocache = false, $scope = 0) { - return $this->compiled_filepath === null ? - ($this->compiled_filepath = !$this->resource_object->isEvaluated ? $this->resource_object->getCompiledFilepath($this) : false) : - $this->compiled_filepath; - } + if (isset($this->tpl_vars[ $varName ])) { + $this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ]; + $this->tpl_vars[ $varName ]->value = $value; + if ($nocache || $this->isRenderingCache) { + $this->tpl_vars[ $varName ]->nocache = true; + } + } else { + $this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache || $this->isRenderingCache); + } + if ($scope >= 0) { + if ($scope > 0 || $this->scope > 0) { + $this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope); + } + } + } /** - * Returns the timpestamp of the compiled template - * - * @return integer the template timestamp + * Check if plugins are callable require file otherwise + * + * @param array $plugins required plugins + * + * @throws \SmartyException */ - public function getCompiledTimestamp () + public function _checkPlugins($plugins) { - return $this->compiled_timestamp === null ? - ($this->compiled_timestamp = (!$this->resource_object->isEvaluated && file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false) : - $this->compiled_timestamp; - } + static $checked = array(); + foreach ($plugins as $plugin) { + $name = join('::', (array)$plugin[ 'function' ]); + if (!isset($checked[ $name ])) { + if (!is_callable($plugin[ 'function' ])) { + if (is_file($plugin[ 'file' ])) { + include_once $plugin[ 'file' ]; + if (is_callable($plugin[ 'function' ])) { + $checked[ $name ] = true; + } + } + } else { + $checked[ $name ] = true; + } + } + if (!isset($checked[ $name ])) { + if (false !== $this->smarty->loadPlugin($name)) { + $checked[ $name ] = true; + } else { + throw new SmartyException("Plugin '{$name}' not callable"); + } + } + } + } /** - * Returns the compiled template - * - * It checks if the template must be compiled or just read from the template resource - * - * @return string the compiled template + * This function is executed automatically when a compiled or cached template file is included + * - Decode saved properties from compiled template and cache files + * - Check if compiled or cache file is valid + * + * @param \Smarty_Internal_Template $tpl + * @param array $properties special template properties + * @param bool $cache flag if called from cache file + * + * @return bool flag if compiled or cache file is valid + * @throws \SmartyException */ - public function getCompiledTemplate () + public function _decodeProperties(Smarty_Internal_Template $tpl, $properties, $cache = false) { - if ($this->compiled_template === null) { - // see if template needs compiling. - if ($this->mustCompile()) { - $this->compileTemplateSource(); + // on cache resources other than file check version stored in cache code + if (!isset($properties[ 'version' ]) || Smarty::SMARTY_VERSION !== $properties[ 'version' ]) { + if ($cache) { + $tpl->smarty->clearAllCache(); } else { - if ($this->compiled_template === null) { - $this->compiled_template = !$this->resource_object->isEvaluated && $this->resource_object->usesCompiler ? file_get_contents($this->getCompiledFilepath()) : false; - } - } - } - return $this->compiled_template; - } + $tpl->smarty->clearCompiledTemplate(); + } + return false; + } + $is_valid = true; + if (!empty($properties[ 'file_dependency' ]) + && ((!$cache && $tpl->compile_check) || $tpl->compile_check === Smarty::COMPILECHECK_ON) + ) { + // check file dependencies at compiled code + foreach ($properties[ 'file_dependency' ] as $_file_to_check) { + if ($_file_to_check[ 2 ] === 'file' || $_file_to_check[ 2 ] === 'php') { + if ($tpl->source->filepath === $_file_to_check[ 0 ]) { + // do not recheck current template + continue; + //$mtime = $tpl->source->getTimeStamp(); + } else { + // file and php types can be checked without loading the respective resource handlers + $mtime = is_file($_file_to_check[ 0 ]) ? filemtime($_file_to_check[ 0 ]) : false; + } + } else { + $handler = Smarty_Resource::load($tpl->smarty, $_file_to_check[ 2 ]); + if ($handler->checkTimestamps()) { + $source = Smarty_Template_Source::load($tpl, $tpl->smarty, $_file_to_check[ 0 ]); + $mtime = $source->getTimeStamp(); + } else { + continue; + } + } + if ($mtime === false || $mtime > $_file_to_check[ 1 ]) { + $is_valid = false; + break; + } + } + } + if ($cache) { + // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc + if ($tpl->caching === Smarty::CACHING_LIFETIME_SAVED && $properties[ 'cache_lifetime' ] >= 0 + && (time() > ($tpl->cached->timestamp + $properties[ 'cache_lifetime' ])) + ) { + $is_valid = false; + } + $tpl->cached->cache_lifetime = $properties[ 'cache_lifetime' ]; + $tpl->cached->valid = $is_valid; + $resource = $tpl->cached; + } else { + $tpl->mustCompile = !$is_valid; + $resource = $tpl->compiled; + $resource->includes = isset($properties[ 'includes' ]) ? $properties[ 'includes' ] : array(); + } + if ($is_valid) { + $resource->unifunc = $properties[ 'unifunc' ]; + $resource->has_nocache_code = $properties[ 'has_nocache_code' ]; + // $tpl->compiled->nocache_hash = $properties['nocache_hash']; + $resource->file_dependency = $properties[ 'file_dependency' ]; + } + return $is_valid && !function_exists($properties[ 'unifunc' ]); + } /** * Compiles the template - * * If the template is not evaluated the compiled template is saved on disk + * + * @throws \Exception */ - public function compileTemplateSource () - { - if (!$this->resource_object->isEvaluated) { - $this->properties['file_dependency'] = array(); - $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type); - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_compile($this); - } - // compile template - if (!is_object($this->compiler_object)) { - // load compiler - $this->smarty->loadPlugin($this->resource_object->compiler_class); - $this->compiler_object = new $this->resource_object->compiler_class($this->resource_object->template_lexer_class, $this->resource_object->template_parser_class, $this->smarty); - } - // compile locking - if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated) { - if ($saved_timestamp = $this->getCompiledTimestamp()) { - touch($this->getCompiledFilepath()); - } - } - // call compiler - try { - $this->compiler_object->compileTemplate($this); - } - catch (Exception $e) { - // restore old timestamp in case of error - if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated && $saved_timestamp) { - touch($this->getCompiledFilepath(), $saved_timestamp); - } - throw $e; - } - // compiling succeded - if (!$this->resource_object->isEvaluated && $this->write_compiled_code) { - // write compiled template - Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->compiled_template, $this->smarty); - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_compile($this); - } - // release objects to free memory - Smarty_Internal_TemplateCompilerBase::$_tag_objects = array(); - unset($this->compiler_object->parser->root_buffer, - $this->compiler_object->parser->current_buffer, - $this->compiler_object->parser, - $this->compiler_object->lex, - $this->compiler_object->template, - $this->compiler_object - ); - } - - /** - * Returns the filepath of the cached template output - * - * The filepath is determined by the actual cache resource - * - * @return string the cache filepath - */ - public function getCachedFilepath () + public function compileTemplateSource() { - return $this->cached_filepath === null ? - $this->cached_filepath = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedFilepath($this) : - $this->cached_filepath; - } + return $this->compiled->compileTemplateSource($this); + } /** - * Returns the timpestamp of the cached template output - * - * The timestamp is determined by the actual cache resource - * - * @return integer the template timestamp + * Writes the content to cache resource + * + * @param string $content + * + * @return bool */ - public function getCachedTimestamp () + public function writeCachedContent($content) { - return $this->cached_timestamp === null ? - $this->cached_timestamp = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedTimestamp($this) : - $this->cached_timestamp; - } + return $this->smarty->ext->_updateCache->writeCachedContent($this, $content); + } /** - * Returns the cached template output - * - * @return string |booelan the template content or false if the file does not exist + * Get unique template id + * + * @return string + * @throws \SmartyException */ - public function getCachedContent () + public function _getTemplateId() { - return $this->rendered_content === null ? - $this->rendered_content = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedContents($this) : - $this->rendered_content; - } + return isset($this->templateId) ? $this->templateId : $this->templateId = + $this->smarty->_getTemplateId($this->template_resource, $this->cache_id, $this->compile_id); + } /** - * Writes the cached template output + * runtime error not matching capture tags + * + * @throws \SmartyException */ - public function writeCachedContent ($content) + public function capture_error() { - if ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) { - // don't write cache file - return false; - } - $this->properties['cache_lifetime'] = $this->cache_lifetime; - return $this->cache_resource_object->writeCachedContent($this, $this->createPropertyHeader(true) .$content); - } + throw new SmartyException("Not matching {capture} open/close in '{$this->template_resource}'"); + } /** - * Checks of a valid version redered HTML output is in the cache - * - * If the cache is valid the contents is stored in the template object - * - * @return boolean true if cache is valid + * Load compiled object + * + * @param bool $force force new compiled object */ - public function isCached ($template = null, $cache_id = null, $compile_id = null, $parent = null) - { - if ($template === null) { - $no_render = true; - } elseif ($template === false) { - $no_render = false; - } else { - if ($parent === null) { - $parent = $this; - } - $this->smarty->isCached ($template, $cache_id, $compile_id, $parent); - } - if ($this->isCached === null) { - $this->isCached = false; - if (($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED) && !$this->resource_object->isEvaluated) { - $cachedTimestamp = $this->getCachedTimestamp(); - if ($cachedTimestamp === false || $this->smarty->force_compile || $this->smarty->force_cache) { - return $this->isCached; - } - if ($this->caching === Smarty::CACHING_LIFETIME_SAVED || ($this->caching == Smarty::CACHING_LIFETIME_CURRENT && (time() <= ($cachedTimestamp + $this->cache_lifetime) || $this->cache_lifetime < 0))) { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_cache($this); - } - $this->rendered_content = $this->cache_resource_object->getCachedContents($this, $no_render); - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_cache($this); - } - if ($this->cacheFileChecked) { - $this->isCached = true; - return $this->isCached; - } - $this->cacheFileChecked = true; - if ($this->caching === Smarty::CACHING_LIFETIME_SAVED && $this->properties['cache_lifetime'] >= 0 && (time() > ($this->getCachedTimestamp() + $this->properties['cache_lifetime']))) { - $this->tpl_vars = array(); - $this->rendered_content = null; - return $this->isCached; - } - if (!empty($this->properties['file_dependency']) && $this->smarty->compile_check) { - $resource_type = null; - $resource_name = null; - foreach ($this->properties['file_dependency'] as $_file_to_check) { - If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') { - $mtime = filemtime($_file_to_check[0]); - } else { - $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name); - $resource_handler = $this->loadTemplateResourceHandler($resource_type); - $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name); - } - // If ($mtime > $this->getCachedTimestamp()) { - If ($mtime > $_file_to_check[1]) { - $this->tpl_vars = array(); - $this->rendered_content = null; - return $this->isCached; - } - } - } - $this->isCached = true; - } - } - } - return $this->isCached; - } - - /** - * Render the output using the compiled template or the PHP template source - * - * The rendering process is accomplished by just including the PHP files. - * The only exceptions are evaluated templates (string template). Their code has - * to be evaluated - */ - public function renderTemplate () - { - if ($this->resource_object->usesCompiler) { - if ($this->mustCompile() && $this->compiled_template === null) { - $this->compileTemplateSource(); - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_render($this); - } - $_smarty_tpl = $this; - ob_start(); - if ($this->resource_object->isEvaluated) { - eval("?>" . $this->compiled_template); - } else { - include($this->getCompiledFilepath ()); - // check file dependencies at compiled code - if ($this->smarty->compile_check) { - if (!empty($this->properties['file_dependency'])) { - $this->mustCompile = false; - $resource_type = null; - $resource_name = null; - foreach ($this->properties['file_dependency'] as $_file_to_check) { - If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') { - $mtime = filemtime($_file_to_check[0]); - } else { - $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name); - $resource_handler = $this->loadTemplateResourceHandler($resource_type); - $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name); - } - // If ($mtime != $_file_to_check[1]) { - If ($mtime > $_file_to_check[1]) { - $this->mustCompile = true; - break; - } - } - if ($this->mustCompile) { - // recompile and render again - ob_get_clean(); - $this->compileTemplateSource(); - ob_start(); - include($this->getCompiledFilepath ()); - } - } - } - } - } else { - if (is_callable(array($this->resource_object, 'renderUncompiled'))) { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_render($this); - } - ob_start(); - $this->resource_object->renderUncompiled($this); - } else { - throw new SmartyException("Resource '$this->resource_type' must have 'renderUncompiled' methode"); - } - } - $this->rendered_content = ob_get_clean(); - if (!$this->resource_object->isEvaluated && empty($this->properties['file_dependency'][$this->templateUid])) { - $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type); - } - if ($this->parent instanceof Smarty_Internal_Template) { - $this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']); - foreach($this->required_plugins as $code => $tmp1) { - foreach($tmp1 as $name => $tmp) { - foreach($tmp as $type => $data) { - $this->parent->required_plugins[$code][$name][$type] = $data; - } - } - } - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_render($this); - } - // write to cache when nessecary - if (!$this->resource_object->isEvaluated && ($this->caching == Smarty::CACHING_LIFETIME_SAVED || $this->caching == Smarty::CACHING_LIFETIME_CURRENT)) { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_cache($this); - } - $this->properties['has_nocache_code'] = false; - // get text between non-cached items - $cache_split = preg_split("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content); - // get non-cached items - preg_match_all("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content, $cache_parts); - $output = ''; - // loop over items, stitch back together - foreach($cache_split as $curr_idx => $curr_split) { - // escape PHP tags in template content - $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '', $curr_split); - if (isset($cache_parts[0][$curr_idx])) { - $this->properties['has_nocache_code'] = true; - // remove nocache tags from cache output - $output .= preg_replace("!/\*/?%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]); - } - } - if (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output'])) { - $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $this); - } - // rendering (must be done before writing cache file because of {function} nocache handling) - $_smarty_tpl = $this; - ob_start(); - eval("?>" . $output); - $this->rendered_content = ob_get_clean(); - // write cache file content - $this->writeCachedContent(''. $output. ''); - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_cache($this); - } - } else { - // var_dump('renderTemplate', $this->has_nocache_code, $this->template_resource, $this->properties['nocache_hash'], $this->parent->properties['nocache_hash'], $this->rendered_content); - if ($this->has_nocache_code && !empty($this->properties['nocache_hash']) && !empty($this->parent->properties['nocache_hash'])) { - // replace nocache_hash - $this->rendered_content = preg_replace("/{$this->properties['nocache_hash']}/", $this->parent->properties['nocache_hash'], $this->rendered_content); - $this->parent->has_nocache_code = $this->has_nocache_code; - } - } - } - - /** - * Returns the rendered HTML output - * - * If the cache is valid the cached content is used, otherwise - * the output is rendered from the compiled template or PHP template source - * - * @return string rendered HTML output - */ - public function getRenderedTemplate () - { - // disable caching for evaluated code - if ($this->resource_object->isEvaluated) { - $this->caching = false; - } - // checks if template exists - $this->isExisting(true); - // read from cache or render - if ($this->rendered_content === null) { - if ($this->isCached) { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_cache($this); - } - $this->rendered_content = $this->cache_resource_object->getCachedContents($this, false); - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_cache($this); - } - } - if ($this->isCached === null) { - $this->isCached(false); - } - if (!$this->isCached) { - // render template (not loaded and not in cache) - $this->renderTemplate(); - } - } - $this->updateParentVariables(); - $this->isCached = null; - return $this->rendered_content; - } - - /** - * Parse a template resource in its name and type - * Load required resource handler - * - * @param string $template_resource template resource specification - * @param string $resource_type return resource type - * @param string $resource_name return resource name - * @param object $resource_handler return resource handler object - */ - public function parseResourceName($template_resource, &$resource_type, &$resource_name, &$resource_handler) + public function loadCompiled($force = false) { - if (empty($template_resource)) - return false; - $this->getResourceTypeName($template_resource, $resource_type, $resource_name); - $resource_handler = $this->loadTemplateResourceHandler($resource_type); - // cache template object under a unique ID - // do not cache eval resources - if ($resource_type != 'eval') { - $this->smarty->template_objects[sha1($this->template_resource . $this->cache_id . $this->compile_id)] = $this; - } - return true; - } + if ($force || !isset($this->compiled)) { + $this->compiled = Smarty_Template_Compiled::load($this); + } + } /** - * get system filepath to template + * Load cached object + * + * @param bool $force force new cached object */ - public function buildTemplateFilepath ($file = null) + public function loadCached($force = false) { - if ($file == null) { - $file = $this->resource_name; + if ($force || !isset($this->cached)) { + $this->cached = Smarty_Template_Cached::load($this); } - // relative file name? - if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) { - foreach((array)$this->smarty->template_dir as $_template_dir) { - if (strpos('/\\', substr($_template_dir, -1)) === false) { - $_template_dir .= DS; - } - $_filepath = $_template_dir . $file; - if (file_exists($_filepath)) { - return $_filepath; - } - if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) { - // try PHP include_path - if (($_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath)) !== false) { - return $_filepath; - } - } - } - } - // try absolute filepath - if (file_exists($file)) return $file; - // no tpl file found - if (!empty($this->smarty->default_template_handler_func)) { - if (!is_callable($this->smarty->default_template_handler_func)) { - throw new SmartyException("Default template handler not callable"); - } else { - $_return = call_user_func_array($this->smarty->default_template_handler_func, - array($this->resource_type, $this->resource_name, &$this->template_source, &$this->template_timestamp, $this)); - if (is_string($_return)) { - return $_return; - } elseif ($_return === true) { - return $file; - } - } - } - return false; - } - - /** - * Update Smarty variables in other scopes - */ - public function updateParentVariables ($scope = Smarty::SCOPE_LOCAL) - { - $has_root = false; - foreach ($this->tpl_vars as $_key => $_variable) { - $_variable_scope = $this->tpl_vars[$_key]->scope; - if ($scope == Smarty::SCOPE_LOCAL && $_variable_scope == Smarty::SCOPE_LOCAL) { - continue; - } - if (isset($this->parent) && ($scope == Smarty::SCOPE_PARENT || $_variable_scope == Smarty::SCOPE_PARENT)) { - if (isset($this->parent->tpl_vars[$_key])) { - // variable is already defined in parent, copy value - $this->parent->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value; - } else { - // create variable in parent - $this->parent->tpl_vars[$_key] = clone $_variable; - $this->parent->tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL; - } - } - if ($scope == Smarty::SCOPE_ROOT || $_variable_scope == Smarty::SCOPE_ROOT) { - if ($this->parent == null) { - continue; - } - if (!$has_root) { - // find root - $root_ptr = $this; - while ($root_ptr->parent != null) { - $root_ptr = $root_ptr->parent; - $has_root = true; - } - } - if (isset($root_ptr->tpl_vars[$_key])) { - // variable is already defined in root, copy value - $root_ptr->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value; - } else { - // create variable in root - $root_ptr->tpl_vars[$_key] = clone $_variable; - $root_ptr->tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL; - } - } - if ($scope == Smarty::SCOPE_GLOBAL || $_variable_scope == Smarty::SCOPE_GLOBAL) { - if (isset(Smarty::$global_tpl_vars[$_key])) { - // variable is already defined in root, copy value - Smarty::$global_tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value; - } else { - // create global variable - Smarty::$global_tpl_vars[$_key] = clone $_variable; - } - Smarty::$global_tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL; - } - } - } - - /** - * Split a template resource in its name and type - * - * @param string $template_resource template resource specification - * @param string $resource_type return resource type - * @param string $resource_name return resource name - */ - protected function getResourceTypeName ($template_resource, &$resource_type, &$resource_name) - { - if (strpos($template_resource, ':') === false) { - // no resource given, use default - $resource_type = $this->smarty->default_resource_type; - $resource_name = $template_resource; - } else { - // get type and name from path - list($resource_type, $resource_name) = explode(':', $template_resource, 2); - if (strlen($resource_type) == 1) { - // 1 char is not resource type, but part of filepath - $resource_type = 'file'; - $resource_name = $template_resource; - } - } - } + } /** - * Load template resource handler by type - * - * @param string $resource_type template resource type - * @return object resource handler object + * Load inheritance object */ - protected function loadTemplateResourceHandler ($resource_type) - { - // try registered resource - if (isset($this->smarty->registered_resources[$resource_type])) { - return new Smarty_Internal_Resource_Registered($this); - } else { - // try sysplugins dir - if (in_array($resource_type, array('file', 'string', 'extends', 'php', 'stream', 'eval'))) { - $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($resource_type); - return new $_resource_class($this->smarty); - } else { - // try plugins dir - $_resource_class = 'Smarty_Resource_' . ucfirst($resource_type); - if ($this->smarty->loadPlugin($_resource_class)) { - if (class_exists($_resource_class, false)) { - return new $_resource_class($this->smarty); - } else { - return new Smarty_Internal_Resource_Registered($this, $resource_type); - } - } else { - // try streams - $_known_stream = stream_get_wrappers(); - if (in_array($resource_type, $_known_stream)) { - // is known stream - if (is_object($this->smarty->security_policy)) { - $this->smarty->security_policy->isTrustedStream($resource_type); - } - return new Smarty_Internal_Resource_Stream($this->smarty); - } else { - throw new SmartyException('Unkown resource type \'' . $resource_type . '\''); - } - } - } - } - } + public function _loadInheritance() + { + if (!isset($this->inheritance)) { + $this->inheritance = new Smarty_Internal_Runtime_Inheritance(); + } + } /** - * Create property header + * Unload inheritance object */ - public function createPropertyHeader ($cache = false) + public function _cleanUp() { - $plugins_string = ''; - // include code for plugins - if (!$cache) { - if (!empty($this->required_plugins['compiled'])) { - $plugins_string = 'required_plugins['compiled'] as $tmp) { - foreach($tmp as $data) { - $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$data['file']}';\n"; - } - } - $plugins_string .= '?>'; - } - if (!empty($this->required_plugins['nocache'])) { - $this->has_nocache_code = true; - $plugins_string .= "properties['nocache_hash']}%%*/required_plugins['nocache'] as $tmp) { - foreach($tmp as $data) { - $plugins_string .= "if (!is_callable(\'{$data['function']}\')) include \'{$data['file']}\';\n"; - } - } - $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n"; - } - } - // build property code - $this->properties['has_nocache_code'] = $this->has_nocache_code; - $properties_string = "properties['nocache_hash']}%%*/" ; - if ($this->smarty->direct_access_security) { - $properties_string .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n"; - } - if ($cache) { - // remove compiled code of{function} definition - unset($this->properties['function']); - if (!empty($this->smarty->template_functions)) { - // copy code of {function} tags called in nocache mode - foreach ($this->smarty->template_functions as $name => $function_data) { - if (isset($function_data['called_nocache'])) { - unset($function_data['called_nocache'], $this->smarty->template_functions[$name]['called_nocache']); - $this->properties['function'][$name] = $function_data; - } - } - } - } - $properties_string .= "\$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . "); /*/%%SmartyHeaderCode%%*/?>\n"; - return $properties_string . $plugins_string; - } - - /** - * Decode saved properties from compiled template and cache files - */ - public function decodeProperties ($properties) - { - $this->has_nocache_code = $properties['has_nocache_code']; - $this->properties['nocache_hash'] = $properties['nocache_hash']; - if (isset($properties['cache_lifetime'])) { - $this->properties['cache_lifetime'] = $properties['cache_lifetime']; - } - if (isset($properties['file_dependency'])) { - $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']); - } - if (!empty($properties['function'])) { - $this->properties['function'] = array_merge($this->properties['function'], $properties['function']); - $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']); - } - } - - /** - * creates a local Smarty variable for array assignments - */ - public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL) - { - if (!isset($this->tpl_vars[$tpl_var])) { - $tpl_var_inst = $this->getVariable($tpl_var, null, true, false); - if ($tpl_var_inst instanceof Undefined_Smarty_Variable) { - $this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope); - } else { - $this->tpl_vars[$tpl_var] = clone $tpl_var_inst; - if ($scope != Smarty::SCOPE_LOCAL) { - $this->tpl_vars[$tpl_var]->scope = $scope; - } - } - } - if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) { - settype($this->tpl_vars[$tpl_var]->value, 'array'); - } - } - - /** - * [util function] counts an array, arrayaccess/traversable or PDOStatement object - * @param mixed $value - * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 for empty elements - */ - public function _count($value) - { - if (is_array($value) === true || $value instanceof Countable) { - return count($value); - } elseif ($value instanceof Iterator) { - $value->rewind(); - if ($value->valid()) { - return iterator_count($value); - } - } elseif ($value instanceof PDOStatement) { - return $value->rowCount(); - } elseif ($value instanceof Traversable) { - return iterator_count($value); - } elseif ($value instanceof ArrayAccess) { - if ($value->offsetExists(0)) { - return 1; - } - } elseif (is_object($value)) { - return count($value); - } - return 0; + $this->startRenderCallbacks = array(); + $this->endRenderCallbacks = array(); + $this->inheritance = null; } /** - * wrapper for fetch + * Load compiler object + * + * @throws \SmartyException */ - public function fetch ($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false) + public function loadCompiler() { - if ($template == null) { - return $this->smarty->fetch($this); - } else { - if (!isset($parent)) { - $parent = $this; - } - return $this->smarty->fetch($template, $cache_id, $compile_id, $parent, $display); + if (!class_exists($this->source->compiler_class)) { + $this->smarty->loadPlugin($this->source->compiler_class); } - - } - - /** - * wrapper for display + $this->compiler = + new $this->source->compiler_class( + $this->source->template_lexer_class, + $this->source->template_parser_class, + $this->smarty + ); + } + + /** + * Handle unknown class methods + * + * @param string $name unknown method-name + * @param array $args argument array + * + * @return mixed */ - public function display ($template = null, $cache_id = null, $compile_id = null, $parent = null) + public function __call($name, $args) { - if ($template == null) { - return $this->smarty->display($this); - } else { - if (!isset($parent)) { - $parent = $this; - } - return $this->smarty->display($template, $cache_id, $compile_id, $parent); + // method of Smarty object? + if (method_exists($this->smarty, $name)) { + return call_user_func_array(array($this->smarty, $name), $args); } - - } + // parent + return parent::__call($name, $args); + } /** - * set Smarty property in template context + * get Smarty property in template context + * * @param string $property_name property name - * @param mixed $value value + * + * @return mixed|Smarty_Template_Cached + * @throws SmartyException */ - public function __set($property_name, $value) + public function __get($property_name) { - if ($property_name == 'resource_object' || $property_name == 'cache_resource_object') { - $this->$property_name = $value; - } elseif (property_exists($this->smarty, $property_name)) { - $this->smarty->$property_name = $value; - } else { - throw new SmartyException("invalid template property '$property_name'."); + switch ($property_name) { + case 'compiled': + $this->loadCompiled(); + return $this->compiled; + case 'cached': + $this->loadCached(); + return $this->cached; + case 'compiler': + $this->loadCompiler(); + return $this->compiler; + default: + // Smarty property ? + if (property_exists($this->smarty, $property_name)) { + return $this->smarty->$property_name; + } } + throw new SmartyException("template property '$property_name' does not exist."); } /** - * get Smarty property in template context + * set Smarty property in template context + * * @param string $property_name property name + * @param mixed $value value + * + * @throws SmartyException */ - public function __get($property_name) + public function __set($property_name, $value) { - if ($property_name == 'resource_object') { - // load template resource - $this->resource_object = null; - if (!$this->parseResourceName ($this->template_resource, $this->resource_type, $this->resource_name, $this->resource_object)) { - throw new SmartyException ("Unable to parse resource name \"{$template_resource}\""); - } - return $this->resource_object; - } - if ($property_name == 'cache_resource_object') { - // load cache resource - $this->cache_resource_object = $this->loadCacheResource(); - return $this->cache_resource_object; - } - if (property_exists($this->smarty, $property_name)) { - return $this->smarty->$property_name; - } else { - throw new SmartyException("template property '$property_name' does not exist."); + switch ($property_name) { + case 'compiled': + case 'cached': + case 'compiler': + $this->$property_name = $value; + return; + default: + // Smarty property ? + if (property_exists($this->smarty, $property_name)) { + $this->smarty->$property_name = $value; + return; + } } + throw new SmartyException("invalid template property '$property_name'."); } - /** - * Takes unknown class methods and lazy loads sysplugin files for them - * class name format: Smarty_Method_MethodName - * plugin filename format: method.methodname.php - * - * @param string $name unknown methode name - * @param array $args aurgument array + * Template data object destructor */ - public function __call($name, $args) + public function __destruct() { - static $camel_func; - if (!isset($camel_func)) - $camel_func = create_function('$c', 'return "_" . strtolower($c[1]);'); - // see if this is a set/get for a property - $first3 = strtolower(substr($name, 0, 3)); - if (in_array($first3, array('set', 'get')) && substr($name, 3, 1) !== '_') { - // try to keep case correct for future PHP 6.0 case-sensitive class methods - // lcfirst() not available < PHP 5.3.0, so improvise - $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); - // convert camel case to underscored name - $property_name = preg_replace_callback('/([A-Z])/', $camel_func, $property_name); - if (property_exists($this, $property_name)) { - if ($first3 == 'get') - return $this->$property_name; - else - return $this->$property_name = $args[0]; - } + if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) { + $this->cached->handler->releaseLock($this->smarty, $this->cached); } - // Smarty Backward Compatible wrapper - if (strpos($name,'_') !== false) { - if (!isset($this->wrapper)) { - $this->wrapper = new Smarty_Internal_Wrapper($this); - } - return $this->wrapper->convert($name, $args); - } - // pass call to Smarty object - return call_user_func_array(array($this->smarty,$name),$args); - } - + } } -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatebase.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatebase.php new file mode 100644 index 000000000..200c11bb5 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatebase.php @@ -0,0 +1,386 @@ +_execute($template, $cache_id, $compile_id, $parent, 0); + return $result === null ? ob_get_clean() : $result; + } + + /** + * displays a Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * + * @throws \Exception + * @throws \SmartyException + */ + public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + // display template + $this->_execute($template, $cache_id, $compile_id, $parent, 1); + } + + /** + * test if cache is valid + * + * @api Smarty::isCached() + * @link http://www.smarty.net/docs/en/api.is.cached.tpl + * + * @param null|string|\Smarty_Internal_Template $template the resource handle of the template file or template + * object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * + * @return bool cache status + * @throws \Exception + * @throws \SmartyException + */ + public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + return $this->_execute($template, $cache_id, $compile_id, $parent, 2); + } + + /** + * fetches a rendered Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param string $function function type 0 = fetch, 1 = display, 2 = isCache + * + * @return mixed + * @throws \Exception + * @throws \SmartyException + */ + private function _execute($template, $cache_id, $compile_id, $parent, $function) + { + $smarty = $this->_getSmartyObj(); + $saveVars = true; + if ($template === null) { + if (!$this->_isTplObj()) { + throw new SmartyException($function . '():Missing \'$template\' parameter'); + } else { + $template = $this; + } + } elseif (is_object($template)) { + /* @var Smarty_Internal_Template $template */ + if (!isset($template->_objType) || !$template->_isTplObj()) { + throw new SmartyException($function . '():Template object expected'); + } + } else { + // get template object + $saveVars = false; + $template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent ? $parent : $this, false); + if ($this->_objType === 1) { + // set caching in template object + $template->caching = $this->caching; + } + } + // make sure we have integer values + $template->caching = (int)$template->caching; + // fetch template content + $level = ob_get_level(); + try { + $_smarty_old_error_level = + isset($smarty->error_reporting) ? error_reporting($smarty->error_reporting) : null; + if ($this->_objType === 2) { + /* @var Smarty_Internal_Template $this */ + $template->tplFunctions = $this->tplFunctions; + $template->inheritance = $this->inheritance; + } + /* @var Smarty_Internal_Template $parent */ + if (isset($parent->_objType) && ($parent->_objType === 2) && !empty($parent->tplFunctions)) { + $template->tplFunctions = array_merge($parent->tplFunctions, $template->tplFunctions); + } + if ($function === 2) { + if ($template->caching) { + // return cache status of template + if (!isset($template->cached)) { + $template->loadCached(); + } + $result = $template->cached->isCached($template); + Smarty_Internal_Template::$isCacheTplObj[ $template->_getTemplateId() ] = $template; + } else { + return false; + } + } else { + if ($saveVars) { + $savedTplVars = $template->tpl_vars; + $savedConfigVars = $template->config_vars; + } + ob_start(); + $template->_mergeVars(); + if (!empty(Smarty::$global_tpl_vars)) { + $template->tpl_vars = array_merge(Smarty::$global_tpl_vars, $template->tpl_vars); + } + $result = $template->render(false, $function); + $template->_cleanUp(); + if ($saveVars) { + $template->tpl_vars = $savedTplVars; + $template->config_vars = $savedConfigVars; + } else { + if (!$function && !isset(Smarty_Internal_Template::$tplObjCache[ $template->templateId ])) { + $template->parent = null; + $template->tpl_vars = $template->config_vars = array(); + Smarty_Internal_Template::$tplObjCache[ $template->templateId ] = $template; + } + } + } + if (isset($_smarty_old_error_level)) { + error_reporting($_smarty_old_error_level); + } + return $result; + } catch (Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + if (isset($_smarty_old_error_level)) { + error_reporting($_smarty_old_error_level); + } + throw $e; + } + } + + /** + * Registers plugin to be used in templates + * + * @api Smarty::registerPlugin() + * @link http://www.smarty.net/docs/en/api.register.plugin.tpl + * + * @param string $type plugin type + * @param string $name name of template tag + * @param callable $callback PHP callback to register + * @param bool $cacheable if true (default) this function is cache able + * @param mixed $cache_attr caching attributes if any + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function registerPlugin($type, $name, $callback, $cacheable = true, $cache_attr = null) + { + return $this->ext->registerPlugin->registerPlugin($this, $type, $name, $callback, $cacheable, $cache_attr); + } + + /** + * load a filter of specified type and name + * + * @api Smarty::loadFilter() + * @link http://www.smarty.net/docs/en/api.load.filter.tpl + * + * @param string $type filter type + * @param string $name filter name + * + * @return bool + * @throws \SmartyException + */ + public function loadFilter($type, $name) + { + return $this->ext->loadFilter->loadFilter($this, $type, $name); + } + + /** + * Registers a filter function + * + * @api Smarty::registerFilter() + * @link http://www.smarty.net/docs/en/api.register.filter.tpl + * + * @param string $type filter type + * @param callable $callback + * @param string|null $name optional filter name + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function registerFilter($type, $callback, $name = null) + { + return $this->ext->registerFilter->registerFilter($this, $type, $callback, $name); + } + + /** + * Registers object to be used in templates + * + * @api Smarty::registerObject() + * @link http://www.smarty.net/docs/en/api.register.object.tpl + * + * @param string $object_name + * @param object $object the referenced PHP object to register + * @param array $allowed_methods_properties list of allowed methods (empty = all) + * @param bool $format smarty argument format, else traditional + * @param array $block_methods list of block-methods + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function registerObject( + $object_name, + $object, + $allowed_methods_properties = array(), + $format = true, + $block_methods = array() + ) { + return $this->ext->registerObject->registerObject( + $this, + $object_name, + $object, + $allowed_methods_properties, + $format, + $block_methods + ); + } + + /** + * @param int $compile_check + */ + public function setCompileCheck($compile_check) + { + $this->compile_check = (int)$compile_check; + } + + /** + * @param int $caching + */ + public function setCaching($caching) + { + $this->caching = (int)$caching; + } + + /** + * @param int $cache_lifetime + */ + public function setCacheLifetime($cache_lifetime) + { + $this->cache_lifetime = $cache_lifetime; + } + + /** + * @param string $compile_id + */ + public function setCompileId($compile_id) + { + $this->compile_id = $compile_id; + } + + /** + * @param string $cache_id + */ + public function setCacheId($cache_id) + { + $this->cache_id = $cache_id; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatecompilerbase.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatecompilerbase.php index 2a95eca4d..3cc957dec 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatecompilerbase.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatecompilerbase.php @@ -1,435 +1,1760 @@ array(), 'nocache' => array()); + + /** + * Required plugins stack + * + * @var array + */ + public $required_plugins_stack = array(); + + /** + * current template + * + * @var Smarty_Internal_Template + */ public $template = null; - // optional log of tag/attributes - public $used_tags = array(); + + /** + * merged included sub template data + * + * @var array + */ + public $mergedSubTemplatesData = array(); + + /** + * merged sub template code + * + * @var array + */ + public $mergedSubTemplatesCode = array(); + + /** + * collected template properties during compilation + * + * @var array + */ + public $templateProperties = array(); + + /** + * source line offset for error messages + * + * @var int + */ + public $trace_line_offset = 0; + + /** + * trace uid + * + * @var string + */ + public $trace_uid = ''; + + /** + * trace file path + * + * @var string + */ + public $trace_filepath = ''; + + /** + * stack for tracing file and line of nested {block} tags + * + * @var array + */ + public $trace_stack = array(); + + /** + * plugins loaded by default plugin handler + * + * @var array + */ + public $default_handler_plugins = array(); + + /** + * saved preprocessed modifier list + * + * @var mixed + */ + public $default_modifier_list = null; + + /** + * force compilation of complete template as nocache + * + * @var boolean + */ + public $forceNocache = false; + + /** + * flag if compiled template file shall we written + * + * @var bool + */ + public $write_compiled_code = true; + + /** + * Template functions + * + * @var array + */ + public $tpl_function = array(); + + /** + * called sub functions from template function + * + * @var array + */ + public $called_functions = array(); + + /** + * compiled template or block function code + * + * @var string + */ + public $blockOrFunctionCode = ''; + + /** + * php_handling setting either from Smarty or security + * + * @var int + */ + public $php_handling = 0; + + /** + * flags for used modifier plugins + * + * @var array + */ + public $modifier_plugins = array(); + + /** + * type of already compiled modifier + * + * @var array + */ + public $known_modifier_type = array(); + + /** + * parent compiler object for merged subtemplates and template functions + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $parent_compiler = null; + + /** + * Flag true when compiling nocache section + * + * @var bool + */ + public $nocache = false; + + /** + * Flag true when tag is compiled as nocache + * + * @var bool + */ + public $tag_nocache = false; + + /** + * Compiled tag prefix code + * + * @var array + */ + public $prefix_code = array(); + + /** + * used prefix variables by current compiled tag + * + * @var array + */ + public $usedPrefixVariables = array(); + + /** + * Prefix code stack + * + * @var array + */ + public $prefixCodeStack = array(); + + /** + * Tag has compiled code + * + * @var bool + */ + public $has_code = false; + + /** + * A variable string was compiled + * + * @var bool + */ + public $has_variable_string = false; + + /** + * Stack for {setfilter} {/setfilter} + * + * @var array + */ + public $variable_filter_stack = array(); + + /** + * variable filters for {setfilter} {/setfilter} + * + * @var array + */ + public $variable_filters = array(); + + /** + * Nesting count of looping tags like {foreach}, {for}, {section}, {while} + * + * @var int + */ + public $loopNesting = 0; + + /** + * Strip preg pattern + * + * @var string + */ + public $stripRegEx = '![\t ]*[\r\n]+[\t ]*!'; + + /** + * plugin search order + * + * @var array + */ + public $plugin_search_order = array( + 'function', + 'block', + 'compiler', + 'class' + ); + + /** + * General storage area for tag compiler plugins + * + * @var array + */ + public $_cache = array(); + + /** + * Lexer preg pattern for left delimiter + * + * @var string + */ + private $ldelPreg = '[{]'; + + /** + * Lexer preg pattern for right delimiter + * + * @var string + */ + private $rdelPreg = '[}]'; + + /** + * Length of right delimiter + * + * @var int + */ + private $rdelLength = 0; + + /** + * Length of left delimiter + * + * @var int + */ + private $ldelLength = 0; + + /** + * Lexer preg pattern for user literals + * + * @var string + */ + private $literalPreg = ''; /** * Initialize compiler + * + * @param Smarty $smarty global instance */ - public function __construct() + public function __construct(Smarty $smarty) { - $this->nocache_hash = str_replace('.', '-', uniqid(rand(), true)); - } + $this->smarty = $smarty; + $this->nocache_hash = str_replace( + array( + '.', + ',' + ), + '_', + uniqid(mt_rand(), true) + ); + } /** - * Methode to compile a Smarty template - * - * @param $template template object to compile + * Method to compile a Smarty template + * + * @param Smarty_Internal_Template $template template object to compile + * @param bool $nocache true is shall be compiled in nocache mode + * @param null|Smarty_Internal_TemplateCompilerBase $parent_compiler + * * @return bool true if compiling succeeded, false if it failed + * @throws \Exception */ - public function compileTemplate($template) + public function compileTemplate( + Smarty_Internal_Template $template, + $nocache = null, + Smarty_Internal_TemplateCompilerBase $parent_compiler = null + ) { + // get code frame of compiled template + $_compiled_code = $template->smarty->ext->_codeFrame->create( + $template, + $this->compileTemplateSource( + $template, + $nocache, + $parent_compiler + ), + $this->postFilter($this->blockOrFunctionCode) . + join('', $this->mergedSubTemplatesCode), + false, + $this + ); + return $_compiled_code; + } + + /** + * Compile template source and run optional post filter + * + * @param \Smarty_Internal_Template $template + * @param null|bool $nocache flag if template must be compiled in nocache mode + * @param \Smarty_Internal_TemplateCompilerBase $parent_compiler + * + * @return string + * @throws \Exception + */ + public function compileTemplateSource( + Smarty_Internal_Template $template, + $nocache = null, + Smarty_Internal_TemplateCompilerBase $parent_compiler = null + ) { + try { + // save template object in compiler class + $this->template = $template; + if (property_exists($this->template->smarty, 'plugin_search_order')) { + $this->plugin_search_order = $this->template->smarty->plugin_search_order; + } + if ($this->smarty->debugging) { + if (!isset($this->smarty->_debug)) { + $this->smarty->_debug = new Smarty_Internal_Debug(); + } + $this->smarty->_debug->start_compile($this->template); + } + if (isset($this->template->smarty->security_policy)) { + $this->php_handling = $this->template->smarty->security_policy->php_handling; + } else { + $this->php_handling = $this->template->smarty->php_handling; + } + $this->parent_compiler = $parent_compiler ? $parent_compiler : $this; + $nocache = isset($nocache) ? $nocache : false; + if (empty($template->compiled->nocache_hash)) { + $template->compiled->nocache_hash = $this->nocache_hash; + } else { + $this->nocache_hash = $template->compiled->nocache_hash; + } + $this->caching = $template->caching; + // flag for nocache sections + $this->nocache = $nocache; + $this->tag_nocache = false; + // reset has nocache code flag + $this->template->compiled->has_nocache_code = false; + $this->has_variable_string = false; + $this->prefix_code = array(); + // add file dependency + if ($this->smarty->merge_compiled_includes || $this->template->source->handler->checkTimestamps()) { + $this->parent_compiler->template->compiled->file_dependency[ $this->template->source->uid ] = + array( + $this->template->source->filepath, + $this->template->source->getTimeStamp(), + $this->template->source->type, + ); + } + $this->smarty->_current_file = $this->template->source->filepath; + // get template source + if (!empty($this->template->source->components)) { + // we have array of inheritance templates by extends: resource + // generate corresponding source code sequence + $_content = + Smarty_Internal_Compile_Extends::extendsSourceArrayCode($this->template); + } else { + // get template source + $_content = $this->template->source->getContent(); + } + $_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true)); + if (!empty($this->required_plugins[ 'compiled' ]) || !empty($this->required_plugins[ 'nocache' ])) { + $_compiled_code = 'compileRequiredPlugins() . "?>\n" . $_compiled_code; + } + } catch (Exception $e) { + if ($this->smarty->debugging) { + $this->smarty->_debug->end_compile($this->template); + } + $this->_tag_stack = array(); + // free memory + $this->parent_compiler = null; + $this->template = null; + $this->parser = null; + throw $e; + } + if ($this->smarty->debugging) { + $this->smarty->_debug->end_compile($this->template); + } + $this->parent_compiler = null; + $this->parser = null; + return $_compiled_code; + } + + /** + * Optionally process compiled code by post filter + * + * @param string $code compiled code + * + * @return string + * @throws \SmartyException + */ + public function postFilter($code) { - if (empty($template->properties['nocache_hash'])) { - $template->properties['nocache_hash'] = $this->nocache_hash; + // run post filter if on code + if (!empty($code) + && (isset($this->smarty->autoload_filters[ 'post' ]) || isset($this->smarty->registered_filters[ 'post' ])) + ) { + return $this->smarty->ext->_filterHandler->runFilter('post', $code, $this->template); } else { - $this->nocache_hash = $template->properties['nocache_hash']; - } - // flag for nochache sections - $this->nocache = false; - $this->tag_nocache = false; - // save template object in compiler class - $this->template = $template; - $this->smarty->_current_file = $this->template->getTemplateFilepath(); - // template header code - $template_header = ''; - if (!$template->suppressHeader) { - $template_header .= "template->getTemplateFilepath() . "\" */ ?>\n"; - } - - do { - // flag for aborting current and start recompile - $this->abort_and_recompile = false; - // get template source - $_content = $template->getTemplateSource(); - // run prefilter if required - if (isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) { - $template->template_source = $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template); - } - // on empty template just return header - if ($_content == '') { - if ($template->suppressFileDependency) { - $template->compiled_template = ''; - } else { - $template->compiled_template = $template_header . $template->createPropertyHeader(); - } - return true; - } - // call compiler - $_compiled_code = $this->doCompile($_content); - } while ($this->abort_and_recompile); - // return compiled code to template object - if ($template->suppressFileDependency) { - $template->compiled_template = $_compiled_code; + return $code; + } + } + + /** + * Run optional prefilter + * + * @param string $_content template source + * + * @return string + * @throws \SmartyException + */ + public function preFilter($_content) + { + // run pre filter if required + if ($_content !== '' + && ((isset($this->smarty->autoload_filters[ 'pre' ]) || isset($this->smarty->registered_filters[ 'pre' ]))) + ) { + return $this->smarty->ext->_filterHandler->runFilter('pre', $_content, $this->template); } else { - $template->compiled_template = $template_header . $template->createPropertyHeader() . $_compiled_code; - } - // run postfilter if required - if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { - $template->compiled_template = Smarty_Internal_Filter_Handler::runFilter('post', $template->compiled_template, $template); - } - } + return $_content; + } + } /** * Compile Tag - * * This is a call back from the lexer/parser - * It executes the required compile plugin for the Smarty tag - * - * @param string $tag tag name - * @param array $args array with tag attributes - * @param array $parameter array with compilation parameter + * + * Save current prefix code + * Compile tag + * Merge tag prefix code with saved one + * (required nested tags in attributes) + * + * @param string $tag tag name + * @param array $args array with tag attributes + * @param array $parameter array with compilation parameter + * + * @throws SmartyCompilerException + * @throws SmartyException * @return string compiled code */ public function compileTag($tag, $args, $parameter = array()) - { + { + $this->prefixCodeStack[] = $this->prefix_code; + $this->prefix_code = array(); + $result = $this->compileTag2($tag, $args, $parameter); + $this->prefix_code = array_merge($this->prefix_code, array_pop($this->prefixCodeStack)); + return $result; + } + + /** + * compile variable + * + * @param string $variable + * + * @return string + */ + public function compileVariable($variable) + { + if (!strpos($variable, '(')) { + // not a variable variable + $var = trim($variable, '\''); + $this->tag_nocache = $this->tag_nocache | + $this->template->ext->getTemplateVars->_getVariable( + $this->template, + $var, + null, + true, + false + )->nocache; + // todo $this->template->compiled->properties['variables'][$var] = $this->tag_nocache | $this->nocache; + } + return '$_smarty_tpl->tpl_vars[' . $variable . ']->value'; + } + + /** + * compile config variable + * + * @param string $variable + * + * @return string + */ + public function compileConfigVariable($variable) + { + // return '$_smarty_tpl->config_vars[' . $variable . ']'; + return '$_smarty_tpl->smarty->ext->configLoad->_getConfigVariable($_smarty_tpl, ' . $variable . ')'; + } + + /** + * compile PHP function call + * + * @param string $name + * @param array $parameter + * + * @return string + * @throws \SmartyCompilerException + */ + public function compilePHPFunctionCall($name, $parameter) + { + if (!$this->smarty->security_policy || $this->smarty->security_policy->isTrustedPhpFunction($name, $this)) { + if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0 + || strcasecmp($name, 'array') === 0 || is_callable($name) + ) { + $func_name = strtolower($name); + + if ($func_name === 'isset') { + if (count($parameter) === 0) { + $this->trigger_template_error('Illegal number of parameter in "isset()"'); + } + + $pa = array(); + foreach ($parameter as $p) { + $pa[] = $this->syntaxMatchesVariable($p) ? 'isset(' . $p . ')' : '(' . $p . ' !== null )'; + } + return '(' . implode(' && ', $pa) . ')'; + + } elseif (in_array( + $func_name, + array( + 'empty', + 'reset', + 'current', + 'end', + 'prev', + 'next' + ) + ) + ) { + if (count($parameter) !== 1) { + $this->trigger_template_error("Illegal number of parameter in '{$func_name()}'"); + } + if ($func_name === 'empty') { + if (!$this->syntaxMatchesVariable($parameter[0]) && version_compare(PHP_VERSION, '5.5.0', '<')) { + return '(' . $parameter[ 0 ] . ' === false )'; + } else { + return $func_name . '(' . + str_replace("')->value", "',null,true,false)->value", $parameter[ 0 ]) . ')'; + } + } else { + return $func_name . '(' . $parameter[ 0 ] . ')'; + } + } else { + return $name . '(' . implode(',', $parameter) . ')'; + } + } else { + $this->trigger_template_error("unknown function '{$name}'"); + } + } + } + + /** + * Determines whether the passed string represents a valid (PHP) variable. + * This is important, because `isset()` only works on variables and `empty()` can only be passed + * a variable prior to php5.5 + * @param $string + * @return bool + */ + private function syntaxMatchesVariable($string) { + static $regex_pattern = '/^\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*((->)[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\[.*]*\])*$/'; + return 1 === preg_match($regex_pattern, trim($string)); + } + + /** + * This method is called from parser to process a text content section if strip is enabled + * - remove text from inheritance child templates as they may generate output + * + * @param string $text + * + * @return string + */ + public function processText($text) + { + + if (strpos($text, '<') === false) { + return preg_replace($this->stripRegEx, '', $text); + } + + $store = array(); + $_store = 0; + + // capture html elements not to be messed with + $_offset = 0; + if (preg_match_all( + '#(]*>.*?]*>)|(]*>.*?]*>)|(]*>.*?]*>)#is', + $text, + $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + ) + ) { + foreach ($matches as $match) { + $store[] = $match[ 0 ][ 0 ]; + $_length = strlen($match[ 0 ][ 0 ]); + $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@'; + $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] - $_offset, $_length); + $_offset += $_length - strlen($replace); + $_store++; + } + } + $expressions = array(// replace multiple spaces between tags by a single space + '#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2', + // remove newline between tags + '#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2', + // remove multiple spaces between attributes (but not in attribute values!) + '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5', + '#>[\040\011]+$#Ss' => '> ', + '#>[\040\011]*[\n]\s*$#Ss' => '>', + $this->stripRegEx => '', + ); + $text = preg_replace(array_keys($expressions), array_values($expressions), $text); + $_offset = 0; + if (preg_match_all( + '#@!@SMARTY:([0-9]+):SMARTY@!@#is', + $text, + $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER + ) + ) { + foreach ($matches as $match) { + $_length = strlen($match[ 0 ][ 0 ]); + $replace = $store[ $match[ 1 ][ 0 ] ]; + $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] + $_offset, $_length); + $_offset += strlen($replace) - $_length; + $_store++; + } + } + return $text; + } + + /** + * lazy loads internal compile plugin for tag and calls the compile method + * compile objects cached for reuse. + * class name format: Smarty_Internal_Compile_TagName + * plugin filename format: Smarty_Internal_TagName.php + * + * @param string $tag tag name + * @param array $args list of tag attributes + * @param mixed $param1 optional parameter + * @param mixed $param2 optional parameter + * @param mixed $param3 optional parameter + * + * @return bool|string compiled code or false + * @throws \SmartyCompilerException + */ + public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) + { + /* @var Smarty_Internal_CompileBase $tagCompiler */ + $tagCompiler = $this->getTagCompiler($tag); + // compile this tag + return $tagCompiler === false ? false : $tagCompiler->compile($args, $this, $param1, $param2, $param3); + } + + /** + * lazy loads internal compile plugin for tag compile objects cached for reuse. + * + * class name format: Smarty_Internal_Compile_TagName + * plugin filename format: Smarty_Internal_TagName.php + * + * @param string $tag tag name + * + * @return bool|\Smarty_Internal_CompileBase tag compiler object or false if not found + */ + public function getTagCompiler($tag) + { + // re-use object if already exists + if (!isset(self::$_tag_objects[ $tag ])) { + // lazy load internal compiler plugin + $_tag = explode('_', $tag); + $_tag = array_map('ucfirst', $_tag); + $class_name = 'Smarty_Internal_Compile_' . implode('_', $_tag); + if (class_exists($class_name) + && (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { + self::$_tag_objects[ $tag ] = new $class_name; + } else { + self::$_tag_objects[ $tag ] = false; + } + } + return self::$_tag_objects[ $tag ]; + } + + /** + * Check for plugins and return function name + * + * @param $plugin_name + * @param string $plugin_type type of plugin + * + * @return string call name of function + * @throws \SmartyException + */ + public function getPlugin($plugin_name, $plugin_type) + { + $function = null; + if ($this->caching && ($this->nocache || $this->tag_nocache)) { + if (isset($this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { + $function = + $this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } elseif (isset($this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { + $this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ] = + $this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ]; + $function = + $this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } + } else { + if (isset($this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { + $function = + $this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } elseif (isset($this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { + $this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ] = + $this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ]; + $function = + $this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } + } + if (isset($function)) { + if ($plugin_type === 'modifier') { + $this->modifier_plugins[ $plugin_name ] = true; + } + return $function; + } + // loop through plugin dirs and find the plugin + $function = 'smarty_' . $plugin_type . '_' . $plugin_name; + $file = $this->smarty->loadPlugin($function, false); + if (is_string($file)) { + if ($this->caching && ($this->nocache || $this->tag_nocache)) { + $this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'file' ] = + $file; + $this->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ] = + $function; + } else { + $this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'file' ] = + $file; + $this->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'function' ] = + $function; + } + if ($plugin_type === 'modifier') { + $this->modifier_plugins[ $plugin_name ] = true; + } + return $function; + } + if (is_callable($function)) { + // plugin function is defined in the script + return $function; + } + return false; + } + + /** + * Check for plugins by default plugin handler + * + * @param string $tag name of tag + * @param string $plugin_type type of plugin + * + * @return bool true if found + * @throws \SmartyCompilerException + */ + public function getPluginFromDefaultHandler($tag, $plugin_type) + { + $callback = null; + $script = null; + $cacheable = true; + $result = call_user_func_array( + $this->smarty->default_plugin_handler_func, + array( + $tag, + $plugin_type, + $this->template, + &$callback, + &$script, + &$cacheable, + ) + ); + if ($result) { + $this->tag_nocache = $this->tag_nocache || !$cacheable; + if ($script !== null) { + if (is_file($script)) { + if ($this->caching && ($this->nocache || $this->tag_nocache)) { + $this->required_plugins[ 'nocache' ][ $tag ][ $plugin_type ][ 'file' ] = + $script; + $this->required_plugins[ 'nocache' ][ $tag ][ $plugin_type ][ 'function' ] = + $callback; + } else { + $this->required_plugins[ 'compiled' ][ $tag ][ $plugin_type ][ 'file' ] = + $script; + $this->required_plugins[ 'compiled' ][ $tag ][ $plugin_type ][ 'function' ] = + $callback; + } + include_once $script; + } else { + $this->trigger_template_error("Default plugin handler: Returned script file '{$script}' for '{$tag}' not found"); + } + } + if (is_callable($callback)) { + $this->default_handler_plugins[ $plugin_type ][ $tag ] = array( + $callback, + true, + array() + ); + return true; + } else { + $this->trigger_template_error("Default plugin handler: Returned callback for '{$tag}' not callable"); + } + } + return false; + } + + /** + * Append code segments and remove unneeded ?> \s?$/D', $left) && preg_match('/^<\?php\s+/', $right)) { + $left = preg_replace('/\s*\?>\s?$/D', "\n", $left); + $left .= preg_replace('/^<\?php\s+/', '', $right); + } else { + $left .= $right; + } + return $left; + } + + /** + * Inject inline code for nocache template sections + * This method gets the content of each template element from the parser. + * If the content is compiled code and it should be not cached the code is injected + * into the rendered output. + * + * @param string $content content of template element + * @param boolean $is_code true if content is compiled code + * + * @return string content + */ + public function processNocacheCode($content, $is_code) + { + // If the template is not evaluated and we have a nocache section and or a nocache tag + if ($is_code && !empty($content)) { + // generate replacement code + if ((!($this->template->source->handler->recompiled) || $this->forceNocache) && $this->caching + && !$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache) + ) { + $this->template->compiled->has_nocache_code = true; + $_output = addcslashes($content, '\'\\'); + $_output = str_replace('^#^', '\'', $_output); + $_output = + "nocache_hash}%%*/{$_output}/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n"; + // make sure we include modifier plugins for nocache code + foreach ($this->modifier_plugins as $plugin_name => $dummy) { + if (isset($this->required_plugins[ 'compiled' ][ $plugin_name ][ 'modifier' ])) { + $this->required_plugins[ 'nocache' ][ $plugin_name ][ 'modifier' ] = + $this->required_plugins[ 'compiled' ][ $plugin_name ][ 'modifier' ]; + } + } + } else { + $_output = $content; + } + } else { + $_output = $content; + } + $this->modifier_plugins = array(); + $this->suppressNocacheProcessing = false; + $this->tag_nocache = false; + return $_output; + } + + /** + * Get Id + * + * @param string $input + * + * @return bool|string + */ + public function getId($input) + { + if (preg_match('~^([\'"]*)([0-9]*[a-zA-Z_]\w*)\1$~', $input, $match)) { + return $match[ 2 ]; + } + return false; + } + + /** + * Get variable name from string + * + * @param string $input + * + * @return bool|string + */ + public function getVariableName($input) + { + if (preg_match('~^[$]_smarty_tpl->tpl_vars\[[\'"]*([0-9]*[a-zA-Z_]\w*)[\'"]*\]->value$~', $input, $match)) { + return $match[ 1 ]; + } + return false; + } + + /** + * Set nocache flag in variable or create new variable + * + * @param string $varName + */ + public function setNocacheInVariable($varName) + { + // create nocache var to make it know for further compiling + if ($_var = $this->getId($varName)) { + if (isset($this->template->tpl_vars[ $_var ])) { + $this->template->tpl_vars[ $_var ] = clone $this->template->tpl_vars[ $_var ]; + $this->template->tpl_vars[ $_var ]->nocache = true; + } else { + $this->template->tpl_vars[ $_var ] = new Smarty_Variable(null, true); + } + } + } + + /** + * @param array $_attr tag attributes + * @param array $validScopes + * + * @return int|string + * @throws \SmartyCompilerException + */ + public function convertScope($_attr, $validScopes) + { + $_scope = 0; + if (isset($_attr[ 'scope' ])) { + $_scopeName = trim($_attr[ 'scope' ], '\'"'); + if (is_numeric($_scopeName) && in_array($_scopeName, $validScopes)) { + $_scope = $_scopeName; + } elseif (is_string($_scopeName)) { + $_scopeName = trim($_scopeName, '\'"'); + $_scope = isset($validScopes[ $_scopeName ]) ? $validScopes[ $_scopeName ] : false; + } else { + $_scope = false; + } + if ($_scope === false) { + $err = var_export($_scopeName, true); + $this->trigger_template_error("illegal value '{$err}' for \"scope\" attribute", null, true); + } + } + return $_scope; + } + + /** + * Generate nocache code string + * + * @param string $code PHP code + * + * @return string + */ + public function makeNocacheCode($code) + { + return "echo '/*%%SmartyNocache:{$this->nocache_hash}%%*//*/%%SmartyNocache:{$this->nocache_hash}%%*/';\n"; + } + + /** + * display compiler error messages without dying + * If parameter $args is empty it is a parser detected syntax error. + * In this case the parser is called to obtain information about expected tokens. + * If parameter $args contains a string this is used as error message + * + * @param string $args individual error message or null + * @param string $line line-number + * @param null|bool $tagline if true the line number of last tag + * + * @throws \SmartyCompilerException when an unexpected token is found + */ + public function trigger_template_error($args = null, $line = null, $tagline = null) + { + $lex = $this->parser->lex; + if ($tagline === true) { + // get line number of Tag + $line = $lex->taglineno; + } elseif (!isset($line)) { + // get template source line which has error + $line = $lex->line; + } else { + $line = (int)$line; + } + if (in_array( + $this->template->source->type, + array( + 'eval', + 'string' + ) + ) + ) { + $templateName = $this->template->source->type . ':' . trim( + preg_replace( + '![\t\r\n]+!', + ' ', + strlen($lex->data) > 40 ? + substr($lex->data, 0, 40) . + '...' : $lex->data + ) + ); + } else { + $templateName = $this->template->source->type . ':' . $this->template->source->filepath; + } + // $line += $this->trace_line_offset; + $match = preg_split("/\n/", $lex->data); + $error_text = + 'Syntax error in template "' . (empty($this->trace_filepath) ? $templateName : $this->trace_filepath) . + '" on line ' . ($line + $this->trace_line_offset) . ' "' . + trim(preg_replace('![\t\r\n]+!', ' ', $match[ $line - 1 ])) . '" '; + if (isset($args)) { + // individual error message + $error_text .= $args; + } else { + $expect = array(); + // expected token from parser + $error_text .= ' - Unexpected "' . $lex->value . '"'; + if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4) { + foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) { + $exp_token = $this->parser->yyTokenName[ $token ]; + if (isset($lex->smarty_token_names[ $exp_token ])) { + // token type from lexer + $expect[] = '"' . $lex->smarty_token_names[ $exp_token ] . '"'; + } else { + // otherwise internal token name + $expect[] = $this->parser->yyTokenName[ $token ]; + } + } + $error_text .= ', expected one of: ' . implode(' , ', $expect); + } + } + if ($this->smarty->_parserdebug) { + $this->parser->errorRunDown(); + echo ob_get_clean(); + flush(); + } + $e = new SmartyCompilerException($error_text); + $e->line = $line; + $e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[ $line - 1 ])); + $e->desc = $args; + $e->template = $this->template->source->filepath; + throw $e; + } + + /** + * Return var_export() value with all white spaces removed + * + * @param mixed $value + * + * @return string + */ + public function getVarExport($value) + { + return preg_replace('/\s/', '', var_export($value, true)); + } + + /** + * enter double quoted string + * - save tag stack count + */ + public function enterDoubleQuote() + { + array_push($this->_tag_stack_count, $this->getTagStackCount()); + } + + /** + * Return tag stack count + * + * @return int + */ + public function getTagStackCount() + { + return count($this->_tag_stack); + } + + /** + * @param $lexerPreg + * + * @return mixed + */ + public function replaceDelimiter($lexerPreg) + { + return str_replace( + array('SMARTYldel', 'SMARTYliteral', 'SMARTYrdel', 'SMARTYautoliteral', 'SMARTYal'), + array( + $this->ldelPreg, $this->literalPreg, $this->rdelPreg, + $this->smarty->getAutoLiteral() ? '{1,}' : '{9}', + $this->smarty->getAutoLiteral() ? '' : '\\s*' + ), + $lexerPreg + ); + } + + /** + * Build lexer regular expressions for left and right delimiter and user defined literals + */ + public function initDelimiterPreg() + { + $ldel = $this->smarty->getLeftDelimiter(); + $this->ldelLength = strlen($ldel); + $this->ldelPreg = ''; + foreach (str_split($ldel, 1) as $chr) { + $this->ldelPreg .= '[' . preg_quote($chr,'/') . ']'; + } + $rdel = $this->smarty->getRightDelimiter(); + $this->rdelLength = strlen($rdel); + $this->rdelPreg = ''; + foreach (str_split($rdel, 1) as $chr) { + $this->rdelPreg .= '[' . preg_quote($chr,'/') . ']'; + } + $literals = $this->smarty->getLiterals(); + if (!empty($literals)) { + foreach ($literals as $key => $literal) { + $literalPreg = ''; + foreach (str_split($literal, 1) as $chr) { + $literalPreg .= '[' . preg_quote($chr,'/') . ']'; + } + $literals[ $key ] = $literalPreg; + } + $this->literalPreg = '|' . implode('|', $literals); + } else { + $this->literalPreg = ''; + } + } + + /** + * leave double quoted string + * - throw exception if block in string was not closed + * + * @throws \SmartyCompilerException + */ + public function leaveDoubleQuote() + { + if (array_pop($this->_tag_stack_count) !== $this->getTagStackCount()) { + $tag = $this->getOpenBlockTag(); + $this->trigger_template_error( + "unclosed '{{$tag}}' in doubled quoted string", + null, + true + ); + } + } + + /** + * Get left delimiter preg + * + * @return string + */ + public function getLdelPreg() + { + return $this->ldelPreg; + } + + /** + * Get right delimiter preg + * + * @return string + */ + public function getRdelPreg() + { + return $this->rdelPreg; + } + + /** + * Get length of left delimiter + * + * @return int + */ + public function getLdelLength() + { + return $this->ldelLength; + } + + /** + * Get length of right delimiter + * + * @return int + */ + public function getRdelLength() + { + return $this->rdelLength; + } + + /** + * Get name of current open block tag + * + * @return string|boolean + */ + public function getOpenBlockTag() + { + $tagCount = $this->getTagStackCount(); + if ($tagCount) { + return $this->_tag_stack[ $tagCount - 1 ][ 0 ]; + } else { + return false; + } + } + + /** + * Check if $value contains variable elements + * + * @param mixed $value + * + * @return bool|int + */ + public function isVariable($value) + { + if (is_string($value)) { + return preg_match('/[$(]/', $value); + } + if (is_bool($value) || is_numeric($value)) { + return false; + } + if (is_array($value)) { + foreach ($value as $k => $v) { + if ($this->isVariable($k) || $this->isVariable($v)) { + return true; + } + } + return false; + } + return false; + } + + /** + * Get new prefix variable name + * + * @return string + */ + public function getNewPrefixVariable() + { + ++self::$prefixVariableNumber; + return $this->getPrefixVariable(); + } + + /** + * Get current prefix variable name + * + * @return string + */ + public function getPrefixVariable() + { + return '$_prefixVariable' . self::$prefixVariableNumber; + } + + /** + * append code to prefix buffer + * + * @param string $code + */ + public function appendPrefixCode($code) + { + $this->prefix_code[] = $code; + } + + /** + * get prefix code string + * + * @return string + */ + public function getPrefixCode() + { + $code = ''; + $prefixArray = array_merge($this->prefix_code, array_pop($this->prefixCodeStack)); + $this->prefixCodeStack[] = array(); + foreach ($prefixArray as $c) { + $code = $this->appendCode($code, $c); + } + $this->prefix_code = array(); + return $code; + } + + /** + * Save current required plugins + * + * @param bool $init if true init required plugins + */ + public function saveRequiredPlugins($init = false) + { + $this->required_plugins_stack[] = $this->required_plugins; + if ($init) { + $this->required_plugins = array('compiled' => array(), 'nocache' => array()); + } + } + + /** + * Restore required plugins + */ + public function restoreRequiredPlugins() + { + $this->required_plugins = array_pop($this->required_plugins_stack); + } + + /** + * Compile code to call Smarty_Internal_Template::_checkPlugins() + * for required plugins + * + * @return string + */ + public function compileRequiredPlugins() + { + $code = $this->compileCheckPlugins($this->required_plugins[ 'compiled' ]); + if ($this->caching && !empty($this->required_plugins[ 'nocache' ])) { + $code .= $this->makeNocacheCode($this->compileCheckPlugins($this->required_plugins[ 'nocache' ])); + } + return $code; + } + + /** + * Compile code to call Smarty_Internal_Template::_checkPlugins + * - checks if plugin is callable require otherwise + * + * @param $requiredPlugins + * + * @return string + */ + public function compileCheckPlugins($requiredPlugins) + { + if (!empty($requiredPlugins)) { + $plugins = array(); + foreach ($requiredPlugins as $plugin) { + foreach ($plugin as $data) { + $plugins[] = $data; + } + } + return '$_smarty_tpl->_checkPlugins(' . $this->getVarExport($plugins) . ');' . "\n"; + } else { + return ''; + } + } + + /** + * method to compile a Smarty template + * + * @param mixed $_content template source + * @param bool $isTemplateSource + * + * @return bool true if compiling succeeded, false if it failed + */ + abstract protected function doCompile($_content, $isTemplateSource = false); + + /** + * Compile Tag + * + * @param string $tag tag name + * @param array $args array with tag attributes + * @param array $parameter array with compilation parameter + * + * @throws SmartyCompilerException + * @throws SmartyException + * @return string compiled code + */ + private function compileTag2($tag, $args, $parameter) + { + $plugin_type = ''; // $args contains the attributes parsed and compiled by the lexer/parser // assume that tag does compile into code, but creates no HTML output $this->has_code = true; - $this->has_output = false; // log tag/attributes - if (isset($this->smarty->get_used_tags) && $this->smarty->get_used_tags) { - $this->used_tags[] = array($tag,$args); - } - // check nocache option flag - if (in_array("'nocache'",$args) || in_array(array('nocache'=>'true'),$args) - || in_array(array('nocache'=>'"true"'),$args) || in_array(array('nocache'=>"'true'"),$args)) { - $this->tag_nocache = true; - } - // compile the smarty tag (required compile classes to compile the tag are autoloaded) + if (isset($this->smarty->_cache[ 'get_used_tags' ])) { + $this->template->_cache[ 'used_tags' ][] = array( + $tag, + $args + ); + } + // check nocache option flag + foreach ($args as $arg) { + if (!is_array($arg)) { + if ($arg === "'nocache'" || $arg === 'nocache') { + $this->tag_nocache = true; + } + } else { + foreach ($arg as $k => $v) { + if (($k === "'nocache'" || $k === 'nocache') && (trim($v, "'\" ") === 'true')) { + $this->tag_nocache = true; + } + } + } + } + // compile the smarty tag (required compile classes to compile the tag are auto loaded) if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { - if (isset($this->smarty->template_functions[$tag])) { + if (isset($this->parent_compiler->tpl_function[ $tag ]) + || (isset($this->template->smarty->ext->_tplFunction) + && $this->template->smarty->ext->_tplFunction->getTplFunction($this->template, $tag) !== false) + ) { // template defined by {template} tag - $args['_attr']['name'] = "'" . $tag . "'"; + $args[ '_attr' ][ 'name' ] = "'{$tag}'"; $_output = $this->callTagCompiler('call', $args, $parameter); - } - } + } + } if ($_output !== false) { if ($_output !== true) { // did we get compiled code if ($this->has_code) { - // Does it create output? - if ($this->has_output) { - $_output .= "\n"; - } // return compiled code return $_output; - } - } + } + } // tag did not produce compiled code - return ''; + return null; } else { // map_named attributes - if (isset($args['_attr'])) { - foreach ($args['_attr'] as $key => $attribute) { + if (isset($args[ '_attr' ])) { + foreach ($args[ '_attr' ] as $key => $attribute) { if (is_array($attribute)) { $args = array_merge($args, $attribute); - } - } - } + } + } + } // not an internal compiler tag - if (strlen($tag) < 6 || substr($tag, -5) != 'close') { + if (strlen($tag) < 6 || substr($tag, -5) !== 'close') { // check if tag is a registered object - if (isset($this->smarty->registered_objects[$tag]) && isset($parameter['object_methode'])) { - $methode = $parameter['object_methode']; - if (!in_array($methode, $this->smarty->registered_objects[$tag][3]) && - (empty($this->smarty->registered_objects[$tag][1]) || in_array($methode, $this->smarty->registered_objects[$tag][1]))) { - return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $methode); - } elseif (in_array($methode, $this->smarty->registered_objects[$tag][3])) { - return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); + if (isset($this->smarty->registered_objects[ $tag ]) && isset($parameter[ 'object_method' ])) { + $method = $parameter[ 'object_method' ]; + if (!in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ]) + && (empty($this->smarty->registered_objects[ $tag ][ 1 ]) + || in_array($method, $this->smarty->registered_objects[ $tag ][ 1 ])) + ) { + return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method); + } elseif (in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ])) { + return $this->callTagCompiler( + 'private_object_block_function', + $args, + $parameter, + $tag, + $method + ); } else { - return $this->trigger_template_error ('unallowed methode "' . $methode . '" in registered object "' . $tag . '"', $this->lex->taglineno); - } - } + // throw exception + $this->trigger_template_error( + 'not allowed method "' . $method . '" in registered object "' . + $tag . '"', + null, + true + ); + } + } // check if tag is registered - foreach (array(Smarty::PLUGIN_COMPILER, Smarty::PLUGIN_FUNCTION, Smarty::PLUGIN_BLOCK) as $type) { - if (isset($this->smarty->registered_plugins[$type][$tag])) { + foreach (array( + Smarty::PLUGIN_COMPILER, + Smarty::PLUGIN_FUNCTION, + Smarty::PLUGIN_BLOCK, + ) as $plugin_type) { + if (isset($this->smarty->registered_plugins[ $plugin_type ][ $tag ])) { // if compiler function plugin call it now - if ($type == Smarty::PLUGIN_COMPILER) { + if ($plugin_type === Smarty::PLUGIN_COMPILER) { $new_args = array(); - foreach ($args as $mixed) { - $new_args = array_merge($new_args, $mixed); - } - if (!$this->smarty->registered_plugins[$type][$tag][1]) { + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + if (!$this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 1 ]) { $this->tag_nocache = true; - } - $function = $this->smarty->registered_plugins[$type][$tag][0]; - if (!is_array($function)) { - return $function($new_args, $this); - } else if (is_object($function[0])) { - return $this->smarty->registered_plugins[$type][$tag][0][0]->$function[1]($new_args, $this); - } else { - return call_user_func_array($this->smarty->registered_plugins[$type][$tag][0], array($new_args, $this)); - } - } + } + return call_user_func_array( + $this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 0 ], + array( + $new_args, + $this + ) + ); + } // compile registered function or block function - if ($type == Smarty::PLUGIN_FUNCTION || $type == Smarty::PLUGIN_BLOCK) { - return $this->callTagCompiler('private_registered_' . $type, $args, $parameter, $tag); - } - } - } + if ($plugin_type === Smarty::PLUGIN_FUNCTION || $plugin_type === Smarty::PLUGIN_BLOCK) { + return $this->callTagCompiler( + 'private_registered_' . $plugin_type, + $args, + $parameter, + $tag + ); + } + } + } // check plugins from plugins folder - foreach ($this->smarty->plugin_search_order as $plugin_type) { - if ($plugin_type == Smarty::PLUGIN_BLOCK && $this->smarty->loadPlugin('smarty_compiler_' . $tag)) { + foreach ($this->plugin_search_order as $plugin_type) { + if ($plugin_type === Smarty::PLUGIN_COMPILER + && $this->smarty->loadPlugin('smarty_compiler_' . $tag) + && (!isset($this->smarty->security_policy) + || $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { $plugin = 'smarty_compiler_' . $tag; if (is_callable($plugin)) { - // convert arguments format for old compiler plugins + // convert arguments format for old compiler plugins $new_args = array(); - foreach ($args as $mixed) { - $new_args = array_merge($new_args, $mixed); - } + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } return $plugin($new_args, $this->smarty); - } + } if (class_exists($plugin, false)) { $plugin_object = new $plugin; if (method_exists($plugin_object, 'compile')) { return $plugin_object->compile($args, $this); - } - } - throw new SmartyException("Plugin \"{$tag}\" not callable"); + } + } + throw new SmartyException("Plugin '{$tag}' not callable"); } else { if ($function = $this->getPlugin($tag, $plugin_type)) { - return $this->callTagCompiler('private_' . $plugin_type . '_plugin', $args, $parameter, $tag, $function); - } - } - } + if (!isset($this->smarty->security_policy) + || $this->smarty->security_policy->isTrustedTag($tag, $this) + ) { + return $this->callTagCompiler( + 'private_' . $plugin_type . '_plugin', + $args, + $parameter, + $tag, + $function + ); + } + } + } + } + if (is_callable($this->smarty->default_plugin_handler_func)) { + $found = false; + // look for already resolved tags + foreach ($this->plugin_search_order as $plugin_type) { + if (isset($this->default_handler_plugins[ $plugin_type ][ $tag ])) { + $found = true; + break; + } + } + if (!$found) { + // call default handler + foreach ($this->plugin_search_order as $plugin_type) { + if ($this->getPluginFromDefaultHandler($tag, $plugin_type)) { + $found = true; + break; + } + } + } + if ($found) { + // if compiler function plugin call it now + if ($plugin_type === Smarty::PLUGIN_COMPILER) { + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + return call_user_func_array( + $this->default_handler_plugins[ $plugin_type ][ $tag ][ 0 ], + array( + $new_args, + $this + ) + ); + } else { + return $this->callTagCompiler( + 'private_registered_' . $plugin_type, + $args, + $parameter, + $tag + ); + } + } + } } else { // compile closing tag of block function - $base_tag = substr($tag, 0, -5); + $base_tag = substr($tag, 0, -5); // check if closing tag is a registered object - if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_methode'])) { - $methode = $parameter['object_methode']; - if (in_array($methode, $this->smarty->registered_objects[$base_tag][3])) { - return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); + if (isset($this->smarty->registered_objects[ $base_tag ]) && isset($parameter[ 'object_method' ])) { + $method = $parameter[ 'object_method' ]; + if (in_array($method, $this->smarty->registered_objects[ $base_tag ][ 3 ])) { + return $this->callTagCompiler( + 'private_object_block_function', + $args, + $parameter, + $tag, + $method + ); } else { - return $this->trigger_template_error ('unallowed closing tag methode "' . $methode . '" in registered object "' . $base_tag . '"', $this->lex->taglineno); - } - } + // throw exception + $this->trigger_template_error( + 'not allowed closing tag method "' . $method . + '" in registered object "' . $base_tag . '"', + null, + true + ); + } + } // registered block tag ? - if (isset($this->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$base_tag])) { + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) + || isset($this->default_handler_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) + ) { return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag); - } + } + // registered function tag ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ])) { + return $this->callTagCompiler('private_registered_function', $args, $parameter, $tag); + } // block plugin? if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function); - } + } + // function plugin? + if ($function = $this->getPlugin($tag, Smarty::PLUGIN_FUNCTION)) { + if (!isset($this->smarty->security_policy) + || $this->smarty->security_policy->isTrustedTag($tag, $this) + ) { + return $this->callTagCompiler('private_function_plugin', $args, $parameter, $tag, $function); + } + } + // registered compiler plugin ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ])) { + // if compiler function plugin call it now + $args = array(); + if (!$this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 1 ]) { + $this->tag_nocache = true; + } + return call_user_func_array( + $this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 0 ], + array( + $args, + $this + ) + ); + } if ($this->smarty->loadPlugin('smarty_compiler_' . $tag)) { $plugin = 'smarty_compiler_' . $tag; if (is_callable($plugin)) { return $plugin($args, $this->smarty); - } + } if (class_exists($plugin, false)) { $plugin_object = new $plugin; if (method_exists($plugin_object, 'compile')) { return $plugin_object->compile($args, $this); - } - } - throw new SmartyException("Plugin \"{$tag}\" not callable"); - } - } - $this->trigger_template_error ("unknown tag \"" . $tag . "\"", $this->lex->taglineno); - } - } - - /** - * lazy loads internal compile plugin for tag and calls the compile methode - * - * compile objects cached for reuse. - * class name format: Smarty_Internal_Compile_TagName - * plugin filename format: Smarty_Internal_Tagname.php - * - * @param $tag string tag name - * @param $args array with tag attributes - * @param $param1 optional parameter - * @param $param2 optional parameter - * @param $param3 optional parameter - * @return string compiled code - */ - public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) - { - // re-use object if already exists - if (isset(self::$_tag_objects[$tag])) { - // compile this tag - return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); - } - // lazy load internal compiler plugin - $class_name = 'Smarty_Internal_Compile_' . $tag; - if ($this->smarty->loadPlugin($class_name)) { - // use plugin if found - self::$_tag_objects[$tag] = new $class_name; - // compile this tag - return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); - } - // no internal compile plugin for this tag - return false; - } - - /** - * Check for plugins and return function name - * - * @param $pugin_name string name of plugin or function - * @param $type string type of plugin - * @return string call name of function - */ - public function getPlugin($plugin_name, $type) - { - $function = null; - if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { - if (isset($this->template->required_plugins['nocache'][$plugin_name][$type])) { - $function = $this->template->required_plugins['nocache'][$plugin_name][$type]['function']; - } else if (isset($this->template->required_plugins['compiled'][$plugin_name][$type])) { - $this->template->required_plugins['nocache'][$plugin_name][$type] = $this->template->required_plugins['compiled'][$plugin_name][$type]; - $function = $this->template->required_plugins['nocache'][$plugin_name][$type]['function']; - } - } else { - if (isset($this->template->required_plugins['compiled'][$plugin_name][$type])) { - $function = $this->template->required_plugins['compiled'][$plugin_name][$type]['function']; - } else if (isset($this->template->required_plugins['compiled'][$plugin_name][$type])) { - $this->template->required_plugins['compiled'][$plugin_name][$type] = $this->template->required_plugins['nocache'][$plugin_name][$type]; - $function = $this->template->required_plugins['compiled'][$plugin_name][$type]['function']; - } - } - if (isset($function)) { - if ($type == 'modifier') { - $this->template->saved_modifier[$plugin_name] = true; - } - return $function; - } - // loop through plugin dirs and find the plugin - $function = 'smarty_' . $type . '_' . $plugin_name; - $found = false; - foreach((array)$this->smarty->plugins_dir as $_plugin_dir) { - $file = rtrim($_plugin_dir, '/\\') . DS . $type . '.' . $plugin_name . '.php'; - if (file_exists($file)) { - // require_once($file); - $found = true; - break; - } - } - if ($found) { - if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { - $this->template->required_plugins['nocache'][$plugin_name][$type]['file'] = $file; - $this->template->required_plugins['nocache'][$plugin_name][$type]['function'] = $function; - } else { - $this->template->required_plugins['compiled'][$plugin_name][$type]['file'] = $file; - $this->template->required_plugins['compiled'][$plugin_name][$type]['function'] = $function; - } - if ($type == 'modifier') { - $this->template->saved_modifier[$plugin_name] = true; - } - return $function; - } - if (is_callable($function)) { - // plugin function is defined in the script - return $function; - } - return false; - } - /** - * Inject inline code for nocache template sections - * - * This method gets the content of each template element from the parser. - * If the content is compiled code and it should be not cached the code is injected - * into the rendered output. - * - * @param string $content content of template element - * @param boolean $tag_nocache true if the parser detected a nocache situation - * @param boolean $is_code true if content is compiled code - * @return string content - */ - public function processNocacheCode ($content, $is_code) - { - // If the template is not evaluated and we have a nocache section and or a nocache tag - if ($is_code && !empty($content)) { - // generate replacement code - if ((!$this->template->resource_object->isEvaluated || $this->template->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && - ($this->nocache || $this->tag_nocache || $this->template->forceNocache == 2)) { - $this->template->has_nocache_code = true; - $_output = str_replace("'", "\'", $content); - $_output = str_replace("^#^", "'", $_output); - $_output = "nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>"; - // make sure we include modifer plugins for nocache code - if (isset($this->template->saved_modifier)) { - foreach ($this->template->saved_modifier as $plugin_name => $dummy) { - if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) { - $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier']; - } - } - $this->template->saved_modifier = null; - } - } else { - $_output = $content; - } - } else { - $_output = $content; - } - $this->suppressNocacheProcessing = false; - $this->tag_nocache = false; - return $_output; - } - /** - * display compiler error messages without dying - * - * If parameter $args is empty it is a parser detected syntax error. - * In this case the parser is called to obtain information about expected tokens. - * - * If parameter $args contains a string this is used as error message - * - * @param $args string individual error message or null - */ - public function trigger_template_error($args = null, $line = null) - { - // get template source line which has error - if (!isset($line)) { - $line = $this->lex->line; - } - $match = preg_split("/\n/", $this->lex->data); - $error_text = 'Syntax Error in template "' . $this->template->getTemplateFilepath() . '" on line ' . $line . ' "' . htmlspecialchars(trim(preg_replace('![\t\r\n]+!',' ',$match[$line-1]))) . '" '; - if (isset($args)) { - // individual error message - $error_text .= $args; - } else { - // expected token from parser - $error_text .= ' - Unexpected "' . $this->lex->value.'"'; - if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4 ) { - foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) { - $exp_token = $this->parser->yyTokenName[$token]; - if (isset($this->lex->smarty_token_names[$exp_token])) { - // token type from lexer - $expect[] = '"' . $this->lex->smarty_token_names[$exp_token] . '"'; - } else { - // otherwise internal token name - $expect[] = $this->parser->yyTokenName[$token]; - } - } - $error_text .= ', expected one of: ' . implode(' , ', $expect); - } - } - throw new SmartyCompilerException($error_text); - } -} - -?> \ No newline at end of file + } + } + throw new SmartyException("Plugin '{$tag}' not callable"); + } + } + $this->trigger_template_error("unknown tag '{$tag}'", null, true); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatelexer.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatelexer.php index 5e0e496a3..867a31d26 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatelexer.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templatelexer.php @@ -1,176 +1,362 @@ + */ class Smarty_Internal_Templatelexer { + const TEXT = 1; + const TAG = 2; + const TAGBODY = 3; + const LITERAL = 4; + const DOUBLEQUOTEDSTRING = 5; + + /** + * Source + * + * @var string + */ public $data; + + /** + * Source length + * + * @var int + */ + public $dataLength = null; + + /** + * byte counter + * + * @var int + */ public $counter; + + /** + * token number + * + * @var int + */ public $token; + + /** + * token value + * + * @var string + */ public $value; - public $node; + + /** + * current line + * + * @var int + */ public $line; + + /** + * tag start line + * + * @var + */ public $taglineno; + + /** + * php code type + * + * @var string + */ + public $phpType = ''; + + /** + * state number + * + * @var int + */ public $state = 1; - public $strip = false; - private $heredoc_id_stack = Array(); - public $smarty_token_names = array ( // Text for parser error messages - 'IDENTITY' => '===', - 'NONEIDENTITY' => '!==', - 'EQUALS' => '==', - 'NOTEQUALS' => '!=', - 'GREATEREQUAL' => '(>=,ge)', - 'LESSEQUAL' => '(<=,le)', - 'GREATERTHAN' => '(>,gt)', - 'LESSTHAN' => '(<,lt)', - 'MOD' => '(%,mod)', - 'NOT' => '(!,not)', - 'LAND' => '(&&,and)', - 'LOR' => '(||,or)', - 'LXOR' => 'xor', - 'OPENP' => '(', - 'CLOSEP' => ')', - 'OPENB' => '[', - 'CLOSEB' => ']', - 'PTR' => '->', - 'APTR' => '=>', - 'EQUAL' => '=', - 'NUMBER' => 'number', - 'UNIMATH' => '+" , "-', - 'MATH' => '*" , "/" , "%', - 'INCDEC' => '++" , "--', - 'SPACE' => ' ', - 'DOLLAR' => '$', - 'SEMICOLON' => ';', - 'COLON' => ':', - 'DOUBLECOLON' => '::', - 'AT' => '@', - 'HATCH' => '#', - 'QUOTE' => '"', - 'BACKTICK' => '`', - 'VERT' => '|', - 'DOT' => '.', - 'COMMA' => '","', - 'ANDSYM' => '"&"', - 'QMARK' => '"?"', - 'ID' => 'identifier', - 'OTHER' => 'text', - 'LINEBREAK' => 'newline', - 'FAKEPHPSTARTTAG' => 'Fake PHP start tag', - 'PHPSTARTTAG' => 'PHP start tag', - 'PHPENDTAG' => 'PHP end tag', - 'LITERALSTART' => 'Literal start', - 'LITERALEND' => 'Literal end', - 'LDELSLASH' => 'closing tag', - 'COMMENT' => 'comment', - 'LITERALEND' => 'literal close', - 'AS' => 'as', - 'TO' => 'to', - ); - - - function __construct($data,$compiler) - { -// $this->data = preg_replace("/(\r\n|\r|\n)/", "\n", $data); - $this->data = $data; + + /** + * Smarty object + * + * @var Smarty + */ + public $smarty = null; + + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + + /** + * trace file + * + * @var resource + */ + public $yyTraceFILE; + + /** + * trace prompt + * + * @var string + */ + public $yyTracePrompt; + + /** + * XML flag true while processing xml + * + * @var bool + */ + public $is_xml = false; + + /** + * state names + * + * @var array + */ + public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',); + + /** + * token names + * + * @var array + */ + public $smarty_token_names = array( // Text for parser error messages + 'NOT' => '(!,not)', + 'OPENP' => '(', + 'CLOSEP' => ')', + 'OPENB' => '[', + 'CLOSEB' => ']', + 'PTR' => '->', + 'APTR' => '=>', + 'EQUAL' => '=', + 'NUMBER' => 'number', + 'UNIMATH' => '+" , "-', + 'MATH' => '*" , "/" , "%', + 'INCDEC' => '++" , "--', + 'SPACE' => ' ', + 'DOLLAR' => '$', + 'SEMICOLON' => ';', + 'COLON' => ':', + 'DOUBLECOLON' => '::', + 'AT' => '@', + 'HATCH' => '#', + 'QUOTE' => '"', + 'BACKTICK' => '`', + 'VERT' => '"|" modifier', + 'DOT' => '.', + 'COMMA' => '","', + 'QMARK' => '"?"', + 'ID' => 'id, name', + 'TEXT' => 'text', + 'LDELSLASH' => '{/..} closing tag', + 'LDEL' => '{...} Smarty tag', + 'COMMENT' => 'comment', + 'AS' => 'as', + 'TO' => 'to', + 'PHP' => '" '"<", "==" ... logical operator', + 'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition', + 'SCOND' => '"is even" ... if condition', + ); + + /** + * literal tag nesting level + * + * @var int + */ + private $literal_cnt = 0; + + /** + * preg token pattern for state TEXT + * + * @var string + */ + private $yy_global_pattern1 = null; + + /** + * preg token pattern for state TAG + * + * @var string + */ + private $yy_global_pattern2 = null; + + /** + * preg token pattern for state TAGBODY + * + * @var string + */ + private $yy_global_pattern3 = null; + + /** + * preg token pattern for state LITERAL + * + * @var string + */ + private $yy_global_pattern4 = null; + + /** + * preg token pattern for state DOUBLEQUOTEDSTRING + * + * @var null + */ + private $yy_global_pattern5 = null; + + /** + * preg token pattern for text + * + * @var null + */ + private $yy_global_text = null; + + /** + * preg token pattern for literal + * + * @var null + */ + private $yy_global_literal = null; + + private $_yy_state = 1; + + private $_yy_stack = array(); + + /** + * constructor + * + * @param string $source template source + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + public function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->data = $source; + $this->dataLength = strlen($this->data); $this->counter = 0; + if (preg_match('/^\xEF\xBB\xBF/i', $this->data, $match)) { + $this->counter += strlen($match[ 0 ]); + } $this->line = 1; - $this->smarty = $compiler->smarty; + $this->smarty = $compiler->template->smarty; $this->compiler = $compiler; - $this->ldel = preg_quote($this->smarty->left_delimiter,'/'); - $this->ldel_length = strlen($this->smarty->left_delimiter); - $this->rdel = preg_quote($this->smarty->right_delimiter,'/'); - $this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter; - $this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter; - } + $this->compiler->initDelimiterPreg(); + $this->smarty_token_names[ 'LDEL' ] = $this->smarty->getLeftDelimiter(); + $this->smarty_token_names[ 'RDEL' ] = $this->smarty->getRightDelimiter(); + } + /** + * open lexer/parser trace file + * + */ + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + /** + * replace placeholders with runtime preg code + * + * @param string $preg + * + * @return string + */ + public function replace($preg) + { + return $this->compiler->replaceDelimiter($preg); + } - private $_yy_state = 1; - private $_yy_stack = array(); + /** + * check if current value is an autoliteral left delimiter + * + * @return bool + */ + public function isAutoLiteral() + { + return $this->smarty->getAutoLiteral() && isset($this->value[ $this->compiler->getLdelLength() ]) ? + strpos(" \n\t\r", $this->value[ $this->compiler->getLdelLength() ]) !== false : false; + } // end function - function yylex() + public function yylex() { return $this->{'yylex' . $this->_yy_state}(); } - function yypushstate($state) + public function yypushstate($state) { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sState push %s\n", $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state); + } array_push($this->_yy_stack, $this->_yy_state); $this->_yy_state = $state; + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%snew State %s\n", $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state); + } } - function yypopstate() + public function yypopstate() { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sState pop %s\n", $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state); + } $this->_yy_state = array_pop($this->_yy_stack); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%snew State %s\n", $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state); + } } - function yybegin($state) + public function yybegin($state) { $this->_yy_state = $state; + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sState set %s\n", $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : $this->_yy_state); + } } - - - function yylex1() - { - $tokenMap = array ( - 1 => 0, - 2 => 0, - 3 => 1, - 5 => 0, - 6 => 0, - 7 => 0, - 8 => 0, - 9 => 0, - 10 => 0, - 11 => 0, - 12 => 1, - 14 => 0, - 15 => 0, - 16 => 0, - 17 => 0, - 18 => 0, - 19 => 0, - 20 => 0, - 21 => 0, - 22 => 0, - 23 => 2, - 26 => 0, - 27 => 0, - ); - if ($this->counter >= strlen($this->data)) { + public function yylex1() + { + if (!isset($this->yy_global_pattern1)) { + $this->yy_global_pattern1 = + $this->replace("/\G([{][}])|\G((SMARTYldel)SMARTYal[*])|\G((SMARTYldel)SMARTYalphp([ ].*?)?SMARTYrdel|(SMARTYldel)SMARTYal[\/]phpSMARTYrdel)|\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([<][?]((php\\s+|=)|\\s+)|[<][%]|[<][?]xml\\s+|[<]script\\s+language\\s*=\\s*[\"']?\\s*php\\s*[\"']?\\s*[>]|[?][>]|[%][>])|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^(".$this->ldel."[$]smarty\\.block\\.child".$this->rdel.")|^(\\{\\})|^(".$this->ldel."\\*([\S\s]*?)\\*".$this->rdel.")|^([\t ]*[\r\n]+[\t ]*)|^(".$this->ldel."strip".$this->rdel.")|^(".$this->ldel."\\s{1,}strip\\s{1,}".$this->rdel.")|^(".$this->ldel."\/strip".$this->rdel.")|^(".$this->ldel."\\s{1,}\/strip\\s{1,}".$this->rdel.")|^(".$this->ldel."\\s*literal\\s*".$this->rdel.")|^(".$this->ldel."\\s{1,}\/)|^(".$this->ldel."\\s*(if|elseif|else if|while)(?![^\s]))|^(".$this->ldel."\\s*for(?![^\s]))|^(".$this->ldel."\\s*foreach(?![^\s]))|^(".$this->ldel."\\s{1,})|^(".$this->ldel."\/)|^(".$this->ldel.")|^(<\\?(?:php\\w+|=|[a-zA-Z]+)?)|^(\\?>)|^(<%)|^(%>)|^(([\S\s]*?)(?=([\t ]*[\r\n]+[\t ]*|".$this->ldel."|<\\?|\\?>|<%|%>)))|^([\S\s]+)|^(.)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state TEXT'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state TEXT'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r1_' . $this->token}($yysubmatches); + $r = $this->{'yy_r1_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -183,293 +369,253 @@ function yylex1() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { - throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + } + } else { + throw new Exception('Unexpected input at line ' . $this->line . + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const TEXT = 1; - function yy_r1_1($yy_subpatterns) + public function yy_r1_1() { - - $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILD; + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - function yy_r1_2($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } - function yy_r1_3($yy_subpatterns) + public function yy_r1_2() { - - $this->token = Smarty_Internal_Templateparser::TP_COMMENT; + $to = $this->dataLength; + preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/", $this->data, $match, PREG_OFFSET_CAPTURE, + $this->counter); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ] + strlen($match[ 0 ][ 0 ]); + } else { + $this->compiler->trigger_template_error("missing or misspelled comment closing tag '{$this->smarty->getRightDelimiter()}'"); + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + return false; } - function yy_r1_5($yy_subpatterns) - { - if ($this->strip) { - return false; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LINEBREAK; - } - } - function yy_r1_6($yy_subpatterns) + public function yy_r1_4() { - - $this->strip = true; - return false; + $this->compiler->getTagCompiler('private_php')->parsePhp($this); } - function yy_r1_7($yy_subpatterns) - { - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->strip = true; - return false; - } - } - function yy_r1_8($yy_subpatterns) + public function yy_r1_8() { - - $this->strip = false; - return false; + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - function yy_r1_9($yy_subpatterns) - { - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->strip = false; - return false; - } - } - function yy_r1_10($yy_subpatterns) + public function yy_r1_10() { - - $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART; - $this->yypushstate(self::LITERAL); + $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART; + $this->yypushstate(self::LITERAL); } - function yy_r1_11($yy_subpatterns) - { - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - } - function yy_r1_12($yy_subpatterns) + public function yy_r1_12() { + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypushstate(self::LITERAL); + } // end function - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELIF; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + public function yy_r1_14() + { + $this->yypushstate(self::TAG); + return true; } - function yy_r1_14($yy_subpatterns) + + public function yy_r1_16() { + $this->compiler->getTagCompiler('private_php')->parsePhp($this); + } - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + public function yy_r1_19() + { + if (!isset($this->yy_global_text)) { + $this->yy_global_text = + $this->replace('/(SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*[>]|[?][>]|[%][>]SMARTYliteral/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_text, $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ]; + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - function yy_r1_15($yy_subpatterns) + + public function yylex2() { + if (!isset($this->yy_global_pattern2)) { + $this->yy_global_pattern2 = + $this->replace("/\G((SMARTYldel)SMARTYal(if|elseif|else if|while)\\s+)|\G((SMARTYldel)SMARTYalfor\\s+)|\G((SMARTYldel)SMARTYalforeach(?![^\s]))|\G((SMARTYldel)SMARTYalsetfilter\\s+)|\G((SMARTYldel)SMARTYalmake_nocache\\s+)|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[$]smarty\\.block\\.(child|parent)\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/][0-9]*[a-zA-Z_]\\w*\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[$][0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal)/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + do { + if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state TAG'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r2_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line ' . $this->line . + ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); + } - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + public function yy_r2_1() + { + $this->token = Smarty_Internal_Templateparser::TP_LDELIF; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; } - function yy_r1_16($yy_subpatterns) + + public function yy_r2_4() { + $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDEL; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + public function yy_r2_6() + { + $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; } - function yy_r1_17($yy_subpatterns) + + public function yy_r2_8() { + $this->token = Smarty_Internal_Templateparser::TP_LDELSETFILTER; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } - $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; + public function yy_r2_10() + { + $this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; } - function yy_r1_18($yy_subpatterns) + + public function yy_r2_12() { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG; + $this->taglineno = $this->line; + } - $this->token = Smarty_Internal_Templateparser::TP_LDEL; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; + public function yy_r2_15() + { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT; + $this->taglineno = $this->line; } - function yy_r1_19($yy_subpatterns) + + public function yy_r2_18() { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_CLOSETAG; + $this->taglineno = $this->line; + } - if (in_array($this->value, Array('token = Smarty_Internal_Templateparser::TP_PHPSTARTTAG; - } elseif ($this->value == 'token = Smarty_Internal_Templateparser::TP_XMLTAG; - } else { - $this->token = Smarty_Internal_Templateparser::TP_FAKEPHPSTARTTAG; - $this->value = substr($this->value, 0, 2); - } - } - function yy_r1_20($yy_subpatterns) + public function yy_r2_20() { + if ($this->_yy_stack[ count($this->_yy_stack) - 1 ] === self::TEXT) { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT; + $this->taglineno = $this->line; + } else { + $this->value = $this->smarty->getLeftDelimiter(); + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + } // end function - $this->token = Smarty_Internal_Templateparser::TP_PHPENDTAG; - } - function yy_r1_21($yy_subpatterns) - { - - $this->token = Smarty_Internal_Templateparser::TP_ASPSTARTTAG; - } - function yy_r1_22($yy_subpatterns) + public function yy_r2_23() { + $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } - $this->token = Smarty_Internal_Templateparser::TP_ASPENDTAG; + public function yy_r2_25() + { + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; } - function yy_r1_23($yy_subpatterns) - { - - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } - function yy_r1_26($yy_subpatterns) - { - - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } - function yy_r1_27($yy_subpatterns) - { - - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } - - - function yylex2() - { - $tokenMap = array ( - 1 => 0, - 2 => 0, - 3 => 1, - 5 => 0, - 6 => 0, - 7 => 0, - 8 => 0, - 9 => 0, - 10 => 0, - 11 => 0, - 12 => 0, - 13 => 0, - 14 => 0, - 15 => 0, - 16 => 0, - 17 => 0, - 18 => 0, - 19 => 0, - 20 => 1, - 22 => 1, - 24 => 1, - 26 => 0, - 27 => 0, - 28 => 0, - 29 => 0, - 30 => 0, - 31 => 0, - 32 => 0, - 33 => 0, - 34 => 0, - 35 => 0, - 36 => 0, - 37 => 0, - 38 => 0, - 39 => 0, - 40 => 0, - 41 => 0, - 42 => 0, - 43 => 3, - 47 => 0, - 48 => 0, - 49 => 0, - 50 => 0, - 51 => 0, - 52 => 0, - 53 => 0, - 54 => 0, - 55 => 1, - 57 => 1, - 59 => 0, - 60 => 0, - 61 => 0, - 62 => 0, - 63 => 0, - 64 => 0, - 65 => 0, - 66 => 0, - 67 => 0, - 68 => 0, - 69 => 0, - 70 => 0, - 71 => 0, - 72 => 0, - 73 => 0, - 74 => 0, - 75 => 0, - 76 => 0, - ); - if ($this->counter >= strlen($this->data)) { + + public function yylex3() + { + if (!isset($this->yy_global_pattern3)) { + $this->yy_global_pattern3 = + $this->replace("/\G(\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*([!=][=]{1,2}|[<][=>]?|[>][=]?|[&|]{2})\\s*)|\G(\\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even|div)\\s+by\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G([!]\\s*|not\\s+)|\G([(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\\s*)|\G(\\s*[(]\\s*)|\G(\\s*[)])|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*[-][>]\\s*)|\G(\\s*[=][>]\\s*)|\G(\\s*[=]\\s*)|\G(([+]|[-]){2})|\G(\\s*([+]|[-])\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G([@])|\G(array\\s*[(]\\s*)|\G([#])|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*[=]\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G([`])|\G([|][@]?)|\G([.])|\G(\\s*[,]\\s*)|\G(\\s*[;]\\s*)|\G([:]{2})|\G(\\s*[:]\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|^(".$this->ldel."\\s{1,}\/)|^(".$this->ldel."\\s*(if|elseif|else if|while)(?![^\s]))|^(".$this->ldel."\\s*for(?![^\s]))|^(".$this->ldel."\\s*foreach(?![^\s]))|^(".$this->ldel."\\s{1,})|^(\\s{1,}".$this->rdel.")|^(".$this->ldel."\/)|^(".$this->ldel.")|^(".$this->rdel.")|^(\\s+is\\s+in\\s+)|^(\\s+as\\s+)|^(\\s+to\\s+)|^(\\s+step\\s+)|^(\\s+instanceof\\s+)|^(\\s*===\\s*)|^(\\s*!==\\s*)|^(\\s*==\\s*|\\s+eq\\s+)|^(\\s*!=\\s*|\\s*<>\\s*|\\s+(ne|neq)\\s+)|^(\\s*>=\\s*|\\s+(ge|gte)\\s+)|^(\\s*<=\\s*|\\s+(le|lte)\\s+)|^(\\s*>\\s*|\\s+gt\\s+)|^(\\s*<\\s*|\\s+lt\\s+)|^(\\s+mod\\s+)|^(!\\s*|not\\s+)|^(\\s*&&\\s*|\\s*and\\s+)|^(\\s*\\|\\|\\s*|\\s*or\\s+)|^(\\s*xor\\s+)|^(\\s+is\\s+odd\\s+by\\s+)|^(\\s+is\\s+not\\s+odd\\s+by\\s+)|^(\\s+is\\s+odd)|^(\\s+is\\s+not\\s+odd)|^(\\s+is\\s+even\\s+by\\s+)|^(\\s+is\\s+not\\s+even\\s+by\\s+)|^(\\s+is\\s+even)|^(\\s+is\\s+not\\s+even)|^(\\s+is\\s+div\\s+by\\s+)|^(\\s+is\\s+not\\s+div\\s+by\\s+)|^(\\((int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)\\)\\s*)|^(\\(\\s*)|^(\\s*\\))|^(\\[\\s*)|^(\\s*\\])|^(\\s*->\\s*)|^(\\s*=>\\s*)|^(\\s*=\\s*)|^(\\+\\+|--)|^(\\s*(\\+|-)\\s*)|^(\\s*(\\*|\/|%)\\s*)|^(\\$)|^(\\s*;)|^(::)|^(\\s*:\\s*)|^(@)|^(#)|^(\")|^(`)|^(\\|)|^(\\.)|^(\\s*,\\s*)|^(\\s*&\\s*)|^(\\s*\\?\\s*)|^(0[xX][0-9a-fA-F]+)|^([0-9]*[a-zA-Z_]\\w*)|^(\\d+)|^(\\s+)|^(.)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state SMARTY'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state TAGBODY'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r2_' . $this->token}($yysubmatches); + $r = $this->{'yy_r3_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -482,440 +628,286 @@ function yylex2() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { - throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + } + } else { + throw new Exception('Unexpected input at line ' . $this->line . + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const SMARTY = 2; - function yy_r2_1($yy_subpatterns) + public function yy_r3_1() { - - $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; + $this->token = Smarty_Internal_Templateparser::TP_RDEL; + $this->yypopstate(); } - function yy_r2_2($yy_subpatterns) - { - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - } - function yy_r2_3($yy_subpatterns) + public function yy_r3_2() { - - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELIF; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + $this->yypushstate(self::TAG); + return true; } - function yy_r2_5($yy_subpatterns) - { - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - } - function yy_r2_6($yy_subpatterns) + public function yy_r3_4() { - - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypushstate(self::DOUBLEQUOTEDSTRING); + $this->compiler->enterDoubleQuote(); } - function yy_r2_7($yy_subpatterns) - { - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDEL; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - } - function yy_r2_8($yy_subpatterns) + public function yy_r3_5() { - - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_RDEL; - $this->yypopstate(); - } + $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; } - function yy_r2_9($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - function yy_r2_10($yy_subpatterns) + public function yy_r3_6() { - - $this->token = Smarty_Internal_Templateparser::TP_LDEL; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; } - function yy_r2_11($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_RDEL; - $this->yypopstate(); - } - function yy_r2_12($yy_subpatterns) + public function yy_r3_7() { - - $this->token = Smarty_Internal_Templateparser::TP_ISIN; + $this->token = Smarty_Internal_Templateparser::TP_DOLLAR; } - function yy_r2_13($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_AS; - } - function yy_r2_14($yy_subpatterns) + public function yy_r3_8() { - - $this->token = Smarty_Internal_Templateparser::TP_TO; + $this->token = Smarty_Internal_Templateparser::TP_ISIN; } - function yy_r2_15($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_STEP; - } - function yy_r2_16($yy_subpatterns) + public function yy_r3_9() { - - $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF; + $this->token = Smarty_Internal_Templateparser::TP_AS; } - function yy_r2_17($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_IDENTITY; - } - function yy_r2_18($yy_subpatterns) + public function yy_r3_10() { - - $this->token = Smarty_Internal_Templateparser::TP_NONEIDENTITY; + $this->token = Smarty_Internal_Templateparser::TP_TO; } - function yy_r2_19($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_EQUALS; - } - function yy_r2_20($yy_subpatterns) + public function yy_r3_11() { - - $this->token = Smarty_Internal_Templateparser::TP_NOTEQUALS; + $this->token = Smarty_Internal_Templateparser::TP_STEP; } - function yy_r2_22($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_GREATEREQUAL; - } - function yy_r2_24($yy_subpatterns) + public function yy_r3_12() { - - $this->token = Smarty_Internal_Templateparser::TP_LESSEQUAL; + $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF; } - function yy_r2_26($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_GREATERTHAN; - } - function yy_r2_27($yy_subpatterns) + public function yy_r3_13() { - - $this->token = Smarty_Internal_Templateparser::TP_LESSTHAN; + $this->token = Smarty_Internal_Templateparser::TP_LOGOP; } - function yy_r2_28($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_MOD; - } - function yy_r2_29($yy_subpatterns) + public function yy_r3_15() { - - $this->token = Smarty_Internal_Templateparser::TP_NOT; + $this->token = Smarty_Internal_Templateparser::TP_SLOGOP; } - function yy_r2_30($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_LAND; - } - function yy_r2_31($yy_subpatterns) + public function yy_r3_17() { - - $this->token = Smarty_Internal_Templateparser::TP_LOR; + $this->token = Smarty_Internal_Templateparser::TP_TLOGOP; } - function yy_r2_32($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_LXOR; - } - function yy_r2_33($yy_subpatterns) + public function yy_r3_20() { - - $this->token = Smarty_Internal_Templateparser::TP_ISODDBY; + $this->token = Smarty_Internal_Templateparser::TP_SINGLECOND; } - function yy_r2_34($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_ISNOTODDBY; - } - function yy_r2_35($yy_subpatterns) + public function yy_r3_23() { - - $this->token = Smarty_Internal_Templateparser::TP_ISODD; + $this->token = Smarty_Internal_Templateparser::TP_NOT; } - function yy_r2_36($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_ISNOTODD; - } - function yy_r2_37($yy_subpatterns) + public function yy_r3_24() { - - $this->token = Smarty_Internal_Templateparser::TP_ISEVENBY; + $this->token = Smarty_Internal_Templateparser::TP_TYPECAST; } - function yy_r2_38($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_ISNOTEVENBY; - } - function yy_r2_39($yy_subpatterns) + public function yy_r3_28() { - - $this->token = Smarty_Internal_Templateparser::TP_ISEVEN; + $this->token = Smarty_Internal_Templateparser::TP_OPENP; } - function yy_r2_40($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_ISNOTEVEN; - } - function yy_r2_41($yy_subpatterns) + public function yy_r3_29() { - - $this->token = Smarty_Internal_Templateparser::TP_ISDIVBY; + $this->token = Smarty_Internal_Templateparser::TP_CLOSEP; } - function yy_r2_42($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_ISNOTDIVBY; - } - function yy_r2_43($yy_subpatterns) + public function yy_r3_30() { - - $this->token = Smarty_Internal_Templateparser::TP_TYPECAST; + $this->token = Smarty_Internal_Templateparser::TP_OPENB; } - function yy_r2_47($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_OPENP; - } - function yy_r2_48($yy_subpatterns) + public function yy_r3_31() { - - $this->token = Smarty_Internal_Templateparser::TP_CLOSEP; + $this->token = Smarty_Internal_Templateparser::TP_CLOSEB; } - function yy_r2_49($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_OPENB; - } - function yy_r2_50($yy_subpatterns) + public function yy_r3_32() { - - $this->token = Smarty_Internal_Templateparser::TP_CLOSEB; + $this->token = Smarty_Internal_Templateparser::TP_PTR; } - function yy_r2_51($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_PTR; - } - function yy_r2_52($yy_subpatterns) + public function yy_r3_33() { - - $this->token = Smarty_Internal_Templateparser::TP_APTR; + $this->token = Smarty_Internal_Templateparser::TP_APTR; } - function yy_r2_53($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_EQUAL; - } - function yy_r2_54($yy_subpatterns) + public function yy_r3_34() { - - $this->token = Smarty_Internal_Templateparser::TP_INCDEC; + $this->token = Smarty_Internal_Templateparser::TP_EQUAL; } - function yy_r2_55($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_UNIMATH; - } - function yy_r2_57($yy_subpatterns) + public function yy_r3_35() { - - $this->token = Smarty_Internal_Templateparser::TP_MATH; + $this->token = Smarty_Internal_Templateparser::TP_INCDEC; } - function yy_r2_59($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_DOLLAR; - } - function yy_r2_60($yy_subpatterns) + public function yy_r3_37() { - - $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON; + $this->token = Smarty_Internal_Templateparser::TP_UNIMATH; } - function yy_r2_61($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON; - } - function yy_r2_62($yy_subpatterns) + public function yy_r3_39() { - - $this->token = Smarty_Internal_Templateparser::TP_COLON; + $this->token = Smarty_Internal_Templateparser::TP_MATH; } - function yy_r2_63($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_AT; - } - function yy_r2_64($yy_subpatterns) + public function yy_r3_41() { - - $this->token = Smarty_Internal_Templateparser::TP_HATCH; + $this->token = Smarty_Internal_Templateparser::TP_AT; } - function yy_r2_65($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_QUOTE; - $this->yypushstate(self::DOUBLEQUOTEDSTRING); - } - function yy_r2_66($yy_subpatterns) + public function yy_r3_42() { - - $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; - $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_ARRAYOPEN; } - function yy_r2_67($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_VERT; - } - function yy_r2_68($yy_subpatterns) + public function yy_r3_43() { - - $this->token = Smarty_Internal_Templateparser::TP_DOT; + $this->token = Smarty_Internal_Templateparser::TP_HATCH; } - function yy_r2_69($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_COMMA; - } - function yy_r2_70($yy_subpatterns) + public function yy_r3_44() { - - $this->token = Smarty_Internal_Templateparser::TP_ANDSYM; + // resolve conflicts with shorttag and right_delimiter starting with '=' + if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->compiler->getRdelLength()) === + $this->smarty->getRightDelimiter()) { + preg_match('/\s+/', $this->value, $match); + $this->value = $match[ 0 ]; + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_ATTR; + } } - function yy_r2_71($yy_subpatterns) + + public function yy_r3_45() { + $this->token = Smarty_Internal_Templateparser::TP_NAMESPACE; + } - $this->token = Smarty_Internal_Templateparser::TP_QMARK; + public function yy_r3_48() + { + $this->token = Smarty_Internal_Templateparser::TP_ID; } - function yy_r2_72($yy_subpatterns) + + public function yy_r3_49() { + $this->token = Smarty_Internal_Templateparser::TP_INTEGER; + } - $this->token = Smarty_Internal_Templateparser::TP_HEX; + public function yy_r3_50() + { + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->yypopstate(); } - function yy_r2_73($yy_subpatterns) + + public function yy_r3_51() { + $this->token = Smarty_Internal_Templateparser::TP_VERT; + } - $this->token = Smarty_Internal_Templateparser::TP_ID; + public function yy_r3_52() + { + $this->token = Smarty_Internal_Templateparser::TP_DOT; } - function yy_r2_74($yy_subpatterns) + + public function yy_r3_53() { + $this->token = Smarty_Internal_Templateparser::TP_COMMA; + } - $this->token = Smarty_Internal_Templateparser::TP_INTEGER; + public function yy_r3_54() + { + $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON; } - function yy_r2_75($yy_subpatterns) + + public function yy_r3_55() { + $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON; + } - $this->token = Smarty_Internal_Templateparser::TP_SPACE; + public function yy_r3_56() + { + $this->token = Smarty_Internal_Templateparser::TP_COLON; } - function yy_r2_76($yy_subpatterns) + + public function yy_r3_57() { + $this->token = Smarty_Internal_Templateparser::TP_QMARK; + } - $this->token = Smarty_Internal_Templateparser::TP_OTHER; + public function yy_r3_58() + { + $this->token = Smarty_Internal_Templateparser::TP_HEX; } + public function yy_r3_59() + { + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } // end function + public function yy_r3_60() + { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } - function yylex3() + public function yylex4() { - $tokenMap = array ( - 1 => 0, - 2 => 0, - 3 => 0, - 4 => 0, - 5 => 0, - 6 => 0, - 7 => 0, - 8 => 2, - 11 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern4)) { + $this->yy_global_pattern4 = + $this->replace("/\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^(".$this->ldel."\\s*literal\\s*".$this->rdel.")|^(".$this->ldel."\\s*\/literal\\s*".$this->rdel.")|^([\t ]*[\r\n]+[\t ]*)|^(<\\?(?:php\\w+|=|[a-zA-Z]+)?)|^(\\?>)|^(<%)|^(%>)|^(([\S\s]*?)(?=([\t ]*[\r\n]+[\t ]*|".$this->ldel."\/?literal".$this->rdel."|<\\?|<%)))|^(.)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state LITERAL'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state LITERAL'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r3_' . $this->token}($yysubmatches); + $r = $this->{'yy_r4_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -928,119 +920,81 @@ function yylex3() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { - throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + } + } else { + throw new Exception('Unexpected input at line ' . $this->line . + ': ' . $this->data[ $this->counter ]); } break; } while (true); - - } // end function - - - const LITERAL = 3; - function yy_r3_1($yy_subpatterns) - { - - $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART; - $this->yypushstate(self::LITERAL); } - function yy_r3_2($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; - $this->yypopstate(); - } - function yy_r3_3($yy_subpatterns) + public function yy_r4_1() { - - $this->token = Smarty_Internal_Templateparser::TP_LITERAL; - } - function yy_r3_4($yy_subpatterns) - { - - if (in_array($this->value, Array('token = Smarty_Internal_Templateparser::TP_PHPSTARTTAG; - } else { - $this->token = Smarty_Internal_Templateparser::TP_FAKEPHPSTARTTAG; - $this->value = substr($this->value, 0, 2); - } - } - function yy_r3_5($yy_subpatterns) - { - - $this->token = Smarty_Internal_Templateparser::TP_PHPENDTAG; + $this->literal_cnt++; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; } - function yy_r3_6($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_ASPSTARTTAG; - } - function yy_r3_7($yy_subpatterns) + public function yy_r4_3() { - - $this->token = Smarty_Internal_Templateparser::TP_ASPENDTAG; + if ($this->literal_cnt) { + $this->literal_cnt--; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } else { + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypopstate(); + } } - function yy_r3_8($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_LITERAL; - } - function yy_r3_11($yy_subpatterns) + public function yy_r4_5() { + if (!isset($this->yy_global_literal)) { + $this->yy_global_literal = $this->replace('/(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel/isS'); + } + $to = $this->dataLength; + preg_match($this->yy_global_literal, $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ]; + } else { + $this->compiler->trigger_template_error("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } // end function - $this->compiler->trigger_template_error ("missing or misspelled literal closing tag"); - } - - - function yylex4() + public function yylex5() { - $tokenMap = array ( - 1 => 0, - 2 => 1, - 4 => 0, - 5 => 0, - 6 => 0, - 7 => 0, - 8 => 0, - 9 => 0, - 10 => 0, - 11 => 0, - 12 => 0, - 13 => 3, - 17 => 0, - 18 => 0, - ); - if ($this->counter >= strlen($this->data)) { + if (!isset($this->yy_global_pattern5)) { + $this->yy_global_pattern5 = + $this->replace("/\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G([`][$])|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=((SMARTYldel)SMARTYal|\\$|`\\$|\"SMARTYliteral)))|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { return false; // end of input } - $yy_global_pattern = "/^(".$this->ldel."\\s{1,}\/)|^(".$this->ldel."\\s*(if|elseif|else if|while)(?![^\s]))|^(".$this->ldel."\\s*for(?![^\s]))|^(".$this->ldel."\\s*foreach(?![^\s]))|^(".$this->ldel."\\s{1,})|^(".$this->ldel."\/)|^(".$this->ldel.")|^(\")|^(`\\$)|^(\\$[0-9]*[a-zA-Z_]\\w*)|^(\\$)|^(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=(".$this->ldel."|\\$|`\\$|\")))|^([\S\s]+)|^(.)/iS"; - do { - if (preg_match($yy_global_pattern, substr($this->data, $this->counter), $yymatches)) { - $yysubmatches = $yymatches; - $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns - if (!count($yymatches)) { + if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[ 0 ][ 1 ])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { throw new Exception('Error: lexing failed because a rule matched' . - 'an empty string. Input "' . substr($this->data, - $this->counter, 5) . '... state DOUBLEQUOTEDSTRING'); + ' an empty string. Input "' . substr($this->data, + $this->counter, 5) . '... state DOUBLEQUOTEDSTRING'); } next($yymatches); // skip global match $this->token = key($yymatches); // token number - if ($tokenMap[$this->token]) { - // extract sub-patterns for passing to lex function - $yysubmatches = array_slice($yysubmatches, $this->token + 1, - $tokenMap[$this->token]); - } else { - $yysubmatches = array(); - } $this->value = current($yymatches); // token value - $r = $this->{'yy_r4_' . $this->token}($yysubmatches); + $r = $this->{'yy_r5_' . $this->token}(); if ($r === null) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); @@ -1053,130 +1007,89 @@ function yylex4() } elseif ($r === false) { $this->counter += strlen($this->value); $this->line += substr_count($this->value, "\n"); - if ($this->counter >= strlen($this->data)) { + if ($this->counter >= $this->dataLength) { return false; // end of input } // skip this token continue; - } } else { - throw new Exception('Unexpected input at line' . $this->line . - ': ' . $this->data[$this->counter]); + } + } else { + throw new Exception('Unexpected input at line ' . $this->line . + ': ' . $this->data[ $this->counter ]); } break; } while (true); + } - } // end function - - - const DOUBLEQUOTEDSTRING = 4; - function yy_r4_1($yy_subpatterns) + public function yy_r5_1() { - - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - function yy_r4_2($yy_subpatterns) - { - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELIF; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - } - function yy_r4_4($yy_subpatterns) + public function yy_r5_3() { - - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - function yy_r4_5($yy_subpatterns) - { - if ($this->smarty->auto_literal && trim(substr($this->value,$this->ldel_length,1)) == '') { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - } - function yy_r4_6($yy_subpatterns) + public function yy_r5_5() { - - if ($this->smarty->auto_literal) { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; - } else { - $this->token = Smarty_Internal_Templateparser::TP_LDEL; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - function yy_r4_7($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; - } - function yy_r4_8($yy_subpatterns) + public function yy_r5_7() { - - $this->token = Smarty_Internal_Templateparser::TP_LDEL; - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; + $this->yypushstate(self::TAG); + return true; } - function yy_r4_9($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_QUOTE; - $this->yypopstate(); - } - function yy_r4_10($yy_subpatterns) + public function yy_r5_9() { - - $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; - $this->value = substr($this->value,0,-1); - $this->yypushstate(self::SMARTY); - $this->taglineno = $this->line; + $this->yypushstate(self::TAG); + return true; } - function yy_r4_11($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; - } - function yy_r4_12($yy_subpatterns) + public function yy_r5_11() { - - $this->token = Smarty_Internal_Templateparser::TP_OTHER; + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->taglineno = $this->line; + $this->yypushstate(self::TAGBODY); } - function yy_r4_13($yy_subpatterns) - { - $this->token = Smarty_Internal_Templateparser::TP_OTHER; + public function yy_r5_13() + { + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypopstate(); } - function yy_r4_17($yy_subpatterns) + + public function yy_r5_14() { + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->value = substr($this->value, 0, -1); + $this->yypushstate(self::TAGBODY); + $this->taglineno = $this->line; + } - $this->token = Smarty_Internal_Templateparser::TP_OTHER; + public function yy_r5_15() + { + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; } - function yy_r4_18($yy_subpatterns) + + public function yy_r5_16() { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } - $this->token = Smarty_Internal_Templateparser::TP_OTHER; + public function yy_r5_17() + { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; } + public function yy_r5_22() + { + $to = $this->dataLength; + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } } -?> \ No newline at end of file + + diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templateparser.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templateparser.php index 90e1c9762..aaeae63b7 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_templateparser.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_templateparser.php @@ -1,77 +1,4 @@ string = $s->string; - $this->metadata = $s->metadata; - } else { - $this->string = (string) $s; - if ($m instanceof TP_yyToken) { - $this->metadata = $m->metadata; - } elseif (is_array($m)) { - $this->metadata = $m; - } - } - } - - function __toString() - { - return $this->_string; - } - - function offsetExists($offset) - { - return isset($this->metadata[$offset]); - } - - function offsetGet($offset) - { - return $this->metadata[$offset]; - } - - function offsetSet($offset, $value) - { - if ($offset === null) { - if (isset($value[0])) { - $x = ($value instanceof TP_yyToken) ? - $value->metadata : $value; - $this->metadata = array_merge($this->metadata, $x); - return; - } - $offset = count($this->metadata); - } - if ($value === null) { - return; - } - if ($value instanceof TP_yyToken) { - if ($value->metadata) { - $this->metadata[$offset] = $value->metadata; - } - } elseif ($value) { - $this->metadata[$offset] = $value; - } - } - - function offsetUnset($offset) - { - unset($this->metadata[$offset]); - } -} class TP_yyStackEntry { @@ -80,1430 +7,1861 @@ class TP_yyStackEntry ** number for the token at this stack level */ public $minor; /* The user-supplied minor token value. This ** is the value of the token */ -}; +} +// line 11 "../smarty/lexer/smarty_internal_templateparser.y" -#line 12 "smarty_internal_templateparser.y" -class Smarty_Internal_Templateparser#line 79 "smarty_internal_templateparser.php" +/** + * Smarty Template Parser Class + * + * This is the template parser. + * It is generated from the smarty_internal_templateparser.y file + * + * @author Uwe Tews + */ +class Smarty_Internal_Templateparser { -#line 14 "smarty_internal_templateparser.y" + // line 23 "../smarty/lexer/smarty_internal_templateparser.y" + const ERR1 = 'Security error: Call to private object member not allowed'; + const ERR2 = 'Security error: Call to dynamic object member not allowed'; + const ERR3 = 'PHP in template not allowed. Use SmartyBC to enable it'; + const TP_VERT = 1; + const TP_COLON = 2; + const TP_PHP = 3; + const TP_TEXT = 4; + const TP_STRIPON = 5; + const TP_STRIPOFF = 6; + const TP_LITERALSTART = 7; + const TP_LITERALEND = 8; + const TP_LITERAL = 9; + const TP_SIMPELOUTPUT = 10; + const TP_SIMPLETAG = 11; + const TP_SMARTYBLOCKCHILDPARENT = 12; + const TP_LDEL = 13; + const TP_RDEL = 14; + const TP_DOLLARID = 15; + const TP_EQUAL = 16; + const TP_ID = 17; + const TP_PTR = 18; + const TP_LDELMAKENOCACHE = 19; + const TP_LDELIF = 20; + const TP_LDELFOR = 21; + const TP_SEMICOLON = 22; + const TP_INCDEC = 23; + const TP_TO = 24; + const TP_STEP = 25; + const TP_LDELFOREACH = 26; + const TP_SPACE = 27; + const TP_AS = 28; + const TP_APTR = 29; + const TP_LDELSETFILTER = 30; + const TP_CLOSETAG = 31; + const TP_LDELSLASH = 32; + const TP_ATTR = 33; + const TP_INTEGER = 34; + const TP_COMMA = 35; + const TP_OPENP = 36; + const TP_CLOSEP = 37; + const TP_MATH = 38; + const TP_UNIMATH = 39; + const TP_ISIN = 40; + const TP_QMARK = 41; + const TP_NOT = 42; + const TP_TYPECAST = 43; + const TP_HEX = 44; + const TP_DOT = 45; + const TP_INSTANCEOF = 46; + const TP_SINGLEQUOTESTRING = 47; + const TP_DOUBLECOLON = 48; + const TP_NAMESPACE = 49; + const TP_AT = 50; + const TP_HATCH = 51; + const TP_OPENB = 52; + const TP_CLOSEB = 53; + const TP_DOLLAR = 54; + const TP_LOGOP = 55; + const TP_SLOGOP = 56; + const TP_TLOGOP = 57; + const TP_SINGLECOND = 58; + const TP_ARRAYOPEN = 59; + const TP_QUOTE = 60; + const TP_BACKTICK = 61; + const YY_NO_ACTION = 516; + const YY_ACCEPT_ACTION = 515; + const YY_ERROR_ACTION = 514; + const YY_SZ_ACTTAB = 2071; + const YY_SHIFT_USE_DFLT = -31; + const YY_SHIFT_MAX = 230; + const YY_REDUCE_USE_DFLT = -91; + const YY_REDUCE_MAX = 178; + const YYNOCODE = 110; + const YYSTACKDEPTH = 500; + const YYNSTATE = 327; + const YYNRULE = 187; + const YYERRORSYMBOL = 62; + const YYERRSYMDT = 'yy0'; + const YYFALLBACK = 0; + + public static $yy_action = array( + 251, 234, 237, 1, 144, 127, 428, 184, 199, 212, + 10, 54, 19, 175, 282, 215, 109, 389, 428, 428, + 224, 321, 223, 303, 203, 389, 13, 389, 281, 43, + 389, 428, 41, 40, 266, 225, 389, 213, 389, 194, + 389, 52, 4, 308, 301, 383, 34, 209, 222, 3, + 50, 153, 251, 234, 237, 1, 199, 131, 383, 198, + 305, 212, 10, 54, 383, 16, 199, 428, 109, 385, + 132, 18, 224, 321, 223, 222, 221, 12, 32, 428, + 116, 43, 385, 262, 41, 40, 266, 225, 385, 233, + 95, 194, 16, 52, 4, 131, 301, 252, 18, 265, + 164, 3, 50, 324, 251, 234, 237, 1, 23, 130, + 229, 198, 150, 212, 10, 54, 326, 11, 170, 284, + 109, 42, 22, 239, 224, 321, 223, 193, 221, 261, + 13, 52, 157, 43, 301, 286, 41, 40, 266, 225, + 205, 233, 5, 194, 96, 52, 4, 263, 301, 301, + 99, 349, 96, 3, 50, 199, 251, 234, 237, 1, + 238, 130, 241, 181, 349, 212, 10, 54, 382, 240, + 349, 36, 109, 185, 104, 256, 224, 321, 223, 132, + 191, 382, 13, 49, 91, 43, 12, 382, 41, 40, + 266, 225, 257, 233, 152, 194, 457, 52, 4, 457, + 301, 301, 228, 457, 282, 3, 50, 285, 251, 234, + 237, 1, 301, 131, 441, 198, 238, 212, 10, 54, + 349, 441, 325, 175, 109, 30, 349, 273, 224, 321, + 223, 20, 221, 295, 32, 211, 457, 39, 166, 49, + 41, 40, 266, 225, 87, 233, 205, 194, 279, 52, + 4, 24, 301, 204, 200, 280, 99, 3, 50, 199, + 251, 234, 237, 1, 31, 130, 96, 198, 205, 212, + 10, 54, 350, 55, 293, 207, 109, 283, 99, 96, + 224, 321, 223, 199, 180, 350, 13, 134, 230, 43, + 222, 350, 41, 40, 266, 225, 104, 233, 316, 194, + 279, 52, 4, 24, 301, 165, 284, 280, 85, 3, + 50, 25, 251, 234, 237, 1, 131, 129, 210, 198, + 14, 212, 10, 54, 269, 270, 301, 116, 109, 295, + 216, 211, 224, 321, 223, 171, 221, 95, 13, 28, + 219, 43, 323, 9, 41, 40, 266, 225, 151, 233, + 324, 194, 52, 52, 4, 301, 301, 30, 282, 302, + 178, 3, 50, 7, 251, 234, 237, 1, 136, 130, + 304, 179, 238, 212, 10, 54, 279, 175, 282, 24, + 109, 238, 429, 280, 224, 321, 223, 177, 221, 270, + 13, 255, 281, 43, 429, 49, 41, 40, 266, 225, + 275, 233, 318, 194, 49, 52, 4, 276, 301, 163, + 26, 199, 8, 3, 50, 119, 251, 234, 237, 1, + 11, 93, 291, 51, 107, 212, 10, 54, 226, 428, + 206, 201, 109, 148, 178, 322, 224, 321, 223, 441, + 221, 428, 13, 282, 9, 43, 441, 115, 41, 40, + 266, 225, 167, 233, 227, 194, 457, 52, 4, 457, + 301, 96, 158, 457, 101, 3, 50, 271, 251, 234, + 237, 1, 282, 130, 235, 186, 135, 212, 10, 54, + 199, 37, 119, 315, 109, 165, 284, 176, 224, 321, + 223, 104, 221, 149, 13, 281, 146, 43, 281, 300, + 41, 40, 266, 225, 30, 233, 289, 194, 21, 52, + 4, 272, 301, 211, 18, 301, 161, 3, 50, 110, + 251, 234, 237, 1, 137, 128, 282, 198, 268, 212, + 10, 54, 222, 169, 515, 92, 109, 172, 284, 31, + 224, 321, 223, 29, 221, 238, 6, 260, 53, 43, + 232, 139, 41, 40, 266, 225, 154, 233, 178, 194, + 168, 52, 4, 214, 301, 145, 99, 33, 49, 3, + 50, 245, 208, 211, 320, 282, 90, 111, 311, 183, + 98, 70, 309, 297, 236, 178, 95, 319, 142, 258, + 247, 267, 249, 264, 250, 195, 231, 199, 246, 324, + 317, 253, 254, 259, 126, 137, 133, 251, 234, 237, + 1, 326, 290, 105, 143, 156, 212, 10, 54, 88, + 84, 83, 484, 109, 322, 282, 37, 224, 321, 223, + 245, 208, 211, 320, 281, 90, 111, 298, 182, 98, + 56, 245, 298, 211, 178, 95, 103, 147, 258, 197, + 102, 75, 141, 250, 195, 231, 95, 246, 324, 258, + 279, 242, 89, 24, 250, 195, 231, 280, 246, 324, + 298, 298, 298, 298, 298, 298, 298, 16, 298, 192, + 277, 298, 298, 18, 294, 44, 45, 38, 298, 298, + 251, 234, 237, 2, 298, 296, 298, 298, 298, 212, + 10, 54, 310, 312, 313, 314, 109, 162, 298, 298, + 224, 321, 223, 298, 298, 298, 294, 282, 298, 42, + 22, 239, 251, 234, 237, 2, 298, 296, 298, 298, + 298, 212, 10, 54, 298, 159, 298, 298, 109, 298, + 298, 17, 224, 321, 223, 282, 298, 42, 22, 239, + 298, 298, 245, 298, 211, 278, 298, 103, 111, 298, + 183, 98, 70, 298, 298, 298, 298, 95, 298, 298, + 258, 298, 292, 17, 298, 250, 195, 231, 279, 246, + 324, 24, 298, 395, 245, 280, 211, 298, 298, 103, + 298, 298, 197, 102, 75, 16, 298, 140, 298, 95, + 298, 18, 258, 298, 298, 298, 298, 250, 195, 231, + 298, 246, 324, 298, 298, 298, 298, 428, 298, 395, + 395, 395, 202, 277, 298, 245, 298, 211, 298, 428, + 103, 298, 298, 197, 120, 69, 395, 395, 395, 395, + 95, 298, 298, 258, 298, 298, 298, 160, 250, 195, + 231, 86, 246, 324, 245, 16, 211, 282, 298, 103, + 196, 18, 197, 120, 69, 298, 44, 45, 38, 95, + 298, 298, 258, 298, 298, 298, 178, 250, 195, 231, + 298, 246, 324, 310, 312, 313, 314, 298, 298, 190, + 245, 298, 211, 298, 298, 103, 298, 298, 197, 102, + 75, 298, 298, 298, 298, 95, 298, 298, 258, 298, + 298, 298, 298, 250, 195, 231, 298, 246, 324, 298, + 298, 298, 245, 298, 211, 298, 199, 100, 298, 288, + 197, 120, 47, 298, 106, 298, 298, 95, 298, 353, + 258, 155, 298, 218, 298, 250, 195, 231, 298, 246, + 324, 282, 16, 42, 22, 239, 298, 245, 18, 211, + 298, 428, 103, 298, 298, 197, 120, 69, 298, 298, + 298, 298, 95, 428, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 100, 189, 298, 197, 120, 59, 245, 207, 211, + 298, 95, 103, 298, 258, 197, 120, 81, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 120, 80, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 67, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 120, 57, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 120, 58, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 82, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 97, 76, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 120, 71, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 187, 120, 61, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 120, 63, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 94, 79, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 59, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 120, 77, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 188, 108, 64, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 65, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 97, 66, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 120, 68, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 62, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 120, 60, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 120, 74, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 72, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 120, 48, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 120, 46, 298, 298, + 298, 298, 95, 298, 298, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 120, 78, 245, 298, 211, + 298, 95, 103, 298, 258, 197, 120, 73, 298, 250, + 195, 231, 95, 246, 324, 258, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 125, 298, 298, 298, + 298, 298, 95, 298, 298, 298, 298, 298, 298, 244, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 114, 298, 245, 298, 211, + 298, 95, 103, 298, 298, 197, 122, 298, 243, 250, + 195, 231, 95, 246, 324, 298, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 117, 298, 298, 298, + 298, 298, 95, 298, 298, 298, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 121, 298, 245, 298, 211, + 298, 95, 103, 298, 298, 197, 124, 298, 298, 250, + 195, 231, 95, 246, 324, 298, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 298, 245, 298, 211, + 298, 298, 103, 298, 298, 197, 118, 298, 298, 298, + 298, 298, 95, 298, 298, 298, 298, 298, 298, 298, + 250, 195, 231, 298, 246, 324, 245, 298, 211, 298, + 298, 103, 298, 298, 197, 123, 298, 245, 298, 211, + 298, 95, 103, 298, 298, 197, 113, 298, 298, 250, + 195, 231, 95, 246, 324, 298, 298, 298, 298, 298, + 250, 195, 231, 220, 246, 324, 298, 27, 298, 16, + 298, 457, 298, 298, 457, 18, 298, 26, 457, 441, + 44, 45, 38, 217, 44, 45, 38, 298, 298, 298, + 298, 298, 298, 298, 298, 298, 298, 310, 312, 313, + 314, 310, 312, 313, 314, 298, 441, 298, 298, 441, + 298, 457, 220, 441, 457, 298, 298, 457, 298, 298, + 457, 457, 441, 457, 298, 298, 220, 457, 441, 298, + 298, 298, 298, 298, 457, 298, 298, 457, 298, 298, + 5, 457, 441, 298, 298, 298, 298, 298, 298, 441, + 298, 298, 441, 298, 457, 441, 441, 298, 441, 298, + 457, 298, 441, 306, 298, 298, 298, 298, 298, 441, + 298, 298, 441, 298, 457, 220, 441, 298, 298, 298, + 298, 298, 298, 457, 298, 298, 457, 298, 298, 15, + 457, 441, 35, 274, 44, 45, 38, 457, 298, 298, + 457, 298, 298, 298, 457, 441, 298, 298, 298, 298, + 298, 310, 312, 313, 314, 298, 298, 298, 441, 298, + 298, 441, 298, 457, 298, 441, 287, 298, 44, 45, + 38, 298, 441, 298, 298, 441, 298, 457, 298, 441, + 248, 298, 298, 298, 298, 310, 312, 313, 314, 298, + 44, 45, 38, 298, 298, 112, 298, 44, 45, 38, + 298, 173, 298, 298, 44, 45, 38, 310, 312, 313, + 314, 44, 45, 38, 310, 312, 313, 314, 298, 298, + 299, 310, 312, 313, 314, 44, 45, 38, 310, 312, + 313, 314, 174, 298, 298, 298, 138, 298, 298, 298, + 298, 298, 310, 312, 313, 314, 44, 45, 38, 298, + 298, 298, 44, 45, 38, 298, 44, 45, 38, 298, + 44, 45, 38, 310, 312, 313, 314, 307, 298, 310, + 312, 313, 314, 310, 312, 313, 314, 310, 312, 313, + 314, + ); + + public static $yy_lookahead = array( + 10, 11, 12, 13, 74, 15, 36, 17, 1, 19, + 20, 21, 29, 103, 84, 45, 26, 14, 48, 36, + 30, 31, 32, 53, 34, 22, 36, 24, 98, 39, + 27, 48, 42, 43, 44, 45, 33, 47, 35, 49, + 37, 51, 52, 53, 54, 14, 16, 16, 45, 59, + 60, 96, 10, 11, 12, 13, 1, 15, 27, 17, + 53, 19, 20, 21, 33, 27, 1, 36, 26, 14, + 45, 33, 30, 31, 32, 45, 34, 52, 36, 48, + 72, 39, 27, 75, 42, 43, 44, 45, 33, 47, + 82, 49, 27, 51, 52, 15, 54, 17, 33, 91, + 83, 59, 60, 95, 10, 11, 12, 13, 13, 15, + 15, 17, 17, 19, 20, 21, 97, 35, 99, 100, + 26, 86, 87, 88, 30, 31, 32, 66, 34, 49, + 36, 51, 96, 39, 54, 53, 42, 43, 44, 45, + 72, 47, 16, 49, 18, 51, 52, 79, 54, 54, + 82, 14, 18, 59, 60, 1, 10, 11, 12, 13, + 23, 15, 15, 17, 27, 19, 20, 21, 14, 17, + 33, 13, 26, 15, 48, 17, 30, 31, 32, 45, + 34, 27, 36, 46, 83, 39, 52, 33, 42, 43, + 44, 45, 34, 47, 74, 49, 10, 51, 52, 13, + 54, 54, 50, 17, 84, 59, 60, 14, 10, 11, + 12, 13, 54, 15, 45, 17, 23, 19, 20, 21, + 27, 52, 100, 103, 26, 35, 33, 37, 30, 31, + 32, 22, 34, 67, 36, 69, 50, 39, 83, 46, + 42, 43, 44, 45, 35, 47, 72, 49, 10, 51, + 52, 13, 54, 79, 80, 17, 82, 59, 60, 1, + 10, 11, 12, 13, 16, 15, 18, 17, 72, 19, + 20, 21, 14, 107, 108, 79, 26, 71, 82, 18, + 30, 31, 32, 1, 34, 27, 36, 15, 50, 39, + 45, 33, 42, 43, 44, 45, 48, 47, 53, 49, + 10, 51, 52, 13, 54, 99, 100, 17, 36, 59, + 60, 29, 10, 11, 12, 13, 15, 15, 17, 17, + 13, 19, 20, 21, 8, 9, 54, 72, 26, 67, + 75, 69, 30, 31, 32, 78, 34, 82, 36, 24, + 50, 39, 17, 36, 42, 43, 44, 45, 74, 47, + 95, 49, 51, 51, 52, 54, 54, 35, 84, 37, + 103, 59, 60, 36, 10, 11, 12, 13, 74, 15, + 108, 17, 23, 19, 20, 21, 10, 103, 84, 13, + 26, 23, 36, 17, 30, 31, 32, 7, 34, 9, + 36, 17, 98, 39, 48, 46, 42, 43, 44, 45, + 17, 47, 53, 49, 46, 51, 52, 93, 54, 78, + 16, 1, 36, 59, 60, 101, 10, 11, 12, 13, + 35, 15, 37, 17, 48, 19, 20, 21, 18, 36, + 65, 66, 26, 74, 103, 104, 30, 31, 32, 45, + 34, 48, 36, 84, 36, 39, 52, 17, 42, 43, + 44, 45, 15, 47, 17, 49, 10, 51, 52, 13, + 54, 18, 74, 17, 82, 59, 60, 34, 10, 11, + 12, 13, 84, 15, 93, 17, 15, 19, 20, 21, + 1, 2, 101, 101, 26, 99, 100, 17, 30, 31, + 32, 48, 34, 96, 36, 98, 96, 39, 98, 71, + 42, 43, 44, 45, 35, 47, 37, 49, 27, 51, + 52, 67, 54, 69, 33, 54, 74, 59, 60, 17, + 10, 11, 12, 13, 96, 15, 84, 17, 34, 19, + 20, 21, 45, 78, 63, 64, 26, 99, 100, 16, + 30, 31, 32, 16, 34, 23, 36, 17, 17, 39, + 23, 51, 42, 43, 44, 45, 72, 47, 103, 49, + 78, 51, 52, 17, 54, 74, 82, 41, 46, 59, + 60, 67, 68, 69, 70, 84, 72, 73, 53, 75, + 76, 77, 53, 61, 15, 103, 82, 14, 51, 85, + 14, 37, 17, 8, 90, 91, 92, 1, 94, 95, + 3, 4, 5, 6, 7, 96, 82, 10, 11, 12, + 13, 97, 84, 81, 96, 74, 19, 20, 21, 78, + 82, 82, 1, 26, 104, 84, 2, 30, 31, 32, + 67, 68, 69, 70, 98, 72, 73, 109, 75, 76, + 77, 67, 109, 69, 103, 82, 72, 96, 85, 75, + 76, 77, 96, 90, 91, 92, 82, 94, 95, 85, + 10, 14, 96, 13, 90, 91, 92, 17, 94, 95, + 109, 109, 109, 109, 109, 109, 109, 27, 109, 105, + 106, 109, 109, 33, 4, 38, 39, 40, 109, 109, + 10, 11, 12, 13, 109, 15, 109, 109, 109, 19, + 20, 21, 55, 56, 57, 58, 26, 74, 109, 109, + 30, 31, 32, 109, 109, 109, 4, 84, 109, 86, + 87, 88, 10, 11, 12, 13, 109, 15, 109, 109, + 109, 19, 20, 21, 109, 74, 109, 109, 26, 109, + 60, 61, 30, 31, 32, 84, 109, 86, 87, 88, + 109, 109, 67, 109, 69, 70, 109, 72, 73, 109, + 75, 76, 77, 109, 109, 109, 109, 82, 109, 109, + 85, 109, 60, 61, 109, 90, 91, 92, 10, 94, + 95, 13, 109, 2, 67, 17, 69, 109, 109, 72, + 109, 109, 75, 76, 77, 27, 109, 29, 109, 82, + 109, 33, 85, 109, 109, 109, 109, 90, 91, 92, + 109, 94, 95, 109, 109, 109, 109, 36, 109, 38, + 39, 40, 105, 106, 109, 67, 109, 69, 109, 48, + 72, 109, 109, 75, 76, 77, 55, 56, 57, 58, + 82, 109, 109, 85, 109, 109, 109, 74, 90, 91, + 92, 78, 94, 95, 67, 27, 69, 84, 109, 72, + 102, 33, 75, 76, 77, 109, 38, 39, 40, 82, + 109, 109, 85, 109, 109, 109, 103, 90, 91, 92, + 109, 94, 95, 55, 56, 57, 58, 109, 109, 102, + 67, 109, 69, 109, 109, 72, 109, 109, 75, 76, + 77, 109, 109, 109, 109, 82, 109, 109, 85, 109, + 109, 109, 109, 90, 91, 92, 109, 94, 95, 109, + 109, 109, 67, 109, 69, 109, 1, 72, 109, 106, + 75, 76, 77, 109, 79, 109, 109, 82, 109, 14, + 85, 74, 109, 18, 109, 90, 91, 92, 109, 94, + 95, 84, 27, 86, 87, 88, 109, 67, 33, 69, + 109, 36, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 48, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 102, 109, 75, 76, 77, 67, 79, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 77, 109, 109, + 109, 109, 82, 109, 109, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 77, 67, 109, 69, + 109, 82, 72, 109, 85, 75, 76, 77, 109, 90, + 91, 92, 82, 94, 95, 85, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 109, 109, 109, + 109, 109, 82, 109, 109, 109, 109, 109, 109, 89, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 109, 67, 109, 69, + 109, 82, 72, 109, 109, 75, 76, 109, 89, 90, + 91, 92, 82, 94, 95, 109, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 109, 109, 109, + 109, 109, 82, 109, 109, 109, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 109, 67, 109, 69, + 109, 82, 72, 109, 109, 75, 76, 109, 109, 90, + 91, 92, 82, 94, 95, 109, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 109, 67, 109, 69, + 109, 109, 72, 109, 109, 75, 76, 109, 109, 109, + 109, 109, 82, 109, 109, 109, 109, 109, 109, 109, + 90, 91, 92, 109, 94, 95, 67, 109, 69, 109, + 109, 72, 109, 109, 75, 76, 109, 67, 109, 69, + 109, 82, 72, 109, 109, 75, 76, 109, 109, 90, + 91, 92, 82, 94, 95, 109, 109, 109, 109, 109, + 90, 91, 92, 2, 94, 95, 109, 25, 109, 27, + 109, 10, 109, 109, 13, 33, 109, 16, 17, 18, + 38, 39, 40, 37, 38, 39, 40, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 55, 56, 57, + 58, 55, 56, 57, 58, 109, 45, 109, 109, 48, + 109, 50, 2, 52, 10, 109, 109, 13, 109, 109, + 10, 17, 18, 13, 109, 109, 2, 17, 18, 109, + 109, 109, 109, 109, 10, 109, 109, 13, 109, 109, + 16, 17, 18, 109, 109, 109, 109, 109, 109, 45, + 109, 109, 48, 109, 50, 45, 52, 109, 48, 109, + 50, 109, 52, 53, 109, 109, 109, 109, 109, 45, + 109, 109, 48, 109, 50, 2, 52, 109, 109, 109, + 109, 109, 109, 10, 109, 109, 13, 109, 109, 2, + 17, 18, 2, 37, 38, 39, 40, 10, 109, 109, + 13, 109, 109, 109, 17, 18, 109, 109, 109, 109, + 109, 55, 56, 57, 58, 109, 109, 109, 45, 109, + 109, 48, 109, 50, 109, 52, 14, 109, 38, 39, + 40, 109, 45, 109, 109, 48, 109, 50, 109, 52, + 14, 109, 109, 109, 109, 55, 56, 57, 58, 109, + 38, 39, 40, 109, 109, 22, 109, 38, 39, 40, + 109, 14, 109, 109, 38, 39, 40, 55, 56, 57, + 58, 38, 39, 40, 55, 56, 57, 58, 109, 109, + 61, 55, 56, 57, 58, 38, 39, 40, 55, 56, + 57, 58, 14, 109, 109, 109, 28, 109, 109, 109, + 109, 109, 55, 56, 57, 58, 38, 39, 40, 109, + 109, 109, 38, 39, 40, 109, 38, 39, 40, 109, + 38, 39, 40, 55, 56, 57, 58, 53, 109, 55, + 56, 57, 58, 55, 56, 57, 58, 55, 56, 57, + 58, + ); + + public static $yy_shift_ofst = array( + -31, 406, 406, 458, 458, 94, 510, 94, 94, 94, + 510, 458, -10, 94, 94, 354, 146, 94, 94, 94, + 94, 146, 94, 94, 94, 94, 250, 94, 94, 94, + 94, 94, 94, 302, 94, 94, 94, 198, 42, 42, + 42, 42, 42, 42, 42, 42, 1772, 828, 828, 80, + 712, 925, 301, 65, 272, 680, 1942, 1920, 1886, 1776, + 647, 1949, 1977, 2008, 2004, 1963, 1998, 1956, 2012, 2012, + 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, + 2012, 2012, 2012, 768, 650, 272, 65, 272, 65, 134, + 126, 479, 597, 1854, 154, 290, 95, 55, 258, 366, + 248, 366, 282, 443, 437, 38, 38, 437, 7, 481, + 410, 38, 461, 621, 596, 596, 261, 596, 596, 261, + 596, 596, 596, 596, 596, -31, -31, 1840, 1791, 1917, + 1903, 1834, 158, 238, 394, 446, 38, 25, 147, 169, + 147, 25, 169, 25, 38, 38, 25, 25, 38, 25, + 307, 38, 38, 25, 527, 38, 38, 25, 38, 38, + 38, 38, 38, 596, 624, 261, 624, 327, 596, 596, + 261, 596, 261, -31, -31, -31, -31, -31, -31, 781, + 3, 31, 193, 137, -30, 186, -17, 522, 349, 469, + 322, 30, 82, 316, 346, 376, 190, 358, 393, 152, + 209, 380, 385, 245, 315, 523, 585, 554, 576, 575, + 537, 573, 569, 529, 525, 546, 500, 526, 531, 325, + 530, 487, 494, 502, 470, 433, 430, 408, 383, 327, + 374, + ); + + public static $yy_reduce_ofst = array( + 471, 504, 563, 717, 574, 685, 919, 890, 787, 758, + 855, 823, 1240, 1199, 1140, 1100, 1070, 1129, 1170, 1210, + 1269, 1280, 1310, 1339, 1350, 1380, 1409, 1420, 1450, 1479, + 1490, 1059, 1030, 1000, 930, 960, 989, 1520, 1549, 1700, + 1619, 1689, 1660, 1630, 1590, 1560, 633, 661, 867, 8, + 166, 773, 255, 541, 174, 262, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 294, -70, 196, 120, 68, 274, 19, + 206, 331, 444, 428, 257, 400, 382, 257, 257, 400, + 386, 397, 257, 386, 381, 388, 359, 314, 257, 442, + 482, 491, 484, 257, 257, 455, 386, 257, 257, 438, + 257, 257, 257, 257, 257, 257, 365, 509, 509, 509, + 509, 509, 524, 536, 509, 509, 528, 514, 539, 551, + 538, 514, 556, 514, 528, 528, 514, 514, 528, 514, + 518, 528, 528, 514, 532, 528, 528, 514, 528, 528, + 528, 528, 528, -90, 520, 122, 520, 566, -90, -90, + 122, -90, 122, -45, 36, 155, 101, 61, 17, + ); + + public static $yyExpectedTokens = array( + array(), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 53, 54, 59, + 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array( + 10, 11, 12, 13, 15, 17, 19, 20, 21, 26, 30, 31, 32, 34, 36, 39, 42, 43, 44, 45, 47, 49, 51, 52, 54, 59, 60, + ), + array(25, 27, 33, 38, 39, 40, 55, 56, 57, 58,), + array(27, 33, 38, 39, 40, 55, 56, 57, 58,), + array(27, 33, 38, 39, 40, 55, 56, 57, 58,), + array(15, 17, 49, 51, 54,), + array(4, 10, 11, 12, 13, 15, 19, 20, 21, 26, 30, 31, 32, 60, 61,), + array(1, 14, 18, 27, 33, 36, 48,), + array(15, 17, 51, 54,), + array(1, 27, 33,), + array(15, 36, 54,), + array(4, 10, 11, 12, 13, 15, 19, 20, 21, 26, 30, 31, 32, 60, 61,), + array(14, 38, 39, 40, 55, 56, 57, 58,), + array(2, 38, 39, 40, 55, 56, 57, 58,), + array(37, 38, 39, 40, 55, 56, 57, 58,), + array(37, 38, 39, 40, 55, 56, 57, 58,), + array(14, 38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58, 61,), + array(14, 38, 39, 40, 55, 56, 57, 58,), + array(14, 38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 53, 55, 56, 57, 58,), + array(22, 38, 39, 40, 55, 56, 57, 58,), + array(28, 38, 39, 40, 55, 56, 57, 58,), + array(14, 38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), + array(10, 13, 17, 27, 29, 33,), + array(10, 13, 17, 27, 33,), + array(15, 36, 54,), + array(1, 27, 33,), + array(15, 36, 54,), + array(1, 27, 33,), + array(18, 45, 52,), + array(16, 18, 48,), + array(1, 2,), + array(3, 4, 5, 6, 7, 10, 11, 12, 13, 19, 20, 21, 26, 30, 31, 32,), + array(2, 10, 13, 16, 17, 18, 45, 48, 50, 52,), + array(1, 14, 27, 33,), + array(10, 13, 17, 50,), + array(13, 15, 17, 54,), + array(1, 14, 27, 33,), + array(1, 14, 27, 33,), + array(10, 13, 17,), + array(16, 18, 48,), + array(10, 13, 17,), + array(1, 29,), + array(18, 48,), + array(15, 17,), + array(27, 33,), + array(27, 33,), + array(15, 17,), + array(1, 53,), + array(27, 33,), + array(1, 18,), + array(27, 33,), + array(15, 54,), + array(1,), + array(1,), + array(1,), + array(18,), + array(1,), + array(1,), + array(18,), + array(1,), + array(1,), + array(1,), + array(1,), + array(1,), + array(), + array(), + array(2, 10, 13, 17, 18, 45, 48, 50, 52, 53,), + array(2, 10, 13, 16, 17, 18, 45, 48, 50, 52,), + array(2, 10, 13, 17, 18, 45, 48, 50, 52,), + array(2, 10, 13, 17, 18, 45, 48, 50, 52,), + array(10, 13, 17, 18, 45, 48, 50, 52,), + array(13, 15, 17, 34, 54,), + array(10, 13, 17, 50,), + array(16, 45, 52,), + array(10, 13, 17,), + array(27, 33,), + array(45, 52,), + array(15, 54,), + array(45, 52,), + array(15, 54,), + array(45, 52,), + array(45, 52,), + array(45, 52,), + array(27, 33,), + array(27, 33,), + array(45, 52,), + array(45, 52,), + array(27, 33,), + array(45, 52,), + array(13, 36,), + array(27, 33,), + array(27, 33,), + array(45, 52,), + array(16, 23,), + array(27, 33,), + array(27, 33,), + array(45, 52,), + array(27, 33,), + array(27, 33,), + array(27, 33,), + array(27, 33,), + array(27, 33,), + array(1,), + array(2,), + array(18,), + array(2,), + array(36,), + array(1,), + array(1,), + array(18,), + array(1,), + array(18,), + array(), + array(), + array(), + array(), + array(), + array(), + array(2, 36, 38, 39, 40, 48, 55, 56, 57, 58,), + array(14, 22, 24, 27, 33, 35, 37, 45,), + array(14, 16, 27, 33, 36, 48,), + array(14, 23, 27, 33, 46,), + array(14, 23, 27, 33, 46,), + array(36, 45, 48, 53,), + array(10, 13, 17, 50,), + array(29, 36, 48,), + array(23, 46, 61,), + array(23, 46, 53,), + array(35, 37,), + array(35, 37,), + array(16, 45,), + array(35, 53,), + array(8, 9,), + array(36, 48,), + array(36, 48,), + array(35, 37,), + array(23, 46,), + array(36, 48,), + array(17, 50,), + array(22, 35,), + array(7, 9,), + array(35, 37,), + array(45, 53,), + array(24,), + array(16,), + array(8,), + array(37,), + array(14,), + array(17,), + array(51,), + array(14,), + array(15,), + array(53,), + array(53,), + array(17,), + array(51,), + array(41,), + array(17,), + array(17,), + array(17,), + array(45,), + array(34,), + array(17,), + array(17,), + array(34,), + array(17,), + array(36,), + array(17,), + array(36,), + array(17,), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + array(), + ); + + public static $yy_default = array( + 338, 514, 514, 499, 499, 514, 514, 476, 476, 476, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 379, 358, 379, 514, + 514, 415, 514, 379, 514, 514, 351, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 384, 514, 399, 475, + 351, 403, 390, 474, 500, 502, 384, 501, 363, 381, + 404, 386, 391, 379, 379, 514, 379, 514, 379, 489, + 431, 370, 327, 430, 393, 441, 514, 393, 393, 441, + 431, 441, 393, 431, 514, 379, 360, 514, 393, 379, + 373, 379, 514, 406, 402, 375, 431, 396, 398, 486, + 393, 408, 397, 407, 406, 483, 336, 430, 430, 430, + 430, 430, 514, 443, 457, 441, 367, 438, 514, 436, + 514, 435, 434, 466, 368, 348, 439, 437, 361, 467, + 441, 356, 354, 468, 514, 366, 355, 469, 362, 359, + 352, 369, 365, 371, 478, 463, 477, 441, 374, 376, + 490, 424, 487, 441, 441, 482, 482, 336, 482, 415, + 411, 415, 405, 405, 415, 442, 415, 405, 405, 514, + 514, 411, 514, 514, 425, 514, 514, 405, 415, 514, + 514, 334, 514, 411, 387, 514, 514, 514, 514, 514, + 514, 514, 514, 420, 514, 514, 514, 417, 514, 514, + 514, 411, 413, 514, 514, 514, 514, 488, 514, 457, + 514, 421, 364, 420, 340, 422, 357, 341, 409, 400, + 480, 457, 462, 401, 485, 423, 426, 342, 447, 380, + 416, 339, 428, 329, 330, 444, 445, 446, 394, 331, + 395, 429, 419, 388, 332, 418, 410, 392, 412, 333, + 335, 414, 337, 472, 417, 479, 427, 497, 347, 461, + 460, 459, 378, 346, 464, 510, 495, 511, 498, 473, + 377, 496, 503, 506, 513, 512, 509, 507, 504, 508, + 345, 458, 471, 448, 505, 454, 452, 455, 456, 450, + 491, 449, 492, 493, 494, 470, 451, 328, 453, 343, + 344, 372, 481, 432, 433, 465, 440, + ); + + public static $yyFallback = array(); + + public static $yyRuleName = array( + 'start ::= template', + 'template ::= template PHP', + 'template ::= template TEXT', + 'template ::= template STRIPON', + 'template ::= template STRIPOFF', + 'template ::= template LITERALSTART literal_e2 LITERALEND', + 'literal_e2 ::= literal_e1 LITERALSTART literal_e1 LITERALEND', + 'literal_e2 ::= literal_e1', + 'literal_e1 ::= literal_e1 LITERAL', + 'literal_e1 ::=', + 'template ::= template smartytag', + 'template ::=', + 'smartytag ::= SIMPELOUTPUT', + 'smartytag ::= SIMPLETAG', + 'smartytag ::= SMARTYBLOCKCHILDPARENT', + 'smartytag ::= LDEL tagbody RDEL', + 'smartytag ::= tag RDEL', + 'tagbody ::= outattr', + 'tagbody ::= DOLLARID eqoutattr', + 'tagbody ::= varindexed eqoutattr', + 'eqoutattr ::= EQUAL outattr', + 'outattr ::= output attributes', + 'output ::= variable', + 'output ::= value', + 'output ::= expr', + 'tag ::= LDEL ID attributes', + 'tag ::= LDEL ID', + 'tag ::= LDEL ID modifierlist attributes', + 'tag ::= LDEL ID PTR ID attributes', + 'tag ::= LDEL ID PTR ID modifierlist attributes', + 'tag ::= LDELMAKENOCACHE DOLLARID', + 'tag ::= LDELIF expr', + 'tag ::= LDELIF expr attributes', + 'tag ::= LDELIF statement', + 'tag ::= LDELIF statement attributes', + 'tag ::= LDELFOR statements SEMICOLON expr SEMICOLON varindexed foraction attributes', + 'foraction ::= EQUAL expr', + 'foraction ::= INCDEC', + 'tag ::= LDELFOR statement TO expr attributes', + 'tag ::= LDELFOR statement TO expr STEP expr attributes', + 'tag ::= LDELFOREACH SPACE expr AS varvar attributes', + 'tag ::= LDELFOREACH SPACE expr AS varvar APTR varvar attributes', + 'tag ::= LDELFOREACH attributes', + 'tag ::= LDELSETFILTER ID modparameters', + 'tag ::= LDELSETFILTER ID modparameters modifierlist', + 'smartytag ::= CLOSETAG', + 'tag ::= LDELSLASH ID', + 'tag ::= LDELSLASH ID modifierlist', + 'tag ::= LDELSLASH ID PTR ID', + 'tag ::= LDELSLASH ID PTR ID modifierlist', + 'attributes ::= attributes attribute', + 'attributes ::= attribute', + 'attributes ::=', + 'attribute ::= SPACE ID EQUAL ID', + 'attribute ::= ATTR expr', + 'attribute ::= ATTR value', + 'attribute ::= SPACE ID', + 'attribute ::= SPACE expr', + 'attribute ::= SPACE value', + 'attribute ::= SPACE INTEGER EQUAL expr', + 'statements ::= statement', + 'statements ::= statements COMMA statement', + 'statement ::= DOLLARID EQUAL INTEGER', + 'statement ::= DOLLARID EQUAL expr', + 'statement ::= varindexed EQUAL expr', + 'statement ::= OPENP statement CLOSEP', + 'expr ::= value', + 'expr ::= ternary', + 'expr ::= DOLLARID COLON ID', + 'expr ::= expr MATH value', + 'expr ::= expr UNIMATH value', + 'expr ::= expr tlop value', + 'expr ::= expr lop expr', + 'expr ::= expr scond', + 'expr ::= expr ISIN array', + 'expr ::= expr ISIN value', + 'ternary ::= OPENP expr CLOSEP QMARK DOLLARID COLON expr', + 'ternary ::= OPENP expr CLOSEP QMARK expr COLON expr', + 'value ::= variable', + 'value ::= UNIMATH value', + 'value ::= NOT value', + 'value ::= TYPECAST value', + 'value ::= variable INCDEC', + 'value ::= HEX', + 'value ::= INTEGER', + 'value ::= INTEGER DOT INTEGER', + 'value ::= INTEGER DOT', + 'value ::= DOT INTEGER', + 'value ::= ID', + 'value ::= function', + 'value ::= OPENP expr CLOSEP', + 'value ::= variable INSTANCEOF ns1', + 'value ::= variable INSTANCEOF variable', + 'value ::= SINGLEQUOTESTRING', + 'value ::= doublequoted_with_quotes', + 'value ::= varindexed DOUBLECOLON static_class_access', + 'value ::= smartytag', + 'value ::= value modifierlist', + 'value ::= NAMESPACE', + 'value ::= arraydef', + 'value ::= ns1 DOUBLECOLON static_class_access', + 'ns1 ::= ID', + 'ns1 ::= NAMESPACE', + 'variable ::= DOLLARID', + 'variable ::= varindexed', + 'variable ::= varvar AT ID', + 'variable ::= object', + 'variable ::= HATCH ID HATCH', + 'variable ::= HATCH ID HATCH arrayindex', + 'variable ::= HATCH variable HATCH', + 'variable ::= HATCH variable HATCH arrayindex', + 'varindexed ::= DOLLARID arrayindex', + 'varindexed ::= varvar arrayindex', + 'arrayindex ::= arrayindex indexdef', + 'arrayindex ::=', + 'indexdef ::= DOT DOLLARID', + 'indexdef ::= DOT varvar', + 'indexdef ::= DOT varvar AT ID', + 'indexdef ::= DOT ID', + 'indexdef ::= DOT INTEGER', + 'indexdef ::= DOT LDEL expr RDEL', + 'indexdef ::= OPENB ID CLOSEB', + 'indexdef ::= OPENB ID DOT ID CLOSEB', + 'indexdef ::= OPENB SINGLEQUOTESTRING CLOSEB', + 'indexdef ::= OPENB INTEGER CLOSEB', + 'indexdef ::= OPENB DOLLARID CLOSEB', + 'indexdef ::= OPENB variable CLOSEB', + 'indexdef ::= OPENB value CLOSEB', + 'indexdef ::= OPENB expr CLOSEB', + 'indexdef ::= OPENB CLOSEB', + 'varvar ::= DOLLARID', + 'varvar ::= DOLLAR', + 'varvar ::= varvar varvarele', + 'varvarele ::= ID', + 'varvarele ::= SIMPELOUTPUT', + 'varvarele ::= LDEL expr RDEL', + 'object ::= varindexed objectchain', + 'objectchain ::= objectelement', + 'objectchain ::= objectchain objectelement', + 'objectelement ::= PTR ID arrayindex', + 'objectelement ::= PTR varvar arrayindex', + 'objectelement ::= PTR LDEL expr RDEL arrayindex', + 'objectelement ::= PTR ID LDEL expr RDEL arrayindex', + 'objectelement ::= PTR method', + 'function ::= ns1 OPENP params CLOSEP', + 'method ::= ID OPENP params CLOSEP', + 'method ::= DOLLARID OPENP params CLOSEP', + 'params ::= params COMMA expr', + 'params ::= expr', + 'params ::=', + 'modifierlist ::= modifierlist modifier modparameters', + 'modifierlist ::= modifier modparameters', + 'modifier ::= VERT AT ID', + 'modifier ::= VERT ID', + 'modparameters ::= modparameters modparameter', + 'modparameters ::=', + 'modparameter ::= COLON value', + 'modparameter ::= COLON UNIMATH value', + 'modparameter ::= COLON array', + 'static_class_access ::= method', + 'static_class_access ::= method objectchain', + 'static_class_access ::= ID', + 'static_class_access ::= DOLLARID arrayindex', + 'static_class_access ::= DOLLARID arrayindex objectchain', + 'lop ::= LOGOP', + 'lop ::= SLOGOP', + 'tlop ::= TLOGOP', + 'scond ::= SINGLECOND', + 'arraydef ::= OPENB arrayelements CLOSEB', + 'arraydef ::= ARRAYOPEN arrayelements CLOSEP', + 'arrayelements ::= arrayelement', + 'arrayelements ::= arrayelements COMMA arrayelement', + 'arrayelements ::=', + 'arrayelement ::= value APTR expr', + 'arrayelement ::= ID APTR expr', + 'arrayelement ::= expr', + 'doublequoted_with_quotes ::= QUOTE QUOTE', + 'doublequoted_with_quotes ::= QUOTE doublequoted QUOTE', + 'doublequoted ::= doublequoted doublequotedcontent', + 'doublequoted ::= doublequotedcontent', + 'doublequotedcontent ::= BACKTICK variable BACKTICK', + 'doublequotedcontent ::= BACKTICK expr BACKTICK', + 'doublequotedcontent ::= DOLLARID', + 'doublequotedcontent ::= LDEL variable RDEL', + 'doublequotedcontent ::= LDEL expr RDEL', + 'doublequotedcontent ::= smartytag', + 'doublequotedcontent ::= TEXT', + ); + + public static $yyRuleInfo = array( + array(0 => 63, 1 => 1), + array(0 => 64, 1 => 2), + array(0 => 64, 1 => 2), + array(0 => 64, 1 => 2), + array(0 => 64, 1 => 2), + array(0 => 64, 1 => 4), + array(0 => 65, 1 => 4), + array(0 => 65, 1 => 1), + array(0 => 66, 1 => 2), + array(0 => 66, 1 => 0), + array(0 => 64, 1 => 2), + array(0 => 64, 1 => 0), + array(0 => 67, 1 => 1), + array(0 => 67, 1 => 1), + array(0 => 67, 1 => 1), + array(0 => 67, 1 => 3), + array(0 => 67, 1 => 2), + array(0 => 68, 1 => 1), + array(0 => 68, 1 => 2), + array(0 => 68, 1 => 2), + array(0 => 71, 1 => 2), + array(0 => 70, 1 => 2), + array(0 => 73, 1 => 1), + array(0 => 73, 1 => 1), + array(0 => 73, 1 => 1), + array(0 => 69, 1 => 3), + array(0 => 69, 1 => 2), + array(0 => 69, 1 => 4), + array(0 => 69, 1 => 5), + array(0 => 69, 1 => 6), + array(0 => 69, 1 => 2), + array(0 => 69, 1 => 2), + array(0 => 69, 1 => 3), + array(0 => 69, 1 => 2), + array(0 => 69, 1 => 3), + array(0 => 69, 1 => 8), + array(0 => 81, 1 => 2), + array(0 => 81, 1 => 1), + array(0 => 69, 1 => 5), + array(0 => 69, 1 => 7), + array(0 => 69, 1 => 6), + array(0 => 69, 1 => 8), + array(0 => 69, 1 => 2), + array(0 => 69, 1 => 3), + array(0 => 69, 1 => 4), + array(0 => 67, 1 => 1), + array(0 => 69, 1 => 2), + array(0 => 69, 1 => 3), + array(0 => 69, 1 => 4), + array(0 => 69, 1 => 5), + array(0 => 74, 1 => 2), + array(0 => 74, 1 => 1), + array(0 => 74, 1 => 0), + array(0 => 84, 1 => 4), + array(0 => 84, 1 => 2), + array(0 => 84, 1 => 2), + array(0 => 84, 1 => 2), + array(0 => 84, 1 => 2), + array(0 => 84, 1 => 2), + array(0 => 84, 1 => 4), + array(0 => 80, 1 => 1), + array(0 => 80, 1 => 3), + array(0 => 79, 1 => 3), + array(0 => 79, 1 => 3), + array(0 => 79, 1 => 3), + array(0 => 79, 1 => 3), + array(0 => 77, 1 => 1), + array(0 => 77, 1 => 1), + array(0 => 77, 1 => 3), + array(0 => 77, 1 => 3), + array(0 => 77, 1 => 3), + array(0 => 77, 1 => 3), + array(0 => 77, 1 => 3), + array(0 => 77, 1 => 2), + array(0 => 77, 1 => 3), + array(0 => 77, 1 => 3), + array(0 => 85, 1 => 7), + array(0 => 85, 1 => 7), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 3), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 3), + array(0 => 76, 1 => 3), + array(0 => 76, 1 => 3), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 3), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 2), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 1), + array(0 => 76, 1 => 3), + array(0 => 91, 1 => 1), + array(0 => 91, 1 => 1), + array(0 => 75, 1 => 1), + array(0 => 75, 1 => 1), + array(0 => 75, 1 => 3), + array(0 => 75, 1 => 1), + array(0 => 75, 1 => 3), + array(0 => 75, 1 => 4), + array(0 => 75, 1 => 3), + array(0 => 75, 1 => 4), + array(0 => 72, 1 => 2), + array(0 => 72, 1 => 2), + array(0 => 96, 1 => 2), + array(0 => 96, 1 => 0), + array(0 => 97, 1 => 2), + array(0 => 97, 1 => 2), + array(0 => 97, 1 => 4), + array(0 => 97, 1 => 2), + array(0 => 97, 1 => 2), + array(0 => 97, 1 => 4), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 5), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 3), + array(0 => 97, 1 => 2), + array(0 => 82, 1 => 1), + array(0 => 82, 1 => 1), + array(0 => 82, 1 => 2), + array(0 => 98, 1 => 1), + array(0 => 98, 1 => 1), + array(0 => 98, 1 => 3), + array(0 => 95, 1 => 2), + array(0 => 99, 1 => 1), + array(0 => 99, 1 => 2), + array(0 => 100, 1 => 3), + array(0 => 100, 1 => 3), + array(0 => 100, 1 => 5), + array(0 => 100, 1 => 6), + array(0 => 100, 1 => 2), + array(0 => 90, 1 => 4), + array(0 => 101, 1 => 4), + array(0 => 101, 1 => 4), + array(0 => 102, 1 => 3), + array(0 => 102, 1 => 1), + array(0 => 102, 1 => 0), + array(0 => 78, 1 => 3), + array(0 => 78, 1 => 2), + array(0 => 103, 1 => 3), + array(0 => 103, 1 => 2), + array(0 => 83, 1 => 2), + array(0 => 83, 1 => 0), + array(0 => 104, 1 => 2), + array(0 => 104, 1 => 3), + array(0 => 104, 1 => 2), + array(0 => 93, 1 => 1), + array(0 => 93, 1 => 2), + array(0 => 93, 1 => 1), + array(0 => 93, 1 => 2), + array(0 => 93, 1 => 3), + array(0 => 87, 1 => 1), + array(0 => 87, 1 => 1), + array(0 => 86, 1 => 1), + array(0 => 88, 1 => 1), + array(0 => 94, 1 => 3), + array(0 => 94, 1 => 3), + array(0 => 105, 1 => 1), + array(0 => 105, 1 => 3), + array(0 => 105, 1 => 0), + array(0 => 106, 1 => 3), + array(0 => 106, 1 => 3), + array(0 => 106, 1 => 1), + array(0 => 92, 1 => 2), + array(0 => 92, 1 => 3), + array(0 => 107, 1 => 2), + array(0 => 107, 1 => 1), + array(0 => 108, 1 => 3), + array(0 => 108, 1 => 3), + array(0 => 108, 1 => 1), + array(0 => 108, 1 => 3), + array(0 => 108, 1 => 3), + array(0 => 108, 1 => 1), + array(0 => 108, 1 => 1), + ); + + public static $yyReduceMap = array( + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + 6 => 6, + 7 => 7, + 22 => 7, + 23 => 7, + 24 => 7, + 37 => 7, + 57 => 7, + 58 => 7, + 66 => 7, + 67 => 7, + 78 => 7, + 83 => 7, + 84 => 7, + 89 => 7, + 93 => 7, + 94 => 7, + 98 => 7, + 99 => 7, + 101 => 7, + 106 => 7, + 170 => 7, + 175 => 7, + 8 => 8, + 9 => 9, + 10 => 10, + 12 => 12, + 13 => 13, + 14 => 14, + 15 => 15, + 16 => 16, + 17 => 17, + 18 => 18, + 19 => 19, + 20 => 20, + 21 => 21, + 25 => 25, + 26 => 26, + 27 => 27, + 28 => 28, + 29 => 29, + 30 => 30, + 31 => 31, + 32 => 32, + 34 => 32, + 33 => 33, + 35 => 35, + 36 => 36, + 38 => 38, + 39 => 39, + 40 => 40, + 41 => 41, + 42 => 42, + 43 => 43, + 44 => 44, + 45 => 45, + 46 => 46, + 47 => 47, + 48 => 48, + 49 => 49, + 50 => 50, + 51 => 51, + 60 => 51, + 148 => 51, + 152 => 51, + 156 => 51, + 158 => 51, + 52 => 52, + 149 => 52, + 155 => 52, + 53 => 53, + 54 => 54, + 55 => 54, + 56 => 56, + 133 => 56, + 59 => 59, + 61 => 61, + 62 => 62, + 63 => 62, + 64 => 64, + 65 => 65, + 68 => 68, + 69 => 69, + 70 => 69, + 71 => 71, + 72 => 72, + 73 => 73, + 74 => 74, + 75 => 75, + 76 => 76, + 77 => 77, + 79 => 79, + 81 => 79, + 82 => 79, + 113 => 79, + 80 => 80, + 85 => 85, + 86 => 86, + 87 => 87, + 88 => 88, + 90 => 90, + 91 => 91, + 92 => 91, + 95 => 95, + 96 => 96, + 97 => 97, + 100 => 100, + 102 => 102, + 103 => 103, + 104 => 104, + 105 => 105, + 107 => 107, + 108 => 108, + 109 => 109, + 110 => 110, + 111 => 111, + 112 => 112, + 114 => 114, + 172 => 114, + 115 => 115, + 116 => 116, + 117 => 117, + 118 => 118, + 119 => 119, + 120 => 120, + 128 => 120, + 121 => 121, + 122 => 122, + 123 => 123, + 124 => 123, + 126 => 123, + 127 => 123, + 125 => 125, + 129 => 129, + 130 => 130, + 131 => 131, + 176 => 131, + 132 => 132, + 134 => 134, + 135 => 135, + 136 => 136, + 137 => 137, + 138 => 138, + 139 => 139, + 140 => 140, + 141 => 141, + 142 => 142, + 143 => 143, + 144 => 144, + 145 => 145, + 146 => 146, + 147 => 147, + 150 => 150, + 151 => 151, + 153 => 153, + 154 => 154, + 157 => 157, + 159 => 159, + 160 => 160, + 161 => 161, + 162 => 162, + 163 => 163, + 164 => 164, + 165 => 165, + 166 => 166, + 167 => 167, + 168 => 168, + 169 => 168, + 171 => 171, + 173 => 173, + 174 => 174, + 177 => 177, + 178 => 178, + 179 => 179, + 180 => 180, + 183 => 180, + 181 => 181, + 184 => 181, + 182 => 182, + 185 => 185, + 186 => 186, + ); - const Err1 = "Security error: Call to private object member not allowed"; - const Err2 = "Security error: Call to dynamic object member not allowed"; - // states whether the parse was successful or not + /** + * result status + * + * @var bool + */ public $successful = true; + + /** + * return value + * + * @var mixed + */ public $retvalue = 0; - private $lex; - private $internalError = false; - function __construct($lex, $compiler) { + /** + * @var + */ + public $yymajor; + + /** + * last index of array variable + * + * @var mixed + */ + public $last_index; + + /** + * last variable name + * + * @var string + */ + public $last_variable; + + /** + * root parse tree buffer + * + * @var Smarty_Internal_ParseTree_Template + */ + public $root_buffer; + + /** + * current parse tree object + * + * @var Smarty_Internal_ParseTree + */ + public $current_buffer; + + /** + * lexer object + * + * @var Smarty_Internal_Templatelexer + */ + public $lex; + + /** + * {strip} status + * + * @var bool + */ + public $strip = false; + + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; + + /** + * template object + * + * @var Smarty_Internal_Template + */ + public $template = null; + + /** + * block nesting level + * + * @var int + */ + public $block_nesting_level = 0; + + /** + * security object + * + * @var Smarty_Security + */ + public $security = null; + + /** + * template prefix array + * + * @var \Smarty_Internal_ParseTree[] + */ + public $template_prefix = array(); + + /** + * template prefix array + * + * @var \Smarty_Internal_ParseTree[] + */ + public $template_postfix = array(); + + public $yyTraceFILE; + + public $yyTracePrompt; + + public $yyidx; + + public $yyerrcnt; + + public $yystack = array(); + + public $yyTokenName = array( + '$', 'VERT', 'COLON', 'PHP', + 'TEXT', 'STRIPON', 'STRIPOFF', 'LITERALSTART', + 'LITERALEND', 'LITERAL', 'SIMPELOUTPUT', 'SIMPLETAG', + 'SMARTYBLOCKCHILDPARENT', 'LDEL', 'RDEL', 'DOLLARID', + 'EQUAL', 'ID', 'PTR', 'LDELMAKENOCACHE', + 'LDELIF', 'LDELFOR', 'SEMICOLON', 'INCDEC', + 'TO', 'STEP', 'LDELFOREACH', 'SPACE', + 'AS', 'APTR', 'LDELSETFILTER', 'CLOSETAG', + 'LDELSLASH', 'ATTR', 'INTEGER', 'COMMA', + 'OPENP', 'CLOSEP', 'MATH', 'UNIMATH', + 'ISIN', 'QMARK', 'NOT', 'TYPECAST', + 'HEX', 'DOT', 'INSTANCEOF', 'SINGLEQUOTESTRING', + 'DOUBLECOLON', 'NAMESPACE', 'AT', 'HATCH', + 'OPENB', 'CLOSEB', 'DOLLAR', 'LOGOP', + 'SLOGOP', 'TLOGOP', 'SINGLECOND', 'ARRAYOPEN', + 'QUOTE', 'BACKTICK', 'error', 'start', + 'template', 'literal_e2', 'literal_e1', 'smartytag', + 'tagbody', 'tag', 'outattr', 'eqoutattr', + 'varindexed', 'output', 'attributes', 'variable', + 'value', 'expr', 'modifierlist', 'statement', + 'statements', 'foraction', 'varvar', 'modparameters', + 'attribute', 'ternary', 'tlop', 'lop', + 'scond', 'array', 'function', 'ns1', + 'doublequoted_with_quotes', 'static_class_access', 'arraydef', 'object', + 'arrayindex', 'indexdef', 'varvarele', 'objectchain', + 'objectelement', 'method', 'params', 'modifier', + 'modparameter', 'arrayelements', 'arrayelement', 'doublequoted', + 'doublequotedcontent', + ); + + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; /* Index of top element in stack */ + private $_retvalue; /* Shifts left before out of the error */ + /** + * constructor + * + * @param Smarty_Internal_Templatelexer $lex + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + public function __construct(Smarty_Internal_Templatelexer $lex, Smarty_Internal_TemplateCompilerBase $compiler) + { $this->lex = $lex; $this->compiler = $compiler; - $this->smarty = $this->compiler->smarty; $this->template = $this->compiler->template; - $this->compiler->has_variable_string = false; - $this->compiler->prefix_code = array(); - $this->prefix_number = 0; - $this->block_nesting_level = 0; - if ($this->security = isset($this->smarty->security_policy)) { - $this->php_handling = $this->smarty->security_policy->php_handling; - } else { - $this->php_handling = $this->smarty->php_handling; + $this->smarty = $this->template->smarty; + $this->security = isset($this->smarty->security_policy) ? $this->smarty->security_policy : false; + $this->current_buffer = $this->root_buffer = new Smarty_Internal_ParseTree_Template(); + } /* The parser's stack */ + public static function yy_destructor($yymajor, $yypminor) + { + switch ($yymajor) { + default: + break; /* If no destructor action specified: do nothing */ } - $this->is_xml = false; - $this->asp_tags = (ini_get('asp_tags') != '0'); - $this->current_buffer = $this->root_buffer = new _smarty_template_buffer($this); - } - - public static function escape_start_tag($tag_text) { - $tag = preg_replace('/\A<\?(.*)\z/', '<?\1', $tag_text, -1 , $count); //Escape tag - return $tag; - } - - public static function escape_end_tag($tag_text) { - return '?>'; - } - - -#line 121 "smarty_internal_templateparser.php" - - const TP_VERT = 1; - const TP_COLON = 2; - const TP_COMMENT = 3; - const TP_PHPSTARTTAG = 4; - const TP_PHPENDTAG = 5; - const TP_ASPSTARTTAG = 6; - const TP_ASPENDTAG = 7; - const TP_FAKEPHPSTARTTAG = 8; - const TP_XMLTAG = 9; - const TP_OTHER = 10; - const TP_LINEBREAK = 11; - const TP_LITERALSTART = 12; - const TP_LITERALEND = 13; - const TP_LITERAL = 14; - const TP_LDEL = 15; - const TP_RDEL = 16; - const TP_DOLLAR = 17; - const TP_ID = 18; - const TP_EQUAL = 19; - const TP_PTR = 20; - const TP_LDELIF = 21; - const TP_SPACE = 22; - const TP_LDELFOR = 23; - const TP_SEMICOLON = 24; - const TP_INCDEC = 25; - const TP_TO = 26; - const TP_STEP = 27; - const TP_LDELFOREACH = 28; - const TP_AS = 29; - const TP_APTR = 30; - const TP_SMARTYBLOCKCHILD = 31; - const TP_LDELSLASH = 32; - const TP_INTEGER = 33; - const TP_COMMA = 34; - const TP_OPENP = 35; - const TP_CLOSEP = 36; - const TP_MATH = 37; - const TP_UNIMATH = 38; - const TP_ANDSYM = 39; - const TP_ISIN = 40; - const TP_ISDIVBY = 41; - const TP_ISNOTDIVBY = 42; - const TP_ISEVEN = 43; - const TP_ISNOTEVEN = 44; - const TP_ISEVENBY = 45; - const TP_ISNOTEVENBY = 46; - const TP_ISODD = 47; - const TP_ISNOTODD = 48; - const TP_ISODDBY = 49; - const TP_ISNOTODDBY = 50; - const TP_INSTANCEOF = 51; - const TP_QMARK = 52; - const TP_NOT = 53; - const TP_TYPECAST = 54; - const TP_HEX = 55; - const TP_DOT = 56; - const TP_SINGLEQUOTESTRING = 57; - const TP_DOUBLECOLON = 58; - const TP_AT = 59; - const TP_HATCH = 60; - const TP_OPENB = 61; - const TP_CLOSEB = 62; - const TP_EQUALS = 63; - const TP_NOTEQUALS = 64; - const TP_GREATERTHAN = 65; - const TP_LESSTHAN = 66; - const TP_GREATEREQUAL = 67; - const TP_LESSEQUAL = 68; - const TP_IDENTITY = 69; - const TP_NONEIDENTITY = 70; - const TP_MOD = 71; - const TP_LAND = 72; - const TP_LOR = 73; - const TP_LXOR = 74; - const TP_QUOTE = 75; - const TP_BACKTICK = 76; - const TP_DOLLARID = 77; - const YY_NO_ACTION = 584; - const YY_ACCEPT_ACTION = 583; - const YY_ERROR_ACTION = 582; - - const YY_SZ_ACTTAB = 2566; -static public $yy_action = array( - /* 0 */ 218, 272, 271, 275, 274, 278, 277, 276, 270, 262, - /* 10 */ 260, 264, 268, 196, 298, 285, 42, 22, 159, 265, - /* 20 */ 19, 29, 222, 374, 237, 29, 294, 29, 280, 149, - /* 30 */ 243, 19, 378, 225, 374, 244, 52, 47, 50, 45, - /* 40 */ 38, 37, 331, 332, 40, 39, 340, 337, 30, 25, - /* 50 */ 292, 299, 291, 290, 295, 190, 123, 342, 196, 279, - /* 60 */ 293, 135, 335, 322, 321, 308, 309, 310, 307, 306, - /* 70 */ 302, 303, 304, 305, 218, 242, 319, 175, 199, 133, - /* 80 */ 138, 19, 248, 72, 374, 124, 19, 288, 448, 374, - /* 90 */ 41, 14, 339, 311, 448, 29, 348, 329, 376, 320, - /* 100 */ 34, 583, 95, 273, 271, 275, 219, 3, 301, 3, - /* 110 */ 52, 47, 50, 45, 38, 37, 331, 332, 40, 39, - /* 120 */ 340, 337, 30, 25, 7, 231, 17, 108, 134, 167, - /* 130 */ 140, 35, 140, 143, 336, 192, 335, 322, 321, 308, - /* 140 */ 309, 310, 307, 306, 302, 303, 304, 305, 218, 334, - /* 150 */ 319, 193, 353, 10, 138, 3, 248, 55, 3, 119, - /* 160 */ 136, 36, 31, 371, 218, 19, 339, 311, 374, 29, - /* 170 */ 348, 329, 29, 320, 199, 27, 223, 258, 140, 372, - /* 180 */ 224, 140, 254, 220, 52, 47, 50, 45, 38, 37, - /* 190 */ 331, 332, 40, 39, 340, 337, 30, 25, 341, 179, - /* 200 */ 32, 159, 106, 323, 29, 194, 379, 342, 218, 288, - /* 210 */ 335, 322, 321, 308, 309, 310, 307, 306, 302, 303, - /* 220 */ 304, 305, 218, 366, 319, 199, 186, 218, 138, 190, - /* 230 */ 248, 72, 445, 124, 218, 266, 288, 364, 445, 123, - /* 240 */ 339, 311, 447, 29, 348, 329, 19, 320, 447, 374, - /* 250 */ 23, 3, 199, 16, 211, 29, 297, 170, 52, 47, - /* 260 */ 50, 45, 38, 37, 331, 332, 40, 39, 340, 337, - /* 270 */ 30, 25, 218, 172, 140, 183, 104, 46, 19, 189, - /* 280 */ 379, 374, 41, 288, 335, 322, 321, 308, 309, 310, - /* 290 */ 307, 306, 302, 303, 304, 305, 344, 188, 444, 199, - /* 300 */ 218, 235, 249, 216, 29, 191, 379, 342, 52, 47, - /* 310 */ 50, 45, 38, 37, 331, 332, 40, 39, 340, 337, - /* 320 */ 30, 25, 242, 19, 142, 43, 374, 130, 245, 28, - /* 330 */ 29, 159, 107, 346, 335, 322, 321, 308, 309, 310, - /* 340 */ 307, 306, 302, 303, 304, 305, 218, 347, 319, 27, - /* 350 */ 46, 257, 138, 198, 248, 62, 164, 119, 240, 218, - /* 360 */ 267, 252, 228, 126, 339, 311, 288, 205, 348, 329, - /* 370 */ 103, 320, 8, 261, 444, 357, 180, 376, 376, 29, - /* 380 */ 29, 29, 52, 47, 50, 45, 38, 37, 331, 332, - /* 390 */ 40, 39, 340, 337, 30, 25, 184, 349, 361, 365, - /* 400 */ 27, 284, 358, 29, 29, 29, 288, 29, 335, 322, - /* 410 */ 321, 308, 309, 310, 307, 306, 302, 303, 304, 305, - /* 420 */ 218, 319, 202, 221, 181, 138, 154, 248, 72, 171, - /* 430 */ 124, 313, 9, 162, 288, 289, 163, 339, 311, 288, - /* 440 */ 320, 348, 329, 288, 320, 376, 288, 281, 269, 370, - /* 450 */ 376, 214, 6, 29, 29, 29, 52, 47, 50, 45, - /* 460 */ 38, 37, 331, 332, 40, 39, 340, 337, 30, 25, - /* 470 */ 218, 178, 239, 283, 373, 19, 226, 238, 374, 29, - /* 480 */ 29, 288, 335, 322, 321, 308, 309, 310, 307, 306, - /* 490 */ 302, 303, 304, 305, 177, 205, 286, 202, 227, 377, - /* 500 */ 8, 166, 29, 376, 288, 29, 52, 47, 50, 45, - /* 510 */ 38, 37, 331, 332, 40, 39, 340, 337, 30, 25, - /* 520 */ 202, 218, 363, 375, 380, 315, 235, 296, 29, 29, - /* 530 */ 29, 29, 335, 322, 321, 308, 309, 310, 307, 306, - /* 540 */ 302, 303, 304, 305, 197, 369, 352, 19, 327, 218, - /* 550 */ 236, 29, 29, 165, 234, 156, 174, 52, 47, 50, - /* 560 */ 45, 38, 37, 331, 332, 40, 39, 340, 337, 30, - /* 570 */ 25, 26, 344, 5, 19, 314, 199, 212, 19, 199, - /* 580 */ 159, 241, 218, 335, 322, 321, 308, 309, 310, 307, - /* 590 */ 306, 302, 303, 304, 305, 218, 319, 300, 100, 46, - /* 600 */ 138, 19, 248, 76, 233, 124, 6, 218, 110, 351, - /* 610 */ 201, 338, 339, 311, 115, 168, 348, 329, 123, 320, - /* 620 */ 182, 338, 287, 234, 105, 288, 324, 338, 235, 240, - /* 630 */ 288, 52, 47, 50, 45, 38, 37, 331, 332, 40, - /* 640 */ 39, 340, 337, 30, 25, 218, 333, 144, 263, 33, - /* 650 */ 13, 342, 312, 156, 29, 355, 97, 335, 322, 321, - /* 660 */ 308, 309, 310, 307, 306, 302, 303, 304, 305, 338, - /* 670 */ 141, 32, 325, 121, 195, 131, 356, 229, 127, 2, - /* 680 */ 250, 52, 47, 50, 45, 38, 37, 331, 332, 40, - /* 690 */ 39, 340, 337, 30, 25, 318, 228, 11, 330, 94, - /* 700 */ 129, 282, 218, 253, 159, 29, 323, 335, 322, 321, - /* 710 */ 308, 309, 310, 307, 306, 302, 303, 304, 305, 218, - /* 720 */ 218, 319, 18, 101, 148, 122, 114, 248, 54, 44, - /* 730 */ 124, 202, 99, 158, 316, 367, 376, 339, 311, 338, - /* 740 */ 29, 348, 329, 376, 320, 338, 338, 354, 169, 368, - /* 750 */ 321, 321, 321, 321, 321, 52, 47, 50, 45, 38, - /* 760 */ 37, 331, 332, 40, 39, 340, 337, 30, 25, 218, - /* 770 */ 46, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 780 */ 113, 335, 322, 321, 308, 309, 310, 307, 306, 302, - /* 790 */ 303, 304, 305, 338, 321, 321, 321, 321, 321, 321, - /* 800 */ 321, 321, 321, 321, 256, 52, 47, 50, 45, 38, - /* 810 */ 37, 331, 332, 40, 39, 340, 337, 30, 25, 218, - /* 820 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 830 */ 321, 335, 322, 321, 308, 309, 310, 307, 306, 302, - /* 840 */ 303, 304, 305, 321, 321, 321, 321, 321, 321, 321, - /* 850 */ 321, 321, 321, 321, 321, 52, 47, 50, 45, 38, - /* 860 */ 37, 331, 332, 40, 39, 340, 337, 30, 25, 218, - /* 870 */ 12, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 880 */ 382, 335, 322, 321, 308, 309, 310, 307, 306, 302, - /* 890 */ 303, 304, 305, 321, 321, 321, 321, 321, 321, 321, - /* 900 */ 321, 321, 321, 321, 321, 52, 47, 50, 45, 38, - /* 910 */ 37, 331, 332, 40, 39, 340, 337, 30, 25, 321, - /* 920 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 930 */ 321, 335, 322, 321, 308, 309, 310, 307, 306, 302, - /* 940 */ 303, 304, 305, 218, 319, 321, 321, 321, 138, 321, - /* 950 */ 248, 61, 321, 124, 321, 98, 132, 321, 200, 321, - /* 960 */ 339, 311, 321, 321, 348, 329, 321, 320, 338, 338, - /* 970 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 52, - /* 980 */ 47, 50, 45, 38, 37, 331, 332, 40, 39, 340, - /* 990 */ 337, 30, 25, 218, 321, 321, 321, 321, 321, 321, - /* 1000 */ 321, 321, 321, 321, 321, 335, 322, 321, 308, 309, - /* 1010 */ 310, 307, 306, 302, 303, 304, 305, 321, 321, 321, - /* 1020 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 52, - /* 1030 */ 47, 50, 45, 38, 37, 331, 332, 40, 39, 340, - /* 1040 */ 337, 30, 25, 321, 321, 321, 321, 321, 321, 321, - /* 1050 */ 321, 321, 321, 321, 321, 335, 322, 321, 308, 309, - /* 1060 */ 310, 307, 306, 302, 303, 304, 305, 52, 47, 50, - /* 1070 */ 45, 38, 37, 331, 332, 40, 39, 340, 337, 30, - /* 1080 */ 25, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 1090 */ 321, 321, 321, 335, 322, 321, 308, 309, 310, 307, - /* 1100 */ 306, 302, 303, 304, 305, 321, 321, 321, 321, 42, - /* 1110 */ 321, 139, 207, 321, 319, 222, 321, 237, 138, 321, - /* 1120 */ 248, 78, 149, 124, 321, 378, 225, 232, 321, 15, - /* 1130 */ 339, 311, 49, 321, 348, 329, 321, 320, 321, 321, - /* 1140 */ 321, 321, 321, 321, 321, 321, 321, 51, 48, 317, - /* 1150 */ 247, 328, 321, 319, 103, 1, 255, 145, 321, 248, - /* 1160 */ 321, 321, 124, 321, 42, 321, 139, 209, 321, 96, - /* 1170 */ 222, 321, 237, 348, 329, 321, 320, 149, 345, 321, - /* 1180 */ 378, 225, 232, 24, 15, 321, 321, 49, 321, 222, - /* 1190 */ 321, 237, 321, 321, 321, 321, 149, 321, 321, 378, - /* 1200 */ 225, 321, 51, 48, 317, 247, 328, 321, 319, 103, - /* 1210 */ 1, 321, 146, 321, 248, 321, 321, 124, 321, 42, - /* 1220 */ 161, 130, 209, 193, 96, 222, 321, 237, 348, 329, - /* 1230 */ 288, 320, 149, 36, 31, 378, 225, 232, 321, 21, - /* 1240 */ 321, 321, 49, 350, 20, 343, 199, 319, 218, 321, - /* 1250 */ 321, 155, 321, 248, 321, 321, 124, 51, 48, 317, - /* 1260 */ 247, 328, 321, 450, 103, 1, 321, 348, 329, 450, - /* 1270 */ 320, 321, 321, 321, 42, 321, 125, 209, 321, 96, - /* 1280 */ 222, 321, 237, 321, 321, 321, 321, 149, 345, 321, - /* 1290 */ 378, 225, 232, 24, 4, 321, 321, 49, 46, 222, - /* 1300 */ 321, 237, 321, 321, 321, 321, 149, 321, 321, 378, - /* 1310 */ 225, 321, 51, 48, 317, 247, 328, 321, 319, 103, - /* 1320 */ 1, 321, 151, 321, 248, 321, 321, 124, 321, 42, - /* 1330 */ 176, 139, 204, 193, 96, 222, 321, 237, 348, 329, - /* 1340 */ 288, 320, 149, 36, 31, 378, 225, 215, 321, 15, - /* 1350 */ 321, 321, 49, 362, 20, 343, 199, 319, 218, 321, - /* 1360 */ 321, 150, 321, 248, 321, 321, 124, 51, 48, 317, - /* 1370 */ 247, 328, 321, 259, 103, 1, 321, 348, 329, 29, - /* 1380 */ 320, 321, 321, 321, 42, 173, 128, 92, 193, 96, - /* 1390 */ 222, 321, 237, 321, 218, 288, 321, 149, 36, 31, - /* 1400 */ 378, 225, 232, 321, 15, 321, 321, 49, 46, 381, - /* 1410 */ 321, 199, 319, 230, 321, 29, 152, 321, 248, 321, - /* 1420 */ 321, 124, 51, 48, 317, 247, 328, 321, 3, 103, - /* 1430 */ 1, 321, 348, 329, 321, 320, 321, 321, 321, 42, - /* 1440 */ 185, 139, 208, 102, 96, 222, 321, 237, 321, 321, - /* 1450 */ 288, 140, 149, 36, 31, 378, 225, 232, 321, 15, - /* 1460 */ 321, 321, 49, 321, 321, 321, 199, 319, 321, 321, - /* 1470 */ 321, 147, 321, 248, 321, 321, 124, 51, 48, 317, - /* 1480 */ 247, 328, 321, 321, 103, 1, 321, 348, 329, 321, - /* 1490 */ 320, 321, 321, 321, 42, 187, 139, 203, 193, 96, - /* 1500 */ 222, 321, 237, 321, 321, 288, 321, 149, 36, 31, - /* 1510 */ 378, 225, 232, 321, 15, 321, 160, 49, 321, 193, - /* 1520 */ 321, 199, 321, 321, 321, 321, 288, 321, 321, 36, - /* 1530 */ 31, 321, 51, 48, 317, 247, 328, 321, 321, 103, - /* 1540 */ 1, 321, 199, 321, 321, 321, 321, 321, 321, 42, - /* 1550 */ 321, 139, 206, 218, 96, 222, 321, 237, 321, 321, - /* 1560 */ 321, 321, 149, 321, 321, 378, 225, 232, 450, 15, - /* 1570 */ 321, 321, 49, 321, 450, 321, 321, 321, 321, 321, - /* 1580 */ 321, 246, 321, 321, 321, 321, 321, 51, 48, 317, - /* 1590 */ 247, 328, 321, 321, 103, 1, 321, 321, 321, 321, - /* 1600 */ 321, 321, 321, 46, 42, 321, 137, 209, 321, 96, - /* 1610 */ 222, 321, 237, 321, 321, 321, 321, 149, 321, 321, - /* 1620 */ 378, 225, 232, 321, 15, 321, 321, 49, 321, 321, - /* 1630 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 1640 */ 321, 321, 51, 48, 317, 247, 328, 321, 321, 103, - /* 1650 */ 1, 321, 321, 321, 321, 321, 321, 321, 321, 42, - /* 1660 */ 321, 130, 210, 321, 96, 222, 321, 237, 321, 321, - /* 1670 */ 321, 321, 149, 321, 321, 378, 225, 232, 321, 21, - /* 1680 */ 321, 321, 49, 321, 321, 321, 321, 321, 321, 321, - /* 1690 */ 321, 321, 321, 321, 321, 321, 321, 51, 48, 317, - /* 1700 */ 247, 328, 321, 321, 103, 321, 321, 321, 321, 321, - /* 1710 */ 321, 321, 321, 321, 42, 321, 130, 209, 321, 96, - /* 1720 */ 222, 321, 237, 321, 321, 321, 321, 149, 321, 321, - /* 1730 */ 378, 225, 232, 321, 21, 321, 321, 49, 321, 321, - /* 1740 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 1750 */ 321, 321, 51, 48, 317, 247, 328, 321, 321, 103, - /* 1760 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 493, - /* 1770 */ 321, 321, 321, 321, 96, 493, 321, 493, 321, 493, - /* 1780 */ 493, 321, 493, 321, 321, 321, 321, 493, 3, 493, - /* 1790 */ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321, - /* 1800 */ 321, 321, 321, 319, 493, 321, 321, 117, 321, 248, - /* 1810 */ 82, 140, 124, 321, 321, 493, 321, 321, 321, 339, - /* 1820 */ 311, 321, 321, 348, 329, 321, 320, 321, 321, 493, - /* 1830 */ 321, 321, 321, 321, 321, 321, 319, 217, 360, 321, - /* 1840 */ 117, 321, 248, 82, 321, 124, 321, 321, 321, 321, - /* 1850 */ 321, 321, 339, 311, 321, 321, 348, 329, 319, 320, - /* 1860 */ 321, 321, 138, 321, 248, 90, 321, 124, 321, 321, - /* 1870 */ 321, 359, 321, 321, 339, 311, 321, 321, 348, 329, - /* 1880 */ 321, 320, 321, 321, 321, 321, 319, 321, 321, 321, - /* 1890 */ 138, 321, 248, 69, 321, 124, 321, 321, 321, 321, - /* 1900 */ 321, 321, 339, 311, 321, 321, 348, 329, 321, 320, - /* 1910 */ 321, 321, 319, 321, 321, 321, 138, 321, 248, 67, - /* 1920 */ 321, 124, 321, 321, 321, 321, 321, 321, 339, 311, - /* 1930 */ 321, 321, 348, 329, 321, 320, 319, 321, 321, 321, - /* 1940 */ 138, 321, 248, 58, 321, 124, 321, 321, 321, 321, - /* 1950 */ 321, 321, 339, 311, 319, 321, 348, 329, 138, 320, - /* 1960 */ 248, 62, 321, 124, 321, 321, 321, 321, 321, 321, - /* 1970 */ 339, 311, 321, 321, 348, 329, 319, 320, 321, 321, - /* 1980 */ 138, 321, 248, 56, 321, 124, 321, 321, 321, 321, - /* 1990 */ 321, 321, 339, 311, 321, 321, 348, 329, 321, 320, - /* 2000 */ 321, 319, 321, 321, 321, 112, 321, 248, 71, 321, - /* 2010 */ 124, 321, 321, 321, 321, 321, 321, 339, 311, 319, - /* 2020 */ 321, 348, 329, 111, 320, 248, 81, 321, 124, 321, - /* 2030 */ 321, 321, 321, 321, 321, 339, 311, 319, 321, 348, - /* 2040 */ 329, 138, 320, 248, 74, 321, 124, 321, 321, 321, - /* 2050 */ 321, 321, 321, 339, 311, 321, 321, 348, 329, 319, - /* 2060 */ 320, 321, 321, 138, 321, 248, 91, 321, 124, 321, - /* 2070 */ 321, 321, 321, 321, 321, 339, 311, 321, 321, 348, - /* 2080 */ 329, 321, 320, 321, 319, 321, 321, 321, 138, 321, - /* 2090 */ 248, 64, 321, 124, 321, 321, 321, 321, 321, 321, - /* 2100 */ 339, 311, 319, 321, 348, 329, 138, 320, 248, 63, - /* 2110 */ 321, 124, 321, 321, 321, 321, 321, 321, 339, 311, - /* 2120 */ 319, 321, 348, 329, 138, 320, 248, 83, 321, 124, - /* 2130 */ 321, 321, 321, 321, 321, 321, 339, 311, 321, 321, - /* 2140 */ 348, 329, 319, 320, 321, 321, 138, 321, 248, 79, - /* 2150 */ 321, 124, 321, 321, 321, 321, 321, 321, 339, 311, - /* 2160 */ 321, 321, 348, 329, 321, 320, 321, 319, 321, 321, - /* 2170 */ 321, 138, 321, 248, 75, 321, 124, 321, 321, 321, - /* 2180 */ 321, 321, 321, 339, 311, 319, 321, 348, 329, 138, - /* 2190 */ 320, 248, 70, 321, 124, 321, 321, 321, 321, 321, - /* 2200 */ 321, 339, 311, 319, 321, 348, 329, 109, 320, 248, - /* 2210 */ 68, 321, 124, 321, 321, 321, 321, 321, 321, 339, - /* 2220 */ 311, 321, 321, 348, 329, 319, 320, 321, 321, 138, - /* 2230 */ 321, 248, 77, 321, 124, 321, 321, 321, 321, 321, - /* 2240 */ 321, 339, 311, 321, 321, 348, 329, 321, 320, 321, - /* 2250 */ 319, 321, 321, 321, 138, 321, 248, 73, 321, 124, - /* 2260 */ 321, 321, 321, 321, 321, 321, 339, 311, 319, 321, - /* 2270 */ 348, 329, 138, 320, 213, 65, 321, 124, 321, 321, - /* 2280 */ 321, 321, 321, 321, 339, 311, 319, 321, 348, 329, - /* 2290 */ 138, 320, 248, 86, 321, 124, 321, 321, 321, 321, - /* 2300 */ 321, 321, 339, 311, 321, 321, 348, 329, 319, 320, - /* 2310 */ 321, 321, 138, 321, 248, 88, 321, 124, 321, 321, - /* 2320 */ 321, 321, 321, 321, 339, 311, 321, 321, 348, 329, - /* 2330 */ 321, 320, 321, 319, 321, 321, 321, 93, 321, 120, - /* 2340 */ 59, 321, 116, 321, 321, 321, 321, 321, 321, 339, - /* 2350 */ 311, 319, 321, 348, 329, 138, 320, 248, 57, 321, - /* 2360 */ 124, 321, 321, 321, 321, 321, 321, 339, 311, 319, - /* 2370 */ 321, 348, 329, 138, 320, 248, 60, 321, 124, 321, - /* 2380 */ 321, 321, 321, 321, 321, 339, 311, 321, 321, 348, - /* 2390 */ 329, 319, 320, 321, 321, 138, 321, 248, 89, 321, - /* 2400 */ 124, 321, 321, 321, 321, 321, 321, 339, 311, 321, - /* 2410 */ 321, 348, 329, 321, 320, 321, 319, 321, 321, 321, - /* 2420 */ 138, 321, 248, 85, 321, 124, 321, 321, 321, 321, - /* 2430 */ 321, 321, 339, 311, 319, 321, 348, 329, 138, 320, - /* 2440 */ 248, 80, 321, 124, 321, 321, 321, 321, 321, 321, - /* 2450 */ 339, 311, 319, 321, 348, 329, 138, 320, 248, 84, - /* 2460 */ 321, 124, 321, 321, 321, 321, 321, 321, 339, 311, - /* 2470 */ 321, 321, 348, 329, 319, 320, 321, 321, 138, 321, - /* 2480 */ 248, 66, 321, 124, 321, 321, 321, 321, 321, 321, - /* 2490 */ 339, 311, 321, 321, 348, 329, 321, 320, 321, 319, - /* 2500 */ 321, 321, 321, 138, 321, 248, 87, 321, 124, 321, - /* 2510 */ 321, 321, 321, 321, 321, 339, 311, 319, 321, 348, - /* 2520 */ 329, 93, 320, 118, 53, 321, 116, 321, 321, 321, - /* 2530 */ 321, 321, 321, 339, 311, 319, 321, 348, 329, 153, - /* 2540 */ 320, 248, 319, 321, 124, 321, 157, 321, 248, 321, - /* 2550 */ 321, 124, 326, 321, 321, 348, 329, 321, 320, 251, - /* 2560 */ 321, 321, 348, 329, 321, 320, - ); - static public $yy_lookahead = array( - /* 0 */ 1, 81, 82, 83, 3, 4, 5, 6, 7, 8, - /* 10 */ 9, 10, 11, 12, 22, 16, 15, 19, 20, 16, - /* 20 */ 15, 22, 21, 18, 23, 22, 83, 22, 85, 28, - /* 30 */ 94, 15, 31, 32, 18, 30, 37, 38, 39, 40, - /* 40 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - /* 50 */ 4, 5, 6, 7, 8, 90, 58, 25, 12, 13, - /* 60 */ 14, 17, 63, 64, 65, 66, 67, 68, 69, 70, - /* 70 */ 71, 72, 73, 74, 1, 59, 82, 87, 113, 35, - /* 80 */ 86, 15, 88, 89, 18, 91, 15, 97, 16, 18, - /* 90 */ 19, 19, 98, 99, 22, 22, 102, 103, 108, 105, - /* 100 */ 27, 79, 80, 81, 82, 83, 112, 35, 76, 35, - /* 110 */ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - /* 120 */ 47, 48, 49, 50, 34, 59, 15, 84, 17, 18, - /* 130 */ 58, 15, 58, 17, 18, 114, 63, 64, 65, 66, - /* 140 */ 67, 68, 69, 70, 71, 72, 73, 74, 1, 33, - /* 150 */ 82, 90, 62, 30, 86, 35, 88, 89, 35, 91, - /* 160 */ 92, 100, 101, 16, 1, 15, 98, 99, 18, 22, - /* 170 */ 102, 103, 22, 105, 113, 34, 56, 36, 58, 16, - /* 180 */ 30, 58, 62, 20, 37, 38, 39, 40, 41, 42, - /* 190 */ 43, 44, 45, 46, 47, 48, 49, 50, 16, 87, - /* 200 */ 19, 20, 90, 107, 22, 109, 110, 25, 1, 97, - /* 210 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - /* 220 */ 73, 74, 1, 16, 82, 113, 87, 1, 86, 90, - /* 230 */ 88, 89, 16, 91, 1, 13, 97, 16, 22, 58, - /* 240 */ 98, 99, 16, 22, 102, 103, 15, 105, 22, 18, - /* 250 */ 19, 35, 113, 94, 112, 22, 25, 106, 37, 38, - /* 260 */ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - /* 270 */ 49, 50, 1, 87, 58, 106, 90, 51, 15, 109, - /* 280 */ 110, 18, 19, 97, 63, 64, 65, 66, 67, 68, - /* 290 */ 69, 70, 71, 72, 73, 74, 82, 114, 16, 113, - /* 300 */ 1, 91, 92, 93, 22, 109, 110, 25, 37, 38, - /* 310 */ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - /* 320 */ 49, 50, 59, 15, 17, 19, 18, 17, 18, 30, - /* 330 */ 22, 20, 118, 119, 63, 64, 65, 66, 67, 68, - /* 340 */ 69, 70, 71, 72, 73, 74, 1, 76, 82, 34, - /* 350 */ 51, 36, 86, 24, 88, 89, 87, 91, 92, 1, - /* 360 */ 36, 16, 56, 34, 98, 99, 97, 56, 102, 103, - /* 370 */ 60, 105, 61, 16, 16, 16, 106, 108, 108, 22, - /* 380 */ 22, 22, 37, 38, 39, 40, 41, 42, 43, 44, - /* 390 */ 45, 46, 47, 48, 49, 50, 87, 16, 16, 16, - /* 400 */ 34, 16, 36, 22, 22, 22, 97, 22, 63, 64, - /* 410 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - /* 420 */ 1, 82, 113, 88, 87, 86, 91, 88, 89, 87, - /* 430 */ 91, 18, 15, 87, 97, 16, 87, 98, 99, 97, - /* 440 */ 105, 102, 103, 97, 105, 108, 97, 16, 16, 16, - /* 450 */ 108, 112, 35, 22, 22, 22, 37, 38, 39, 40, - /* 460 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - /* 470 */ 1, 87, 59, 16, 16, 15, 17, 18, 18, 22, - /* 480 */ 22, 97, 63, 64, 65, 66, 67, 68, 69, 70, - /* 490 */ 71, 72, 73, 74, 87, 56, 16, 113, 29, 16, - /* 500 */ 61, 106, 22, 108, 97, 22, 37, 38, 39, 40, - /* 510 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - /* 520 */ 113, 1, 16, 16, 16, 16, 91, 92, 22, 22, - /* 530 */ 22, 22, 63, 64, 65, 66, 67, 68, 69, 70, - /* 540 */ 71, 72, 73, 74, 24, 16, 16, 15, 104, 1, - /* 550 */ 18, 22, 22, 90, 2, 111, 90, 37, 38, 39, - /* 560 */ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - /* 570 */ 50, 19, 82, 35, 15, 18, 113, 18, 15, 113, - /* 580 */ 20, 18, 1, 63, 64, 65, 66, 67, 68, 69, - /* 590 */ 70, 71, 72, 73, 74, 1, 82, 16, 95, 51, - /* 600 */ 86, 15, 88, 89, 18, 91, 35, 1, 95, 119, - /* 610 */ 16, 108, 98, 99, 95, 87, 102, 103, 58, 105, - /* 620 */ 87, 108, 16, 2, 22, 97, 18, 108, 91, 92, - /* 630 */ 97, 37, 38, 39, 40, 41, 42, 43, 44, 45, - /* 640 */ 46, 47, 48, 49, 50, 1, 104, 17, 16, 26, - /* 650 */ 52, 25, 33, 111, 22, 60, 95, 63, 64, 65, - /* 660 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 108, - /* 670 */ 17, 19, 18, 18, 18, 17, 60, 18, 17, 22, - /* 680 */ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - /* 690 */ 46, 47, 48, 49, 50, 33, 56, 2, 18, 18, - /* 700 */ 18, 97, 1, 62, 20, 22, 107, 63, 64, 65, - /* 710 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 1, - /* 720 */ 1, 82, 22, 106, 96, 86, 95, 88, 89, 2, - /* 730 */ 91, 113, 95, 95, 110, 16, 108, 98, 99, 108, - /* 740 */ 22, 102, 103, 108, 105, 108, 108, 111, 106, 115, - /* 750 */ 120, 120, 120, 120, 120, 37, 38, 39, 40, 41, - /* 760 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 1, - /* 770 */ 51, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 780 */ 95, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 790 */ 72, 73, 74, 108, 120, 120, 120, 120, 120, 120, - /* 800 */ 120, 120, 120, 120, 36, 37, 38, 39, 40, 41, - /* 810 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 1, - /* 820 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 830 */ 120, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 840 */ 72, 73, 74, 120, 120, 120, 120, 120, 120, 120, - /* 850 */ 120, 120, 120, 120, 120, 37, 38, 39, 40, 41, - /* 860 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 1, - /* 870 */ 2, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 880 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 890 */ 72, 73, 74, 120, 120, 120, 120, 120, 120, 120, - /* 900 */ 120, 120, 120, 120, 120, 37, 38, 39, 40, 41, - /* 910 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 120, - /* 920 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 930 */ 120, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 940 */ 72, 73, 74, 1, 82, 120, 120, 120, 86, 120, - /* 950 */ 88, 89, 120, 91, 120, 95, 95, 120, 16, 120, - /* 960 */ 98, 99, 120, 120, 102, 103, 120, 105, 108, 108, - /* 970 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 37, - /* 980 */ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - /* 990 */ 48, 49, 50, 1, 120, 120, 120, 120, 120, 120, - /* 1000 */ 120, 120, 120, 120, 120, 63, 64, 65, 66, 67, - /* 1010 */ 68, 69, 70, 71, 72, 73, 74, 120, 120, 120, - /* 1020 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 37, - /* 1030 */ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - /* 1040 */ 48, 49, 50, 120, 120, 120, 120, 120, 120, 120, - /* 1050 */ 120, 120, 120, 120, 120, 63, 64, 65, 66, 67, - /* 1060 */ 68, 69, 70, 71, 72, 73, 74, 37, 38, 39, - /* 1070 */ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - /* 1080 */ 50, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 1090 */ 120, 120, 120, 63, 64, 65, 66, 67, 68, 69, - /* 1100 */ 70, 71, 72, 73, 74, 120, 120, 120, 120, 15, - /* 1110 */ 120, 17, 18, 120, 82, 21, 120, 23, 86, 120, - /* 1120 */ 88, 89, 28, 91, 120, 31, 32, 33, 120, 35, - /* 1130 */ 98, 99, 38, 120, 102, 103, 120, 105, 120, 120, - /* 1140 */ 120, 120, 120, 120, 120, 120, 120, 53, 54, 55, - /* 1150 */ 56, 57, 120, 82, 60, 61, 62, 86, 120, 88, - /* 1160 */ 120, 120, 91, 120, 15, 120, 17, 18, 120, 75, - /* 1170 */ 21, 120, 23, 102, 103, 120, 105, 28, 10, 120, - /* 1180 */ 31, 32, 33, 15, 35, 120, 120, 38, 120, 21, - /* 1190 */ 120, 23, 120, 120, 120, 120, 28, 120, 120, 31, - /* 1200 */ 32, 120, 53, 54, 55, 56, 57, 120, 82, 60, - /* 1210 */ 61, 120, 86, 120, 88, 120, 120, 91, 120, 15, - /* 1220 */ 87, 17, 18, 90, 75, 21, 120, 23, 102, 103, - /* 1230 */ 97, 105, 28, 100, 101, 31, 32, 33, 120, 35, - /* 1240 */ 120, 120, 38, 75, 76, 77, 113, 82, 1, 120, - /* 1250 */ 120, 86, 120, 88, 120, 120, 91, 53, 54, 55, - /* 1260 */ 56, 57, 120, 16, 60, 61, 120, 102, 103, 22, - /* 1270 */ 105, 120, 120, 120, 15, 120, 17, 18, 120, 75, - /* 1280 */ 21, 120, 23, 120, 120, 120, 120, 28, 10, 120, - /* 1290 */ 31, 32, 33, 15, 35, 120, 120, 38, 51, 21, - /* 1300 */ 120, 23, 120, 120, 120, 120, 28, 120, 120, 31, - /* 1310 */ 32, 120, 53, 54, 55, 56, 57, 120, 82, 60, - /* 1320 */ 61, 120, 86, 120, 88, 120, 120, 91, 120, 15, - /* 1330 */ 87, 17, 18, 90, 75, 21, 120, 23, 102, 103, - /* 1340 */ 97, 105, 28, 100, 101, 31, 32, 33, 120, 35, - /* 1350 */ 120, 120, 38, 75, 76, 77, 113, 82, 1, 120, - /* 1360 */ 120, 86, 120, 88, 120, 120, 91, 53, 54, 55, - /* 1370 */ 56, 57, 120, 16, 60, 61, 120, 102, 103, 22, - /* 1380 */ 105, 120, 120, 120, 15, 87, 17, 18, 90, 75, - /* 1390 */ 21, 120, 23, 120, 1, 97, 120, 28, 100, 101, - /* 1400 */ 31, 32, 33, 120, 35, 120, 120, 38, 51, 16, - /* 1410 */ 120, 113, 82, 20, 120, 22, 86, 120, 88, 120, - /* 1420 */ 120, 91, 53, 54, 55, 56, 57, 120, 35, 60, - /* 1430 */ 61, 120, 102, 103, 120, 105, 120, 120, 120, 15, - /* 1440 */ 87, 17, 18, 90, 75, 21, 120, 23, 120, 120, - /* 1450 */ 97, 58, 28, 100, 101, 31, 32, 33, 120, 35, - /* 1460 */ 120, 120, 38, 120, 120, 120, 113, 82, 120, 120, - /* 1470 */ 120, 86, 120, 88, 120, 120, 91, 53, 54, 55, - /* 1480 */ 56, 57, 120, 120, 60, 61, 120, 102, 103, 120, - /* 1490 */ 105, 120, 120, 120, 15, 87, 17, 18, 90, 75, - /* 1500 */ 21, 120, 23, 120, 120, 97, 120, 28, 100, 101, - /* 1510 */ 31, 32, 33, 120, 35, 120, 87, 38, 120, 90, - /* 1520 */ 120, 113, 120, 120, 120, 120, 97, 120, 120, 100, - /* 1530 */ 101, 120, 53, 54, 55, 56, 57, 120, 120, 60, - /* 1540 */ 61, 120, 113, 120, 120, 120, 120, 120, 120, 15, - /* 1550 */ 120, 17, 18, 1, 75, 21, 120, 23, 120, 120, - /* 1560 */ 120, 120, 28, 120, 120, 31, 32, 33, 16, 35, - /* 1570 */ 120, 120, 38, 120, 22, 120, 120, 120, 120, 120, - /* 1580 */ 120, 29, 120, 120, 120, 120, 120, 53, 54, 55, - /* 1590 */ 56, 57, 120, 120, 60, 61, 120, 120, 120, 120, - /* 1600 */ 120, 120, 120, 51, 15, 120, 17, 18, 120, 75, - /* 1610 */ 21, 120, 23, 120, 120, 120, 120, 28, 120, 120, - /* 1620 */ 31, 32, 33, 120, 35, 120, 120, 38, 120, 120, - /* 1630 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 1640 */ 120, 120, 53, 54, 55, 56, 57, 120, 120, 60, - /* 1650 */ 61, 120, 120, 120, 120, 120, 120, 120, 120, 15, - /* 1660 */ 120, 17, 18, 120, 75, 21, 120, 23, 120, 120, - /* 1670 */ 120, 120, 28, 120, 120, 31, 32, 33, 120, 35, - /* 1680 */ 120, 120, 38, 120, 120, 120, 120, 120, 120, 120, - /* 1690 */ 120, 120, 120, 120, 120, 120, 120, 53, 54, 55, - /* 1700 */ 56, 57, 120, 120, 60, 120, 120, 120, 120, 120, - /* 1710 */ 120, 120, 120, 120, 15, 120, 17, 18, 120, 75, - /* 1720 */ 21, 120, 23, 120, 120, 120, 120, 28, 120, 120, - /* 1730 */ 31, 32, 33, 120, 35, 120, 120, 38, 120, 120, - /* 1740 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 1750 */ 120, 120, 53, 54, 55, 56, 57, 120, 120, 60, - /* 1760 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 16, - /* 1770 */ 120, 120, 120, 120, 75, 22, 120, 24, 120, 26, - /* 1780 */ 27, 120, 29, 120, 120, 120, 120, 34, 35, 36, - /* 1790 */ 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - /* 1800 */ 120, 120, 120, 82, 51, 120, 120, 86, 120, 88, - /* 1810 */ 89, 58, 91, 120, 120, 62, 120, 120, 120, 98, - /* 1820 */ 99, 120, 120, 102, 103, 120, 105, 120, 120, 76, - /* 1830 */ 120, 120, 120, 120, 120, 120, 82, 116, 117, 120, - /* 1840 */ 86, 120, 88, 89, 120, 91, 120, 120, 120, 120, - /* 1850 */ 120, 120, 98, 99, 120, 120, 102, 103, 82, 105, - /* 1860 */ 120, 120, 86, 120, 88, 89, 120, 91, 120, 120, - /* 1870 */ 120, 117, 120, 120, 98, 99, 120, 120, 102, 103, - /* 1880 */ 120, 105, 120, 120, 120, 120, 82, 120, 120, 120, - /* 1890 */ 86, 120, 88, 89, 120, 91, 120, 120, 120, 120, - /* 1900 */ 120, 120, 98, 99, 120, 120, 102, 103, 120, 105, - /* 1910 */ 120, 120, 82, 120, 120, 120, 86, 120, 88, 89, - /* 1920 */ 120, 91, 120, 120, 120, 120, 120, 120, 98, 99, - /* 1930 */ 120, 120, 102, 103, 120, 105, 82, 120, 120, 120, - /* 1940 */ 86, 120, 88, 89, 120, 91, 120, 120, 120, 120, - /* 1950 */ 120, 120, 98, 99, 82, 120, 102, 103, 86, 105, - /* 1960 */ 88, 89, 120, 91, 120, 120, 120, 120, 120, 120, - /* 1970 */ 98, 99, 120, 120, 102, 103, 82, 105, 120, 120, - /* 1980 */ 86, 120, 88, 89, 120, 91, 120, 120, 120, 120, - /* 1990 */ 120, 120, 98, 99, 120, 120, 102, 103, 120, 105, - /* 2000 */ 120, 82, 120, 120, 120, 86, 120, 88, 89, 120, - /* 2010 */ 91, 120, 120, 120, 120, 120, 120, 98, 99, 82, - /* 2020 */ 120, 102, 103, 86, 105, 88, 89, 120, 91, 120, - /* 2030 */ 120, 120, 120, 120, 120, 98, 99, 82, 120, 102, - /* 2040 */ 103, 86, 105, 88, 89, 120, 91, 120, 120, 120, - /* 2050 */ 120, 120, 120, 98, 99, 120, 120, 102, 103, 82, - /* 2060 */ 105, 120, 120, 86, 120, 88, 89, 120, 91, 120, - /* 2070 */ 120, 120, 120, 120, 120, 98, 99, 120, 120, 102, - /* 2080 */ 103, 120, 105, 120, 82, 120, 120, 120, 86, 120, - /* 2090 */ 88, 89, 120, 91, 120, 120, 120, 120, 120, 120, - /* 2100 */ 98, 99, 82, 120, 102, 103, 86, 105, 88, 89, - /* 2110 */ 120, 91, 120, 120, 120, 120, 120, 120, 98, 99, - /* 2120 */ 82, 120, 102, 103, 86, 105, 88, 89, 120, 91, - /* 2130 */ 120, 120, 120, 120, 120, 120, 98, 99, 120, 120, - /* 2140 */ 102, 103, 82, 105, 120, 120, 86, 120, 88, 89, - /* 2150 */ 120, 91, 120, 120, 120, 120, 120, 120, 98, 99, - /* 2160 */ 120, 120, 102, 103, 120, 105, 120, 82, 120, 120, - /* 2170 */ 120, 86, 120, 88, 89, 120, 91, 120, 120, 120, - /* 2180 */ 120, 120, 120, 98, 99, 82, 120, 102, 103, 86, - /* 2190 */ 105, 88, 89, 120, 91, 120, 120, 120, 120, 120, - /* 2200 */ 120, 98, 99, 82, 120, 102, 103, 86, 105, 88, - /* 2210 */ 89, 120, 91, 120, 120, 120, 120, 120, 120, 98, - /* 2220 */ 99, 120, 120, 102, 103, 82, 105, 120, 120, 86, - /* 2230 */ 120, 88, 89, 120, 91, 120, 120, 120, 120, 120, - /* 2240 */ 120, 98, 99, 120, 120, 102, 103, 120, 105, 120, - /* 2250 */ 82, 120, 120, 120, 86, 120, 88, 89, 120, 91, - /* 2260 */ 120, 120, 120, 120, 120, 120, 98, 99, 82, 120, - /* 2270 */ 102, 103, 86, 105, 88, 89, 120, 91, 120, 120, - /* 2280 */ 120, 120, 120, 120, 98, 99, 82, 120, 102, 103, - /* 2290 */ 86, 105, 88, 89, 120, 91, 120, 120, 120, 120, - /* 2300 */ 120, 120, 98, 99, 120, 120, 102, 103, 82, 105, - /* 2310 */ 120, 120, 86, 120, 88, 89, 120, 91, 120, 120, - /* 2320 */ 120, 120, 120, 120, 98, 99, 120, 120, 102, 103, - /* 2330 */ 120, 105, 120, 82, 120, 120, 120, 86, 120, 88, - /* 2340 */ 89, 120, 91, 120, 120, 120, 120, 120, 120, 98, - /* 2350 */ 99, 82, 120, 102, 103, 86, 105, 88, 89, 120, - /* 2360 */ 91, 120, 120, 120, 120, 120, 120, 98, 99, 82, - /* 2370 */ 120, 102, 103, 86, 105, 88, 89, 120, 91, 120, - /* 2380 */ 120, 120, 120, 120, 120, 98, 99, 120, 120, 102, - /* 2390 */ 103, 82, 105, 120, 120, 86, 120, 88, 89, 120, - /* 2400 */ 91, 120, 120, 120, 120, 120, 120, 98, 99, 120, - /* 2410 */ 120, 102, 103, 120, 105, 120, 82, 120, 120, 120, - /* 2420 */ 86, 120, 88, 89, 120, 91, 120, 120, 120, 120, - /* 2430 */ 120, 120, 98, 99, 82, 120, 102, 103, 86, 105, - /* 2440 */ 88, 89, 120, 91, 120, 120, 120, 120, 120, 120, - /* 2450 */ 98, 99, 82, 120, 102, 103, 86, 105, 88, 89, - /* 2460 */ 120, 91, 120, 120, 120, 120, 120, 120, 98, 99, - /* 2470 */ 120, 120, 102, 103, 82, 105, 120, 120, 86, 120, - /* 2480 */ 88, 89, 120, 91, 120, 120, 120, 120, 120, 120, - /* 2490 */ 98, 99, 120, 120, 102, 103, 120, 105, 120, 82, - /* 2500 */ 120, 120, 120, 86, 120, 88, 89, 120, 91, 120, - /* 2510 */ 120, 120, 120, 120, 120, 98, 99, 82, 120, 102, - /* 2520 */ 103, 86, 105, 88, 89, 120, 91, 120, 120, 120, - /* 2530 */ 120, 120, 120, 98, 99, 82, 120, 102, 103, 86, - /* 2540 */ 105, 88, 82, 120, 91, 120, 86, 120, 88, 120, - /* 2550 */ 120, 91, 99, 120, 120, 102, 103, 120, 105, 99, - /* 2560 */ 120, 120, 102, 103, 120, 105, -); - const YY_SHIFT_USE_DFLT = -9; - const YY_SHIFT_MAX = 250; - static public $yy_shift_ofst = array( - /* 0 */ 1, 1424, 1259, 1149, 1259, 1149, 1149, 1424, 1094, 1149, - /* 10 */ 1149, 1479, 1149, 1589, 1534, 1149, 1149, 1149, 1314, 1149, - /* 20 */ 1149, 1149, 1149, 1149, 1369, 1149, 1149, 1149, 1149, 1314, - /* 30 */ 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, - /* 40 */ 1149, 1149, 1369, 1149, 1204, 1204, 1644, 1699, 1699, 1699, - /* 50 */ 1699, 1699, 1699, 147, 221, -1, 73, 718, 718, 718, - /* 60 */ 768, 818, 644, 594, 345, 271, 419, 942, 469, 520, - /* 70 */ 868, 992, 992, 992, 992, 992, 992, 992, 992, 992, - /* 80 */ 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, - /* 90 */ 1030, 1030, 1393, 1357, 233, 1, 1278, 150, 5, 308, - /* 100 */ 308, 311, 358, 310, 233, 44, 233, 1168, 46, 1552, - /* 110 */ 263, 1247, 226, 231, 71, 16, -2, 299, 182, 181, - /* 120 */ 282, 163, 719, 459, 560, 532, 44, 460, 559, 581, - /* 130 */ 460, 460, 460, 44, 563, 460, 632, 586, 548, 532, - /* 140 */ 459, 460, 460, 460, 460, 701, 701, 701, 683, 700, - /* 150 */ 701, 701, 701, 701, 684, 701, 684, -9, 66, 111, - /* 160 */ 3, 357, 359, 382, 381, 606, 439, 417, 509, 439, - /* 170 */ 439, 530, 508, 458, 207, 431, 480, 507, 506, 483, - /* 180 */ 439, 457, 432, 439, 529, 433, 385, 383, 727, 684, - /* 190 */ 701, 684, 727, 701, 684, 538, 222, -8, -8, -9, - /* 200 */ -9, -9, -9, 1753, 72, 116, 216, 120, 123, 74, - /* 210 */ 74, 141, 552, 32, 315, 306, 329, 90, 413, 366, - /* 220 */ 682, 616, 657, 659, 658, 655, 656, 661, 662, 641, - /* 230 */ 681, 680, 640, 695, 654, 652, 621, 602, 571, 557, - /* 240 */ 324, 538, 608, 307, 630, 595, 653, 619, 626, 623, - /* 250 */ 598, -); - const YY_REDUCE_USE_DFLT = -81; - const YY_REDUCE_MAX = 202; - static public $yy_reduce_ofst = array( - /* 0 */ 22, 1721, 68, 339, 266, -6, 142, 1754, 862, 2020, - /* 10 */ 514, 1977, 1776, 2103, 1919, 1872, 1804, 1830, 2121, 2392, - /* 20 */ 2186, 2287, 2269, 2168, 2435, 2143, 639, 1955, 2085, 1937, - /* 30 */ 1032, 2060, 2038, 1894, 1854, 2002, 2352, 2417, 2370, 2334, - /* 40 */ 2204, 2226, 2251, 2309, 2460, 2453, 1071, 1126, 1275, 1385, - /* 50 */ 1330, 1236, 1165, 1353, 1408, 1243, 1429, 1298, 1133, 1353, - /* 60 */ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - /* 70 */ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - /* 80 */ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - /* 90 */ 61, 61, 186, 139, 112, -80, 214, -10, 342, 337, - /* 100 */ 269, 96, 309, 335, 384, 210, 407, 490, -57, -35, - /* 110 */ 270, -35, -35, 628, 270, 270, 170, -35, 528, 170, - /* 120 */ 528, 466, -35, 444, 170, 513, 435, 561, 519, 463, - /* 130 */ 519, 637, 395, 537, 861, 631, 533, 519, -35, 519, - /* 140 */ 542, 860, 685, 638, 503, -35, -35, -35, 346, 349, - /* 150 */ -35, -35, -35, -35, 170, -35, 196, -35, 635, 636, - /* 160 */ 604, 604, 604, 604, 604, 618, 599, 642, 604, 599, - /* 170 */ 599, 604, 604, 604, 618, 604, 604, 604, 604, 604, - /* 180 */ 599, 604, 604, 599, 604, 604, 604, 604, 634, 624, - /* 190 */ 618, 624, 634, 618, 624, 617, 43, -64, 159, 21, - /* 200 */ 169, 151, 183, -); - static public $yyExpectedTokens = array( - /* 0 */ array(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 21, 23, 28, 31, 32, ), - /* 1 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 2 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 3 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 4 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 5 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 6 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 7 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 8 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 62, 75, ), - /* 9 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 10 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 11 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 12 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 13 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 14 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 15 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 16 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 17 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 18 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 19 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 20 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 21 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 22 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 23 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 24 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 25 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 26 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 27 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 28 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 29 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 30 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 31 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 32 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 33 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 34 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 35 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 36 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 37 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 38 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 39 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 40 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 41 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 42 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 43 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 44 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 45 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 61, 75, ), - /* 46 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 47 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 48 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 49 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 50 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 51 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 52 */ array(15, 17, 18, 21, 23, 28, 31, 32, 33, 35, 38, 53, 54, 55, 56, 57, 60, 75, ), - /* 53 */ array(1, 16, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 54 */ array(1, 16, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 55 */ array(1, 16, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 56 */ array(1, 22, 27, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 57 */ array(1, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 58 */ array(1, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 59 */ array(1, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 60 */ array(1, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 61 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 62 */ array(1, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 63 */ array(1, 16, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 64 */ array(1, 16, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 65 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, ), - /* 66 */ array(1, 16, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 67 */ array(1, 16, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 68 */ array(1, 29, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 69 */ array(1, 24, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 70 */ array(1, 2, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 71 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 72 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 73 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 74 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 75 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 76 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 77 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 78 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 79 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 80 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 81 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 82 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 83 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 84 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 85 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 86 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 87 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 88 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 89 */ array(1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 90 */ array(37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 91 */ array(37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, ), - /* 92 */ array(1, 16, 20, 22, 35, 58, ), - /* 93 */ array(1, 16, 22, 51, ), - /* 94 */ array(1, 22, ), - /* 95 */ array(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 21, 23, 28, 31, 32, ), - /* 96 */ array(10, 15, 21, 23, 28, 31, 32, 75, 76, 77, ), - /* 97 */ array(15, 18, 22, 30, ), - /* 98 */ array(15, 18, 22, 30, ), - /* 99 */ array(15, 18, 22, ), - /* 100 */ array(15, 18, 22, ), - /* 101 */ array(20, 56, 61, ), - /* 102 */ array(1, 16, 22, ), - /* 103 */ array(17, 18, 60, ), - /* 104 */ array(1, 22, ), - /* 105 */ array(17, 35, ), - /* 106 */ array(1, 22, ), - /* 107 */ array(10, 15, 21, 23, 28, 31, 32, 75, 76, 77, ), - /* 108 */ array(4, 5, 6, 7, 8, 12, 13, 14, ), - /* 109 */ array(1, 16, 22, 29, 51, ), - /* 110 */ array(15, 18, 19, 59, ), - /* 111 */ array(1, 16, 22, 51, ), - /* 112 */ array(1, 16, 22, 51, ), - /* 113 */ array(15, 18, 19, 25, ), - /* 114 */ array(15, 18, 19, ), - /* 115 */ array(15, 18, 59, ), - /* 116 */ array(19, 20, 58, ), - /* 117 */ array(1, 30, 51, ), - /* 118 */ array(16, 22, 25, ), - /* 119 */ array(19, 20, 58, ), - /* 120 */ array(16, 22, 25, ), - /* 121 */ array(1, 16, 20, ), - /* 122 */ array(1, 16, 51, ), - /* 123 */ array(17, 18, ), - /* 124 */ array(20, 58, ), - /* 125 */ array(15, 18, ), - /* 126 */ array(17, 35, ), - /* 127 */ array(15, 18, ), - /* 128 */ array(15, 18, ), - /* 129 */ array(1, 16, ), - /* 130 */ array(15, 18, ), - /* 131 */ array(15, 18, ), - /* 132 */ array(15, 18, ), - /* 133 */ array(17, 35, ), - /* 134 */ array(15, 18, ), - /* 135 */ array(15, 18, ), - /* 136 */ array(16, 22, ), - /* 137 */ array(15, 18, ), - /* 138 */ array(1, 51, ), - /* 139 */ array(15, 18, ), - /* 140 */ array(17, 18, ), - /* 141 */ array(15, 18, ), - /* 142 */ array(15, 18, ), - /* 143 */ array(15, 18, ), - /* 144 */ array(15, 18, ), - /* 145 */ array(1, ), - /* 146 */ array(1, ), - /* 147 */ array(1, ), - /* 148 */ array(22, ), - /* 149 */ array(22, ), - /* 150 */ array(1, ), - /* 151 */ array(1, ), - /* 152 */ array(1, ), - /* 153 */ array(1, ), - /* 154 */ array(20, ), - /* 155 */ array(1, ), - /* 156 */ array(20, ), - /* 157 */ array(), - /* 158 */ array(15, 18, 59, ), - /* 159 */ array(15, 17, 18, ), - /* 160 */ array(16, 22, ), - /* 161 */ array(16, 22, ), - /* 162 */ array(16, 22, ), - /* 163 */ array(16, 22, ), - /* 164 */ array(16, 22, ), - /* 165 */ array(1, 16, ), - /* 166 */ array(56, 61, ), - /* 167 */ array(15, 35, ), - /* 168 */ array(16, 22, ), - /* 169 */ array(56, 61, ), - /* 170 */ array(56, 61, ), - /* 171 */ array(16, 22, ), - /* 172 */ array(16, 22, ), - /* 173 */ array(16, 22, ), - /* 174 */ array(1, 16, ), - /* 175 */ array(16, 22, ), - /* 176 */ array(16, 22, ), - /* 177 */ array(16, 22, ), - /* 178 */ array(16, 22, ), - /* 179 */ array(16, 22, ), - /* 180 */ array(56, 61, ), - /* 181 */ array(16, 22, ), - /* 182 */ array(16, 22, ), - /* 183 */ array(56, 61, ), - /* 184 */ array(16, 22, ), - /* 185 */ array(16, 22, ), - /* 186 */ array(16, 22, ), - /* 187 */ array(16, 22, ), - /* 188 */ array(2, ), - /* 189 */ array(20, ), - /* 190 */ array(1, ), - /* 191 */ array(20, ), - /* 192 */ array(2, ), - /* 193 */ array(1, ), - /* 194 */ array(20, ), - /* 195 */ array(35, ), - /* 196 */ array(13, ), - /* 197 */ array(22, ), - /* 198 */ array(22, ), - /* 199 */ array(), - /* 200 */ array(), - /* 201 */ array(), - /* 202 */ array(), - /* 203 */ array(16, 22, 24, 26, 27, 29, 34, 35, 36, 51, 58, 62, 76, ), - /* 204 */ array(16, 19, 22, 35, 58, ), - /* 205 */ array(15, 17, 18, 33, ), - /* 206 */ array(16, 22, 35, 58, ), - /* 207 */ array(35, 56, 58, 62, ), - /* 208 */ array(30, 35, 58, ), - /* 209 */ array(35, 58, ), - /* 210 */ array(35, 58, ), - /* 211 */ array(34, 36, ), - /* 212 */ array(2, 19, ), - /* 213 */ array(25, 76, ), - /* 214 */ array(34, 36, ), - /* 215 */ array(19, 56, ), - /* 216 */ array(24, 34, ), - /* 217 */ array(34, 62, ), - /* 218 */ array(18, 59, ), - /* 219 */ array(34, 36, ), - /* 220 */ array(18, ), - /* 221 */ array(60, ), - /* 222 */ array(22, ), - /* 223 */ array(18, ), - /* 224 */ array(17, ), - /* 225 */ array(18, ), - /* 226 */ array(18, ), - /* 227 */ array(17, ), - /* 228 */ array(33, ), - /* 229 */ array(62, ), - /* 230 */ array(18, ), - /* 231 */ array(18, ), - /* 232 */ array(56, ), - /* 233 */ array(2, ), - /* 234 */ array(18, ), - /* 235 */ array(19, ), - /* 236 */ array(2, ), - /* 237 */ array(22, ), - /* 238 */ array(35, ), - /* 239 */ array(18, ), - /* 240 */ array(36, ), - /* 241 */ array(35, ), - /* 242 */ array(18, ), - /* 243 */ array(17, ), - /* 244 */ array(17, ), - /* 245 */ array(60, ), - /* 246 */ array(17, ), - /* 247 */ array(33, ), - /* 248 */ array(25, ), - /* 249 */ array(26, ), - /* 250 */ array(52, ), - /* 251 */ array(), - /* 252 */ array(), - /* 253 */ array(), - /* 254 */ array(), - /* 255 */ array(), - /* 256 */ array(), - /* 257 */ array(), - /* 258 */ array(), - /* 259 */ array(), - /* 260 */ array(), - /* 261 */ array(), - /* 262 */ array(), - /* 263 */ array(), - /* 264 */ array(), - /* 265 */ array(), - /* 266 */ array(), - /* 267 */ array(), - /* 268 */ array(), - /* 269 */ array(), - /* 270 */ array(), - /* 271 */ array(), - /* 272 */ array(), - /* 273 */ array(), - /* 274 */ array(), - /* 275 */ array(), - /* 276 */ array(), - /* 277 */ array(), - /* 278 */ array(), - /* 279 */ array(), - /* 280 */ array(), - /* 281 */ array(), - /* 282 */ array(), - /* 283 */ array(), - /* 284 */ array(), - /* 285 */ array(), - /* 286 */ array(), - /* 287 */ array(), - /* 288 */ array(), - /* 289 */ array(), - /* 290 */ array(), - /* 291 */ array(), - /* 292 */ array(), - /* 293 */ array(), - /* 294 */ array(), - /* 295 */ array(), - /* 296 */ array(), - /* 297 */ array(), - /* 298 */ array(), - /* 299 */ array(), - /* 300 */ array(), - /* 301 */ array(), - /* 302 */ array(), - /* 303 */ array(), - /* 304 */ array(), - /* 305 */ array(), - /* 306 */ array(), - /* 307 */ array(), - /* 308 */ array(), - /* 309 */ array(), - /* 310 */ array(), - /* 311 */ array(), - /* 312 */ array(), - /* 313 */ array(), - /* 314 */ array(), - /* 315 */ array(), - /* 316 */ array(), - /* 317 */ array(), - /* 318 */ array(), - /* 319 */ array(), - /* 320 */ array(), - /* 321 */ array(), - /* 322 */ array(), - /* 323 */ array(), - /* 324 */ array(), - /* 325 */ array(), - /* 326 */ array(), - /* 327 */ array(), - /* 328 */ array(), - /* 329 */ array(), - /* 330 */ array(), - /* 331 */ array(), - /* 332 */ array(), - /* 333 */ array(), - /* 334 */ array(), - /* 335 */ array(), - /* 336 */ array(), - /* 337 */ array(), - /* 338 */ array(), - /* 339 */ array(), - /* 340 */ array(), - /* 341 */ array(), - /* 342 */ array(), - /* 343 */ array(), - /* 344 */ array(), - /* 345 */ array(), - /* 346 */ array(), - /* 347 */ array(), - /* 348 */ array(), - /* 349 */ array(), - /* 350 */ array(), - /* 351 */ array(), - /* 352 */ array(), - /* 353 */ array(), - /* 354 */ array(), - /* 355 */ array(), - /* 356 */ array(), - /* 357 */ array(), - /* 358 */ array(), - /* 359 */ array(), - /* 360 */ array(), - /* 361 */ array(), - /* 362 */ array(), - /* 363 */ array(), - /* 364 */ array(), - /* 365 */ array(), - /* 366 */ array(), - /* 367 */ array(), - /* 368 */ array(), - /* 369 */ array(), - /* 370 */ array(), - /* 371 */ array(), - /* 372 */ array(), - /* 373 */ array(), - /* 374 */ array(), - /* 375 */ array(), - /* 376 */ array(), - /* 377 */ array(), - /* 378 */ array(), - /* 379 */ array(), - /* 380 */ array(), - /* 381 */ array(), - /* 382 */ array(), -); - static public $yy_default = array( - /* 0 */ 386, 565, 582, 536, 582, 536, 536, 582, 582, 582, - /* 10 */ 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, - /* 20 */ 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, - /* 30 */ 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, - /* 40 */ 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, - /* 50 */ 582, 582, 582, 582, 582, 582, 444, 444, 444, 444, - /* 60 */ 582, 582, 582, 582, 582, 582, 582, 582, 449, 582, - /* 70 */ 582, 446, 535, 428, 534, 566, 567, 478, 477, 468, - /* 80 */ 465, 449, 568, 455, 469, 474, 473, 470, 454, 451, - /* 90 */ 482, 481, 493, 457, 444, 383, 582, 444, 444, 444, - /* 100 */ 444, 548, 464, 582, 444, 582, 444, 582, 582, 457, - /* 110 */ 509, 457, 457, 582, 509, 509, 502, 457, 483, 502, - /* 120 */ 483, 582, 457, 582, 502, 582, 582, 582, 582, 582, - /* 130 */ 582, 582, 509, 582, 582, 582, 582, 582, 457, 582, - /* 140 */ 582, 582, 582, 582, 582, 480, 461, 484, 444, 444, - /* 150 */ 486, 485, 462, 467, 502, 460, 545, 543, 510, 582, - /* 160 */ 582, 582, 582, 582, 582, 582, 527, 509, 582, 526, - /* 170 */ 529, 582, 582, 582, 582, 582, 582, 582, 582, 582, - /* 180 */ 507, 582, 582, 528, 582, 582, 582, 582, 537, 523, - /* 190 */ 501, 546, 538, 464, 549, 509, 401, 581, 581, 542, - /* 200 */ 509, 509, 542, 459, 493, 582, 493, 493, 493, 493, - /* 210 */ 479, 582, 521, 483, 582, 489, 582, 582, 582, 582, - /* 220 */ 582, 582, 582, 582, 582, 582, 582, 582, 491, 582, - /* 230 */ 582, 582, 489, 521, 582, 582, 521, 582, 547, 582, - /* 240 */ 582, 521, 582, 582, 582, 582, 582, 582, 483, 452, - /* 250 */ 495, 544, 514, 516, 515, 518, 495, 531, 532, 409, - /* 260 */ 395, 431, 394, 425, 396, 430, 398, 456, 397, 426, - /* 270 */ 393, 387, 385, 384, 388, 389, 392, 391, 390, 399, - /* 280 */ 400, 435, 442, 436, 410, 423, 424, 441, 443, 522, - /* 290 */ 408, 407, 404, 403, 402, 405, 453, 429, 580, 406, - /* 300 */ 440, 573, 558, 559, 560, 561, 557, 556, 553, 554, - /* 310 */ 555, 463, 492, 540, 539, 411, 525, 488, 490, 500, - /* 320 */ 504, 552, 551, 508, 503, 459, 466, 499, 496, 497, - /* 330 */ 511, 471, 472, 498, 513, 550, 512, 476, 519, 458, - /* 340 */ 475, 576, 487, 575, 578, 579, 572, 574, 494, 434, - /* 350 */ 570, 571, 433, 562, 530, 505, 506, 427, 533, 564, - /* 360 */ 563, 432, 569, 421, 415, 416, 439, 414, 541, 412, - /* 370 */ 413, 577, 438, 417, 521, 422, 520, 420, 437, 524, - /* 380 */ 418, 419, 517, -); - const YYNOCODE = 121; - const YYSTACKDEPTH = 100; - const YYNSTATE = 383; - const YYNRULE = 199; - const YYERRORSYMBOL = 78; - const YYERRSYMDT = 'yy0'; - const YYFALLBACK = 0; - static public $yyFallback = array( - ); - static function Trace($TraceFILE, $zTracePrompt) + } + + /** + * insert PHP code in current buffer + * + * @param string $code + */ + public function insertPhpCode($code) + { + $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Tag($this, $code)); + } + + /** + * error rundown + * + */ + public function errorRunDown() + { + while ($this->yystack !== array()) { + $this->yy_pop_parser_stack(); + } + if (is_resource($this->yyTraceFILE)) { + fclose($this->yyTraceFILE); + } + } + + /** + * merge PHP code with prefix code and return parse tree tag object + * + * @param string $code + * + * @return Smarty_Internal_ParseTree_Tag + */ + public function mergePrefixCode($code) + { + $tmp = ''; + foreach ($this->compiler->prefix_code as $preCode) { + $tmp .= $preCode; + } + $this->compiler->prefix_code = array(); + $tmp .= $code; + return new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp, true)); + } + + public function Trace($TraceFILE, $zTracePrompt) { if (!$TraceFILE) { $zTracePrompt = 0; } elseif (!$zTracePrompt) { $TraceFILE = 0; } - self::$yyTraceFILE = $TraceFILE; - self::$yyTracePrompt = $zTracePrompt; - } - - static function PrintTrace() - { - self::$yyTraceFILE = fopen('php://output', 'w'); - self::$yyTracePrompt = '
'; - } - - static public $yyTraceFILE; - static public $yyTracePrompt; - public $yyidx; /* Index of top element in stack */ - public $yyerrcnt; /* Shifts left before out of the error */ - public $yystack = array(); /* The parser's stack */ - - public $yyTokenName = array( - '$', 'VERT', 'COLON', 'COMMENT', - 'PHPSTARTTAG', 'PHPENDTAG', 'ASPSTARTTAG', 'ASPENDTAG', - 'FAKEPHPSTARTTAG', 'XMLTAG', 'OTHER', 'LINEBREAK', - 'LITERALSTART', 'LITERALEND', 'LITERAL', 'LDEL', - 'RDEL', 'DOLLAR', 'ID', 'EQUAL', - 'PTR', 'LDELIF', 'SPACE', 'LDELFOR', - 'SEMICOLON', 'INCDEC', 'TO', 'STEP', - 'LDELFOREACH', 'AS', 'APTR', 'SMARTYBLOCKCHILD', - 'LDELSLASH', 'INTEGER', 'COMMA', 'OPENP', - 'CLOSEP', 'MATH', 'UNIMATH', 'ANDSYM', - 'ISIN', 'ISDIVBY', 'ISNOTDIVBY', 'ISEVEN', - 'ISNOTEVEN', 'ISEVENBY', 'ISNOTEVENBY', 'ISODD', - 'ISNOTODD', 'ISODDBY', 'ISNOTODDBY', 'INSTANCEOF', - 'QMARK', 'NOT', 'TYPECAST', 'HEX', - 'DOT', 'SINGLEQUOTESTRING', 'DOUBLECOLON', 'AT', - 'HATCH', 'OPENB', 'CLOSEB', 'EQUALS', - 'NOTEQUALS', 'GREATERTHAN', 'LESSTHAN', 'GREATEREQUAL', - 'LESSEQUAL', 'IDENTITY', 'NONEIDENTITY', 'MOD', - 'LAND', 'LOR', 'LXOR', 'QUOTE', - 'BACKTICK', 'DOLLARID', 'error', 'start', - 'template', 'template_element', 'smartytag', 'literal', - 'literal_elements', 'literal_element', 'value', 'attributes', - 'variable', 'expr', 'modifierlist', 'varindexed', - 'statement', 'statements', 'optspace', 'varvar', - 'foraction', 'attribute', 'ternary', 'array', - 'ifcond', 'lop', 'function', 'doublequoted_with_quotes', - 'static_class_access', 'object', 'arrayindex', 'indexdef', - 'varvarele', 'objectchain', 'objectelement', 'method', - 'params', 'modifier', 'modparameters', 'modparameter', - 'arrayelements', 'arrayelement', 'doublequoted', 'doublequotedcontent', - ); + $this->yyTraceFILE = $TraceFILE; + $this->yyTracePrompt = $zTracePrompt; + } - static public $yyRuleName = array( - /* 0 */ "start ::= template", - /* 1 */ "template ::= template_element", - /* 2 */ "template ::= template template_element", - /* 3 */ "template ::=", - /* 4 */ "template_element ::= smartytag", - /* 5 */ "template_element ::= COMMENT", - /* 6 */ "template_element ::= literal", - /* 7 */ "template_element ::= PHPSTARTTAG", - /* 8 */ "template_element ::= PHPENDTAG", - /* 9 */ "template_element ::= ASPSTARTTAG", - /* 10 */ "template_element ::= ASPENDTAG", - /* 11 */ "template_element ::= FAKEPHPSTARTTAG", - /* 12 */ "template_element ::= XMLTAG", - /* 13 */ "template_element ::= OTHER", - /* 14 */ "template_element ::= LINEBREAK", - /* 15 */ "literal ::= LITERALSTART LITERALEND", - /* 16 */ "literal ::= LITERALSTART literal_elements LITERALEND", - /* 17 */ "literal_elements ::= literal_elements literal_element", - /* 18 */ "literal_elements ::=", - /* 19 */ "literal_element ::= literal", - /* 20 */ "literal_element ::= LITERAL", - /* 21 */ "literal_element ::= PHPSTARTTAG", - /* 22 */ "literal_element ::= FAKEPHPSTARTTAG", - /* 23 */ "literal_element ::= PHPENDTAG", - /* 24 */ "literal_element ::= ASPSTARTTAG", - /* 25 */ "literal_element ::= ASPENDTAG", - /* 26 */ "smartytag ::= LDEL value RDEL", - /* 27 */ "smartytag ::= LDEL value attributes RDEL", - /* 28 */ "smartytag ::= LDEL variable attributes RDEL", - /* 29 */ "smartytag ::= LDEL expr modifierlist attributes RDEL", - /* 30 */ "smartytag ::= LDEL expr attributes RDEL", - /* 31 */ "smartytag ::= LDEL DOLLAR ID EQUAL value RDEL", - /* 32 */ "smartytag ::= LDEL DOLLAR ID EQUAL expr RDEL", - /* 33 */ "smartytag ::= LDEL DOLLAR ID EQUAL expr attributes RDEL", - /* 34 */ "smartytag ::= LDEL varindexed EQUAL expr attributes RDEL", - /* 35 */ "smartytag ::= LDEL ID attributes RDEL", - /* 36 */ "smartytag ::= LDEL ID RDEL", - /* 37 */ "smartytag ::= LDEL ID PTR ID attributes RDEL", - /* 38 */ "smartytag ::= LDEL ID modifierlist attributes RDEL", - /* 39 */ "smartytag ::= LDEL ID PTR ID modifierlist attributes RDEL", - /* 40 */ "smartytag ::= LDELIF SPACE expr RDEL", - /* 41 */ "smartytag ::= LDELIF SPACE expr attributes RDEL", - /* 42 */ "smartytag ::= LDELIF SPACE statement RDEL", - /* 43 */ "smartytag ::= LDELIF SPACE statement attributes RDEL", - /* 44 */ "smartytag ::= LDELFOR SPACE statements SEMICOLON optspace expr SEMICOLON optspace DOLLAR varvar foraction attributes RDEL", - /* 45 */ "foraction ::= EQUAL expr", - /* 46 */ "foraction ::= INCDEC", - /* 47 */ "smartytag ::= LDELFOR SPACE statement TO expr attributes RDEL", - /* 48 */ "smartytag ::= LDELFOR SPACE statement TO expr STEP expr attributes RDEL", - /* 49 */ "smartytag ::= LDELFOREACH attributes RDEL", - /* 50 */ "smartytag ::= LDELFOREACH SPACE value AS DOLLAR varvar attributes RDEL", - /* 51 */ "smartytag ::= LDELFOREACH SPACE value AS DOLLAR varvar APTR DOLLAR varvar attributes RDEL", - /* 52 */ "smartytag ::= LDELFOREACH SPACE expr AS DOLLAR varvar attributes RDEL", - /* 53 */ "smartytag ::= LDELFOREACH SPACE expr AS DOLLAR varvar APTR DOLLAR varvar attributes RDEL", - /* 54 */ "smartytag ::= SMARTYBLOCKCHILD", - /* 55 */ "smartytag ::= LDELSLASH ID RDEL", - /* 56 */ "smartytag ::= LDELSLASH ID modifierlist RDEL", - /* 57 */ "smartytag ::= LDELSLASH ID PTR ID RDEL", - /* 58 */ "smartytag ::= LDELSLASH ID PTR ID modifierlist RDEL", - /* 59 */ "attributes ::= attributes attribute", - /* 60 */ "attributes ::= attribute", - /* 61 */ "attributes ::=", - /* 62 */ "attribute ::= SPACE ID EQUAL ID", - /* 63 */ "attribute ::= SPACE ID EQUAL expr", - /* 64 */ "attribute ::= SPACE ID EQUAL value", - /* 65 */ "attribute ::= SPACE ID", - /* 66 */ "attribute ::= SPACE expr", - /* 67 */ "attribute ::= SPACE value", - /* 68 */ "attribute ::= SPACE INTEGER EQUAL expr", - /* 69 */ "statements ::= statement", - /* 70 */ "statements ::= statements COMMA statement", - /* 71 */ "statement ::= DOLLAR varvar EQUAL expr", - /* 72 */ "statement ::= varindexed EQUAL expr", - /* 73 */ "statement ::= OPENP statement CLOSEP", - /* 74 */ "expr ::= value", - /* 75 */ "expr ::= ternary", - /* 76 */ "expr ::= DOLLAR ID COLON ID", - /* 77 */ "expr ::= expr MATH value", - /* 78 */ "expr ::= expr UNIMATH value", - /* 79 */ "expr ::= expr ANDSYM value", - /* 80 */ "expr ::= array", - /* 81 */ "expr ::= expr modifierlist", - /* 82 */ "expr ::= expr ifcond expr", - /* 83 */ "expr ::= expr ISIN array", - /* 84 */ "expr ::= expr ISIN value", - /* 85 */ "expr ::= expr lop expr", - /* 86 */ "expr ::= expr ISDIVBY expr", - /* 87 */ "expr ::= expr ISNOTDIVBY expr", - /* 88 */ "expr ::= expr ISEVEN", - /* 89 */ "expr ::= expr ISNOTEVEN", - /* 90 */ "expr ::= expr ISEVENBY expr", - /* 91 */ "expr ::= expr ISNOTEVENBY expr", - /* 92 */ "expr ::= expr ISODD", - /* 93 */ "expr ::= expr ISNOTODD", - /* 94 */ "expr ::= expr ISODDBY expr", - /* 95 */ "expr ::= expr ISNOTODDBY expr", - /* 96 */ "expr ::= value INSTANCEOF ID", - /* 97 */ "expr ::= value INSTANCEOF value", - /* 98 */ "ternary ::= OPENP expr CLOSEP QMARK DOLLAR ID COLON expr", - /* 99 */ "ternary ::= OPENP expr CLOSEP QMARK expr COLON expr", - /* 100 */ "value ::= variable", - /* 101 */ "value ::= UNIMATH value", - /* 102 */ "value ::= NOT value", - /* 103 */ "value ::= TYPECAST value", - /* 104 */ "value ::= variable INCDEC", - /* 105 */ "value ::= HEX", - /* 106 */ "value ::= INTEGER", - /* 107 */ "value ::= INTEGER DOT INTEGER", - /* 108 */ "value ::= INTEGER DOT", - /* 109 */ "value ::= DOT INTEGER", - /* 110 */ "value ::= ID", - /* 111 */ "value ::= function", - /* 112 */ "value ::= OPENP expr CLOSEP", - /* 113 */ "value ::= SINGLEQUOTESTRING", - /* 114 */ "value ::= doublequoted_with_quotes", - /* 115 */ "value ::= ID DOUBLECOLON static_class_access", - /* 116 */ "value ::= varindexed DOUBLECOLON static_class_access", - /* 117 */ "value ::= smartytag", - /* 118 */ "value ::= value modifierlist", - /* 119 */ "variable ::= varindexed", - /* 120 */ "variable ::= DOLLAR varvar AT ID", - /* 121 */ "variable ::= object", - /* 122 */ "variable ::= HATCH ID HATCH", - /* 123 */ "variable ::= HATCH variable HATCH", - /* 124 */ "varindexed ::= DOLLAR varvar arrayindex", - /* 125 */ "arrayindex ::= arrayindex indexdef", - /* 126 */ "arrayindex ::=", - /* 127 */ "indexdef ::= DOT DOLLAR varvar", - /* 128 */ "indexdef ::= DOT DOLLAR varvar AT ID", - /* 129 */ "indexdef ::= DOT ID", - /* 130 */ "indexdef ::= DOT INTEGER", - /* 131 */ "indexdef ::= DOT LDEL expr RDEL", - /* 132 */ "indexdef ::= OPENB ID CLOSEB", - /* 133 */ "indexdef ::= OPENB ID DOT ID CLOSEB", - /* 134 */ "indexdef ::= OPENB expr CLOSEB", - /* 135 */ "indexdef ::= OPENB CLOSEB", - /* 136 */ "varvar ::= varvarele", - /* 137 */ "varvar ::= varvar varvarele", - /* 138 */ "varvarele ::= ID", - /* 139 */ "varvarele ::= LDEL expr RDEL", - /* 140 */ "object ::= varindexed objectchain", - /* 141 */ "objectchain ::= objectelement", - /* 142 */ "objectchain ::= objectchain objectelement", - /* 143 */ "objectelement ::= PTR ID arrayindex", - /* 144 */ "objectelement ::= PTR DOLLAR varvar arrayindex", - /* 145 */ "objectelement ::= PTR LDEL expr RDEL arrayindex", - /* 146 */ "objectelement ::= PTR ID LDEL expr RDEL arrayindex", - /* 147 */ "objectelement ::= PTR method", - /* 148 */ "function ::= ID OPENP params CLOSEP", - /* 149 */ "method ::= ID OPENP params CLOSEP", - /* 150 */ "method ::= DOLLAR ID OPENP params CLOSEP", - /* 151 */ "params ::= params COMMA expr", - /* 152 */ "params ::= expr", - /* 153 */ "params ::=", - /* 154 */ "modifierlist ::= modifierlist modifier modparameters", - /* 155 */ "modifierlist ::= modifier modparameters", - /* 156 */ "modifier ::= VERT AT ID", - /* 157 */ "modifier ::= VERT ID", - /* 158 */ "modparameters ::= modparameters modparameter", - /* 159 */ "modparameters ::=", - /* 160 */ "modparameter ::= COLON value", - /* 161 */ "modparameter ::= COLON array", - /* 162 */ "static_class_access ::= method", - /* 163 */ "static_class_access ::= method objectchain", - /* 164 */ "static_class_access ::= ID", - /* 165 */ "static_class_access ::= DOLLAR ID arrayindex", - /* 166 */ "static_class_access ::= DOLLAR ID arrayindex objectchain", - /* 167 */ "ifcond ::= EQUALS", - /* 168 */ "ifcond ::= NOTEQUALS", - /* 169 */ "ifcond ::= GREATERTHAN", - /* 170 */ "ifcond ::= LESSTHAN", - /* 171 */ "ifcond ::= GREATEREQUAL", - /* 172 */ "ifcond ::= LESSEQUAL", - /* 173 */ "ifcond ::= IDENTITY", - /* 174 */ "ifcond ::= NONEIDENTITY", - /* 175 */ "ifcond ::= MOD", - /* 176 */ "lop ::= LAND", - /* 177 */ "lop ::= LOR", - /* 178 */ "lop ::= LXOR", - /* 179 */ "array ::= OPENB arrayelements CLOSEB", - /* 180 */ "arrayelements ::= arrayelement", - /* 181 */ "arrayelements ::= arrayelements COMMA arrayelement", - /* 182 */ "arrayelements ::=", - /* 183 */ "arrayelement ::= value APTR expr", - /* 184 */ "arrayelement ::= ID APTR expr", - /* 185 */ "arrayelement ::= expr", - /* 186 */ "doublequoted_with_quotes ::= QUOTE QUOTE", - /* 187 */ "doublequoted_with_quotes ::= QUOTE doublequoted QUOTE", - /* 188 */ "doublequoted ::= doublequoted doublequotedcontent", - /* 189 */ "doublequoted ::= doublequotedcontent", - /* 190 */ "doublequotedcontent ::= BACKTICK variable BACKTICK", - /* 191 */ "doublequotedcontent ::= BACKTICK expr BACKTICK", - /* 192 */ "doublequotedcontent ::= DOLLARID", - /* 193 */ "doublequotedcontent ::= LDEL variable RDEL", - /* 194 */ "doublequotedcontent ::= LDEL expr RDEL", - /* 195 */ "doublequotedcontent ::= smartytag", - /* 196 */ "doublequotedcontent ::= OTHER", - /* 197 */ "optspace ::= SPACE", - /* 198 */ "optspace ::=", - ); + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } - function tokenName($tokenType) + public function tokenName($tokenType) { if ($tokenType === 0) { return 'End of Input'; } if ($tokenType > 0 && $tokenType < count($this->yyTokenName)) { - return $this->yyTokenName[$tokenType]; + return $this->yyTokenName[ $tokenType ]; } else { - return "Unknown"; - } - } - - static function yy_destructor($yymajor, $yypminor) - { - switch ($yymajor) { - default: break; /* If no destructor action specified: do nothing */ + return 'Unknown'; } } - function yy_pop_parser_stack() + public function yy_pop_parser_stack() { - if (!count($this->yystack)) { + if (empty($this->yystack)) { return; } $yytos = array_pop($this->yystack); - if (self::$yyTraceFILE && $this->yyidx >= 0) { - fwrite(self::$yyTraceFILE, - self::$yyTracePrompt . 'Popping ' . $this->yyTokenName[$yytos->major] . - "\n"); + if ($this->yyTraceFILE && $this->yyidx >= 0) { + fwrite($this->yyTraceFILE, + $this->yyTracePrompt . 'Popping ' . $this->yyTokenName[ $yytos->major ] . + "\n"); } $yymajor = $yytos->major; self::yy_destructor($yymajor, $yytos->minor); @@ -1511,22 +1869,30 @@ function yy_pop_parser_stack() return $yymajor; } - function __destruct() + public function __destruct() { - while ($this->yystack !== Array()) { + while ($this->yystack !== array()) { $this->yy_pop_parser_stack(); } - if (is_resource(self::$yyTraceFILE)) { - fclose(self::$yyTraceFILE); + if (is_resource($this->yyTraceFILE)) { + fclose($this->yyTraceFILE); } } - function yy_get_expected_tokens($token) + public function yy_get_expected_tokens($token) { - $state = $this->yystack[$this->yyidx]->stateno; - $expected = self::$yyExpectedTokens[$state]; - if (in_array($token, self::$yyExpectedTokens[$state], true)) { - return $expected; + static $res3 = array(); + static $res4 = array(); + $state = $this->yystack[ $this->yyidx ]->stateno; + $expected = self::$yyExpectedTokens[ $state ]; + if (isset($res3[ $state ][ $token ])) { + if ($res3[ $state ][ $token ]) { + return $expected; + } + } else { + if ($res3[ $state ][ $token ] = in_array($token, self::$yyExpectedTokens[ $state ], true)) { + return $expected; + } } $stack = $this->yystack; $yyidx = $this->yyidx; @@ -1536,7 +1902,7 @@ function yy_get_expected_tokens($token) // reduce action $done = 0; do { - if ($done++ == 100) { + if ($done++ === 100) { $this->yyidx = $yyidx; $this->yystack = $stack; // too much recursion prevents proper detection @@ -1544,17 +1910,25 @@ function yy_get_expected_tokens($token) return array_unique($expected); } $yyruleno = $yyact - self::YYNSTATE; - $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][ 1 ]; $nextstate = $this->yy_find_reduce_action( - $this->yystack[$this->yyidx]->stateno, - self::$yyRuleInfo[$yyruleno]['lhs']); - if (isset(self::$yyExpectedTokens[$nextstate])) { - $expected = array_merge($expected, self::$yyExpectedTokens[$nextstate]); - if (in_array($token, - self::$yyExpectedTokens[$nextstate], true)) { - $this->yyidx = $yyidx; - $this->yystack = $stack; - return array_unique($expected); + $this->yystack[ $this->yyidx ]->stateno, + self::$yyRuleInfo[ $yyruleno ][ 0 ]); + if (isset(self::$yyExpectedTokens[ $nextstate ])) { + $expected = array_merge($expected, self::$yyExpectedTokens[ $nextstate ]); + if (isset($res4[ $nextstate ][ $token ])) { + if ($res4[ $nextstate ][ $token ]) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } else { + if ($res4[ $nextstate ][ $token ] = + in_array($token, self::$yyExpectedTokens[ $nextstate ], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } } } if ($nextstate < self::YYNSTATE) { @@ -1562,10 +1936,10 @@ function yy_get_expected_tokens($token) $this->yyidx++; $x = new TP_yyStackEntry; $x->stateno = $nextstate; - $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; - $this->yystack[$this->yyidx] = $x; + $x->major = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $this->yystack[ $this->yyidx ] = $x; continue 2; - } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) { $this->yyidx = $yyidx; $this->yystack = $stack; // the last token was just ignored, we can't accept @@ -1584,19 +1958,27 @@ function yy_get_expected_tokens($token) } break; } while (true); - $this->yyidx = $yyidx; - $this->yystack = $stack; + $this->yyidx = $yyidx; + $this->yystack = $stack; return array_unique($expected); } - function yy_is_expected_token($token) + public function yy_is_expected_token($token) { + static $res = array(); + static $res2 = array(); if ($token === 0) { return true; // 0 is not part of this } - $state = $this->yystack[$this->yyidx]->stateno; - if (in_array($token, self::$yyExpectedTokens[$state], true)) { - return true; + $state = $this->yystack[ $this->yyidx ]->stateno; + if (isset($res[ $state ][ $token ])) { + if ($res[ $state ][ $token ]) { + return true; + } + } else { + if ($res[ $state ][ $token ] = in_array($token, self::$yyExpectedTokens[ $state ], true)) { + return true; + } } $stack = $this->yystack; $yyidx = $this->yyidx; @@ -1606,7 +1988,7 @@ function yy_is_expected_token($token) // reduce action $done = 0; do { - if ($done++ == 100) { + if ($done++ === 100) { $this->yyidx = $yyidx; $this->yystack = $stack; // too much recursion prevents proper detection @@ -1614,25 +1996,34 @@ function yy_is_expected_token($token) return true; } $yyruleno = $yyact - self::YYNSTATE; - $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][ 1 ]; $nextstate = $this->yy_find_reduce_action( - $this->yystack[$this->yyidx]->stateno, - self::$yyRuleInfo[$yyruleno]['lhs']); - if (isset(self::$yyExpectedTokens[$nextstate]) && - in_array($token, self::$yyExpectedTokens[$nextstate], true)) { - $this->yyidx = $yyidx; - $this->yystack = $stack; - return true; + $this->yystack[ $this->yyidx ]->stateno, + self::$yyRuleInfo[ $yyruleno ][ 0 ]); + if (isset($res2[ $nextstate ][ $token ])) { + if ($res2[ $nextstate ][ $token ]) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + } else { + if ($res2[ $nextstate ][ $token ] = + (isset(self::$yyExpectedTokens[ $nextstate ]) && + in_array($token, self::$yyExpectedTokens[ $nextstate ], true))) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } } if ($nextstate < self::YYNSTATE) { // we need to shift a non-terminal $this->yyidx++; $x = new TP_yyStackEntry; $x->stateno = $nextstate; - $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; - $this->yystack[$this->yyidx] = $x; + $x->major = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $this->yystack[ $this->yyidx ] = $x; continue 2; - } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) { $this->yyidx = $yyidx; $this->yystack = $stack; if (!$token) { @@ -1660,1223 +2051,1491 @@ function yy_is_expected_token($token) return true; } - function yy_find_shift_action($iLookAhead) + public function yy_find_shift_action($iLookAhead) { - $stateno = $this->yystack[$this->yyidx]->stateno; - + $stateno = $this->yystack[ $this->yyidx ]->stateno; /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ - if (!isset(self::$yy_shift_ofst[$stateno])) { + if (!isset(self::$yy_shift_ofst[ $stateno ])) { // no shift actions - return self::$yy_default[$stateno]; + return self::$yy_default[ $stateno ]; } - $i = self::$yy_shift_ofst[$stateno]; + $i = self::$yy_shift_ofst[ $stateno ]; if ($i === self::YY_SHIFT_USE_DFLT) { - return self::$yy_default[$stateno]; + return self::$yy_default[ $stateno ]; } - if ($iLookAhead == self::YYNOCODE) { + if ($iLookAhead === self::YYNOCODE) { return self::YY_NO_ACTION; } $i += $iLookAhead; if ($i < 0 || $i >= self::YY_SZ_ACTTAB || - self::$yy_lookahead[$i] != $iLookAhead) { + self::$yy_lookahead[ $i ] != $iLookAhead) { if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback) - && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) { - if (self::$yyTraceFILE) { - fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " . - $this->yyTokenName[$iLookAhead] . " => " . - $this->yyTokenName[$iFallback] . "\n"); + && ($iFallback = self::$yyFallback[ $iLookAhead ]) != 0) { + if ($this->yyTraceFILE) { + fwrite($this->yyTraceFILE, $this->yyTracePrompt . 'FALLBACK ' . + $this->yyTokenName[ $iLookAhead ] . ' => ' . + $this->yyTokenName[ $iFallback ] . "\n"); } return $this->yy_find_shift_action($iFallback); } - return self::$yy_default[$stateno]; + return self::$yy_default[ $stateno ]; } else { - return self::$yy_action[$i]; + return self::$yy_action[ $i ]; } } - function yy_find_reduce_action($stateno, $iLookAhead) + public function yy_find_reduce_action($stateno, $iLookAhead) { /* $stateno = $this->yystack[$this->yyidx]->stateno; */ - - if (!isset(self::$yy_reduce_ofst[$stateno])) { - return self::$yy_default[$stateno]; + if (!isset(self::$yy_reduce_ofst[ $stateno ])) { + return self::$yy_default[ $stateno ]; } - $i = self::$yy_reduce_ofst[$stateno]; - if ($i == self::YY_REDUCE_USE_DFLT) { - return self::$yy_default[$stateno]; + $i = self::$yy_reduce_ofst[ $stateno ]; + if ($i === self::YY_REDUCE_USE_DFLT) { + return self::$yy_default[ $stateno ]; } - if ($iLookAhead == self::YYNOCODE) { + if ($iLookAhead === self::YYNOCODE) { return self::YY_NO_ACTION; } $i += $iLookAhead; if ($i < 0 || $i >= self::YY_SZ_ACTTAB || - self::$yy_lookahead[$i] != $iLookAhead) { - return self::$yy_default[$stateno]; + self::$yy_lookahead[ $i ] != $iLookAhead) { + return self::$yy_default[ $stateno ]; } else { - return self::$yy_action[$i]; + return self::$yy_action[ $i ]; } } - function yy_shift($yyNewState, $yyMajor, $yypMinor) + // line 234 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_shift($yyNewState, $yyMajor, $yypMinor) { $this->yyidx++; if ($this->yyidx >= self::YYSTACKDEPTH) { $this->yyidx--; - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sStack Overflow!\n", $this->yyTracePrompt); } while ($this->yyidx >= 0) { $this->yy_pop_parser_stack(); } -#line 73 "smarty_internal_templateparser.y" - - $this->internalError = true; - $this->compiler->trigger_template_error("Stack overflow in template parser"); -#line 1731 "smarty_internal_templateparser.php" + // line 221 "../smarty/lexer/smarty_internal_templateparser.y" + $this->internalError = true; + $this->compiler->trigger_template_error('Stack overflow in template parser'); return; } $yytos = new TP_yyStackEntry; $yytos->stateno = $yyNewState; $yytos->major = $yyMajor; $yytos->minor = $yypMinor; - array_push($this->yystack, $yytos); - if (self::$yyTraceFILE && $this->yyidx > 0) { - fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt, + $this->yystack[] = $yytos; + if ($this->yyTraceFILE && $this->yyidx > 0) { + fprintf($this->yyTraceFILE, "%sShift %d\n", $this->yyTracePrompt, $yyNewState); - fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt); - for($i = 1; $i <= $this->yyidx; $i++) { - fprintf(self::$yyTraceFILE, " %s", - $this->yyTokenName[$this->yystack[$i]->major]); + fprintf($this->yyTraceFILE, "%sStack:", $this->yyTracePrompt); + for ($i = 1; $i <= $this->yyidx; $i++) { + fprintf($this->yyTraceFILE, " %s", + $this->yyTokenName[ $this->yystack[ $i ]->major ]); } - fwrite(self::$yyTraceFILE,"\n"); + fwrite($this->yyTraceFILE, "\n"); } } - static public $yyRuleInfo = array( - array( 'lhs' => 79, 'rhs' => 1 ), - array( 'lhs' => 80, 'rhs' => 1 ), - array( 'lhs' => 80, 'rhs' => 2 ), - array( 'lhs' => 80, 'rhs' => 0 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 81, 'rhs' => 1 ), - array( 'lhs' => 83, 'rhs' => 2 ), - array( 'lhs' => 83, 'rhs' => 3 ), - array( 'lhs' => 84, 'rhs' => 2 ), - array( 'lhs' => 84, 'rhs' => 0 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 85, 'rhs' => 1 ), - array( 'lhs' => 82, 'rhs' => 3 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 5 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 6 ), - array( 'lhs' => 82, 'rhs' => 6 ), - array( 'lhs' => 82, 'rhs' => 7 ), - array( 'lhs' => 82, 'rhs' => 6 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 3 ), - array( 'lhs' => 82, 'rhs' => 6 ), - array( 'lhs' => 82, 'rhs' => 5 ), - array( 'lhs' => 82, 'rhs' => 7 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 5 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 5 ), - array( 'lhs' => 82, 'rhs' => 13 ), - array( 'lhs' => 96, 'rhs' => 2 ), - array( 'lhs' => 96, 'rhs' => 1 ), - array( 'lhs' => 82, 'rhs' => 7 ), - array( 'lhs' => 82, 'rhs' => 9 ), - array( 'lhs' => 82, 'rhs' => 3 ), - array( 'lhs' => 82, 'rhs' => 8 ), - array( 'lhs' => 82, 'rhs' => 11 ), - array( 'lhs' => 82, 'rhs' => 8 ), - array( 'lhs' => 82, 'rhs' => 11 ), - array( 'lhs' => 82, 'rhs' => 1 ), - array( 'lhs' => 82, 'rhs' => 3 ), - array( 'lhs' => 82, 'rhs' => 4 ), - array( 'lhs' => 82, 'rhs' => 5 ), - array( 'lhs' => 82, 'rhs' => 6 ), - array( 'lhs' => 87, 'rhs' => 2 ), - array( 'lhs' => 87, 'rhs' => 1 ), - array( 'lhs' => 87, 'rhs' => 0 ), - array( 'lhs' => 97, 'rhs' => 4 ), - array( 'lhs' => 97, 'rhs' => 4 ), - array( 'lhs' => 97, 'rhs' => 4 ), - array( 'lhs' => 97, 'rhs' => 2 ), - array( 'lhs' => 97, 'rhs' => 2 ), - array( 'lhs' => 97, 'rhs' => 2 ), - array( 'lhs' => 97, 'rhs' => 4 ), - array( 'lhs' => 93, 'rhs' => 1 ), - array( 'lhs' => 93, 'rhs' => 3 ), - array( 'lhs' => 92, 'rhs' => 4 ), - array( 'lhs' => 92, 'rhs' => 3 ), - array( 'lhs' => 92, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 1 ), - array( 'lhs' => 89, 'rhs' => 1 ), - array( 'lhs' => 89, 'rhs' => 4 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 1 ), - array( 'lhs' => 89, 'rhs' => 2 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 2 ), - array( 'lhs' => 89, 'rhs' => 2 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 2 ), - array( 'lhs' => 89, 'rhs' => 2 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 89, 'rhs' => 3 ), - array( 'lhs' => 98, 'rhs' => 8 ), - array( 'lhs' => 98, 'rhs' => 7 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 3 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 3 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 3 ), - array( 'lhs' => 86, 'rhs' => 3 ), - array( 'lhs' => 86, 'rhs' => 1 ), - array( 'lhs' => 86, 'rhs' => 2 ), - array( 'lhs' => 88, 'rhs' => 1 ), - array( 'lhs' => 88, 'rhs' => 4 ), - array( 'lhs' => 88, 'rhs' => 1 ), - array( 'lhs' => 88, 'rhs' => 3 ), - array( 'lhs' => 88, 'rhs' => 3 ), - array( 'lhs' => 91, 'rhs' => 3 ), - array( 'lhs' => 106, 'rhs' => 2 ), - array( 'lhs' => 106, 'rhs' => 0 ), - array( 'lhs' => 107, 'rhs' => 3 ), - array( 'lhs' => 107, 'rhs' => 5 ), - array( 'lhs' => 107, 'rhs' => 2 ), - array( 'lhs' => 107, 'rhs' => 2 ), - array( 'lhs' => 107, 'rhs' => 4 ), - array( 'lhs' => 107, 'rhs' => 3 ), - array( 'lhs' => 107, 'rhs' => 5 ), - array( 'lhs' => 107, 'rhs' => 3 ), - array( 'lhs' => 107, 'rhs' => 2 ), - array( 'lhs' => 95, 'rhs' => 1 ), - array( 'lhs' => 95, 'rhs' => 2 ), - array( 'lhs' => 108, 'rhs' => 1 ), - array( 'lhs' => 108, 'rhs' => 3 ), - array( 'lhs' => 105, 'rhs' => 2 ), - array( 'lhs' => 109, 'rhs' => 1 ), - array( 'lhs' => 109, 'rhs' => 2 ), - array( 'lhs' => 110, 'rhs' => 3 ), - array( 'lhs' => 110, 'rhs' => 4 ), - array( 'lhs' => 110, 'rhs' => 5 ), - array( 'lhs' => 110, 'rhs' => 6 ), - array( 'lhs' => 110, 'rhs' => 2 ), - array( 'lhs' => 102, 'rhs' => 4 ), - array( 'lhs' => 111, 'rhs' => 4 ), - array( 'lhs' => 111, 'rhs' => 5 ), - array( 'lhs' => 112, 'rhs' => 3 ), - array( 'lhs' => 112, 'rhs' => 1 ), - array( 'lhs' => 112, 'rhs' => 0 ), - array( 'lhs' => 90, 'rhs' => 3 ), - array( 'lhs' => 90, 'rhs' => 2 ), - array( 'lhs' => 113, 'rhs' => 3 ), - array( 'lhs' => 113, 'rhs' => 2 ), - array( 'lhs' => 114, 'rhs' => 2 ), - array( 'lhs' => 114, 'rhs' => 0 ), - array( 'lhs' => 115, 'rhs' => 2 ), - array( 'lhs' => 115, 'rhs' => 2 ), - array( 'lhs' => 104, 'rhs' => 1 ), - array( 'lhs' => 104, 'rhs' => 2 ), - array( 'lhs' => 104, 'rhs' => 1 ), - array( 'lhs' => 104, 'rhs' => 3 ), - array( 'lhs' => 104, 'rhs' => 4 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 100, 'rhs' => 1 ), - array( 'lhs' => 101, 'rhs' => 1 ), - array( 'lhs' => 101, 'rhs' => 1 ), - array( 'lhs' => 101, 'rhs' => 1 ), - array( 'lhs' => 99, 'rhs' => 3 ), - array( 'lhs' => 116, 'rhs' => 1 ), - array( 'lhs' => 116, 'rhs' => 3 ), - array( 'lhs' => 116, 'rhs' => 0 ), - array( 'lhs' => 117, 'rhs' => 3 ), - array( 'lhs' => 117, 'rhs' => 3 ), - array( 'lhs' => 117, 'rhs' => 1 ), - array( 'lhs' => 103, 'rhs' => 2 ), - array( 'lhs' => 103, 'rhs' => 3 ), - array( 'lhs' => 118, 'rhs' => 2 ), - array( 'lhs' => 118, 'rhs' => 1 ), - array( 'lhs' => 119, 'rhs' => 3 ), - array( 'lhs' => 119, 'rhs' => 3 ), - array( 'lhs' => 119, 'rhs' => 1 ), - array( 'lhs' => 119, 'rhs' => 3 ), - array( 'lhs' => 119, 'rhs' => 3 ), - array( 'lhs' => 119, 'rhs' => 1 ), - array( 'lhs' => 119, 'rhs' => 1 ), - array( 'lhs' => 94, 'rhs' => 1 ), - array( 'lhs' => 94, 'rhs' => 0 ), - ); - - static public $yyReduceMap = array( - 0 => 0, - 1 => 1, - 2 => 1, - 4 => 4, - 5 => 5, - 6 => 6, - 7 => 7, - 8 => 8, - 9 => 9, - 10 => 10, - 11 => 11, - 12 => 12, - 13 => 13, - 14 => 14, - 15 => 15, - 18 => 15, - 16 => 16, - 17 => 17, - 101 => 17, - 103 => 17, - 104 => 17, - 163 => 17, - 19 => 19, - 20 => 19, - 74 => 19, - 75 => 19, - 100 => 19, - 105 => 19, - 106 => 19, - 111 => 19, - 113 => 19, - 114 => 19, - 121 => 19, - 162 => 19, - 180 => 19, - 21 => 21, - 22 => 21, - 23 => 23, - 24 => 24, - 25 => 25, - 26 => 26, - 27 => 27, - 28 => 27, - 30 => 27, - 29 => 29, - 31 => 31, - 32 => 31, - 33 => 33, - 34 => 34, - 35 => 35, - 36 => 36, - 37 => 37, - 38 => 38, - 39 => 39, - 40 => 40, - 42 => 40, - 41 => 41, - 43 => 41, - 44 => 44, - 45 => 45, - 46 => 46, - 66 => 46, - 67 => 46, - 164 => 46, - 185 => 46, - 47 => 47, - 48 => 48, - 49 => 49, - 50 => 50, - 51 => 51, - 52 => 52, - 53 => 53, - 54 => 54, - 55 => 55, - 56 => 56, - 57 => 57, - 58 => 58, - 59 => 59, - 60 => 60, - 69 => 60, - 152 => 60, - 156 => 60, - 61 => 61, - 153 => 61, - 62 => 62, - 63 => 63, - 64 => 63, - 65 => 65, - 68 => 68, - 70 => 70, - 71 => 71, - 72 => 71, - 73 => 73, - 76 => 76, - 77 => 77, - 78 => 77, - 79 => 77, - 80 => 80, - 136 => 80, - 197 => 80, - 81 => 81, - 118 => 81, - 82 => 82, - 85 => 82, - 96 => 82, - 83 => 83, - 84 => 84, - 86 => 86, - 87 => 87, - 88 => 88, - 93 => 88, - 89 => 89, - 92 => 89, - 90 => 90, - 95 => 90, - 91 => 91, - 94 => 91, - 97 => 97, - 98 => 98, - 99 => 99, - 102 => 102, - 107 => 107, - 108 => 108, - 109 => 109, - 110 => 110, - 112 => 112, - 115 => 115, - 116 => 116, - 117 => 117, - 119 => 119, - 120 => 120, - 122 => 122, - 123 => 123, - 124 => 124, - 125 => 125, - 126 => 126, - 127 => 127, - 128 => 128, - 129 => 129, - 130 => 130, - 131 => 131, - 134 => 131, - 132 => 132, - 133 => 133, - 135 => 135, - 137 => 137, - 138 => 138, - 139 => 139, - 140 => 140, - 141 => 141, - 142 => 142, - 143 => 143, - 144 => 144, - 145 => 145, - 146 => 146, - 147 => 147, - 148 => 148, - 149 => 149, - 150 => 150, - 151 => 151, - 154 => 154, - 155 => 155, - 157 => 157, - 158 => 158, - 159 => 159, - 160 => 160, - 161 => 160, - 165 => 165, - 166 => 166, - 167 => 167, - 168 => 168, - 169 => 169, - 170 => 170, - 171 => 171, - 172 => 172, - 173 => 173, - 174 => 174, - 175 => 175, - 176 => 176, - 177 => 177, - 178 => 178, - 179 => 179, - 181 => 181, - 182 => 182, - 183 => 183, - 184 => 184, - 186 => 186, - 187 => 187, - 188 => 188, - 189 => 189, - 190 => 190, - 191 => 190, - 193 => 190, - 192 => 192, - 194 => 194, - 195 => 195, - 196 => 196, - 198 => 198, - ); -#line 84 "smarty_internal_templateparser.y" - function yy_r0(){ $this->_retvalue = $this->root_buffer->to_smarty_php(); } -#line 2155 "smarty_internal_templateparser.php" -#line 90 "smarty_internal_templateparser.y" - function yy_r1(){ $this->current_buffer->append_subtree($this->yystack[$this->yyidx + 0]->minor); } -#line 2158 "smarty_internal_templateparser.php" -#line 102 "smarty_internal_templateparser.y" - function yy_r4(){ - if ($this->compiler->has_code) { - $tmp =''; foreach ($this->compiler->prefix_code as $code) {$tmp.=$code;} $this->compiler->prefix_code=array(); - $this->_retvalue = new _smarty_tag($this, $this->compiler->processNocacheCode($tmp.$this->yystack[$this->yyidx + 0]->minor,true)); - } else { - $this->_retvalue = new _smarty_tag($this, $this->yystack[$this->yyidx + 0]->minor); - } - $this->compiler->has_variable_string = false; - $this->block_nesting_level = count($this->compiler->_tag_stack); - } -#line 2170 "smarty_internal_templateparser.php" -#line 114 "smarty_internal_templateparser.y" - function yy_r5(){ $this->_retvalue = new _smarty_tag($this, ''); } -#line 2173 "smarty_internal_templateparser.php" -#line 117 "smarty_internal_templateparser.y" - function yy_r6(){ $this->_retvalue = new _smarty_text($this, $this->yystack[$this->yyidx + 0]->minor); } -#line 2176 "smarty_internal_templateparser.php" -#line 120 "smarty_internal_templateparser.y" - function yy_r7(){ - if ($this->php_handling == Smarty::PHP_PASSTHRU) { - $this->_retvalue = new _smarty_text($this, self::escape_start_tag($this->yystack[$this->yyidx + 0]->minor)); - } elseif ($this->php_handling == Smarty::PHP_QUOTE) { - $this->_retvalue = new _smarty_text($this, htmlspecialchars($this->yystack[$this->yyidx + 0]->minor, ENT_QUOTES)); - }elseif ($this->php_handling == Smarty::PHP_ALLOW) { - $this->_retvalue = new _smarty_text($this, $this->compiler->processNocacheCode('php_handling == Smarty::PHP_REMOVE) { - $this->_retvalue = new _smarty_text($this, ''); - } - } -#line 2189 "smarty_internal_templateparser.php" -#line 132 "smarty_internal_templateparser.y" - function yy_r8(){if ($this->is_xml) { - $this->compiler->tag_nocache = true; - $this->is_xml = true; - $this->_retvalue = new _smarty_text($this, $this->compiler->processNocacheCode("';?>", $this->compiler, true)); - }elseif ($this->php_handling == Smarty::PHP_PASSTHRU) { - $this->_retvalue = new _smarty_text($this, '?>'); - } elseif ($this->php_handling == Smarty::PHP_QUOTE) { - $this->_retvalue = new _smarty_text($this, htmlspecialchars('?>', ENT_QUOTES)); - }elseif ($this->php_handling == Smarty::PHP_ALLOW) { - $this->_retvalue = new _smarty_text($this, $this->compiler->processNocacheCode('?>', true)); - }elseif ($this->php_handling == Smarty::PHP_REMOVE) { - $this->_retvalue = new _smarty_text($this, ''); - } - } -#line 2205 "smarty_internal_templateparser.php" -#line 148 "smarty_internal_templateparser.y" - function yy_r9(){ - if ($this->php_handling == Smarty::PHP_PASSTHRU) { - $this->_retvalue = new _smarty_text($this, '<%'); - } elseif ($this->php_handling == Smarty::PHP_QUOTE) { - $this->_retvalue = new _smarty_text($this, htmlspecialchars($this->yystack[$this->yyidx + 0]->minor, ENT_QUOTES)); - }elseif ($this->php_handling == Smarty::PHP_ALLOW) { - if ($this->asp_tags) { - $this->_retvalue = new _smarty_text($this, $this->compiler->processNocacheCode('<%', true)); - } else { - $this->_retvalue = new _smarty_text($this, '<%'); - } - }elseif ($this->php_handling == Smarty::PHP_REMOVE) { - if ($this->asp_tags) { - $this->_retvalue = new _smarty_text($this, ''); - } else { - $this->_retvalue = new _smarty_text($this, '<%'); - } - } - } -#line 2226 "smarty_internal_templateparser.php" -#line 169 "smarty_internal_templateparser.y" - function yy_r10(){ - if ($this->php_handling == Smarty::PHP_PASSTHRU) { - $this->_retvalue = new _smarty_text($this, '%>'); - } elseif ($this->php_handling == Smarty::PHP_QUOTE) { - $this->_retvalue = new _smarty_text($this, htmlspecialchars('%>', ENT_QUOTES)); - }elseif ($this->php_handling == Smarty::PHP_ALLOW) { - if ($this->asp_tags) { - $this->_retvalue = new _smarty_text($this, $this->compiler->processNocacheCode('%>', true)); - } else { - $this->_retvalue = new _smarty_text($this, '%>'); - } - }elseif ($this->php_handling == Smarty::PHP_REMOVE) { - if ($this->asp_tags) { - $this->_retvalue = new _smarty_text($this, ''); - } else { - $this->_retvalue = new _smarty_text($this, '%>'); - } - } - } -#line 2247 "smarty_internal_templateparser.php" -#line 189 "smarty_internal_templateparser.y" - function yy_r11(){if ($this->lex->strip) { - $this->_retvalue = new _smarty_text($this, preg_replace('![\$this->yystack[$this->yyidx + 0]->minor ]*[\r\n]+[\$this->yystack[$this->yyidx + 0]->minor ]*!', '', self::escape_start_tag($this->yystack[$this->yyidx + 0]->minor))); - } else { - $this->_retvalue = new _smarty_text($this, self::escape_start_tag($this->yystack[$this->yyidx + 0]->minor)); - } - } -#line 2255 "smarty_internal_templateparser.php" -#line 197 "smarty_internal_templateparser.y" - function yy_r12(){ $this->compiler->tag_nocache = true; $this->is_xml = true; $this->_retvalue = new _smarty_text($this, $this->compiler->processNocacheCode("", $this->compiler, true)); } -#line 2258 "smarty_internal_templateparser.php" -#line 200 "smarty_internal_templateparser.y" - function yy_r13(){if ($this->lex->strip) { - $this->_retvalue = new _smarty_text($this, preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $this->yystack[$this->yyidx + 0]->minor)); - } else { - $this->_retvalue = new _smarty_text($this, $this->yystack[$this->yyidx + 0]->minor); - } - } -#line 2266 "smarty_internal_templateparser.php" -#line 206 "smarty_internal_templateparser.y" - function yy_r14(){ - $this->_retvalue = new _smarty_linebreak($this, $this->yystack[$this->yyidx + 0]->minor); - } -#line 2271 "smarty_internal_templateparser.php" -#line 211 "smarty_internal_templateparser.y" - function yy_r15(){ $this->_retvalue = ''; } -#line 2274 "smarty_internal_templateparser.php" -#line 212 "smarty_internal_templateparser.y" - function yy_r16(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; } -#line 2277 "smarty_internal_templateparser.php" -#line 214 "smarty_internal_templateparser.y" - function yy_r17(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; } -#line 2280 "smarty_internal_templateparser.php" -#line 217 "smarty_internal_templateparser.y" - function yy_r19(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 2283 "smarty_internal_templateparser.php" -#line 219 "smarty_internal_templateparser.y" - function yy_r21(){ $this->_retvalue = self::escape_start_tag($this->yystack[$this->yyidx + 0]->minor); } -#line 2286 "smarty_internal_templateparser.php" -#line 221 "smarty_internal_templateparser.y" - function yy_r23(){ $this->_retvalue = self::escape_end_tag($this->yystack[$this->yyidx + 0]->minor); } -#line 2289 "smarty_internal_templateparser.php" -#line 222 "smarty_internal_templateparser.y" - function yy_r24(){ $this->_retvalue = '<%'; } -#line 2292 "smarty_internal_templateparser.php" -#line 223 "smarty_internal_templateparser.y" - function yy_r25(){ $this->_retvalue = '%>'; } -#line 2295 "smarty_internal_templateparser.php" -#line 231 "smarty_internal_templateparser.y" - function yy_r26(){ $this->_retvalue = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$this->yystack[$this->yyidx + -1]->minor)); } -#line 2298 "smarty_internal_templateparser.php" -#line 232 "smarty_internal_templateparser.y" - function yy_r27(){ $this->_retvalue = $this->compiler->compileTag('private_print_expression',$this->yystack[$this->yyidx + -1]->minor,array('value'=>$this->yystack[$this->yyidx + -2]->minor)); } -#line 2301 "smarty_internal_templateparser.php" -#line 234 "smarty_internal_templateparser.y" - function yy_r29(){ $this->_retvalue = $this->compiler->compileTag('private_print_expression',$this->yystack[$this->yyidx + -1]->minor,array('value'=>$this->yystack[$this->yyidx + -3]->minor,'modifierlist'=>$this->yystack[$this->yyidx + -2]->minor)); } -#line 2304 "smarty_internal_templateparser.php" -#line 242 "smarty_internal_templateparser.y" - function yy_r31(){ $this->_retvalue = $this->compiler->compileTag('assign',array(array('value'=>$this->yystack[$this->yyidx + -1]->minor),array('var'=>"'".$this->yystack[$this->yyidx + -3]->minor."'"))); } -#line 2307 "smarty_internal_templateparser.php" -#line 244 "smarty_internal_templateparser.y" - function yy_r33(){ $this->_retvalue = $this->compiler->compileTag('assign',array_merge(array(array('value'=>$this->yystack[$this->yyidx + -2]->minor),array('var'=>"'".$this->yystack[$this->yyidx + -4]->minor."'")),$this->yystack[$this->yyidx + -1]->minor)); } -#line 2310 "smarty_internal_templateparser.php" -#line 245 "smarty_internal_templateparser.y" - function yy_r34(){ $this->_retvalue = $this->compiler->compileTag('assign',array_merge(array(array('value'=>$this->yystack[$this->yyidx + -2]->minor),array('var'=>$this->yystack[$this->yyidx + -4]->minor['var'])),$this->yystack[$this->yyidx + -1]->minor),array('smarty_internal_index'=>$this->yystack[$this->yyidx + -4]->minor['smarty_internal_index'])); } -#line 2313 "smarty_internal_templateparser.php" -#line 247 "smarty_internal_templateparser.y" - function yy_r35(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -2]->minor,$this->yystack[$this->yyidx + -1]->minor); } -#line 2316 "smarty_internal_templateparser.php" -#line 248 "smarty_internal_templateparser.y" - function yy_r36(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -1]->minor,array()); } -#line 2319 "smarty_internal_templateparser.php" -#line 250 "smarty_internal_templateparser.y" - function yy_r37(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -4]->minor,$this->yystack[$this->yyidx + -1]->minor,array('object_methode'=>$this->yystack[$this->yyidx + -2]->minor)); } -#line 2322 "smarty_internal_templateparser.php" -#line 252 "smarty_internal_templateparser.y" - function yy_r38(){ $this->_retvalue = ''.$this->compiler->compileTag($this->yystack[$this->yyidx + -3]->minor,$this->yystack[$this->yyidx + -1]->minor).'_retvalue .= $this->compiler->compileTag('private_modifier',array(),array('modifierlist'=>$this->yystack[$this->yyidx + -2]->minor,'value'=>'ob_get_clean()')).'?>'; - } -#line 2327 "smarty_internal_templateparser.php" -#line 256 "smarty_internal_templateparser.y" - function yy_r39(){ $this->_retvalue = ''.$this->compiler->compileTag($this->yystack[$this->yyidx + -5]->minor,$this->yystack[$this->yyidx + -1]->minor,array('object_methode'=>$this->yystack[$this->yyidx + -3]->minor)).'_retvalue .= $this->compiler->compileTag('private_modifier',array(),array('modifierlist'=>$this->yystack[$this->yyidx + -2]->minor,'value'=>'ob_get_clean()')).'?>'; - } -#line 2332 "smarty_internal_templateparser.php" -#line 260 "smarty_internal_templateparser.y" - function yy_r40(){ $tag = trim(substr($this->yystack[$this->yyidx + -3]->minor,$this->lex->ldel_length)); $this->_retvalue = $this->compiler->compileTag(($tag == 'else if')? 'elseif' : $tag,array(),array('if condition'=>$this->yystack[$this->yyidx + -1]->minor)); } -#line 2335 "smarty_internal_templateparser.php" -#line 261 "smarty_internal_templateparser.y" - function yy_r41(){ $tag = trim(substr($this->yystack[$this->yyidx + -4]->minor,$this->lex->ldel_length)); $this->_retvalue = $this->compiler->compileTag(($tag == 'else if')? 'elseif' : $tag,$this->yystack[$this->yyidx + -1]->minor,array('if condition'=>$this->yystack[$this->yyidx + -2]->minor)); } -#line 2338 "smarty_internal_templateparser.php" -#line 265 "smarty_internal_templateparser.y" - function yy_r44(){ - $this->_retvalue = $this->compiler->compileTag('for',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('start'=>$this->yystack[$this->yyidx + -10]->minor),array('ifexp'=>$this->yystack[$this->yyidx + -7]->minor),array('var'=>$this->yystack[$this->yyidx + -3]->minor),array('step'=>$this->yystack[$this->yyidx + -2]->minor))),1); } -#line 2342 "smarty_internal_templateparser.php" -#line 268 "smarty_internal_templateparser.y" - function yy_r45(){ $this->_retvalue = '='.$this->yystack[$this->yyidx + 0]->minor; } -#line 2345 "smarty_internal_templateparser.php" -#line 269 "smarty_internal_templateparser.y" - function yy_r46(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 2348 "smarty_internal_templateparser.php" -#line 270 "smarty_internal_templateparser.y" - function yy_r47(){ $this->_retvalue = $this->compiler->compileTag('for',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('start'=>$this->yystack[$this->yyidx + -4]->minor),array('to'=>$this->yystack[$this->yyidx + -2]->minor))),0); } -#line 2351 "smarty_internal_templateparser.php" -#line 271 "smarty_internal_templateparser.y" - function yy_r48(){ $this->_retvalue = $this->compiler->compileTag('for',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('start'=>$this->yystack[$this->yyidx + -6]->minor),array('to'=>$this->yystack[$this->yyidx + -4]->minor),array('step'=>$this->yystack[$this->yyidx + -2]->minor))),0); } -#line 2354 "smarty_internal_templateparser.php" -#line 273 "smarty_internal_templateparser.y" - function yy_r49(){ $this->_retvalue = $this->compiler->compileTag('foreach',$this->yystack[$this->yyidx + -1]->minor); } -#line 2357 "smarty_internal_templateparser.php" -#line 275 "smarty_internal_templateparser.y" - function yy_r50(){ - $this->_retvalue = $this->compiler->compileTag('foreach',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('from'=>$this->yystack[$this->yyidx + -5]->minor),array('item'=>$this->yystack[$this->yyidx + -2]->minor)))); } -#line 2361 "smarty_internal_templateparser.php" -#line 277 "smarty_internal_templateparser.y" - function yy_r51(){ - $this->_retvalue = $this->compiler->compileTag('foreach',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('from'=>$this->yystack[$this->yyidx + -8]->minor),array('item'=>$this->yystack[$this->yyidx + -2]->minor),array('key'=>$this->yystack[$this->yyidx + -5]->minor)))); } -#line 2365 "smarty_internal_templateparser.php" -#line 279 "smarty_internal_templateparser.y" - function yy_r52(){ - $this->_retvalue = $this->compiler->compileTag('foreach',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('from'=>$this->yystack[$this->yyidx + -5]->minor),array('item'=>$this->yystack[$this->yyidx + -2]->minor)))); } -#line 2369 "smarty_internal_templateparser.php" -#line 281 "smarty_internal_templateparser.y" - function yy_r53(){ - $this->_retvalue = $this->compiler->compileTag('foreach',array_merge($this->yystack[$this->yyidx + -1]->minor,array(array('from'=>$this->yystack[$this->yyidx + -8]->minor),array('item'=>$this->yystack[$this->yyidx + -2]->minor),array('key'=>$this->yystack[$this->yyidx + -5]->minor)))); } -#line 2373 "smarty_internal_templateparser.php" -#line 285 "smarty_internal_templateparser.y" - function yy_r54(){ $this->_retvalue = SMARTY_INTERNAL_COMPILE_BLOCK::compileChildBlock($this->compiler); } -#line 2376 "smarty_internal_templateparser.php" -#line 289 "smarty_internal_templateparser.y" - function yy_r55(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -1]->minor.'close',array()); } -#line 2379 "smarty_internal_templateparser.php" -#line 291 "smarty_internal_templateparser.y" - function yy_r56(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -2]->minor.'close',array(),array('modifier_list'=>$this->yystack[$this->yyidx + -1]->minor)); - } -#line 2383 "smarty_internal_templateparser.php" -#line 294 "smarty_internal_templateparser.y" - function yy_r57(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -3]->minor.'close',array(),array('object_methode'=>$this->yystack[$this->yyidx + -1]->minor)); } -#line 2386 "smarty_internal_templateparser.php" -#line 295 "smarty_internal_templateparser.y" - function yy_r58(){ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -4]->minor.'close',array(),array('object_methode'=>$this->yystack[$this->yyidx + -2]->minor, 'modifier_list'=>$this->yystack[$this->yyidx + -1]->minor)); } -#line 2389 "smarty_internal_templateparser.php" -#line 301 "smarty_internal_templateparser.y" - function yy_r59(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; $this->_retvalue[] = $this->yystack[$this->yyidx + 0]->minor; } -#line 2392 "smarty_internal_templateparser.php" -#line 303 "smarty_internal_templateparser.y" - function yy_r60(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor); } -#line 2395 "smarty_internal_templateparser.php" -#line 305 "smarty_internal_templateparser.y" - function yy_r61(){ $this->_retvalue = array(); } -#line 2398 "smarty_internal_templateparser.php" -#line 308 "smarty_internal_templateparser.y" - function yy_r62(){ if (preg_match('~^true$~i', $this->yystack[$this->yyidx + 0]->minor)) { - $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>'true'); - } elseif (preg_match('~^false$~i', $this->yystack[$this->yyidx + 0]->minor)) { - $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>'false'); - } elseif (preg_match('~^null$~i', $this->yystack[$this->yyidx + 0]->minor)) { - $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>'null'); - } else - $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>"'".$this->yystack[$this->yyidx + 0]->minor."'"); } -#line 2408 "smarty_internal_templateparser.php" -#line 316 "smarty_internal_templateparser.y" - function yy_r63(){ $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>$this->yystack[$this->yyidx + 0]->minor); } -#line 2411 "smarty_internal_templateparser.php" -#line 318 "smarty_internal_templateparser.y" - function yy_r65(){ $this->_retvalue = "'".$this->yystack[$this->yyidx + 0]->minor."'"; } -#line 2414 "smarty_internal_templateparser.php" -#line 321 "smarty_internal_templateparser.y" - function yy_r68(){$this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>$this->yystack[$this->yyidx + 0]->minor); } -#line 2417 "smarty_internal_templateparser.php" -#line 328 "smarty_internal_templateparser.y" - function yy_r70(){ $this->yystack[$this->yyidx + -2]->minor[]=$this->yystack[$this->yyidx + 0]->minor; $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor; } -#line 2420 "smarty_internal_templateparser.php" -#line 330 "smarty_internal_templateparser.y" - function yy_r71(){ $this->_retvalue = array('var' => $this->yystack[$this->yyidx + -2]->minor, 'value'=>$this->yystack[$this->yyidx + 0]->minor); } -#line 2423 "smarty_internal_templateparser.php" -#line 332 "smarty_internal_templateparser.y" - function yy_r73(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; } -#line 2426 "smarty_internal_templateparser.php" -#line 343 "smarty_internal_templateparser.y" - function yy_r76(){$this->_retvalue = '$_smarty_tpl->getStreamVariable(\''. $this->yystack[$this->yyidx + -2]->minor .'://'. $this->yystack[$this->yyidx + 0]->minor . '\')'; } -#line 2429 "smarty_internal_templateparser.php" -#line 345 "smarty_internal_templateparser.y" - function yy_r77(){ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor . trim($this->yystack[$this->yyidx + -1]->minor) . $this->yystack[$this->yyidx + 0]->minor; } -#line 2432 "smarty_internal_templateparser.php" -#line 351 "smarty_internal_templateparser.y" - function yy_r80(){$this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 2435 "smarty_internal_templateparser.php" -#line 354 "smarty_internal_templateparser.y" - function yy_r81(){ $this->_retvalue = $this->compiler->compileTag('private_modifier',array(),array('value'=>$this->yystack[$this->yyidx + -1]->minor,'modifierlist'=>$this->yystack[$this->yyidx + 0]->minor)); } -#line 2438 "smarty_internal_templateparser.php" -#line 358 "smarty_internal_templateparser.y" - function yy_r82(){$this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; } -#line 2441 "smarty_internal_templateparser.php" -#line 359 "smarty_internal_templateparser.y" - function yy_r83(){$this->_retvalue = 'in_array('.$this->yystack[$this->yyidx + -2]->minor.','.$this->yystack[$this->yyidx + 0]->minor.')'; } -#line 2444 "smarty_internal_templateparser.php" -#line 360 "smarty_internal_templateparser.y" - function yy_r84(){$this->_retvalue = 'in_array('.$this->yystack[$this->yyidx + -2]->minor.',(array)'.$this->yystack[$this->yyidx + 0]->minor.')'; } -#line 2447 "smarty_internal_templateparser.php" -#line 362 "smarty_internal_templateparser.y" - function yy_r86(){$this->_retvalue = '!('.$this->yystack[$this->yyidx + -2]->minor.' % '.$this->yystack[$this->yyidx + 0]->minor.')'; } -#line 2450 "smarty_internal_templateparser.php" -#line 363 "smarty_internal_templateparser.y" - function yy_r87(){$this->_retvalue = '('.$this->yystack[$this->yyidx + -2]->minor.' % '.$this->yystack[$this->yyidx + 0]->minor.')'; } -#line 2453 "smarty_internal_templateparser.php" -#line 364 "smarty_internal_templateparser.y" - function yy_r88(){$this->_retvalue = '!(1 & '.$this->yystack[$this->yyidx + -1]->minor.')'; } -#line 2456 "smarty_internal_templateparser.php" -#line 365 "smarty_internal_templateparser.y" - function yy_r89(){$this->_retvalue = '(1 & '.$this->yystack[$this->yyidx + -1]->minor.')'; } -#line 2459 "smarty_internal_templateparser.php" -#line 366 "smarty_internal_templateparser.y" - function yy_r90(){$this->_retvalue = '!(1 & '.$this->yystack[$this->yyidx + -2]->minor.' / '.$this->yystack[$this->yyidx + 0]->minor.')'; } -#line 2462 "smarty_internal_templateparser.php" -#line 367 "smarty_internal_templateparser.y" - function yy_r91(){$this->_retvalue = '(1 & '.$this->yystack[$this->yyidx + -2]->minor.' / '.$this->yystack[$this->yyidx + 0]->minor.')'; } -#line 2465 "smarty_internal_templateparser.php" -#line 373 "smarty_internal_templateparser.y" - function yy_r97(){$this->prefix_number++; $this->compiler->prefix_code[] = 'prefix_number.'='.$this->yystack[$this->yyidx + 0]->minor.';?>'; $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + -1]->minor.'$_tmp'.$this->prefix_number; } -#line 2468 "smarty_internal_templateparser.php" -#line 379 "smarty_internal_templateparser.y" - function yy_r98(){ $this->_retvalue = $this->yystack[$this->yyidx + -6]->minor.' ? $_smarty_tpl->getVariable(\''. $this->yystack[$this->yyidx + -2]->minor .'\')->value : '.$this->yystack[$this->yyidx + 0]->minor; $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable('$this->yystack[$this->yyidx + -2]->minor', null, true, false)->nocache; } -#line 2471 "smarty_internal_templateparser.php" -#line 380 "smarty_internal_templateparser.y" - function yy_r99(){ $this->_retvalue = $this->yystack[$this->yyidx + -5]->minor.' ? '.$this->yystack[$this->yyidx + -2]->minor.' : '.$this->yystack[$this->yyidx + 0]->minor; } -#line 2474 "smarty_internal_templateparser.php" -#line 387 "smarty_internal_templateparser.y" - function yy_r102(){ $this->_retvalue = '!'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2477 "smarty_internal_templateparser.php" -#line 393 "smarty_internal_templateparser.y" - function yy_r107(){ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'.'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2480 "smarty_internal_templateparser.php" -#line 394 "smarty_internal_templateparser.y" - function yy_r108(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.'.'; } -#line 2483 "smarty_internal_templateparser.php" -#line 395 "smarty_internal_templateparser.y" - function yy_r109(){ $this->_retvalue = '.'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2486 "smarty_internal_templateparser.php" -#line 397 "smarty_internal_templateparser.y" - function yy_r110(){ if (preg_match('~^true$~i', $this->yystack[$this->yyidx + 0]->minor)) { - $this->_retvalue = 'true'; - } elseif (preg_match('~^false$~i', $this->yystack[$this->yyidx + 0]->minor)) { - $this->_retvalue = 'false'; - } elseif (preg_match('~^null$~i', $this->yystack[$this->yyidx + 0]->minor)) { - $this->_retvalue = 'null'; - } else - $this->_retvalue = "'".$this->yystack[$this->yyidx + 0]->minor."'"; } -#line 2496 "smarty_internal_templateparser.php" -#line 408 "smarty_internal_templateparser.y" - function yy_r112(){ $this->_retvalue = "(". $this->yystack[$this->yyidx + -1]->minor .")"; } -#line 2499 "smarty_internal_templateparser.php" -#line 414 "smarty_internal_templateparser.y" - function yy_r115(){if (!$this->security || isset($this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor]) || $this->smarty->security_policy->isTrustedStaticClass($this->yystack[$this->yyidx + -2]->minor, $this->compiler)) { - if (isset($this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor])) { - $this->_retvalue = $this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor].'::'.$this->yystack[$this->yyidx + 0]->minor; - } else { - $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'::'.$this->yystack[$this->yyidx + 0]->minor; - } - } else { - $this->compiler->trigger_template_error ("static class '".$this->yystack[$this->yyidx + -2]->minor."' is undefined or not allowed by security setting"); - } - } -#line 2511 "smarty_internal_templateparser.php" -#line 424 "smarty_internal_templateparser.y" - function yy_r116(){ if ($this->yystack[$this->yyidx + -2]->minor['var'] == '\'smarty\'') { $this->_retvalue = $this->compiler->compileTag('private_special_variable',array(),$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index']).'::'.$this->yystack[$this->yyidx + 0]->minor;} else { - $this->_retvalue = '$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + -2]->minor['var'] .')->value'.$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index'].'::'.$this->yystack[$this->yyidx + 0]->minor; $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable(trim($this->yystack[$this->yyidx + -2]->minor['var'],"'"), null, true, false)->nocache;} } -#line 2515 "smarty_internal_templateparser.php" -#line 427 "smarty_internal_templateparser.y" - function yy_r117(){ $this->prefix_number++; $this->compiler->prefix_code[] = ''.$this->yystack[$this->yyidx + 0]->minor.'prefix_number.'=ob_get_clean();?>'; $this->_retvalue = '$_tmp'.$this->prefix_number; } -#line 2518 "smarty_internal_templateparser.php" -#line 437 "smarty_internal_templateparser.y" - function yy_r119(){if ($this->yystack[$this->yyidx + 0]->minor['var'] == '\'smarty\'') { - $smarty_var = $this->compiler->compileTag('private_special_variable',array(),$this->yystack[$this->yyidx + 0]->minor['smarty_internal_index']); - $this->_retvalue = $smarty_var; - } else { - // used for array reset,next,prev,end,current - $this->last_variable = $this->yystack[$this->yyidx + 0]->minor['var']; - $this->last_index = $this->yystack[$this->yyidx + 0]->minor['smarty_internal_index']; - if (isset($this->compiler->local_var[$this->yystack[$this->yyidx + 0]->minor['var']])) { - $this->_retvalue = '$_smarty_tpl->tpl_vars['. $this->yystack[$this->yyidx + 0]->minor['var'] .']->value'.$this->yystack[$this->yyidx + 0]->minor['smarty_internal_index']; - } else { - $this->_retvalue = '$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + 0]->minor['var'] .')->value'.$this->yystack[$this->yyidx + 0]->minor['smarty_internal_index']; - } - $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable(trim($this->yystack[$this->yyidx + 0]->minor['var'],"'"), null, true, false)->nocache; - } - } -#line 2535 "smarty_internal_templateparser.php" -#line 453 "smarty_internal_templateparser.y" - function yy_r120(){if (isset($this->compiler->local_var[$this->yystack[$this->yyidx + -2]->minor])) { - $this->_retvalue = '$_smarty_tpl->tpl_vars['. $this->yystack[$this->yyidx + -2]->minor .']->'.$this->yystack[$this->yyidx + 0]->minor; - } else { - $this->_retvalue = '$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + -2]->minor .')->'.$this->yystack[$this->yyidx + 0]->minor; - } - $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable(trim($this->yystack[$this->yyidx + -2]->minor,"'"), null, true, false)->nocache; } -#line 2543 "smarty_internal_templateparser.php" -#line 462 "smarty_internal_templateparser.y" - function yy_r122(){$this->_retvalue = '$_smarty_tpl->getConfigVariable(\''. $this->yystack[$this->yyidx + -1]->minor .'\')'; } -#line 2546 "smarty_internal_templateparser.php" -#line 463 "smarty_internal_templateparser.y" - function yy_r123(){$this->_retvalue = '$_smarty_tpl->getConfigVariable('. $this->yystack[$this->yyidx + -1]->minor .')'; } -#line 2549 "smarty_internal_templateparser.php" -#line 466 "smarty_internal_templateparser.y" - function yy_r124(){$this->_retvalue = array('var'=>$this->yystack[$this->yyidx + -1]->minor, 'smarty_internal_index'=>$this->yystack[$this->yyidx + 0]->minor); } -#line 2552 "smarty_internal_templateparser.php" -#line 472 "smarty_internal_templateparser.y" - function yy_r125(){$this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; } -#line 2555 "smarty_internal_templateparser.php" -#line 474 "smarty_internal_templateparser.y" - function yy_r126(){return; } -#line 2558 "smarty_internal_templateparser.php" -#line 478 "smarty_internal_templateparser.y" - function yy_r127(){ $this->_retvalue = '[$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + 0]->minor .')->value]'; $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable('$this->yystack[$this->yyidx + 0]->minor', null, true, false)->nocache; } -#line 2561 "smarty_internal_templateparser.php" -#line 479 "smarty_internal_templateparser.y" - function yy_r128(){ $this->_retvalue = '[$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + -2]->minor .')->'.$this->yystack[$this->yyidx + 0]->minor.']'; $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable(trim($this->yystack[$this->yyidx + -2]->minor,"'"), null, true, false)->nocache; } -#line 2564 "smarty_internal_templateparser.php" -#line 480 "smarty_internal_templateparser.y" - function yy_r129(){ $this->_retvalue = "['". $this->yystack[$this->yyidx + 0]->minor ."']"; } -#line 2567 "smarty_internal_templateparser.php" -#line 481 "smarty_internal_templateparser.y" - function yy_r130(){ $this->_retvalue = "[". $this->yystack[$this->yyidx + 0]->minor ."]"; } -#line 2570 "smarty_internal_templateparser.php" -#line 482 "smarty_internal_templateparser.y" - function yy_r131(){ $this->_retvalue = "[". $this->yystack[$this->yyidx + -1]->minor ."]"; } -#line 2573 "smarty_internal_templateparser.php" -#line 484 "smarty_internal_templateparser.y" - function yy_r132(){ $this->_retvalue = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.$this->yystack[$this->yyidx + -1]->minor.'\'][\'index\']').']'; } -#line 2576 "smarty_internal_templateparser.php" -#line 485 "smarty_internal_templateparser.y" - function yy_r133(){ $this->_retvalue = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.$this->yystack[$this->yyidx + -3]->minor.'\'][\''.$this->yystack[$this->yyidx + -1]->minor.'\']').']'; } -#line 2579 "smarty_internal_templateparser.php" -#line 489 "smarty_internal_templateparser.y" - function yy_r135(){$this->_retvalue = '[]'; } -#line 2582 "smarty_internal_templateparser.php" -#line 497 "smarty_internal_templateparser.y" - function yy_r137(){$this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.'.'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2585 "smarty_internal_templateparser.php" -#line 499 "smarty_internal_templateparser.y" - function yy_r138(){$this->_retvalue = '\''.$this->yystack[$this->yyidx + 0]->minor.'\''; } -#line 2588 "smarty_internal_templateparser.php" -#line 501 "smarty_internal_templateparser.y" - function yy_r139(){$this->_retvalue = '('.$this->yystack[$this->yyidx + -1]->minor.')'; } -#line 2591 "smarty_internal_templateparser.php" -#line 506 "smarty_internal_templateparser.y" - function yy_r140(){ if ($this->yystack[$this->yyidx + -1]->minor['var'] == '\'smarty\'') { $this->_retvalue = $this->compiler->compileTag('private_special_variable',array(),$this->yystack[$this->yyidx + -1]->minor['smarty_internal_index']).$this->yystack[$this->yyidx + 0]->minor;} else { - $this->_retvalue = '$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + -1]->minor['var'] .')->value'.$this->yystack[$this->yyidx + -1]->minor['smarty_internal_index'].$this->yystack[$this->yyidx + 0]->minor; $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable(trim($this->yystack[$this->yyidx + -1]->minor['var'],"'"), null, true, false)->nocache;} } -#line 2595 "smarty_internal_templateparser.php" -#line 509 "smarty_internal_templateparser.y" - function yy_r141(){$this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 2598 "smarty_internal_templateparser.php" -#line 511 "smarty_internal_templateparser.y" - function yy_r142(){$this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; } -#line 2601 "smarty_internal_templateparser.php" -#line 513 "smarty_internal_templateparser.y" - function yy_r143(){if ($this->security && substr($this->yystack[$this->yyidx + -1]->minor,0,1) == '_') { - $this->compiler->trigger_template_error (self::Err1); - } - $this->_retvalue = '->'.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; - } -#line 2608 "smarty_internal_templateparser.php" -#line 518 "smarty_internal_templateparser.y" - function yy_r144(){if ($this->security) { - $this->compiler->trigger_template_error (self::Err2); - } - $this->_retvalue = '->{$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + -1]->minor .')->value'.$this->yystack[$this->yyidx + 0]->minor.'}'; $this->compiler->tag_nocache=$this->compiler->tag_nocache|$this->template->getVariable(trim($this->yystack[$this->yyidx + -1]->minor,"'"), null, true, false)->nocache; - } -#line 2615 "smarty_internal_templateparser.php" -#line 523 "smarty_internal_templateparser.y" - function yy_r145(){if ($this->security) { - $this->compiler->trigger_template_error (self::Err2); - } - $this->_retvalue = '->{'.$this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + 0]->minor.'}'; - } -#line 2622 "smarty_internal_templateparser.php" -#line 528 "smarty_internal_templateparser.y" - function yy_r146(){if ($this->security) { - $this->compiler->trigger_template_error (self::Err2); - } - $this->_retvalue = '->{\''.$this->yystack[$this->yyidx + -4]->minor.'\'.'.$this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + 0]->minor.'}'; - } -#line 2629 "smarty_internal_templateparser.php" -#line 534 "smarty_internal_templateparser.y" - function yy_r147(){ $this->_retvalue = '->'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2632 "smarty_internal_templateparser.php" -#line 540 "smarty_internal_templateparser.y" - function yy_r148(){if (!$this->security || $this->smarty->security_policy->isTrustedPhpFunction($this->yystack[$this->yyidx + -3]->minor, $this->compiler)) { - if (strcasecmp($this->yystack[$this->yyidx + -3]->minor,'isset') === 0 || strcasecmp($this->yystack[$this->yyidx + -3]->minor,'empty') === 0 || strcasecmp($this->yystack[$this->yyidx + -3]->minor,'array') === 0 || is_callable($this->yystack[$this->yyidx + -3]->minor)) { - $func_name = strtolower($this->yystack[$this->yyidx + -3]->minor); - if ($func_name == 'isset') { - if (count($this->yystack[$this->yyidx + -1]->minor) == 0) { - $this->compiler->trigger_template_error ('Illegal number of paramer in "isset()"'); - } - $isset_par=str_replace("')->value","',null,true,false)->value",implode(',',$this->yystack[$this->yyidx + -1]->minor)); - $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor . "(". $isset_par .")"; - } elseif (in_array($func_name,array('empty','reset','current','end','prev','next'))){ - if (count($this->yystack[$this->yyidx + -1]->minor) != 1) { - $this->compiler->trigger_template_error ('Illegal number of paramer in "empty()"'); - } - if ($func_name == 'empty') { - $this->_retvalue = $func_name.'('.str_replace("')->value","',null,true,false)->value",$this->yystack[$this->yyidx + -1]->minor[0]).')'; - } else { - $this->_retvalue = $func_name.'('.$this->yystack[$this->yyidx + -1]->minor[0].')'; - } - } else { - $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor . "(". implode(',',$this->yystack[$this->yyidx + -1]->minor) .")"; - } - } else { - $this->compiler->trigger_template_error ("unknown function \"" . $this->yystack[$this->yyidx + -3]->minor . "\""); - } - } - } -#line 2660 "smarty_internal_templateparser.php" -#line 570 "smarty_internal_templateparser.y" - function yy_r149(){if ($this->security && substr($this->yystack[$this->yyidx + -3]->minor,0,1) == '_') { - $this->compiler->trigger_template_error (self::Err1); - } - $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor . "(". implode(',',$this->yystack[$this->yyidx + -1]->minor) .")"; - } -#line 2667 "smarty_internal_templateparser.php" -#line 575 "smarty_internal_templateparser.y" - function yy_r150(){if ($this->security) { - $this->compiler->trigger_template_error (self::Err2); - } - $this->prefix_number++; $this->compiler->prefix_code[] = 'prefix_number.'=$_smarty_tpl->getVariable(\''. $this->yystack[$this->yyidx + -3]->minor .'\')->value;?>'; $this->_retvalue = '$_tmp'.$this->prefix_number.'('. implode(',',$this->yystack[$this->yyidx + -1]->minor) .')'; - } -#line 2674 "smarty_internal_templateparser.php" -#line 583 "smarty_internal_templateparser.y" - function yy_r151(){ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -2]->minor,array($this->yystack[$this->yyidx + 0]->minor)); } -#line 2677 "smarty_internal_templateparser.php" -#line 592 "smarty_internal_templateparser.y" - function yy_r154(){$this->_retvalue = array_merge($this->yystack[$this->yyidx + -2]->minor,array(array_merge($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor))); } -#line 2680 "smarty_internal_templateparser.php" -#line 593 "smarty_internal_templateparser.y" - function yy_r155(){$this->_retvalue = array(array_merge($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor)); } -#line 2683 "smarty_internal_templateparser.php" -#line 596 "smarty_internal_templateparser.y" - function yy_r157(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor); } -#line 2686 "smarty_internal_templateparser.php" -#line 601 "smarty_internal_templateparser.y" - function yy_r158(){ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor); } -#line 2689 "smarty_internal_templateparser.php" -#line 603 "smarty_internal_templateparser.y" - function yy_r159(){$this->_retvalue = array(); } -#line 2692 "smarty_internal_templateparser.php" -#line 605 "smarty_internal_templateparser.y" - function yy_r160(){$this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor); } -#line 2695 "smarty_internal_templateparser.php" -#line 615 "smarty_internal_templateparser.y" - function yy_r165(){ $this->_retvalue = '$'.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; } -#line 2698 "smarty_internal_templateparser.php" -#line 617 "smarty_internal_templateparser.y" - function yy_r166(){ $this->_retvalue = '$'.$this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; } -#line 2701 "smarty_internal_templateparser.php" -#line 626 "smarty_internal_templateparser.y" - function yy_r167(){$this->_retvalue = '=='; } -#line 2704 "smarty_internal_templateparser.php" -#line 627 "smarty_internal_templateparser.y" - function yy_r168(){$this->_retvalue = '!='; } -#line 2707 "smarty_internal_templateparser.php" -#line 628 "smarty_internal_templateparser.y" - function yy_r169(){$this->_retvalue = '>'; } -#line 2710 "smarty_internal_templateparser.php" -#line 629 "smarty_internal_templateparser.y" - function yy_r170(){$this->_retvalue = '<'; } -#line 2713 "smarty_internal_templateparser.php" -#line 630 "smarty_internal_templateparser.y" - function yy_r171(){$this->_retvalue = '>='; } -#line 2716 "smarty_internal_templateparser.php" -#line 631 "smarty_internal_templateparser.y" - function yy_r172(){$this->_retvalue = '<='; } -#line 2719 "smarty_internal_templateparser.php" -#line 632 "smarty_internal_templateparser.y" - function yy_r173(){$this->_retvalue = '==='; } -#line 2722 "smarty_internal_templateparser.php" -#line 633 "smarty_internal_templateparser.y" - function yy_r174(){$this->_retvalue = '!=='; } -#line 2725 "smarty_internal_templateparser.php" -#line 634 "smarty_internal_templateparser.y" - function yy_r175(){$this->_retvalue = '%'; } -#line 2728 "smarty_internal_templateparser.php" -#line 636 "smarty_internal_templateparser.y" - function yy_r176(){$this->_retvalue = '&&'; } -#line 2731 "smarty_internal_templateparser.php" -#line 637 "smarty_internal_templateparser.y" - function yy_r177(){$this->_retvalue = '||'; } -#line 2734 "smarty_internal_templateparser.php" -#line 638 "smarty_internal_templateparser.y" - function yy_r178(){$this->_retvalue = ' XOR '; } -#line 2737 "smarty_internal_templateparser.php" -#line 643 "smarty_internal_templateparser.y" - function yy_r179(){ $this->_retvalue = 'array('.$this->yystack[$this->yyidx + -1]->minor.')'; } -#line 2740 "smarty_internal_templateparser.php" -#line 645 "smarty_internal_templateparser.y" - function yy_r181(){ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.','.$this->yystack[$this->yyidx + 0]->minor; } -#line 2743 "smarty_internal_templateparser.php" -#line 646 "smarty_internal_templateparser.y" - function yy_r182(){ return; } -#line 2746 "smarty_internal_templateparser.php" -#line 647 "smarty_internal_templateparser.y" - function yy_r183(){ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'=>'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2749 "smarty_internal_templateparser.php" -#line 648 "smarty_internal_templateparser.y" - function yy_r184(){ $this->_retvalue = '\''.$this->yystack[$this->yyidx + -2]->minor.'\'=>'.$this->yystack[$this->yyidx + 0]->minor; } -#line 2752 "smarty_internal_templateparser.php" -#line 655 "smarty_internal_templateparser.y" - function yy_r186(){ $this->_retvalue = "''"; } -#line 2755 "smarty_internal_templateparser.php" -#line 656 "smarty_internal_templateparser.y" - function yy_r187(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor->to_smarty_php(); } -#line 2758 "smarty_internal_templateparser.php" -#line 658 "smarty_internal_templateparser.y" - function yy_r188(){ $this->yystack[$this->yyidx + -1]->minor->append_subtree($this->yystack[$this->yyidx + 0]->minor); $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; } -#line 2761 "smarty_internal_templateparser.php" -#line 659 "smarty_internal_templateparser.y" - function yy_r189(){ $this->_retvalue = new _smarty_doublequoted($this, $this->yystack[$this->yyidx + 0]->minor); } -#line 2764 "smarty_internal_templateparser.php" -#line 661 "smarty_internal_templateparser.y" - function yy_r190(){ $this->_retvalue = new _smarty_code($this, $this->yystack[$this->yyidx + -1]->minor); } -#line 2767 "smarty_internal_templateparser.php" -#line 663 "smarty_internal_templateparser.y" - function yy_r192(){if (isset($this->compiler->local_var["'".substr($this->yystack[$this->yyidx + 0]->minor,1)."'"])) { - $this->_retvalue = new _smarty_code($this, '$_smarty_tpl->tpl_vars[\''. substr($this->yystack[$this->yyidx + 0]->minor,1) .'\']->value'); - } else { - $this->_retvalue = new _smarty_code($this, '$_smarty_tpl->getVariable(\''. substr($this->yystack[$this->yyidx + 0]->minor,1) .'\')->value'); - } - $this->compiler->tag_nocache = $this->compiler->tag_nocache | $this->template->getVariable(trim($this->yystack[$this->yyidx + 0]->minor,"'"), null, true, false)->nocache; - } -#line 2776 "smarty_internal_templateparser.php" -#line 671 "smarty_internal_templateparser.y" - function yy_r194(){ $this->_retvalue = new _smarty_code($this, '('.$this->yystack[$this->yyidx + -1]->minor.')'); } -#line 2779 "smarty_internal_templateparser.php" -#line 672 "smarty_internal_templateparser.y" - function yy_r195(){ - $this->_retvalue = new _smarty_tag($this, $this->yystack[$this->yyidx + 0]->minor); - } -#line 2784 "smarty_internal_templateparser.php" -#line 675 "smarty_internal_templateparser.y" - function yy_r196(){ $this->_retvalue = new _smarty_dq_content($this, $this->yystack[$this->yyidx + 0]->minor); } -#line 2787 "smarty_internal_templateparser.php" -#line 682 "smarty_internal_templateparser.y" - function yy_r198(){$this->_retvalue = ''; } -#line 2790 "smarty_internal_templateparser.php" - - private $_retvalue; - - function yy_reduce($yyruleno) - { - $yymsp = $this->yystack[$this->yyidx]; - if (self::$yyTraceFILE && $yyruleno >= 0 - && $yyruleno < count(self::$yyRuleName)) { - fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n", - self::$yyTracePrompt, $yyruleno, - self::$yyRuleName[$yyruleno]); - } + // line 242 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r0() + { + $this->root_buffer->prepend_array($this, $this->template_prefix); + $this->root_buffer->append_array($this, $this->template_postfix); + $this->_retvalue = $this->root_buffer->to_smarty_php($this); + } - $this->_retvalue = $yy_lefthand_side = null; - if (array_key_exists($yyruleno, self::$yyReduceMap)) { - // call the action - $this->_retvalue = null; - $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}(); - $yy_lefthand_side = $this->_retvalue; - } - $yygoto = self::$yyRuleInfo[$yyruleno]['lhs']; - $yysize = self::$yyRuleInfo[$yyruleno]['rhs']; - $this->yyidx -= $yysize; - for($i = $yysize; $i; $i--) { - // pop all of the right-hand side parameters - array_pop($this->yystack); - } - $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto); - if ($yyact < self::YYNSTATE) { - if (!self::$yyTraceFILE && $yysize) { - $this->yyidx++; - $x = new TP_yyStackEntry; - $x->stateno = $yyact; - $x->major = $yygoto; - $x->minor = $yy_lefthand_side; - $this->yystack[$this->yyidx] = $x; - } else { - $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); + // line 251 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r1() + { + $code = + $this->compiler->compileTag('private_php', + array(array('code' => $this->yystack[ $this->yyidx + 0 ]->minor), array('type' => $this->lex->phpType)), + array()); + if ($this->compiler->has_code && !empty($code)) { + $tmp = ''; + foreach ($this->compiler->prefix_code as $code) { + $tmp .= $code; } - } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) { - $this->yy_accept(); + $this->compiler->prefix_code = array(); + $this->current_buffer->append_subtree($this, + new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp . $code, true))); } } - function yy_parse_failed() + // line 255 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r2() { - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt); - } - while ($this->yyidx >= 0) { - $this->yy_pop_parser_stack(); - } + $text = $this->yystack[ $this->yyidx + 0 ]->minor; + + if ((string)$text == '') { + $this->current_buffer->append_subtree($this, null); + } + + $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Text($text, $this->strip)); + } + + // line 259 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r3() + { + $this->strip = true; + } + + // line 264 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r4() + { + $this->strip = false; + } + + // line 269 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r5() + { + $this->current_buffer->append_subtree($this, + new Smarty_Internal_ParseTree_Text($this->yystack[ $this->yyidx + -1 ]->minor)); + } + + // line 272 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r6() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -3 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor; + } + + // line 276 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r7() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 281 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r8() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 285 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r9() + { + $this->_retvalue = ''; + } + + // line 297 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r10() + { + if ($this->compiler->has_code) { + $this->current_buffer->append_subtree($this, + $this->mergePrefixCode($this->yystack[ $this->yyidx + 0 ]->minor)); + } + $this->compiler->has_variable_string = false; + $this->block_nesting_level = count($this->compiler->_tag_stack); + } + + // line 307 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r12() + { + $var = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler->getLdelLength(), + -$this->compiler->getRdelLength()), ' $'); + if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) { + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', array('nocache'), + array('value' => $this->compiler->compileVariable('\'' . $match[ 1 ] . '\''))); + } else { + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', array(), + array('value' => $this->compiler->compileVariable('\'' . $var . '\''))); + } + } + + // line 328 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r13() + { + $tag = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler->getLdelLength(), + -$this->compiler->getRdelLength())); + if ($tag == 'strip') { + $this->strip = true; + $this->_retvalue = null; + } else { + if (defined($tag)) { + if ($this->security) { + $this->security->isTrustedConstant($tag, $this->compiler); + } + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', array(), array('value' => $tag)); + } else { + if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) { + $this->_retvalue = $this->compiler->compileTag($match[ 1 ], array('\'nocache\'')); + } else { + $this->_retvalue = $this->compiler->compileTag($tag, array()); + } + } + } + } + + // line 339 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r14() + { + $j = strrpos($this->yystack[ $this->yyidx + 0 ]->minor, '.'); + if ($this->yystack[ $this->yyidx + 0 ]->minor[ $j + 1 ] == 'c') { + // {$smarty.block.child} + $this->_retvalue = + $this->compiler->compileTag('child', array(), array($this->yystack[ $this->yyidx + 0 ]->minor)); + } else { + // {$smarty.block.parent} + $this->_retvalue = + $this->compiler->compileTag('parent', array(), array($this->yystack[ $this->yyidx + 0 ]->minor)); + } + } + + // line 343 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r15() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + // line 347 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r16() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + // line 356 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r17() + { + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ], + array('value' => $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ])); + } + + // line 360 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r18() + { + $this->_retvalue = + $this->compiler->compileTag('assign', array_merge(array( + array('value' => $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ]), + array('var' => '\'' . substr($this->yystack[ $this->yyidx + -1 ]->minor, 1) . '\'') + ), $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ])); + } + + // line 364 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r19() + { + $this->_retvalue = + $this->compiler->compileTag('assign', array_merge(array( + array('value' => $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ]), + array('var' => $this->yystack[ $this->yyidx + -1 ]->minor[ 'var' ]) + ), $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]), array( + 'smarty_internal_index' => $this->yystack[ $this->yyidx + + -1 ]->minor[ 'smarty_internal_index' ] + )); + } + + // line 368 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r20() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 383 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r21() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 393 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r25() + { + if (defined($this->yystack[ $this->yyidx + -1 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + -1 ]->minor, $this->compiler); + } + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', $this->yystack[ $this->yyidx + 0 ]->minor, + array('value' => $this->yystack[ $this->yyidx + -1 ]->minor)); + } else { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -1 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor); + } + } + + // line 406 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r26() + { + if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler); + } + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', array(), + array('value' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } else { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + 0 ]->minor, array()); + } + } + + // line 418 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r27() + { + if (defined($this->yystack[ $this->yyidx + -2 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + -2 ]->minor, $this->compiler); + } + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', $this->yystack[ $this->yyidx + 0 ]->minor, + array( + 'value' => $this->yystack[ $this->yyidx + -2 ]->minor, + 'modifierlist' => $this->yystack[ $this->yyidx + -1 ]->minor + )); + } else { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -2 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('modifierlist' => $this->yystack[ $this->yyidx + -1 ]->minor)); + } + } + + // line 423 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r28() + { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -3 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('object_method' => $this->yystack[ $this->yyidx + -1 ]->minor)); + } + + // line 428 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r29() + { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -4 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, array( + 'modifierlist' => $this->yystack[ $this->yyidx + -1 ]->minor, + 'object_method' => $this->yystack[ $this->yyidx + -2 ]->minor + )); + } + + // line 433 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r30() + { + $this->_retvalue = + $this->compiler->compileTag('make_nocache', + array(array('var' => '\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\''))); + } + + // line 438 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r31() + { + $tag = trim(substr($this->yystack[ $this->yyidx + -1 ]->minor, $this->compiler->getLdelLength())); + $this->_retvalue = + $this->compiler->compileTag(($tag === 'else if') ? 'elseif' : $tag, array(), + array('if condition' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 443 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r32() + { + $tag = trim(substr($this->yystack[ $this->yyidx + -2 ]->minor, $this->compiler->getLdelLength())); + $this->_retvalue = + $this->compiler->compileTag(($tag === 'else if') ? 'elseif' : $tag, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('if condition' => $this->yystack[ $this->yyidx + -1 ]->minor)); + } + + // line 454 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r33() + { + $tag = trim(substr($this->yystack[ $this->yyidx + -1 ]->minor, $this->compiler->getLdelLength())); + $this->_retvalue = + $this->compiler->compileTag(($tag === 'else if') ? 'elseif' : $tag, array(), + array('if condition' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 458 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r35() + { + $this->_retvalue = + $this->compiler->compileTag('for', array_merge($this->yystack[ $this->yyidx + 0 ]->minor, array( + array('start' => $this->yystack[ $this->yyidx + -6 ]->minor), + array('ifexp' => $this->yystack[ $this->yyidx + -4 ]->minor), + array('var' => $this->yystack[ $this->yyidx + -2 ]->minor), + array('step' => $this->yystack[ $this->yyidx + -1 ]->minor) + )), 1); + } + + // line 466 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r36() + { + $this->_retvalue = '=' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 470 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r38() + { + $this->_retvalue = + $this->compiler->compileTag('for', array_merge($this->yystack[ $this->yyidx + 0 ]->minor, array( + array('start' => $this->yystack[ $this->yyidx + -3 ]->minor), + array('to' => $this->yystack[ $this->yyidx + -1 ]->minor) + )), 0); + } + + // line 475 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r39() + { + $this->_retvalue = + $this->compiler->compileTag('for', array_merge($this->yystack[ $this->yyidx + 0 ]->minor, array( + array('start' => $this->yystack[ $this->yyidx + -5 ]->minor), + array('to' => $this->yystack[ $this->yyidx + -3 ]->minor), + array('step' => $this->yystack[ $this->yyidx + -1 ]->minor) + )), 0); + } + + // line 479 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r40() + { + $this->_retvalue = + $this->compiler->compileTag('foreach', array_merge($this->yystack[ $this->yyidx + 0 ]->minor, array( + array('from' => $this->yystack[ $this->yyidx + -3 ]->minor), + array('item' => $this->yystack[ $this->yyidx + -1 ]->minor) + ))); + } + + // line 482 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r41() + { + $this->_retvalue = + $this->compiler->compileTag('foreach', array_merge($this->yystack[ $this->yyidx + 0 ]->minor, array( + array('from' => $this->yystack[ $this->yyidx + -5 ]->minor), + array('item' => $this->yystack[ $this->yyidx + -1 ]->minor), + array('key' => $this->yystack[ $this->yyidx + -3 ]->minor) + ))); + } + + // line 487 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r42() + { + $this->_retvalue = $this->compiler->compileTag('foreach', $this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 491 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r43() + { + $this->_retvalue = + $this->compiler->compileTag('setfilter', array(), array( + 'modifier_list' => array( + array_merge(array($this->yystack[ $this->yyidx + -1 ]->minor), + $this->yystack[ $this->yyidx + 0 ]->minor) + ) + )); + } + + // line 497 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r44() + { + $this->_retvalue = + $this->compiler->compileTag('setfilter', array(), array( + 'modifier_list' => array_merge(array( + array_merge(array( + $this->yystack[ $this->yyidx + + -2 ]->minor + ), $this->yystack[ $this->yyidx + -1 ]->minor) + ), $this->yystack[ $this->yyidx + 0 ]->minor) + )); + } + + // line 506 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r45() + { + $tag = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler->getLdelLength(), + -$this->compiler->getRdelLength()), ' /'); + if ($tag === 'strip') { + $this->strip = false; + $this->_retvalue = null; + } else { + $this->_retvalue = $this->compiler->compileTag($tag . 'close', array()); + } + } + + // line 510 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r46() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + 0 ]->minor . 'close', array()); + } + + // line 515 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r47() + { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -1 ]->minor . 'close', array(), + array('modifier_list' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 519 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r48() + { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -2 ]->minor . 'close', array(), + array('object_method' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 527 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r49() + { + $this->_retvalue = + $this->compiler->compileTag($this->yystack[ $this->yyidx + -3 ]->minor . 'close', array(), array( + 'object_method' => $this->yystack[ $this->yyidx + -1 ]->minor, + 'modifier_list' => $this->yystack[ $this->yyidx + 0 ]->minor + )); + } + + // line 533 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r50() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + $this->_retvalue[] = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 538 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r51() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 543 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r52() + { + $this->_retvalue = array(); + } + + // line 554 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r53() + { + if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler); + } + $this->_retvalue = + array($this->yystack[ $this->yyidx + -2 ]->minor => $this->yystack[ $this->yyidx + 0 ]->minor); + } else { + $this->_retvalue = + array( + $this->yystack[ $this->yyidx + -2 ]->minor => '\'' . + $this->yystack[ $this->yyidx + 0 ]->minor . + '\'' + ); + } + } + + // line 562 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r54() + { + $this->_retvalue = + array( + trim($this->yystack[ $this->yyidx + -1 ]->minor, " =\n\r\t") => $this->yystack[ $this->yyidx + + 0 ]->minor + ); + } + + // line 574 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r56() + { + $this->_retvalue = '\'' . $this->yystack[ $this->yyidx + 0 ]->minor . '\''; + } + + // line 587 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r59() + { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -2 ]->minor => $this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 592 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r61() + { + $this->yystack[ $this->yyidx + -2 ]->minor[] = $this->yystack[ $this->yyidx + 0 ]->minor; + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor; + } + + // line 599 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r62() + { + $this->_retvalue = + array( + 'var' => '\'' . substr($this->yystack[ $this->yyidx + -2 ]->minor, 1) . '\'', + 'value' => $this->yystack[ $this->yyidx + 0 ]->minor + ); + } + + // line 603 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r64() + { + $this->_retvalue = + array( + 'var' => $this->yystack[ $this->yyidx + -2 ]->minor, + 'value' => $this->yystack[ $this->yyidx + 0 ]->minor + ); + } + + // line 623 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r65() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + // line 628 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r68() + { + $this->_retvalue = + '$_smarty_tpl->getStreamVariable(\'' . + substr($this->yystack[ $this->yyidx + -2 ]->minor, 1) . + '://' . + $this->yystack[ $this->yyidx + 0 ]->minor . + '\')'; + } + + // line 638 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r69() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . + trim($this->yystack[ $this->yyidx + -1 ]->minor) . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 642 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r71() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -1 ]->minor[ 'pre' ] . + $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + -1 ]->minor[ 'op' ] . + $this->yystack[ $this->yyidx + 0 ]->minor . + ')'; + } + + // line 646 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r72() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + -1 ]->minor . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 650 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r73() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + // line 654 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r74() + { + $this->_retvalue = + 'in_array(' . + $this->yystack[ $this->yyidx + -2 ]->minor . + ',' . + $this->yystack[ $this->yyidx + 0 ]->minor . + ')'; + } + + // line 662 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r75() + { + $this->_retvalue = + 'in_array(' . + $this->yystack[ $this->yyidx + -2 ]->minor . + ',(array)' . + $this->yystack[ $this->yyidx + 0 ]->minor . + ')'; + } + + // line 666 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r76() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -5 ]->minor . + ' ? ' . + $this->compiler->compileVariable('\'' . substr($this->yystack[ $this->yyidx + -2 ]->minor, 1) . '\'') . + ' : ' . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 676 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r77() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -5 ]->minor . + ' ? ' . + $this->yystack[ $this->yyidx + -2 ]->minor . + ' : ' . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 681 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r79() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 702 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r80() + { + $this->_retvalue = '!' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 706 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r85() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . '.' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 710 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r86() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . '.'; + } + + // line 715 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r87() + { + $this->_retvalue = '.' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 732 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r88() + { + if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler); + } + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } else { + $this->_retvalue = '\'' . $this->yystack[ $this->yyidx + 0 ]->minor . '\''; + } + } + + // line 736 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r90() + { + $this->_retvalue = '(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + // line 754 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r91() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + -1 ]->minor . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 765 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r95() + { + $prefixVar = $this->compiler->getNewPrefixVariable(); + if ($this->yystack[ $this->yyidx + -2 ]->minor[ 'var' ] === '\'smarty\'') { + $this->compiler->appendPrefixCode("compiler->compileTag('private_special_variable', array(), + $this->yystack[ $this->yyidx + + -2 ]->minor[ 'smarty_internal_index' ]) . + ';?>'); + } else { + $this->compiler->appendPrefixCode("compiler->compileVariable($this->yystack[ $this->yyidx + + -2 ]->minor[ 'var' ]) . + $this->yystack[ $this->yyidx + -2 ]->minor[ 'smarty_internal_index' ] . + ';?>'); + } + $this->_retvalue = + $prefixVar . + '::' . + $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ] . + $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]; + } + + // line 772 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r96() + { + $prefixVar = $this->compiler->getNewPrefixVariable(); + $tmp = $this->compiler->appendCode('', $this->yystack[ $this->yyidx + 0 ]->minor); + $this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "")); + $this->_retvalue = $prefixVar; + } + + // line 785 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r97() + { + $this->_retvalue = + $this->compiler->compileTag('private_modifier', array(), array( + 'value' => $this->yystack[ $this->yyidx + -1 ]->minor, + 'modifierlist' => $this->yystack[ $this->yyidx + 0 ]->minor + )); + } + + // line 804 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r100() + { + if (!in_array(strtolower($this->yystack[ $this->yyidx + -2 ]->minor), array('self', 'parent')) && + (!$this->security || + $this->security->isTrustedStaticClassAccess($this->yystack[ $this->yyidx + -2 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler))) { + if (isset($this->smarty->registered_classes[ $this->yystack[ $this->yyidx + -2 ]->minor ])) { + $this->_retvalue = + $this->smarty->registered_classes[ $this->yystack[ $this->yyidx + -2 ]->minor ] . + '::' . + $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ] . + $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]; + } else { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . + '::' . + $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ] . + $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]; + } + } else { + $this->compiler->trigger_template_error('static class \'' . + $this->yystack[ $this->yyidx + -2 ]->minor . + '\' is undefined or not allowed by security setting'); + } + } + + // line 815 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r102() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 818 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r103() + { + $this->_retvalue = + $this->compiler->compileVariable('\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\''); + } + + // line 831 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r104() + { + if ($this->yystack[ $this->yyidx + 0 ]->minor[ 'var' ] === '\'smarty\'') { + $smarty_var = + $this->compiler->compileTag('private_special_variable', array(), + $this->yystack[ $this->yyidx + 0 ]->minor[ 'smarty_internal_index' ]); + $this->_retvalue = $smarty_var; + } else { + // used for array reset,next,prev,end,current + $this->last_variable = $this->yystack[ $this->yyidx + 0 ]->minor[ 'var' ]; + $this->last_index = $this->yystack[ $this->yyidx + 0 ]->minor[ 'smarty_internal_index' ]; + $this->_retvalue = + $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor[ 'var' ]) . + $this->yystack[ $this->yyidx + 0 ]->minor[ 'smarty_internal_index' ]; + } + } + + // line 841 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r105() + { + $this->_retvalue = + '$_smarty_tpl->tpl_vars[' . + $this->yystack[ $this->yyidx + -2 ]->minor . + ']->' . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 845 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r107() + { + $this->_retvalue = + $this->compiler->compileConfigVariable('\'' . $this->yystack[ $this->yyidx + -1 ]->minor . '\''); + } + + // line 849 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r108() + { + $this->_retvalue = + '(is_array($tmp = ' . + $this->compiler->compileConfigVariable('\'' . $this->yystack[ $this->yyidx + -2 ]->minor . '\'') . + ') ? $tmp' . + $this->yystack[ $this->yyidx + 0 ]->minor . + ' :null)'; + } + + // line 853 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r109() + { + $this->_retvalue = $this->compiler->compileConfigVariable($this->yystack[ $this->yyidx + -1 ]->minor); + } + + // line 857 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r110() + { + $this->_retvalue = + '(is_array($tmp = ' . + $this->compiler->compileConfigVariable($this->yystack[ $this->yyidx + -2 ]->minor) . + ') ? $tmp' . + $this->yystack[ $this->yyidx + 0 ]->minor . + ' : null)'; + } + + // line 860 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r111() + { + $this->_retvalue = + array( + 'var' => '\'' . substr($this->yystack[ $this->yyidx + -1 ]->minor, 1) . '\'', + 'smarty_internal_index' => $this->yystack[ $this->yyidx + 0 ]->minor + ); + } + + // line 873 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r112() + { + $this->_retvalue = + array( + 'var' => $this->yystack[ $this->yyidx + -1 ]->minor, + 'smarty_internal_index' => $this->yystack[ $this->yyidx + 0 ]->minor + ); + } + + // line 879 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r114() + { + return; + } + + // line 882 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r115() + { + $this->_retvalue = + '[' . + $this->compiler->compileVariable('\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\'') . + ']'; + } + + // line 886 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r116() + { + $this->_retvalue = '[' . $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor) . ']'; + } + + // line 890 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r117() + { + $this->_retvalue = + '[' . + $this->compiler->compileVariable($this->yystack[ $this->yyidx + -2 ]->minor) . + '->' . + $this->yystack[ $this->yyidx + 0 ]->minor . + ']'; + } + + // line 894 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r118() + { + $this->_retvalue = '[\'' . $this->yystack[ $this->yyidx + 0 ]->minor . '\']'; + } + + // line 899 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r119() + { + $this->_retvalue = '[' . $this->yystack[ $this->yyidx + 0 ]->minor . ']'; + } + + // line 904 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r120() + { + $this->_retvalue = '[' . $this->yystack[ $this->yyidx + -1 ]->minor . ']'; + } + + // line 908 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r121() + { + $this->_retvalue = + '[' . + $this->compiler->compileTag('private_special_variable', array(), + '[\'section\'][\'' . $this->yystack[ $this->yyidx + -1 ]->minor . '\'][\'index\']') . + ']'; + } + + // line 911 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r122() + { + $this->_retvalue = + '[' . + $this->compiler->compileTag('private_special_variable', array(), '[\'section\'][\'' . + $this->yystack[ $this->yyidx + + -3 ]->minor . + '\'][\'' . + $this->yystack[ $this->yyidx + + -1 ]->minor . + '\']') . + ']'; + } + + // line 917 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r123() + { + $this->_retvalue = '[' . $this->yystack[ $this->yyidx + -1 ]->minor . ']'; + } + + // line 933 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r125() + { + $this->_retvalue = + '[' . + $this->compiler->compileVariable('\'' . substr($this->yystack[ $this->yyidx + -1 ]->minor, 1) . '\'') . + ']'; + } + + // line 943 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r129() + { + $this->_retvalue = '[]'; + } + + // line 947 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r130() + { + $this->_retvalue = '\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\''; + } + + // line 952 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r131() + { + $this->_retvalue = '\'\''; + } + + // line 960 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r132() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . '.' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 966 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r134() + { + $var = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler->getLdelLength(), + -$this->compiler->getRdelLength()), ' $'); + $this->_retvalue = $this->compiler->compileVariable('\'' . $var . '\''); + } + + // line 973 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r135() + { + $this->_retvalue = '(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + // line 982 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r136() + { + if ($this->yystack[ $this->yyidx + -1 ]->minor[ 'var' ] === '\'smarty\'') { + $this->_retvalue = + $this->compiler->compileTag('private_special_variable', array(), + $this->yystack[ $this->yyidx + -1 ]->minor[ 'smarty_internal_index' ]) . + $this->yystack[ $this->yyidx + 0 ]->minor; + } else { + $this->_retvalue = + $this->compiler->compileVariable($this->yystack[ $this->yyidx + -1 ]->minor[ 'var' ]) . + $this->yystack[ $this->yyidx + -1 ]->minor[ 'smarty_internal_index' ] . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + } + + // line 987 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r137() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 992 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r138() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 999 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r139() + { + if ($this->security && substr($this->yystack[ $this->yyidx + -1 ]->minor, 0, 1) === '_') { + $this->compiler->trigger_template_error(self::ERR1); + } + $this->_retvalue = + '->' . $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 1006 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r140() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::ERR2); + } + $this->_retvalue = + '->{' . + $this->compiler->compileVariable($this->yystack[ $this->yyidx + -1 ]->minor) . + $this->yystack[ $this->yyidx + 0 ]->minor . + '}'; + } + + // line 1013 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r141() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::ERR2); + } + $this->_retvalue = + '->{' . $this->yystack[ $this->yyidx + -2 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor . '}'; + } + + // line 1021 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r142() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::ERR2); + } + $this->_retvalue = + '->{\'' . + $this->yystack[ $this->yyidx + -4 ]->minor . + '\'.' . + $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + 0 ]->minor . + '}'; + } + + // line 1029 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r143() + { + $this->_retvalue = '->' . $this->yystack[ $this->yyidx + 0 ]->minor; } - function yy_syntax_error($yymajor, $TOKEN) + // line 1037 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r144() { -#line 66 "smarty_internal_templateparser.y" + $this->_retvalue = + $this->compiler->compilePHPFunctionCall($this->yystack[ $this->yyidx + -3 ]->minor, + $this->yystack[ $this->yyidx + -1 ]->minor); + } + + // line 1044 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r145() + { + if ($this->security && substr($this->yystack[ $this->yyidx + -3 ]->minor, 0, 1) === '_') { + $this->compiler->trigger_template_error(self::ERR1); + } + $this->_retvalue = + $this->yystack[ $this->yyidx + -3 ]->minor . + '(' . + implode(',', $this->yystack[ $this->yyidx + -1 ]->minor) . + ')'; + } + + // line 1055 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r146() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::ERR2); + } + $prefixVar = $this->compiler->getNewPrefixVariable(); + $this->compiler->appendPrefixCode("compiler->compileVariable('\'' . + substr($this->yystack[ $this->yyidx + + -3 ]->minor, 1) . + '\'') . + ';?>'); + $this->_retvalue = $prefixVar . '(' . implode(',', $this->yystack[ $this->yyidx + -1 ]->minor) . ')'; + } + + // line 1072 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r147() + { + $this->_retvalue = + array_merge($this->yystack[ $this->yyidx + -2 ]->minor, array($this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 1076 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r150() + { + $this->_retvalue = + array_merge($this->yystack[ $this->yyidx + -2 ]->minor, array( + array_merge($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor) + )); + } + + // line 1084 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r151() + { + $this->_retvalue = + array(array_merge($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + // line 1092 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r153() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 1105 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r154() + { + $this->_retvalue = + array_merge($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 1114 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r157() + { + $this->_retvalue = + array(trim($this->yystack[ $this->yyidx + -1 ]->minor) . $this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 1119 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r159() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor, '', 'method'); + } + + // line 1124 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r160() + { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor, 'method'); + } + + // line 1129 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r161() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor, ''); + } + + // line 1134 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r162() + { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor, 'property'); + } + + // line 1140 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r163() + { + $this->_retvalue = + array( + $this->yystack[ $this->yyidx + -2 ]->minor, + $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor, 'property' + ); + } + + // line 1144 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r164() + { + $this->_retvalue = ' ' . trim($this->yystack[ $this->yyidx + 0 ]->minor) . ' '; + } + + // line 1163 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r165() + { + static $lops = array( + 'eq' => ' == ', + 'ne' => ' != ', + 'neq' => ' != ', + 'gt' => ' > ', + 'ge' => ' >= ', + 'gte' => ' >= ', + 'lt' => ' < ', + 'le' => ' <= ', + 'lte' => ' <= ', + 'mod' => ' % ', + 'and' => ' && ', + 'or' => ' || ', + 'xor' => ' xor ', + ); + $op = strtolower(preg_replace('/\s*/', '', $this->yystack[ $this->yyidx + 0 ]->minor)); + $this->_retvalue = $lops[ $op ]; + } + + // line 1176 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r166() + { + static $tlops = array( + 'isdivby' => array('op' => ' % ', 'pre' => '!('), + 'isnotdivby' => array('op' => ' % ', 'pre' => '('), + 'isevenby' => array('op' => ' / ', 'pre' => '!(1 & '), + 'isnotevenby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isoddby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isnotoddby' => array('op' => ' / ', 'pre' => '!(1 & '), + ); + $op = strtolower(preg_replace('/\s*/', '', $this->yystack[ $this->yyidx + 0 ]->minor)); + $this->_retvalue = $tlops[ $op ]; + } + + // line 1190 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r167() + { + static $scond = array( + 'iseven' => '!(1 & ', + 'isnoteven' => '(1 & ', + 'isodd' => '(1 & ', + 'isnotodd' => '!(1 & ', + ); + $op = strtolower(str_replace(' ', '', $this->yystack[ $this->yyidx + 0 ]->minor)); + $this->_retvalue = $scond[ $op ]; + } + + // line 1201 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r168() + { + $this->_retvalue = 'array(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + // line 1209 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r171() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . ',' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 1213 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r173() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . '=>' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 1229 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r174() + { + $this->_retvalue = + '\'' . $this->yystack[ $this->yyidx + -2 ]->minor . '\'=>' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + // line 1235 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r177() + { + $this->compiler->leaveDoubleQuote(); + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor->to_smarty_php($this); + } + + // line 1240 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r178() + { + $this->yystack[ $this->yyidx + -1 ]->minor->append_subtree($this, $this->yystack[ $this->yyidx + 0 ]->minor); + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + // line 1244 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r179() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Dq($this, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + // line 1248 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r180() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)' . $this->yystack[ $this->yyidx + -1 ]->minor); + } - $this->internalError = true; - $this->yymajor = $yymajor; - $this->compiler->trigger_template_error(); -#line 2853 "smarty_internal_templateparser.php" + // line 1252 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r181() + { + $this->_retvalue = + new Smarty_Internal_ParseTree_Code('(string)(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'); + } + + // line 1264 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r182() + { + $this->_retvalue = + new Smarty_Internal_ParseTree_Code('(string)$_smarty_tpl->tpl_vars[\'' . + substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . + '\']->value'); + } + + // line 1268 "../smarty/lexer/smarty_internal_templateparser.y" + public function yy_r185() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Tag($this, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + public function yy_r186() + { + $this->_retvalue = new Smarty_Internal_ParseTree_DqContent($this->yystack[ $this->yyidx + 0 ]->minor); + } + + public function yy_reduce($yyruleno) + { + if ($this->yyTraceFILE && $yyruleno >= 0 + && $yyruleno < count(self::$yyRuleName)) { + fprintf($this->yyTraceFILE, "%sReduce (%d) [%s].\n", + $this->yyTracePrompt, $yyruleno, + self::$yyRuleName[ $yyruleno ]); + } + $this->_retvalue = $yy_lefthand_side = null; + if (isset(self::$yyReduceMap[ $yyruleno ])) { + // call the action + $this->_retvalue = null; + $this->{'yy_r' . self::$yyReduceMap[ $yyruleno ]}(); + $yy_lefthand_side = $this->_retvalue; + } + $yygoto = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $yysize = self::$yyRuleInfo[ $yyruleno ][ 1 ]; + $this->yyidx -= $yysize; + for ($i = $yysize; $i; $i--) { + // pop all of the right-hand side parameters + array_pop($this->yystack); + } + $yyact = $this->yy_find_reduce_action($this->yystack[ $this->yyidx ]->stateno, $yygoto); + if ($yyact < self::YYNSTATE) { + if (!$this->yyTraceFILE && $yysize) { + $this->yyidx++; + $x = new TP_yyStackEntry; + $x->stateno = $yyact; + $x->major = $yygoto; + $x->minor = $yy_lefthand_side; + $this->yystack[ $this->yyidx ] = $x; + } else { + $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); + } + } elseif ($yyact === self::YYNSTATE + self::YYNRULE + 1) { + $this->yy_accept(); + } } - function yy_accept() + public function yy_parse_failed() { - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sFail!\n", $this->yyTracePrompt); } while ($this->yyidx >= 0) { - $stack = $this->yy_pop_parser_stack(); + $this->yy_pop_parser_stack(); } -#line 58 "smarty_internal_templateparser.y" + } - $this->successful = !$this->internalError; - $this->internalError = false; - $this->retvalue = $this->_retvalue; - //echo $this->retvalue."\n\n"; -#line 2871 "smarty_internal_templateparser.php" + public function yy_syntax_error($yymajor, $TOKEN) + { + // line 214 "../smarty/lexer/smarty_internal_templateparser.y" + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_template_error(); } - function doParse($yymajor, $yytokenvalue) + public function yy_accept() + { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sAccept!\n", $this->yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + // line 207 "../smarty/lexer/smarty_internal_templateparser.y" + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; + } + + public function doParse($yymajor, $yytokenvalue) { $yyerrorhit = 0; /* True if yymajor has invoked an error */ - if ($this->yyidx === null || $this->yyidx < 0) { $this->yyidx = 0; $this->yyerrcnt = -1; @@ -2884,19 +3543,17 @@ function doParse($yymajor, $yytokenvalue) $x->stateno = 0; $x->major = 0; $this->yystack = array(); - array_push($this->yystack, $x); + $this->yystack[] = $x; } - $yyendofinput = ($yymajor==0); - - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sInput %s\n", - self::$yyTracePrompt, $this->yyTokenName[$yymajor]); + $yyendofinput = ($yymajor == 0); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sInput %s\n", + $this->yyTracePrompt, $this->yyTokenName[ $yymajor ]); } - do { $yyact = $this->yy_find_shift_action($yymajor); if ($yymajor < self::YYERRORSYMBOL && - !$this->yy_is_expected_token($yymajor)) { + !$this->yy_is_expected_token($yymajor)) { // force a syntax error $yyact = self::YY_ERROR_ACTION; } @@ -2910,35 +3567,35 @@ function doParse($yymajor, $yytokenvalue) } } elseif ($yyact < self::YYNSTATE + self::YYNRULE) { $this->yy_reduce($yyact - self::YYNSTATE); - } elseif ($yyact == self::YY_ERROR_ACTION) { - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sSyntax Error!\n", - self::$yyTracePrompt); + } elseif ($yyact === self::YY_ERROR_ACTION) { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sSyntax Error!\n", + $this->yyTracePrompt); } if (self::YYERRORSYMBOL) { if ($this->yyerrcnt < 0) { $this->yy_syntax_error($yymajor, $yytokenvalue); } - $yymx = $this->yystack[$this->yyidx]->major; - if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){ - if (self::$yyTraceFILE) { - fprintf(self::$yyTraceFILE, "%sDiscard input token %s\n", - self::$yyTracePrompt, $this->yyTokenName[$yymajor]); + $yymx = $this->yystack[ $this->yyidx ]->major; + if ($yymx === self::YYERRORSYMBOL || $yyerrorhit) { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sDiscard input token %s\n", + $this->yyTracePrompt, $this->yyTokenName[ $yymajor ]); } $this->yy_destructor($yymajor, $yytokenvalue); $yymajor = self::YYNOCODE; } else { while ($this->yyidx >= 0 && - $yymx != self::YYERRORSYMBOL && - ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE - ){ + $yymx !== self::YYERRORSYMBOL && + ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE + ) { $this->yy_pop_parser_stack(); } - if ($this->yyidx < 0 || $yymajor==0) { + if ($this->yyidx < 0 || $yymajor == 0) { $this->yy_destructor($yymajor, $yytokenvalue); $this->yy_parse_failed(); $yymajor = self::YYNOCODE; - } elseif ($yymx != self::YYERRORSYMBOL) { + } elseif ($yymx !== self::YYERRORSYMBOL) { $u2 = 0; $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2); } @@ -2959,8 +3616,8 @@ function doParse($yymajor, $yytokenvalue) } else { $this->yy_accept(); $yymajor = self::YYNOCODE; - } - } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); + } + } while ($yymajor !== self::YYNOCODE && $this->yyidx >= 0); } } -?> \ No newline at end of file + diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_testinstall.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_testinstall.php new file mode 100644 index 000000000..504a4582c --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_testinstall.php @@ -0,0 +1,609 @@ +\n"; + echo "Smarty Installation test...\n"; + echo "Testing template directory...\n"; + } + $_stream_resolve_include_path = function_exists('stream_resolve_include_path'); + // test if all registered template_dir are accessible + foreach ($smarty->getTemplateDir() as $template_dir) { + $_template_dir = $template_dir; + $template_dir = realpath($template_dir); + // resolve include_path or fail existence + if (!$template_dir) { + if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) { + // try PHP include_path + if ($_stream_resolve_include_path) { + $template_dir = stream_resolve_include_path($_template_dir); + } else { + $template_dir = $smarty->ext->_getIncludePath->getIncludePath($_template_dir, null, $smarty); + } + if ($template_dir !== false) { + if ($errors === null) { + echo "$template_dir is OK.\n"; + } + continue; + } else { + $status = false; + $message = + "FAILED: $_template_dir does not exist (and couldn't be found in include_path either)"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'template_dir' ] = $message; + } + continue; + } + } else { + $status = false; + $message = "FAILED: $_template_dir does not exist"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'template_dir' ] = $message; + } + continue; + } + } + if (!is_dir($template_dir)) { + $status = false; + $message = "FAILED: $template_dir is not a directory"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'template_dir' ] = $message; + } + } elseif (!is_readable($template_dir)) { + $status = false; + $message = "FAILED: $template_dir is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'template_dir' ] = $message; + } + } else { + if ($errors === null) { + echo "$template_dir is OK.\n"; + } + } + } + if ($errors === null) { + echo "Testing compile directory...\n"; + } + // test if registered compile_dir is accessible + $__compile_dir = $smarty->getCompileDir(); + $_compile_dir = realpath($__compile_dir); + if (!$_compile_dir) { + $status = false; + $message = "FAILED: {$__compile_dir} does not exist"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'compile_dir' ] = $message; + } + } elseif (!is_dir($_compile_dir)) { + $status = false; + $message = "FAILED: {$_compile_dir} is not a directory"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'compile_dir' ] = $message; + } + } elseif (!is_readable($_compile_dir)) { + $status = false; + $message = "FAILED: {$_compile_dir} is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'compile_dir' ] = $message; + } + } elseif (!is_writable($_compile_dir)) { + $status = false; + $message = "FAILED: {$_compile_dir} is not writable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'compile_dir' ] = $message; + } + } else { + if ($errors === null) { + echo "{$_compile_dir} is OK.\n"; + } + } + if ($errors === null) { + echo "Testing plugins directory...\n"; + } + // test if all registered plugins_dir are accessible + // and if core plugins directory is still registered + $_core_plugins_dir = realpath(dirname(__FILE__) . '/../plugins'); + $_core_plugins_available = false; + foreach ($smarty->getPluginsDir() as $plugin_dir) { + $_plugin_dir = $plugin_dir; + $plugin_dir = realpath($plugin_dir); + // resolve include_path or fail existence + if (!$plugin_dir) { + if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) { + // try PHP include_path + if ($_stream_resolve_include_path) { + $plugin_dir = stream_resolve_include_path($_plugin_dir); + } else { + $plugin_dir = $smarty->ext->_getIncludePath->getIncludePath($_plugin_dir, null, $smarty); + } + if ($plugin_dir !== false) { + if ($errors === null) { + echo "$plugin_dir is OK.\n"; + } + continue; + } else { + $status = false; + $message = "FAILED: $_plugin_dir does not exist (and couldn't be found in include_path either)"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'plugins_dir' ] = $message; + } + continue; + } + } else { + $status = false; + $message = "FAILED: $_plugin_dir does not exist"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'plugins_dir' ] = $message; + } + continue; + } + } + if (!is_dir($plugin_dir)) { + $status = false; + $message = "FAILED: $plugin_dir is not a directory"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'plugins_dir' ] = $message; + } + } elseif (!is_readable($plugin_dir)) { + $status = false; + $message = "FAILED: $plugin_dir is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'plugins_dir' ] = $message; + } + } elseif ($_core_plugins_dir && $_core_plugins_dir == realpath($plugin_dir)) { + $_core_plugins_available = true; + if ($errors === null) { + echo "$plugin_dir is OK.\n"; + } + } else { + if ($errors === null) { + echo "$plugin_dir is OK.\n"; + } + } + } + if (!$_core_plugins_available) { + $status = false; + $message = "WARNING: Smarty's own libs/plugins is not available"; + if ($errors === null) { + echo $message . ".\n"; + } elseif (!isset($errors[ 'plugins_dir' ])) { + $errors[ 'plugins_dir' ] = $message; + } + } + if ($errors === null) { + echo "Testing cache directory...\n"; + } + // test if all registered cache_dir is accessible + $__cache_dir = $smarty->getCacheDir(); + $_cache_dir = realpath($__cache_dir); + if (!$_cache_dir) { + $status = false; + $message = "FAILED: {$__cache_dir} does not exist"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'cache_dir' ] = $message; + } + } elseif (!is_dir($_cache_dir)) { + $status = false; + $message = "FAILED: {$_cache_dir} is not a directory"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'cache_dir' ] = $message; + } + } elseif (!is_readable($_cache_dir)) { + $status = false; + $message = "FAILED: {$_cache_dir} is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'cache_dir' ] = $message; + } + } elseif (!is_writable($_cache_dir)) { + $status = false; + $message = "FAILED: {$_cache_dir} is not writable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'cache_dir' ] = $message; + } + } else { + if ($errors === null) { + echo "{$_cache_dir} is OK.\n"; + } + } + if ($errors === null) { + echo "Testing configs directory...\n"; + } + // test if all registered config_dir are accessible + foreach ($smarty->getConfigDir() as $config_dir) { + $_config_dir = $config_dir; + // resolve include_path or fail existence + if (!$config_dir) { + if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_config_dir)) { + // try PHP include_path + if ($_stream_resolve_include_path) { + $config_dir = stream_resolve_include_path($_config_dir); + } else { + $config_dir = $smarty->ext->_getIncludePath->getIncludePath($_config_dir, null, $smarty); + } + if ($config_dir !== false) { + if ($errors === null) { + echo "$config_dir is OK.\n"; + } + continue; + } else { + $status = false; + $message = "FAILED: $_config_dir does not exist (and couldn't be found in include_path either)"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'config_dir' ] = $message; + } + continue; + } + } else { + $status = false; + $message = "FAILED: $_config_dir does not exist"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'config_dir' ] = $message; + } + continue; + } + } + if (!is_dir($config_dir)) { + $status = false; + $message = "FAILED: $config_dir is not a directory"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'config_dir' ] = $message; + } + } elseif (!is_readable($config_dir)) { + $status = false; + $message = "FAILED: $config_dir is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'config_dir' ] = $message; + } + } else { + if ($errors === null) { + echo "$config_dir is OK.\n"; + } + } + } + if ($errors === null) { + echo "Testing sysplugin files...\n"; + } + // test if sysplugins are available + $source = SMARTY_SYSPLUGINS_DIR; + if (is_dir($source)) { + $expectedSysplugins = array( + 'smartycompilerexception.php' => true, + 'smartyexception.php' => true, + 'smarty_cacheresource.php' => true, + 'smarty_cacheresource_custom.php' => true, + 'smarty_cacheresource_keyvaluestore.php' => true, + 'smarty_data.php' => true, + 'smarty_internal_block.php' => true, + 'smarty_internal_cacheresource_file.php' => true, + 'smarty_internal_compilebase.php' => true, + 'smarty_internal_compile_append.php' => true, + 'smarty_internal_compile_assign.php' => true, + 'smarty_internal_compile_block.php' => true, + 'smarty_internal_compile_block_child.php' => true, + 'smarty_internal_compile_block_parent.php' => true, + 'smarty_internal_compile_child.php' => true, + 'smarty_internal_compile_parent.php' => true, + 'smarty_internal_compile_break.php' => true, + 'smarty_internal_compile_call.php' => true, + 'smarty_internal_compile_capture.php' => true, + 'smarty_internal_compile_config_load.php' => true, + 'smarty_internal_compile_continue.php' => true, + 'smarty_internal_compile_debug.php' => true, + 'smarty_internal_compile_eval.php' => true, + 'smarty_internal_compile_extends.php' => true, + 'smarty_internal_compile_for.php' => true, + 'smarty_internal_compile_foreach.php' => true, + 'smarty_internal_compile_function.php' => true, + 'smarty_internal_compile_if.php' => true, + 'smarty_internal_compile_include.php' => true, + 'smarty_internal_compile_include_php.php' => true, + 'smarty_internal_compile_insert.php' => true, + 'smarty_internal_compile_ldelim.php' => true, + 'smarty_internal_compile_make_nocache.php' => true, + 'smarty_internal_compile_nocache.php' => true, + 'smarty_internal_compile_private_block_plugin.php' => true, + 'smarty_internal_compile_private_foreachsection.php' => true, + 'smarty_internal_compile_private_function_plugin.php' => true, + 'smarty_internal_compile_private_modifier.php' => true, + 'smarty_internal_compile_private_object_block_function.php' => true, + 'smarty_internal_compile_private_object_function.php' => true, + 'smarty_internal_compile_private_php.php' => true, + 'smarty_internal_compile_private_print_expression.php' => true, + 'smarty_internal_compile_private_registered_block.php' => true, + 'smarty_internal_compile_private_registered_function.php' => true, + 'smarty_internal_compile_private_special_variable.php' => true, + 'smarty_internal_compile_rdelim.php' => true, + 'smarty_internal_compile_section.php' => true, + 'smarty_internal_compile_setfilter.php' => true, + 'smarty_internal_compile_shared_inheritance.php' => true, + 'smarty_internal_compile_while.php' => true, + 'smarty_internal_configfilelexer.php' => true, + 'smarty_internal_configfileparser.php' => true, + 'smarty_internal_config_file_compiler.php' => true, + 'smarty_internal_data.php' => true, + 'smarty_internal_debug.php' => true, + 'smarty_internal_errorhandler.php' => true, + 'smarty_internal_extension_handler.php' => true, + 'smarty_internal_method_addautoloadfilters.php' => true, + 'smarty_internal_method_adddefaultmodifiers.php' => true, + 'smarty_internal_method_append.php' => true, + 'smarty_internal_method_appendbyref.php' => true, + 'smarty_internal_method_assignbyref.php' => true, + 'smarty_internal_method_assignglobal.php' => true, + 'smarty_internal_method_clearallassign.php' => true, + 'smarty_internal_method_clearallcache.php' => true, + 'smarty_internal_method_clearassign.php' => true, + 'smarty_internal_method_clearcache.php' => true, + 'smarty_internal_method_clearcompiledtemplate.php' => true, + 'smarty_internal_method_clearconfig.php' => true, + 'smarty_internal_method_compileallconfig.php' => true, + 'smarty_internal_method_compilealltemplates.php' => true, + 'smarty_internal_method_configload.php' => true, + 'smarty_internal_method_createdata.php' => true, + 'smarty_internal_method_getautoloadfilters.php' => true, + 'smarty_internal_method_getconfigvariable.php' => true, + 'smarty_internal_method_getconfigvars.php' => true, + 'smarty_internal_method_getdebugtemplate.php' => true, + 'smarty_internal_method_getdefaultmodifiers.php' => true, + 'smarty_internal_method_getglobal.php' => true, + 'smarty_internal_method_getregisteredobject.php' => true, + 'smarty_internal_method_getstreamvariable.php' => true, + 'smarty_internal_method_gettags.php' => true, + 'smarty_internal_method_gettemplatevars.php' => true, + 'smarty_internal_method_literals.php' => true, + 'smarty_internal_method_loadfilter.php' => true, + 'smarty_internal_method_loadplugin.php' => true, + 'smarty_internal_method_mustcompile.php' => true, + 'smarty_internal_method_registercacheresource.php' => true, + 'smarty_internal_method_registerclass.php' => true, + 'smarty_internal_method_registerdefaultconfighandler.php' => true, + 'smarty_internal_method_registerdefaultpluginhandler.php' => true, + 'smarty_internal_method_registerdefaulttemplatehandler.php' => true, + 'smarty_internal_method_registerfilter.php' => true, + 'smarty_internal_method_registerobject.php' => true, + 'smarty_internal_method_registerplugin.php' => true, + 'smarty_internal_method_registerresource.php' => true, + 'smarty_internal_method_setautoloadfilters.php' => true, + 'smarty_internal_method_setdebugtemplate.php' => true, + 'smarty_internal_method_setdefaultmodifiers.php' => true, + 'smarty_internal_method_unloadfilter.php' => true, + 'smarty_internal_method_unregistercacheresource.php' => true, + 'smarty_internal_method_unregisterfilter.php' => true, + 'smarty_internal_method_unregisterobject.php' => true, + 'smarty_internal_method_unregisterplugin.php' => true, + 'smarty_internal_method_unregisterresource.php' => true, + 'smarty_internal_nocache_insert.php' => true, + 'smarty_internal_parsetree.php' => true, + 'smarty_internal_parsetree_code.php' => true, + 'smarty_internal_parsetree_dq.php' => true, + 'smarty_internal_parsetree_dqcontent.php' => true, + 'smarty_internal_parsetree_tag.php' => true, + 'smarty_internal_parsetree_template.php' => true, + 'smarty_internal_parsetree_text.php' => true, + 'smarty_internal_resource_eval.php' => true, + 'smarty_internal_resource_extends.php' => true, + 'smarty_internal_resource_file.php' => true, + 'smarty_internal_resource_php.php' => true, + 'smarty_internal_resource_registered.php' => true, + 'smarty_internal_resource_stream.php' => true, + 'smarty_internal_resource_string.php' => true, + 'smarty_internal_runtime_cachemodify.php' => true, + 'smarty_internal_runtime_cacheresourcefile.php' => true, + 'smarty_internal_runtime_capture.php' => true, + 'smarty_internal_runtime_codeframe.php' => true, + 'smarty_internal_runtime_filterhandler.php' => true, + 'smarty_internal_runtime_foreach.php' => true, + 'smarty_internal_runtime_getincludepath.php' => true, + 'smarty_internal_runtime_inheritance.php' => true, + 'smarty_internal_runtime_make_nocache.php' => true, + 'smarty_internal_runtime_tplfunction.php' => true, + 'smarty_internal_runtime_updatecache.php' => true, + 'smarty_internal_runtime_updatescope.php' => true, + 'smarty_internal_runtime_writefile.php' => true, + 'smarty_internal_smartytemplatecompiler.php' => true, + 'smarty_internal_template.php' => true, + 'smarty_internal_templatebase.php' => true, + 'smarty_internal_templatecompilerbase.php' => true, + 'smarty_internal_templatelexer.php' => true, + 'smarty_internal_templateparser.php' => true, + 'smarty_internal_testinstall.php' => true, + 'smarty_internal_undefined.php' => true, + 'smarty_resource.php' => true, + 'smarty_resource_custom.php' => true, + 'smarty_resource_recompiled.php' => true, + 'smarty_resource_uncompiled.php' => true, + 'smarty_security.php' => true, + 'smarty_template_cached.php' => true, + 'smarty_template_compiled.php' => true, + 'smarty_template_config.php' => true, + 'smarty_template_resource_base.php' => true, + 'smarty_template_source.php' => true, + 'smarty_undefined_variable.php' => true, + 'smarty_variable.php' => true, + ); + $iterator = new DirectoryIterator($source); + foreach ($iterator as $file) { + if (!$file->isDot()) { + $filename = $file->getFilename(); + if (isset($expectedSysplugins[ $filename ])) { + unset($expectedSysplugins[ $filename ]); + } + } + } + if ($expectedSysplugins) { + $status = false; + $message = "FAILED: files missing from libs/sysplugins: " . join(', ', array_keys($expectedSysplugins)); + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'sysplugins' ] = $message; + } + } elseif ($errors === null) { + echo "... OK\n"; + } + } else { + $status = false; + $message = "FAILED: " . SMARTY_SYSPLUGINS_DIR . ' is not a directory'; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'sysplugins_dir_constant' ] = $message; + } + } + if ($errors === null) { + echo "Testing plugin files...\n"; + } + // test if core plugins are available + $source = SMARTY_PLUGINS_DIR; + if (is_dir($source)) { + $expectedPlugins = array( + 'block.textformat.php' => true, + 'function.counter.php' => true, + 'function.cycle.php' => true, + 'function.fetch.php' => true, + 'function.html_checkboxes.php' => true, + 'function.html_image.php' => true, + 'function.html_options.php' => true, + 'function.html_radios.php' => true, + 'function.html_select_date.php' => true, + 'function.html_select_time.php' => true, + 'function.html_table.php' => true, + 'function.mailto.php' => true, + 'function.math.php' => true, + 'modifier.capitalize.php' => true, + 'modifier.date_format.php' => true, + 'modifier.debug_print_var.php' => true, + 'modifier.escape.php' => true, + 'modifier.mb_wordwrap.php' => true, + 'modifier.regex_replace.php' => true, + 'modifier.replace.php' => true, + 'modifier.spacify.php' => true, + 'modifier.truncate.php' => true, + 'modifiercompiler.cat.php' => true, + 'modifiercompiler.count_characters.php' => true, + 'modifiercompiler.count_paragraphs.php' => true, + 'modifiercompiler.count_sentences.php' => true, + 'modifiercompiler.count_words.php' => true, + 'modifiercompiler.default.php' => true, + 'modifiercompiler.escape.php' => true, + 'modifiercompiler.from_charset.php' => true, + 'modifiercompiler.indent.php' => true, + 'modifiercompiler.lower.php' => true, + 'modifiercompiler.noprint.php' => true, + 'modifiercompiler.string_format.php' => true, + 'modifiercompiler.strip.php' => true, + 'modifiercompiler.strip_tags.php' => true, + 'modifiercompiler.to_charset.php' => true, + 'modifiercompiler.unescape.php' => true, + 'modifiercompiler.upper.php' => true, + 'modifiercompiler.wordwrap.php' => true, + 'outputfilter.trimwhitespace.php' => true, + 'shared.escape_special_chars.php' => true, + 'shared.literal_compiler_param.php' => true, + 'shared.make_timestamp.php' => true, + 'shared.mb_str_replace.php' => true, + 'shared.mb_unicode.php' => true, + 'variablefilter.htmlspecialchars.php' => true, + ); + $iterator = new DirectoryIterator($source); + foreach ($iterator as $file) { + if (!$file->isDot()) { + $filename = $file->getFilename(); + if (isset($expectedPlugins[ $filename ])) { + unset($expectedPlugins[ $filename ]); + } + } + } + if ($expectedPlugins) { + $status = false; + $message = "FAILED: files missing from libs/plugins: " . join(', ', array_keys($expectedPlugins)); + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'plugins' ] = $message; + } + } elseif ($errors === null) { + echo "... OK\n"; + } + } else { + $status = false; + $message = "FAILED: " . SMARTY_PLUGINS_DIR . ' is not a directory'; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors[ 'plugins_dir_constant' ] = $message; + } + } + if ($errors === null) { + echo "Tests complete.\n"; + echo "\n"; + } + return $status; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_undefined.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_undefined.php new file mode 100644 index 000000000..7df0acc2d --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_undefined.php @@ -0,0 +1,67 @@ +class = $class; + } + + /** + * Wrapper for obsolete class Smarty_Internal_Runtime_ValidateCompiled + * + * @param \Smarty_Internal_Template $tpl + * @param array $properties special template properties + * @param bool $cache flag if called from cache file + * + * @return bool false + */ + public function decodeProperties(Smarty_Internal_Template $tpl, $properties, $cache = false) + { + if ($cache) { + $tpl->cached->valid = false; + } else { + $tpl->mustCompile = true; + } + return false; + } + + /** + * Call error handler for undefined method + * + * @param string $name unknown method-name + * @param array $args argument array + * + * @return mixed + * @throws SmartyException + */ + public function __call($name, $args) + { + if (isset($this->class)) { + throw new SmartyException("undefined extension class '{$this->class}'"); + } else { + throw new SmartyException(get_class($args[ 0 ]) . "->{$name}() undefined method"); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_utility.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_utility.php deleted file mode 100644 index b532e4a1e..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_utility.php +++ /dev/null @@ -1,300 +0,0 @@ - - * @author Uwe Tews - * @package Smarty - * @subpackage PluginsInternal - * @version 3-SVN$Rev: 3286 $ - */ - -class Smarty_Internal_Utility { - protected $smarty; - - function __construct($smarty) - { - $this->smarty = $smarty; - } - - /** - * Compile all template files - * - * @param string $extension file extension - * @param bool $force_compile force all to recompile - * @param int $time_limit - * @param int $max_errors - * @return integer number of template files recompiled - */ - function compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) - { - // switch off time limit - if (function_exists('set_time_limit')) { - @set_time_limit($time_limit); - } - $this->smarty->force_compile = $force_compile; - $_count = 0; - $_error_count = 0; - // loop over array of template directories - foreach((array)$this->smarty->template_dir as $_dir) { - if (strpos('/\\', substr($_dir, -1)) === false) { - $_dir .= DS; - } - $_compileDirs = new RecursiveDirectoryIterator($_dir); - $_compile = new RecursiveIteratorIterator($_compileDirs); - foreach ($_compile as $_fileinfo) { - if (strpos($_fileinfo, '.svn') !== false) continue; - $_file = $_fileinfo->getFilename(); - if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue; - if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { - $_template_file = $_file; - } else { - $_template_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; - } - echo '
', $_dir, '---', $_template_file; - flush(); - $_start_time = microtime(true); - try { - $_tpl = $this->smarty->createTemplate($_template_file,null,null,null,false); - if ($_tpl->mustCompile()) { - $_tpl->compileTemplateSource(); - echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; - flush(); - } else { - echo ' is up to date'; - flush(); - } - } - catch (Exception $e) { - echo 'Error: ', $e->getMessage(), "

"; - $_error_count++; - } - // free memory - $this->smarty->template_objects = array(); - $_tpl->smarty->template_objects = array(); - $_tpl = null; - if ($max_errors !== null && $_error_count == $max_errors) { - echo '

too many errors'; - exit(); - } - } - } - return $_count; - } - - /** - * Compile all config files - * - * @param string $extension file extension - * @param bool $force_compile force all to recompile - * @param int $time_limit - * @param int $max_errors - * @return integer number of template files recompiled - */ - function compileAllConfig($extention = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null) - { - // switch off time limit - if (function_exists('set_time_limit')) { - @set_time_limit($time_limit); - } - $this->smarty->force_compile = $force_compile; - $_count = 0; - $_error_count = 0; - // loop over array of template directories - foreach((array)$this->smarty->config_dir as $_dir) { - if (strpos('/\\', substr($_dir, -1)) === false) { - $_dir .= DS; - } - $_compileDirs = new RecursiveDirectoryIterator($_dir); - $_compile = new RecursiveIteratorIterator($_compileDirs); - foreach ($_compile as $_fileinfo) { - if (strpos($_fileinfo, '.svn') !== false) continue; - $_file = $_fileinfo->getFilename(); - if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue; - if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { - $_config_file = $_file; - } else { - $_config_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; - } - echo '
', $_dir, '---', $_config_file; - flush(); - $_start_time = microtime(true); - try { - $_config = new Smarty_Internal_Config($_config_file, $this->smarty); - if ($_config->mustCompile()) { - $_config->compileConfigSource(); - echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; - flush(); - } else { - echo ' is up to date'; - flush(); - } - } - catch (Exception $e) { - echo 'Error: ', $e->getMessage(), "

"; - $_error_count++; - } - if ($max_errors !== null && $_error_count == $max_errors) { - echo '

too many errors'; - exit(); - } - } - } - return $_count; - } - - /** - * Delete compiled template file - * - * @param string $resource_name template name - * @param string $compile_id compile id - * @param integer $exp_time expiration time - * @return integer number of template files deleted - */ - function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) - { - $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; - $_dir_sep = $this->smarty->use_sub_dirs ? DS : '^'; - if (isset($resource_name)) { - $_resource_part_1 = $resource_name . '.php'; - $_resource_part_2 = $resource_name . '.cache' . '.php'; - } else { - $_resource_part = ''; - } - $_dir = $this->smarty->compile_dir; - if ($this->smarty->use_sub_dirs && isset($_compile_id)) { - $_dir .= $_compile_id . $_dir_sep; - } - if (isset($_compile_id)) { - $_compile_id_part = $this->smarty->compile_dir . $_compile_id . $_dir_sep; - } - $_count = 0; - $_compileDirs = new RecursiveDirectoryIterator($_dir); - $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); - foreach ($_compile as $_file) { - if (strpos($_file, '.svn') !== false) continue; - if ($_file->isDir()) { - if (!$_compile->isDot()) { - // delete folder if empty - @rmdir($_file->getPathname()); - } - } else { - if ((!isset($_compile_id) || (strlen((string)$_file) > strlen($_compile_id_part) && substr_compare((string)$_file, $_compile_id_part, 0, strlen($_compile_id_part)) == 0)) && - (!isset($resource_name) || (strlen((string)$_file) > strlen($_resource_part_1) && substr_compare((string)$_file, $_resource_part_1, - strlen($_resource_part_1), strlen($_resource_part_1)) == 0) || - (strlen((string)$_file) > strlen($_resource_part_2) && substr_compare((string)$_file, $_resource_part_2, - strlen($_resource_part_2), strlen($_resource_part_2)) == 0))) { - if (isset($exp_time)) { - if (time() - @filemtime($_file) >= $exp_time) { - $_count += @unlink((string) $_file) ? 1 : 0; - } - } else { - $_count += @unlink((string) $_file) ? 1 : 0; - } - } - } - } - return $_count; - } - - /** - * Return array of tag/attributes of all tags used by an template - * - * @param object $templae template object - * @return array of tag/attributes - */ - function getTags(Smarty_Internal_Template $template) - { - $template->smarty->get_used_tags = true; - $template->compileTemplateSource(); - return $template->compiler_object->used_tags; - } - - function testInstall() - { - echo "
\n";
-
-        echo "Smarty Installation test...\n";
-
-        echo "Testing template directory...\n";
-
-        foreach((array)$this->smarty->template_dir as $template_dir) {
-            if (!is_dir($template_dir))
-                echo "FAILED: $template_dir is not a directory.\n";
-            elseif (!is_readable($template_dir))
-                echo "FAILED: $template_dir is not readable.\n";
-            else
-                echo "$template_dir is OK.\n";
-        } 
-
-        echo "Testing compile directory...\n";
-
-        if (!is_dir($this->smarty->compile_dir))
-            echo "FAILED: {$this->smarty->compile_dir} is not a directory.\n";
-        elseif (!is_readable($this->smarty->compile_dir))
-            echo "FAILED: {$this->smarty->compile_dir} is not readable.\n";
-        elseif (!is_writable($this->smarty->compile_dir))
-            echo "FAILED: {$this->smarty->compile_dir} is not writable.\n";
-        else
-            echo "{$this->smarty->compile_dir} is OK.\n";
-
-        echo "Testing plugins directory...\n";
-
-        foreach((array)$this->smarty->plugins_dir as $plugin_dir) {
-            if (!is_dir($plugin_dir))
-                echo "FAILED: $plugin_dir is not a directory.\n";
-            elseif (!is_readable($plugin_dir))
-                echo "FAILED: $plugin_dir is not readable.\n";
-            else
-                echo "$plugin_dir is OK.\n";
-        } 
-
-        echo "Testing cache directory...\n";
-
-        if (!is_dir($this->smarty->cache_dir))
-            echo "FAILED: {$this->smarty->cache_dir} is not a directory.\n";
-        elseif (!is_readable($this->smarty->cache_dir))
-            echo "FAILED: {$this->smarty->cache_dir} is not readable.\n";
-        elseif (!is_writable($this->smarty->cache_dir))
-            echo "FAILED: {$this->smarty->cache_dir} is not writable.\n";
-        else
-            echo "{$this->smarty->cache_dir} is OK.\n";
-
-        echo "Testing configs directory...\n";
-
-        if (!is_dir($this->smarty->config_dir))
-            echo "FAILED: {$this->smarty->config_dir} is not a directory.\n";
-        elseif (!is_readable($this->smarty->config_dir))
-            echo "FAILED: {$this->smarty->config_dir} is not readable.\n";
-        else
-            echo "{$this->smarty->config_dir} is OK.\n";
-
-        echo "Tests complete.\n";
-
-        echo "
\n"; - - return true; - } -} -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_wrapper.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_wrapper.php deleted file mode 100644 index f45153c34..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_wrapper.php +++ /dev/null @@ -1,131 +0,0 @@ - - * @author Uwe Tews - * @package Smarty - * @subpackage PluginsInternal - * @version 3-SVN$Rev: 3286 $ - */ - -/* - * Smarty Backward Compatability Wrapper - */ - -class Smarty_Internal_Wrapper { - - protected $smarty; - - function __construct($smarty) { - $this->smarty = $smarty; - } - - /** - * Converts smarty2-style function call to smarty 3-style function call - * This is expensive, be sure to port your code to Smarty 3! - * - * @param string $name Smarty 2 function name - * @param array $args Smarty 2 function args - */ - function convert($name, $args) { - // throw notice about deprecated function - if($this->smarty->deprecation_notices) - trigger_error("function call '$name' is unknown or deprecated.",E_USER_NOTICE); - // get first and last part of function name - $name_parts = explode('_',$name,2); - switch($name_parts[0]) { - case 'register': - case 'unregister': - switch($name_parts[1]) { - case 'object': - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Object"),$args); - case 'compiler_function': - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Plugin"),array_merge(array('compiler'),$args)); - case 'prefilter': - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Filter"),array_merge(array('pre'),$args)); - case 'postfilter': - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Filter"),array_merge(array('post'),$args)); - case 'outputfilter': - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Filter"),array_merge(array('output'),$args)); - case 'resource': - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Resource"),$args); - default: - return call_user_func_array(array($this->smarty,"{$name_parts[0]}Plugin"),array_merge(array($name_parts[1]),$args)); - } - case 'get': - switch($name_parts[1]) { - case 'template_vars': - return call_user_func_array(array($this->smarty,'getTemplateVars'),$args); - case 'config_vars': - return call_user_func_array(array($this->smarty,'getConfigVars'),$args); - default: - return call_user_func_array(array($myobj,$name_parts[1]),$args); - } - case 'clear': - switch($name_parts[1]) { - case 'all_assign': - return call_user_func_array(array($this->smarty,'clearAllAssign'),$args); - case 'assign': - return call_user_func_array(array($this->smarty,'clearAssign'),$args); - case 'all_cache': - return call_user_func_array(array($this->smarty,'clearAllCache'),$args); - case 'cache': - return call_user_func_array(array($this->smarty,'clearCache'),$args); - case 'compiled_template': - return call_user_func_array(array($this->smarty,'clearCompiledTemplate'),$args); - } - case 'config': - switch($name_parts[1]) { - case 'load': - return call_user_func_array(array($this->smarty,'configLoad'),$args); - } - case 'trigger': - switch($name_parts[1]) { - case 'error': - return call_user_func_array('trigger_error',$args); - } - case 'load': - switch($name_parts[1]) { - case 'filter': - return call_user_func_array(array($this->smarty,'loadFilter'),$args); - } - } - throw new SmartyException("unknown method '$name'"); - } - - /** - * trigger Smarty error - * - * @param string $error_msg - * @param integer $error_type - */ - function trigger_error($error_msg, $error_type = E_USER_WARNING) - { - trigger_error("Smarty error: $error_msg", $error_type); - } -} -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_write_file.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_write_file.php deleted file mode 100644 index 4e34335fb..000000000 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_write_file.php +++ /dev/null @@ -1,56 +0,0 @@ -_dir_perms, true); - } - // write to tmp file, then move to overt file lock race condition - $_tmp_file = tempnam($_dirpath, 'wrt'); - - if (!($fd = @fopen($_tmp_file, 'wb'))) { - $_tmp_file = $_dirpath . DS . uniqid('wrt'); - if (!($fd = @fopen($_tmp_file, 'wb'))) { - throw new SmartyException("unable to write file {$_tmp_file}"); - return false; - } - } - - fwrite($fd, $_contents); - fclose($fd); - - // remove original file - if (file_exists($_filepath)) - @unlink($_filepath); - // rename tmp file - rename($_tmp_file, $_filepath); - // set file permissions - chmod($_filepath, $smarty->_file_perms); - umask($old_umask); - return true; - } -} - -?> \ No newline at end of file diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_resource.php b/WEB-INF/lib/smarty/sysplugins/smarty_resource.php new file mode 100644 index 000000000..aae7e42f7 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_resource.php @@ -0,0 +1,262 @@ + 'smarty_internal_resource_file.php', + 'string' => 'smarty_internal_resource_string.php', + 'extends' => 'smarty_internal_resource_extends.php', + 'stream' => 'smarty_internal_resource_stream.php', + 'eval' => 'smarty_internal_resource_eval.php', + 'php' => 'smarty_internal_resource_php.php' + ); + + /** + * Source is bypassing compiler + * + * @var boolean + */ + public $uncompiled = false; + + /** + * Source must be recompiled on every occasion + * + * @var boolean + */ + public $recompiled = false; + + /** + * Flag if resource does implement populateCompiledFilepath() method + * + * @var bool + */ + public $hasCompiledHandler = false; + + /** + * Load Resource Handler + * + * @param Smarty $smarty smarty object + * @param string $type name of the resource + * + * @throws SmartyException + * @return Smarty_Resource Resource Handler + */ + public static function load(Smarty $smarty, $type) + { + // try smarty's cache + if (isset($smarty->_cache[ 'resource_handlers' ][ $type ])) { + return $smarty->_cache[ 'resource_handlers' ][ $type ]; + } + // try registered resource + if (isset($smarty->registered_resources[ $type ])) { + return $smarty->_cache[ 'resource_handlers' ][ $type ] = + $smarty->registered_resources[ $type ] instanceof Smarty_Resource ? + $smarty->registered_resources[ $type ] : new Smarty_Internal_Resource_Registered(); + } + // try sysplugins dir + if (isset(self::$sysplugins[ $type ])) { + $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type); + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); + } + // try plugins dir + $_resource_class = 'Smarty_Resource_' . ucfirst($type); + if ($smarty->loadPlugin($_resource_class)) { + if (class_exists($_resource_class, false)) { + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); + } else { + $smarty->registerResource( + $type, + array( + "smarty_resource_{$type}_source", "smarty_resource_{$type}_timestamp", + "smarty_resource_{$type}_secure", "smarty_resource_{$type}_trusted" + ) + ); + // give it another try, now that the resource is registered properly + return self::load($smarty, $type); + } + } + // try streams + $_known_stream = stream_get_wrappers(); + if (in_array($type, $_known_stream)) { + // is known stream + if (is_object($smarty->security_policy)) { + $smarty->security_policy->isTrustedStream($type); + } + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new Smarty_Internal_Resource_Stream(); + } + // TODO: try default_(template|config)_handler + // give up + throw new SmartyException("Unknown resource type '{$type}'"); + } + + /** + * extract resource_type and resource_name from template_resource and config_resource + * + * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including). + * + * @param string $resource_name template_resource or config_resource to parse + * @param string $default_resource the default resource_type defined in $smarty + * + * @return array with parsed resource name and type + */ + public static function parseResourceName($resource_name, $default_resource) + { + if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]/', $resource_name, $match)) { + $type = $match[ 1 ]; + $name = substr($resource_name, strlen($match[ 0 ])); + } else { + // no resource given, use default + // or single character before the colon is not a resource type, but part of the filepath + $type = $default_resource; + $name = $resource_name; + } + return array($name, $type); + } + + /** + * modify template_resource according to resource handlers specifications + * + * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance + * @param string $template_resource template_resource to extract resource handler and + * name of + * + * @return string unique resource name + * @throws \SmartyException + */ + public static function getUniqueTemplateName($obj, $template_resource) + { + $smarty = $obj->_getSmartyObj(); + list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); + // TODO: optimize for Smarty's internal resource types + $resource = Smarty_Resource::load($smarty, $type); + // go relative to a given template? + $_file_is_dotted = $name[ 0 ] === '.' && ($name[ 1 ] === '.' || $name[ 1 ] === '/'); + if ($obj->_isTplObj() && $_file_is_dotted + && ($obj->source->type === 'file' || $obj->parent->source->type === 'extends') + ) { + $name = $smarty->_realpath(dirname($obj->parent->source->filepath) . DIRECTORY_SEPARATOR . $name); + } + return $resource->buildUniqueResourceName($smarty, $name); + } + + /** + * initialize Source Object for given resource + * wrapper for backward compatibility to versions < 3.1.22 + * Either [$_template] or [$smarty, $template_resource] must be specified + * + * @param Smarty_Internal_Template $_template template object + * @param Smarty $smarty smarty object + * @param string $template_resource resource identifier + * + * @return \Smarty_Template_Source Source Object + * @throws \SmartyException + */ + public static function source( + Smarty_Internal_Template $_template = null, + Smarty $smarty = null, + $template_resource = null + ) { + return Smarty_Template_Source::load($_template, $smarty, $template_resource); + } + + /** + * Load template's source into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + abstract public function getContent(Smarty_Template_Source $source); + + /** + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + */ + abstract public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null); + + /** + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + */ + public function populateTimestamp(Smarty_Template_Source $source) + { + // intentionally left blank + } + + /** + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name + */ + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + if ($isConfig) { + if (!isset($smarty->_joined_config_dir)) { + $smarty->getTemplateDir(null, true); + } + return get_class($this) . '#' . $smarty->_joined_config_dir . '#' . $resource_name; + } else { + if (!isset($smarty->_joined_template_dir)) { + $smarty->getTemplateDir(); + } + return get_class($this) . '#' . $smarty->_joined_template_dir . '#' . $resource_name; + } + } + + /* + * Check if resource must check time stamps when when loading complied or cached templates. + * Resources like 'extends' which use source components my disable timestamp checks on own resource. + * + * @return bool + */ + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename(preg_replace('![^\w]+!', '_', $source->name)); + } + + /** + * @return bool + */ + public function checkTimestamps() + { + return true; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_resource_custom.php b/WEB-INF/lib/smarty/sysplugins/smarty_resource_custom.php new file mode 100644 index 000000000..8d66be3ae --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_resource_custom.php @@ -0,0 +1,93 @@ +filepath = $source->type . ':' . substr(preg_replace('/[^A-Za-z0-9.]/', '', $source->name), 0, 25); + $source->uid = sha1($source->type . ':' . $source->name); + $mtime = $this->fetchTimestamp($source->name); + if ($mtime !== null) { + $source->timestamp = $mtime; + } else { + $this->fetch($source->name, $content, $timestamp); + $source->timestamp = isset($timestamp) ? $timestamp : false; + if (isset($content)) { + $source->content = $content; + } + } + $source->exists = !!$source->timestamp; + } + + /** + * Load template's source into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + $this->fetch($source->name, $content, $timestamp); + if (isset($content)) { + return $content; + } + throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename(substr(preg_replace('/[^A-Za-z0-9.]/', '', $source->name), 0, 25)); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_resource_recompiled.php b/WEB-INF/lib/smarty/sysplugins/smarty_resource_recompiled.php new file mode 100644 index 000000000..760c4dd33 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_resource_recompiled.php @@ -0,0 +1,94 @@ +compiled; + $compiled->file_dependency = array(); + $compiled->includes = array(); + $compiled->nocache_hash = null; + $compiled->unifunc = null; + $level = ob_get_level(); + ob_start(); + $_smarty_tpl->loadCompiler(); + // call compiler + try { + eval('?>' . $_smarty_tpl->compiler->compileTemplate($_smarty_tpl)); + } catch (Exception $e) { + unset($_smarty_tpl->compiler); + while (ob_get_level() > $level) { + ob_end_clean(); + } + throw $e; + } + // release compiler object to free memory + unset($_smarty_tpl->compiler); + ob_get_clean(); + $compiled->timestamp = time(); + $compiled->exists = true; + } + + /** + * populate Compiled Object with compiled filepath + * + * @param Smarty_Template_Compiled $compiled compiled object + * @param Smarty_Internal_Template $_template template object + * + * @return void + */ + public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template) + { + $compiled->filepath = false; + $compiled->timestamp = false; + $compiled->exists = false; + } + + /* + * Disable timestamp checks for recompiled resource. + * + * @return bool + */ + /** + * @return bool + */ + public function checkTimestamps() + { + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_resource_uncompiled.php b/WEB-INF/lib/smarty/sysplugins/smarty_resource_uncompiled.php new file mode 100644 index 000000000..a11e2c14c --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_resource_uncompiled.php @@ -0,0 +1,49 @@ +filepath = $_template->source->filepath; + $compiled->timestamp = $_template->source->timestamp; + $compiled->exists = $_template->source->exists; + if ($_template->smarty->merge_compiled_includes || $_template->source->handler->checkTimestamps()) { + $compiled->file_dependency[ $_template->source->uid ] = + array($compiled->filepath, $compiled->timestamp, $_template->source->type,); + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_security.php b/WEB-INF/lib/smarty/sysplugins/smarty_security.php index cd066fb4e..441a7e284 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_security.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_security.php @@ -1,16 +1,26 @@ " tags in templates. * possible values: @@ -20,210 +30,692 @@ class Smarty_Security { *
  • Smarty::PHP_REMOVE -> remove php tags
  • *
  • Smarty::PHP_ALLOW -> execute php tags
  • * - * - * @var integer + * + * @var integer */ public $php_handling = Smarty::PHP_PASSTHRU; /** * This is the list of template directories that are considered secure. * $template_dir is in this list implicitly. - * - * @var array + * + * @var array */ public $secure_dir = array(); - /** * This is an array of directories where trusted php scripts reside. * {@link $security} is disabled during their inclusion/execution. - * - * @var array + * + * @var array */ public $trusted_dir = array(); + /** + * List of regular expressions (PCRE) that include trusted URIs + * + * @var array + */ + public $trusted_uri = array(); /** - * This is an array of trusted static classes. + * List of trusted constants names * + * @var array + */ + public $trusted_constants = array(); + + /** + * This is an array of trusted static classes. * If empty access to all static classes is allowed. * If set to 'none' none is allowed. - * @var array + * + * @var array */ public $static_classes = array(); /** - * This is an array of trusted PHP functions. + * This is an nested array of trusted classes and static methods. + * If empty access to all static classes and methods is allowed. + * Format: + * array ( + * 'class_1' => array('method_1', 'method_2'), // allowed methods listed + * 'class_2' => array(), // all methods of class allowed + * ) + * If set to null none is allowed. * + * @var array + */ + public $trusted_static_methods = array(); + + /** + * This is an array of trusted static properties. + * If empty access to all static classes and properties is allowed. + * Format: + * array ( + * 'class_1' => array('prop_1', 'prop_2'), // allowed properties listed + * 'class_2' => array(), // all properties of class allowed + * ) + * If set to null none is allowed. + * + * @var array + */ + public $trusted_static_properties = array(); + + /** + * This is an array of trusted PHP functions. * If empty all functions are allowed. * To disable all PHP functions set $php_functions = null. - * @var array + * + * @var array */ - public $php_functions = array('isset', 'empty', - 'count', 'sizeof','in_array', 'is_array','time','nl2br'); + public $php_functions = array('isset', 'empty', 'count', 'sizeof', 'in_array', 'is_array', 'time',); /** - * This is an array of trusted PHP modifers. - * + * This is an array of trusted PHP modifiers. * If empty all modifiers are allowed. - * To disable all modifier set $modifiers = null. - * @var array + * To disable all modifier set $php_modifiers = null. + * + * @var array */ - public $php_modifiers = array('escape','count'); + public $php_modifiers = array('escape', 'count', 'nl2br',); /** - * This is an array of trusted streams. + * This is an array of allowed tags. + * If empty no restriction by allowed_tags. + * + * @var array + */ + public $allowed_tags = array(); + + /** + * This is an array of disabled tags. + * If empty no restriction by disabled_tags. * + * @var array + */ + public $disabled_tags = array(); + + /** + * This is an array of allowed modifier plugins. + * If empty no restriction by allowed_modifiers. + * + * @var array + */ + public $allowed_modifiers = array(); + + /** + * This is an array of disabled modifier plugins. + * If empty no restriction by disabled_modifiers. + * + * @var array + */ + public $disabled_modifiers = array(); + + /** + * This is an array of disabled special $smarty variables. + * + * @var array + */ + public $disabled_special_smarty_vars = array(); + + /** + * This is an array of trusted streams. * If empty all streams are allowed. * To disable all streams set $streams = null. - * @var array + * + * @var array */ public $streams = array('file'); + /** * + flag if constants can be accessed from template + * + * @var boolean */ public $allow_constants = true; + /** * + flag if super globals can be accessed from template + * + * @var boolean */ public $allow_super_globals = true; + + /** + * max template nesting level + * + * @var int + */ + public $max_template_nesting = 0; + + /** + * current template nesting level + * + * @var int + */ + private $_current_template_nesting = 0; + + /** + * Cache for $resource_dir lookup + * + * @var array + */ + protected $_resource_dir = array(); + /** - * + flag if the {php} and {include_php} tag can be executed + * Cache for $template_dir lookup + * + * @var array */ - public $allow_php_tag = false; + protected $_template_dir = array(); + /** + * Cache for $config_dir lookup + * + * @var array + */ + protected $_config_dir = array(); + + /** + * Cache for $secure_dir lookup + * + * @var array + */ + protected $_secure_dir = array(); + + /** + * Cache for $php_resource_dir lookup + * + * @var array + */ + protected $_php_resource_dir = null; + + /** + * Cache for $trusted_dir lookup + * + * @var array + */ + protected $_trusted_dir = null; + + /** + * Cache for include path status + * + * @var bool + */ + protected $_include_path_status = false; + + /** + * Cache for $_include_array lookup + * + * @var array + */ + protected $_include_dir = array(); + + /** + * @param Smarty $smarty + */ public function __construct($smarty) { - $this->smarty = $smarty; - } + $this->smarty = $smarty; + } + /** * Check if PHP function is trusted. - * - * @param string $function_name + * + * @param string $function_name * @param object $compiler compiler object - * @return boolean true if function is trusted + * + * @return boolean true if function is trusted */ - function isTrustedPhpFunction($function_name, $compiler) + public function isTrustedPhpFunction($function_name, $compiler) { - if (isset($this->php_functions) && (empty($this->php_functions) || in_array($function_name, $this->php_functions))) { + if (isset($this->php_functions) + && (empty($this->php_functions) || in_array($function_name, $this->php_functions)) + ) { return true; - } else { - $compiler->trigger_template_error ("PHP function '{$function_name}' not allowed by security setting"); - return false; - } - } + } + $compiler->trigger_template_error("PHP function '{$function_name}' not allowed by security setting"); + return false; // should not, but who knows what happens to the compiler in the future? + } /** * Check if static class is trusted. - * - * @param string $class_name + * + * @param string $class_name + * @param object $compiler compiler object + * + * @return boolean true if class is trusted + */ + public function isTrustedStaticClass($class_name, $compiler) + { + if (isset($this->static_classes) + && (empty($this->static_classes) || in_array($class_name, $this->static_classes)) + ) { + return true; + } + $compiler->trigger_template_error("access to static class '{$class_name}' not allowed by security setting"); + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if static class method/property is trusted. + * + * @param string $class_name + * @param string $params + * @param object $compiler compiler object + * + * @return boolean true if class method is trusted + */ + public function isTrustedStaticClassAccess($class_name, $params, $compiler) + { + if (!isset($params[ 2 ])) { + // fall back + return $this->isTrustedStaticClass($class_name, $compiler); + } + if ($params[ 2 ] === 'method') { + $allowed = $this->trusted_static_methods; + $name = substr($params[ 0 ], 0, strpos($params[ 0 ], '(')); + } else { + $allowed = $this->trusted_static_properties; + // strip '$' + $name = substr($params[ 0 ], 1); + } + if (isset($allowed)) { + if (empty($allowed)) { + // fall back + return $this->isTrustedStaticClass($class_name, $compiler); + } + if (isset($allowed[ $class_name ]) + && (empty($allowed[ $class_name ]) || in_array($name, $allowed[ $class_name ])) + ) { + return true; + } + } + $compiler->trigger_template_error("access to static class '{$class_name}' {$params[2]} '{$name}' not allowed by security setting"); + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if PHP modifier is trusted. + * + * @param string $modifier_name * @param object $compiler compiler object - * @return boolean true if class is trusted + * + * @return boolean true if modifier is trusted */ - function isTrustedStaticClass($class_name, $compiler) + public function isTrustedPhpModifier($modifier_name, $compiler) { - if (isset($this->static_classes) && (empty($this->static_classes) || in_array($class_name, $this->static_classes))) { + if (isset($this->php_modifiers) + && (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers)) + ) { + return true; + } + $compiler->trigger_template_error("modifier '{$modifier_name}' not allowed by security setting"); + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if tag is trusted. + * + * @param string $tag_name + * @param object $compiler compiler object + * + * @return boolean true if tag is trusted + */ + public function isTrustedTag($tag_name, $compiler) + { + // check for internal always required tags + if (in_array( + $tag_name, + array( + 'assign', 'call', 'private_filter', 'private_block_plugin', 'private_function_plugin', + 'private_object_block_function', 'private_object_function', 'private_registered_function', + 'private_registered_block', 'private_special_variable', 'private_print_expression', + 'private_modifier' + ) + ) + ) { + return true; + } + // check security settings + if (empty($this->allowed_tags)) { + if (empty($this->disabled_tags) || !in_array($tag_name, $this->disabled_tags)) { + return true; + } else { + $compiler->trigger_template_error("tag '{$tag_name}' disabled by security setting", null, true); + } + } elseif (in_array($tag_name, $this->allowed_tags) && !in_array($tag_name, $this->disabled_tags)) { return true; } else { - $compiler->trigger_template_error ("access to static class '{$class_name}' not allowed by security setting"); - return false; - } - } - /** - * Check if modifier is trusted. - * - * @param string $modifier_name + $compiler->trigger_template_error("tag '{$tag_name}' not allowed by security setting", null, true); + } + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if special $smarty variable is trusted. + * + * @param string $var_name * @param object $compiler compiler object - * @return boolean true if modifier is trusted + * + * @return boolean true if tag is trusted */ - function isTrustedModifier($modifier_name, $compiler) + public function isTrustedSpecialSmartyVar($var_name, $compiler) { - if (isset($this->php_modifiers) && (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers))) { + if (!in_array($var_name, $this->disabled_special_smarty_vars)) { return true; } else { - $compiler->trigger_template_error ("modifier '{$modifier_name}' not allowed by security setting"); - return false; - } - } + $compiler->trigger_template_error( + "special variable '\$smarty.{$var_name}' not allowed by security setting", + null, + true + ); + } + return false; // should not, but who knows what happens to the compiler in the future? + } + /** - * Check if stream is trusted. - * - * @param string $stream_name + * Check if modifier plugin is trusted. + * + * @param string $modifier_name * @param object $compiler compiler object - * @return boolean true if stream is trusted + * + * @return boolean true if tag is trusted */ - function isTrustedStream($stream_name) + public function isTrustedModifier($modifier_name, $compiler) { - if (isset($this->streams) && (empty($this->streams) || in_array($stream_name, $this->streams))) { + // check for internal always allowed modifier + if (in_array($modifier_name, array('default'))) { + return true; + } + // check security settings + if (empty($this->allowed_modifiers)) { + if (empty($this->disabled_modifiers) || !in_array($modifier_name, $this->disabled_modifiers)) { + return true; + } else { + $compiler->trigger_template_error( + "modifier '{$modifier_name}' disabled by security setting", + null, + true + ); + } + } elseif (in_array($modifier_name, $this->allowed_modifiers) + && !in_array($modifier_name, $this->disabled_modifiers) + ) { return true; } else { - throw new SmartyException ("stream '{$stream_name}' not allowed by security setting"); - return false; - } - } + $compiler->trigger_template_error( + "modifier '{$modifier_name}' not allowed by security setting", + null, + true + ); + } + return false; // should not, but who knows what happens to the compiler in the future? + } /** - * Check if directory of file resource is trusted. - * - * @param string $filepath + * Check if constants are enabled or trusted + * + * @param string $const constant name * @param object $compiler compiler object - * @return boolean true if directory is trusted + * + * @return bool */ - function isTrustedResourceDir($filepath) + public function isTrustedConstant($const, $compiler) { - $_rp = realpath($filepath); - if (isset($this->smarty->template_dir)) { - foreach ((array)$this->smarty->template_dir as $curr_dir) { - if (($_cd = realpath($curr_dir)) !== false && - strncmp($_rp, $_cd, strlen($_cd)) == 0 && - (strlen($_rp) == strlen($_cd) || substr($_rp, strlen($_cd), 1) == DS)) { - return true; - } - } - } - if (!empty($this->smarty->security_policy->secure_dir)) { - foreach ((array)$this->smarty->security_policy->secure_dir as $curr_dir) { - if (($_cd = realpath($curr_dir)) !== false) { - if ($_cd == $_rp) { - return true; - } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 && - (strlen($_rp) == strlen($_cd) || substr($_rp, strlen($_cd), 1) == DS)) { - return true; - } - } - } - } - - throw new SmartyException ("directory '{$_rp}' not allowed by security setting"); + if (in_array($const, array('true', 'false', 'null'))) { + return true; + } + if (!empty($this->trusted_constants)) { + if (!in_array(strtolower($const), $this->trusted_constants)) { + $compiler->trigger_template_error("Security: access to constant '{$const}' not permitted"); + return false; + } + return true; + } + if ($this->allow_constants) { + return true; + } + $compiler->trigger_template_error("Security: access to constants not permitted"); return false; - } - + } + + /** + * Check if stream is trusted. + * + * @param string $stream_name + * + * @return boolean true if stream is trusted + * @throws SmartyException if stream is not trusted + */ + public function isTrustedStream($stream_name) + { + if (isset($this->streams) && (empty($this->streams) || in_array($stream_name, $this->streams))) { + return true; + } + throw new SmartyException("stream '{$stream_name}' not allowed by security setting"); + } + /** * Check if directory of file resource is trusted. - * - * @param string $filepath - * @param object $compiler compiler object - * @return boolean true if directory is trusted - */ - function isTrustedPHPDir($filepath) - { - $_rp = realpath($filepath); - if (!empty($this->trusted_dir)) { - foreach ((array)$this->trusted_dir as $curr_dir) { - if (($_cd = realpath($curr_dir)) !== false) { - if ($_cd == $_rp) { - return true; - } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 && - substr($_rp, strlen($_cd), 1) == DS) { - return true; - } - } - } - } - - throw new SmartyException ("directory '{$_rp}' not allowed by security setting"); - return false; - } -} + * + * @param string $filepath + * @param null|bool $isConfig + * + * @return bool true if directory is trusted + * @throws \SmartyException if directory is not trusted + */ + public function isTrustedResourceDir($filepath, $isConfig = null) + { + if ($this->_include_path_status !== $this->smarty->use_include_path) { + $_dir = + $this->smarty->use_include_path ? $this->smarty->ext->_getIncludePath->getIncludePathDirs($this->smarty) : array(); + if ($this->_include_dir !== $_dir) { + $this->_updateResourceDir($this->_include_dir, $_dir); + $this->_include_dir = $_dir; + } + $this->_include_path_status = $this->smarty->use_include_path; + } + $_dir = $this->smarty->getTemplateDir(); + if ($this->_template_dir !== $_dir) { + $this->_updateResourceDir($this->_template_dir, $_dir); + $this->_template_dir = $_dir; + } + $_dir = $this->smarty->getConfigDir(); + if ($this->_config_dir !== $_dir) { + $this->_updateResourceDir($this->_config_dir, $_dir); + $this->_config_dir = $_dir; + } + if ($this->_secure_dir !== $this->secure_dir) { + $this->secure_dir = (array)$this->secure_dir; + foreach ($this->secure_dir as $k => $d) { + $this->secure_dir[ $k ] = $this->smarty->_realpath($d . DIRECTORY_SEPARATOR, true); + } + $this->_updateResourceDir($this->_secure_dir, $this->secure_dir); + $this->_secure_dir = $this->secure_dir; + } + $addPath = $this->_checkDir($filepath, $this->_resource_dir); + if ($addPath !== false) { + $this->_resource_dir = array_merge($this->_resource_dir, $addPath); + } + return true; + } + + /** + * Check if URI (e.g. {fetch} or {html_image}) is trusted + * To simplify things, isTrustedUri() resolves all input to "{$PROTOCOL}://{$HOSTNAME}". + * So "http://username:password@hello.world.example.org:8080/some-path?some=query-string" + * is reduced to "http://hello.world.example.org" prior to applying the patters from {@link $trusted_uri}. + * + * @param string $uri + * + * @return boolean true if URI is trusted + * @throws SmartyException if URI is not trusted + * @uses $trusted_uri for list of patterns to match against $uri + */ + public function isTrustedUri($uri) + { + $_uri = parse_url($uri); + if (!empty($_uri[ 'scheme' ]) && !empty($_uri[ 'host' ])) { + $_uri = $_uri[ 'scheme' ] . '://' . $_uri[ 'host' ]; + foreach ($this->trusted_uri as $pattern) { + if (preg_match($pattern, $_uri)) { + return true; + } + } + } + throw new SmartyException("URI '{$uri}' not allowed by security setting"); + } + + /** + * Check if directory of file resource is trusted. + * + * @param string $filepath + * + * @return boolean true if directory is trusted + * @throws SmartyException if PHP directory is not trusted + */ + public function isTrustedPHPDir($filepath) + { + if (empty($this->trusted_dir)) { + throw new SmartyException("directory '{$filepath}' not allowed by security setting (no trusted_dir specified)"); + } + // check if index is outdated + if (!$this->_trusted_dir || $this->_trusted_dir !== $this->trusted_dir) { + $this->_php_resource_dir = array(); + $this->_trusted_dir = $this->trusted_dir; + foreach ((array)$this->trusted_dir as $directory) { + $directory = $this->smarty->_realpath($directory . '/', true); + $this->_php_resource_dir[ $directory ] = true; + } + } + $addPath = $this->_checkDir($filepath, $this->_php_resource_dir); + if ($addPath !== false) { + $this->_php_resource_dir = array_merge($this->_php_resource_dir, $addPath); + } + return true; + } -?> \ No newline at end of file + /** + * Remove old directories and its sub folders, add new directories + * + * @param array $oldDir + * @param array $newDir + */ + private function _updateResourceDir($oldDir, $newDir) + { + foreach ($oldDir as $directory) { + // $directory = $this->smarty->_realpath($directory, true); + $length = strlen($directory); + foreach ($this->_resource_dir as $dir) { + if (substr($dir, 0, $length) === $directory) { + unset($this->_resource_dir[ $dir ]); + } + } + } + foreach ($newDir as $directory) { + // $directory = $this->smarty->_realpath($directory, true); + $this->_resource_dir[ $directory ] = true; + } + } + + /** + * Check if file is inside a valid directory + * + * @param string $filepath + * @param array $dirs valid directories + * + * @return array|bool + * @throws \SmartyException + */ + private function _checkDir($filepath, $dirs) + { + $directory = dirname($this->smarty->_realpath($filepath, true)) . DIRECTORY_SEPARATOR; + $_directory = array(); + if (!preg_match('#[\\\\/][.][.][\\\\/]#', $directory)) { + while (true) { + // test if the directory is trusted + if (isset($dirs[ $directory ])) { + return $_directory; + } + // abort if we've reached root + if (!preg_match('#[\\\\/][^\\\\/]+[\\\\/]$#', $directory)) { + // give up + break; + } + // remember the directory to add it to _resource_dir in case we're successful + $_directory[ $directory ] = true; + // bubble up one level + $directory = preg_replace('#[\\\\/][^\\\\/]+[\\\\/]$#', DIRECTORY_SEPARATOR, $directory); + } + } + // give up + throw new SmartyException(sprintf('Smarty Security: not trusted file path \'%s\' ', $filepath)); + } + + /** + * Loads security class and enables security + * + * @param \Smarty $smarty + * @param string|Smarty_Security $security_class if a string is used, it must be class-name + * + * @return \Smarty current Smarty instance for chaining + * @throws \SmartyException when an invalid class name is provided + */ + public static function enableSecurity(Smarty $smarty, $security_class) + { + if ($security_class instanceof Smarty_Security) { + $smarty->security_policy = $security_class; + return $smarty; + } elseif (is_object($security_class)) { + throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security."); + } + if ($security_class === null) { + $security_class = $smarty->security_class; + } + if (!class_exists($security_class)) { + throw new SmartyException("Security class '$security_class' is not defined"); + } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) { + throw new SmartyException("Class '$security_class' must extend Smarty_Security."); + } else { + $smarty->security_policy = new $security_class($smarty); + } + return $smarty; + } + + /** + * Start template processing + * + * @param $template + * + * @throws SmartyException + */ + public function startTemplate($template) + { + if ($this->max_template_nesting > 0 && $this->_current_template_nesting++ >= $this->max_template_nesting) { + throw new SmartyException("maximum template nesting level of '{$this->max_template_nesting}' exceeded when calling '{$template->template_resource}'"); + } + } + + /** + * Exit template processing + */ + public function endTemplate() + { + if ($this->max_template_nesting > 0) { + $this->_current_template_nesting--; + } + } + + /** + * Register callback functions call at start/end of template rendering + * + * @param \Smarty_Internal_Template $template + */ + public function registerCallBacks(Smarty_Internal_Template $template) + { + $template->startRenderCallbacks[] = array($this, 'startTemplate'); + $template->endRenderCallbacks[] = array($this, 'endTemplate'); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_template_cached.php b/WEB-INF/lib/smarty/sysplugins/smarty_template_cached.php new file mode 100644 index 000000000..508d27f36 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_template_cached.php @@ -0,0 +1,257 @@ +compile_id = $_template->compile_id; + $this->cache_id = $_template->cache_id; + $this->source = $_template->source; + if (!class_exists('Smarty_CacheResource', false)) { + include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php'; + } + $this->handler = Smarty_CacheResource::load($_template->smarty); + } + + /** + * @param Smarty_Internal_Template $_template + * + * @return Smarty_Template_Cached + */ + public static function load(Smarty_Internal_Template $_template) + { + $_template->cached = new Smarty_Template_Cached($_template); + $_template->cached->handler->populate($_template->cached, $_template); + // caching enabled ? + if (!$_template->caching || $_template->source->handler->recompiled + ) { + $_template->cached->valid = false; + } + return $_template->cached; + } + + /** + * Render cache template + * + * @param \Smarty_Internal_Template $_template + * @param bool $no_output_filter + * + * @throws \Exception + */ + public function render(Smarty_Internal_Template $_template, $no_output_filter = true) + { + if ($this->isCached($_template)) { + if ($_template->smarty->debugging) { + if (!isset($_template->smarty->_debug)) { + $_template->smarty->_debug = new Smarty_Internal_Debug(); + } + $_template->smarty->_debug->start_cache($_template); + } + if (!$this->processed) { + $this->process($_template); + } + $this->getRenderedTemplateCode($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + return; + } else { + $_template->smarty->ext->_updateCache->updateCache($this, $_template, $no_output_filter); + } + } + + /** + * Check if cache is valid, lock cache if required + * + * @param \Smarty_Internal_Template $_template + * + * @return bool flag true if cache is valid + */ + public function isCached(Smarty_Internal_Template $_template) + { + if ($this->valid !== null) { + return $this->valid; + } + while (true) { + while (true) { + if ($this->exists === false || $_template->smarty->force_compile || $_template->smarty->force_cache) { + $this->valid = false; + } else { + $this->valid = true; + } + if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_CURRENT + && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime) + ) { + // lifetime expired + $this->valid = false; + } + if ($this->valid && $_template->compile_check === Smarty::COMPILECHECK_ON + && $_template->source->getTimeStamp() > $this->timestamp + ) { + $this->valid = false; + } + if ($this->valid || !$_template->smarty->cache_locking) { + break; + } + if (!$this->handler->locked($_template->smarty, $this)) { + $this->handler->acquireLock($_template->smarty, $this); + break 2; + } + $this->handler->populate($this, $_template); + } + if ($this->valid) { + if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) { + // load cache file for the following checks + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_cache($_template); + } + if ($this->handler->process($_template, $this) === false) { + $this->valid = false; + } else { + $this->processed = true; + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + } else { + $this->is_locked = true; + continue; + } + } else { + return $this->valid; + } + if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED + && $_template->cached->cache_lifetime >= 0 + && (time() > ($_template->cached->timestamp + $_template->cached->cache_lifetime)) + ) { + $this->valid = false; + } + if ($_template->smarty->cache_locking) { + if (!$this->valid) { + $this->handler->acquireLock($_template->smarty, $this); + } elseif ($this->is_locked) { + $this->handler->releaseLock($_template->smarty, $this); + } + } + return $this->valid; + } + return $this->valid; + } + + /** + * Process cached template + * + * @param Smarty_Internal_Template $_template template object + * @param bool $update flag if called because cache update + */ + public function process(Smarty_Internal_Template $_template, $update = false) + { + if ($this->handler->process($_template, $this, $update) === false) { + $this->valid = false; + } + if ($this->valid) { + $this->processed = true; + } else { + $this->processed = false; + } + } + + /** + * Read cache content from handler + * + * @param Smarty_Internal_Template $_template template object + * + * @return string|false content + */ + public function read(Smarty_Internal_Template $_template) + { + if (!$_template->source->handler->recompiled) { + return $this->handler->readCachedContent($_template); + } + return false; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_template_compiled.php b/WEB-INF/lib/smarty/sysplugins/smarty_template_compiled.php new file mode 100644 index 000000000..37d8f0a9e --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_template_compiled.php @@ -0,0 +1,257 @@ +source->handler->hasCompiledHandler) { + $_template->source->handler->populateCompiledFilepath($compiled, $_template); + } else { + $compiled->populateCompiledFilepath($_template); + } + return $compiled; + } + + /** + * populate Compiled Object with compiled filepath + * + * @param Smarty_Internal_Template $_template template object + **/ + public function populateCompiledFilepath(Smarty_Internal_Template $_template) + { + $source = &$_template->source; + $smarty = &$_template->smarty; + $this->filepath = $smarty->getCompileDir(); + if (isset($_template->compile_id)) { + $this->filepath .= preg_replace('![^\w]+!', '_', $_template->compile_id) . + ($smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'); + } + // if use_sub_dirs, break file into directories + if ($smarty->use_sub_dirs) { + $this->filepath .= $source->uid[ 0 ] . $source->uid[ 1 ] . DIRECTORY_SEPARATOR . $source->uid[ 2 ] . + $source->uid[ 3 ] . DIRECTORY_SEPARATOR . $source->uid[ 4 ] . $source->uid[ 5 ] . + DIRECTORY_SEPARATOR; + } + $this->filepath .= $source->uid . '_'; + if ($source->isConfig) { + $this->filepath .= (int)$smarty->config_read_hidden + (int)$smarty->config_booleanize * 2 + + (int)$smarty->config_overwrite * 4; + } else { + $this->filepath .= (int)$smarty->merge_compiled_includes + (int)$smarty->escape_html * 2 + + (($smarty->merge_compiled_includes && $source->type === 'extends') ? + (int)$smarty->extends_recursion * 4 : 0); + } + $this->filepath .= '.' . $source->type; + $basename = $source->handler->getBasename($source); + if (!empty($basename)) { + $this->filepath .= '.' . $basename; + } + if ($_template->caching) { + $this->filepath .= '.cache'; + } + $this->filepath .= '.php'; + $this->timestamp = $this->exists = is_file($this->filepath); + if ($this->exists) { + $this->timestamp = filemtime($this->filepath); + } + } + + /** + * render compiled template code + * + * @param Smarty_Internal_Template $_template + * + * @return string + * @throws Exception + */ + public function render(Smarty_Internal_Template $_template) + { + // checks if template exists + if (!$_template->source->exists) { + $type = $_template->source->isConfig ? 'config' : 'template'; + throw new SmartyException("Unable to load {$type} '{$_template->source->type}:{$_template->source->name}'"); + } + if ($_template->smarty->debugging) { + if (!isset($_template->smarty->_debug)) { + $_template->smarty->_debug = new Smarty_Internal_Debug(); + } + $_template->smarty->_debug->start_render($_template); + } + if (!$this->processed) { + $this->process($_template); + } + if (isset($_template->cached)) { + $_template->cached->file_dependency = + array_merge($_template->cached->file_dependency, $this->file_dependency); + } + if ($_template->source->handler->uncompiled) { + $_template->source->handler->renderUncompiled($_template->source, $_template); + } else { + $this->getRenderedTemplateCode($_template); + } + if ($_template->caching && $this->has_nocache_code) { + $_template->cached->hashes[ $this->nocache_hash ] = true; + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_render($_template); + } + } + + /** + * load compiled template or compile from source + * + * @param Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template + * + * @throws Exception + */ + public function process(Smarty_Internal_Template $_smarty_tpl) + { + $source = &$_smarty_tpl->source; + $smarty = &$_smarty_tpl->smarty; + if ($source->handler->recompiled) { + $source->handler->process($_smarty_tpl); + } elseif (!$source->handler->uncompiled) { + if (!$this->exists || $smarty->force_compile + || ($_smarty_tpl->compile_check && $source->getTimeStamp() > $this->getTimeStamp()) + ) { + $this->compileTemplateSource($_smarty_tpl); + $compileCheck = $_smarty_tpl->compile_check; + $_smarty_tpl->compile_check = Smarty::COMPILECHECK_OFF; + $this->loadCompiledTemplate($_smarty_tpl); + $_smarty_tpl->compile_check = $compileCheck; + } else { + $_smarty_tpl->mustCompile = true; + @include $this->filepath; + if ($_smarty_tpl->mustCompile) { + $this->compileTemplateSource($_smarty_tpl); + $compileCheck = $_smarty_tpl->compile_check; + $_smarty_tpl->compile_check = Smarty::COMPILECHECK_OFF; + $this->loadCompiledTemplate($_smarty_tpl); + $_smarty_tpl->compile_check = $compileCheck; + } + } + $_smarty_tpl->_subTemplateRegister(); + $this->processed = true; + } + } + + /** + * compile template from source + * + * @param Smarty_Internal_Template $_template + * + * @throws Exception + */ + public function compileTemplateSource(Smarty_Internal_Template $_template) + { + $this->file_dependency = array(); + $this->includes = array(); + $this->nocache_hash = null; + $this->unifunc = null; + // compile locking + if ($saved_timestamp = (!$_template->source->handler->recompiled && is_file($this->filepath))) { + $saved_timestamp = $this->getTimeStamp(); + touch($this->filepath); + } + // compile locking + try { + // call compiler + $_template->loadCompiler(); + $this->write($_template, $_template->compiler->compileTemplate($_template)); + } catch (Exception $e) { + // restore old timestamp in case of error + if ($saved_timestamp && is_file($this->filepath)) { + touch($this->filepath, $saved_timestamp); + } + unset($_template->compiler); + throw $e; + } + // release compiler object to free memory + unset($_template->compiler); + } + + /** + * Write compiled code by handler + * + * @param Smarty_Internal_Template $_template template object + * @param string $code compiled code + * + * @return bool success + * @throws \SmartyException + */ + public function write(Smarty_Internal_Template $_template, $code) + { + if (!$_template->source->handler->recompiled) { + if ($_template->smarty->ext->_writeFile->writeFile($this->filepath, $code, $_template->smarty) === true) { + $this->timestamp = $this->exists = is_file($this->filepath); + if ($this->exists) { + $this->timestamp = filemtime($this->filepath); + return true; + } + } + return false; + } + return true; + } + + /** + * Read compiled content from handler + * + * @param Smarty_Internal_Template $_template template object + * + * @return string content + */ + public function read(Smarty_Internal_Template $_template) + { + if (!$_template->source->handler->recompiled) { + return file_get_contents($this->filepath); + } + return isset($this->content) ? $this->content : false; + } + + /** + * Load fresh compiled template by including the PHP file + * HHVM requires a work around because of a PHP incompatibility + * + * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template + */ + private function loadCompiledTemplate(Smarty_Internal_Template $_smarty_tpl) + { + if (function_exists('opcache_invalidate') + && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) + ) { + opcache_invalidate($this->filepath, true); + } elseif (function_exists('apc_compile_file')) { + apc_compile_file($this->filepath); + } + if (defined('HHVM_VERSION')) { + eval('?>' . file_get_contents($this->filepath)); + } else { + include $this->filepath; + } + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_template_config.php b/WEB-INF/lib/smarty/sysplugins/smarty_template_config.php new file mode 100644 index 000000000..850ae32e7 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_template_config.php @@ -0,0 +1,100 @@ + true, 'php' => true); + if ($_template) { + $smarty = $_template->smarty; + $template_resource = $_template->template_resource; + } + if (empty($template_resource)) { + throw new SmartyException('Source: Missing name'); + } + // parse resource_name, load resource handler + list($name, $type) = Smarty_Resource::parseResourceName($template_resource, $smarty->default_config_type); + // make sure configs are not loaded via anything smarty can't handle + if (isset($_incompatible_resources[ $type ])) { + throw new SmartyException("Unable to use resource '{$type}' for config"); + } + $source = new Smarty_Template_Config($smarty, $template_resource, $type, $name); + $source->handler->populate($source, $_template); + if (!$source->exists && isset($smarty->default_config_handler_func)) { + Smarty_Internal_Method_RegisterDefaultTemplateHandler::_getDefaultTemplate($source); + $source->handler->populate($source, $_template); + } + return $source; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_template_resource_base.php b/WEB-INF/lib/smarty/sysplugins/smarty_template_resource_base.php new file mode 100644 index 000000000..52bfba252 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_template_resource_base.php @@ -0,0 +1,152 @@ +smarty; + $_template->isRenderingCache = $this->isCache; + $level = ob_get_level(); + try { + if (!isset($unifunc)) { + $unifunc = $this->unifunc; + } + if (empty($unifunc) || !function_exists($unifunc)) { + throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'"); + } + if ($_template->startRenderCallbacks) { + foreach ($_template->startRenderCallbacks as $callback) { + call_user_func($callback, $_template); + } + } + $unifunc($_template); + foreach ($_template->endRenderCallbacks as $callback) { + call_user_func($callback, $_template); + } + $_template->isRenderingCache = false; + } catch (Exception $e) { + $_template->isRenderingCache = false; + while (ob_get_level() > $level) { + ob_end_clean(); + } + if (isset($smarty->security_policy)) { + $smarty->security_policy->endTemplate(); + } + throw $e; + } + } + + /** + * Get compiled time stamp + * + * @return int + */ + public function getTimeStamp() + { + if ($this->exists && !$this->timestamp) { + $this->timestamp = filemtime($this->filepath); + } + return $this->timestamp; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_template_source.php b/WEB-INF/lib/smarty/sysplugins/smarty_template_source.php new file mode 100644 index 000000000..16b47f23c --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_template_source.php @@ -0,0 +1,213 @@ +handler = + isset($smarty->_cache[ 'resource_handlers' ][ $type ]) ? $smarty->_cache[ 'resource_handlers' ][ $type ] : + Smarty_Resource::load($smarty, $type); + $this->smarty = $smarty; + $this->resource = $resource; + $this->type = $type; + $this->name = $name; + } + + /** + * initialize Source Object for given resource + * Either [$_template] or [$smarty, $template_resource] must be specified + * + * @param Smarty_Internal_Template $_template template object + * @param Smarty $smarty smarty object + * @param string $template_resource resource identifier + * + * @return Smarty_Template_Source Source Object + * @throws SmartyException + */ + public static function load( + Smarty_Internal_Template $_template = null, + Smarty $smarty = null, + $template_resource = null + ) { + if ($_template) { + $smarty = $_template->smarty; + $template_resource = $_template->template_resource; + } + if (empty($template_resource)) { + throw new SmartyException('Source: Missing name'); + } + // parse resource_name, load resource handler, identify unique resource name + if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]([\s\S]*)$/', $template_resource, $match)) { + $type = $match[ 1 ]; + $name = $match[ 2 ]; + } else { + // no resource given, use default + // or single character before the colon is not a resource type, but part of the filepath + $type = $smarty->default_resource_type; + $name = $template_resource; + } + // create new source object + $source = new Smarty_Template_Source($smarty, $template_resource, $type, $name); + $source->handler->populate($source, $_template); + if (!$source->exists && isset($_template->smarty->default_template_handler_func)) { + Smarty_Internal_Method_RegisterDefaultTemplateHandler::_getDefaultTemplate($source); + $source->handler->populate($source, $_template); + } + return $source; + } + + /** + * Get source time stamp + * + * @return int + */ + public function getTimeStamp() + { + if (!isset($this->timestamp)) { + $this->handler->populateTimestamp($this); + } + return $this->timestamp; + } + + /** + * Get source content + * + * @return string + * @throws \SmartyException + */ + public function getContent() + { + return isset($this->content) ? $this->content : $this->handler->getContent($this); + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_undefined_variable.php b/WEB-INF/lib/smarty/sysplugins/smarty_undefined_variable.php new file mode 100644 index 000000000..6d31a8a05 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_undefined_variable.php @@ -0,0 +1,33 @@ +value = $value; + $this->nocache = $nocache; + } + + /** + * <> String conversion + * + * @return string + */ + public function __toString() + { + return (string)$this->value; + } +} diff --git a/WEB-INF/lib/smarty/sysplugins/smartycompilerexception.php b/WEB-INF/lib/smarty/sysplugins/smartycompilerexception.php new file mode 100644 index 000000000..f7ad39b93 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smartycompilerexception.php @@ -0,0 +1,45 @@ + Smarty Compiler: ' . $this->message . ' <-- '; + } + + /** + * The line number of the template error + * + * @type int|null + */ + public $line = null; + + /** + * The template source snippet relating to the error + * + * @type string|null + */ + public $source = null; + + /** + * The raw text of the error message + * + * @type string|null + */ + public $desc = null; + + /** + * The resource identifier or template name + * + * @type string|null + */ + public $template = null; +} diff --git a/WEB-INF/lib/smarty/sysplugins/smartyexception.php b/WEB-INF/lib/smarty/sysplugins/smartyexception.php new file mode 100644 index 000000000..7f7b9aa43 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smartyexception.php @@ -0,0 +1,19 @@ + Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- '; + } +} From 3ee662bebf8081b7dc65efcb24342943e55313fc Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 27 Oct 2020 21:20:10 +0000 Subject: [PATCH 074/587] Some fixes for no longer supported libchart library to remove PHP warnings. --- WEB-INF/lib/libchart/classes/libchart.php | 2 +- WEB-INF/lib/libchart/classes/model/Point.php | 6 +++--- WEB-INF/lib/libchart/classes/model/XYDataSet.php | 6 +++--- WEB-INF/lib/libchart/classes/model/XYSeriesDataSet.php | 6 +++--- WEB-INF/lib/libchart/classes/view/axis/Axis.php | 6 +++--- WEB-INF/lib/libchart/classes/view/caption/Caption.php | 6 +++--- WEB-INF/lib/libchart/classes/view/chart/BarChart.php | 8 ++++---- WEB-INF/lib/libchart/classes/view/chart/Chart.php | 6 +++--- .../libchart/classes/view/chart/HorizontalBarChart.php | 8 ++++---- WEB-INF/lib/libchart/classes/view/chart/LineChart.php | 8 ++++---- WEB-INF/lib/libchart/classes/view/chart/PieChart.php | 8 +++----- .../lib/libchart/classes/view/chart/VerticalBarChart.php | 8 ++++---- WEB-INF/lib/libchart/classes/view/color/Color.php | 6 +++--- WEB-INF/lib/libchart/classes/view/color/ColorSet.php | 6 +++--- WEB-INF/lib/libchart/classes/view/color/Palette.php | 6 +++--- WEB-INF/lib/libchart/classes/view/plot/Plot.php | 6 +++--- WEB-INF/lib/libchart/classes/view/primitive/Padding.php | 6 +++--- WEB-INF/lib/libchart/classes/view/primitive/Primitive.php | 6 +++--- WEB-INF/lib/libchart/classes/view/primitive/Rectangle.php | 6 +++--- WEB-INF/lib/libchart/classes/view/text/Text.php | 6 +++--- initialize.php | 2 +- 21 files changed, 63 insertions(+), 65 deletions(-) diff --git a/WEB-INF/lib/libchart/classes/libchart.php b/WEB-INF/lib/libchart/classes/libchart.php index f84210fbb..5fc668d79 100644 --- a/WEB-INF/lib/libchart/classes/libchart.php +++ b/WEB-INF/lib/libchart/classes/libchart.php @@ -1,6 +1,6 @@ x = $x; $this->y = $y; } diff --git a/WEB-INF/lib/libchart/classes/model/XYDataSet.php b/WEB-INF/lib/libchart/classes/model/XYDataSet.php index 2713c2985..3190e16c7 100644 --- a/WEB-INF/lib/libchart/classes/model/XYDataSet.php +++ b/WEB-INF/lib/libchart/classes/model/XYDataSet.php @@ -1,6 +1,6 @@ pointList = array(); } diff --git a/WEB-INF/lib/libchart/classes/model/XYSeriesDataSet.php b/WEB-INF/lib/libchart/classes/model/XYSeriesDataSet.php index 45f961c5f..8b8d88699 100644 --- a/WEB-INF/lib/libchart/classes/model/XYSeriesDataSet.php +++ b/WEB-INF/lib/libchart/classes/model/XYSeriesDataSet.php @@ -1,6 +1,6 @@ titleList = array(); $this->serieList = array(); } diff --git a/WEB-INF/lib/libchart/classes/view/axis/Axis.php b/WEB-INF/lib/libchart/classes/view/axis/Axis.php index 885019639..fe14671b3 100644 --- a/WEB-INF/lib/libchart/classes/view/axis/Axis.php +++ b/WEB-INF/lib/libchart/classes/view/axis/Axis.php @@ -1,6 +1,6 @@ min = $min; $this->max = $max; diff --git a/WEB-INF/lib/libchart/classes/view/caption/Caption.php b/WEB-INF/lib/libchart/classes/view/caption/Caption.php index 9a48b49d0..4b5c40192 100644 --- a/WEB-INF/lib/libchart/classes/view/caption/Caption.php +++ b/WEB-INF/lib/libchart/classes/view/caption/Caption.php @@ -1,6 +1,6 @@ labelBoxWidth = 15; $this->labelBoxHeight = 15; } diff --git a/WEB-INF/lib/libchart/classes/view/chart/BarChart.php b/WEB-INF/lib/libchart/classes/view/chart/BarChart.php index c5d9b82a0..b14b45e36 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/BarChart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/BarChart.php @@ -1,6 +1,6 @@ bound = new Bound(); diff --git a/WEB-INF/lib/libchart/classes/view/chart/Chart.php b/WEB-INF/lib/libchart/classes/view/chart/Chart.php index 599b98fec..99cbde161 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/Chart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/Chart.php @@ -1,6 +1,6 @@ plot = new Plot($width, $height); $this->plot->setTitle("Untitled chart"); diff --git a/WEB-INF/lib/libchart/classes/view/chart/HorizontalBarChart.php b/WEB-INF/lib/libchart/classes/view/chart/HorizontalBarChart.php index 5faad4997..a4bd644d5 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/HorizontalBarChart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/HorizontalBarChart.php @@ -1,6 +1,6 @@ emptyToFullRatio = 1 / 5; $this->plot->setGraphPadding(new Padding(5, 30, 30, 50)); diff --git a/WEB-INF/lib/libchart/classes/view/chart/LineChart.php b/WEB-INF/lib/libchart/classes/view/chart/LineChart.php index 811a060cc..b3a22cf06 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/LineChart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/LineChart.php @@ -1,6 +1,6 @@ plot->setGraphPadding(new Padding(5, 30, 50, 50)); } diff --git a/WEB-INF/lib/libchart/classes/view/chart/PieChart.php b/WEB-INF/lib/libchart/classes/view/chart/PieChart.php index 108b5927e..7d87782cd 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/PieChart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/PieChart.php @@ -32,8 +32,8 @@ class PieChart extends Chart { * @param integer width of the image * @param integer height of the image */ - public function PieChart($width = 600, $height = 250) { - parent::Chart($width, $height); + public function __construct($width = 600, $height = 250) { + parent::__construct($width, $height); $this->plot->setGraphPadding(new Padding(15, 10, 30, 30)); } @@ -64,9 +64,7 @@ protected function computeLayout($hasCaption = true) { * @return integer result of the comparison */ protected function sortPie($v1, $v2) { - return $v1[0] == $v2[0] ? 0 : - $v1[0] > $v2[0] ? -1 : - 1; + return $v1[0] == $v2[0] ? 0 : ($v1[0] > $v2[0] ? -1 : 1); } /** diff --git a/WEB-INF/lib/libchart/classes/view/chart/VerticalBarChart.php b/WEB-INF/lib/libchart/classes/view/chart/VerticalBarChart.php index 65adcf2ad..8bfeed047 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/VerticalBarChart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/VerticalBarChart.php @@ -1,6 +1,6 @@ emptyToFullRatio = 1 / 5; $this->plot->setGraphPadding(new Padding(5, 30, 50, 50)); diff --git a/WEB-INF/lib/libchart/classes/view/color/Color.php b/WEB-INF/lib/libchart/classes/view/color/Color.php index d97c7007f..d39159143 100644 --- a/WEB-INF/lib/libchart/classes/view/color/Color.php +++ b/WEB-INF/lib/libchart/classes/view/color/Color.php @@ -1,6 +1,6 @@ red = (int) $red; $this->green = (int) $green; $this->blue = (int) $blue; diff --git a/WEB-INF/lib/libchart/classes/view/color/ColorSet.php b/WEB-INF/lib/libchart/classes/view/color/ColorSet.php index 9876ef08c..d72a8d987 100644 --- a/WEB-INF/lib/libchart/classes/view/color/ColorSet.php +++ b/WEB-INF/lib/libchart/classes/view/color/ColorSet.php @@ -1,6 +1,6 @@ colorList = $colorList; $this->shadowColorList = array(); diff --git a/WEB-INF/lib/libchart/classes/view/color/Palette.php b/WEB-INF/lib/libchart/classes/view/color/Palette.php index 48189b971..1998b3996 100644 --- a/WEB-INF/lib/libchart/classes/view/color/Palette.php +++ b/WEB-INF/lib/libchart/classes/view/color/Palette.php @@ -1,6 +1,6 @@ red = new Color(255, 0, 0); // Colors for the horizontal and vertical axis diff --git a/WEB-INF/lib/libchart/classes/view/plot/Plot.php b/WEB-INF/lib/libchart/classes/view/plot/Plot.php index a57d4ffbb..acda4309d 100644 --- a/WEB-INF/lib/libchart/classes/view/plot/Plot.php +++ b/WEB-INF/lib/libchart/classes/view/plot/Plot.php @@ -1,6 +1,6 @@ width = $width; $this->height = $height; diff --git a/WEB-INF/lib/libchart/classes/view/primitive/Padding.php b/WEB-INF/lib/libchart/classes/view/primitive/Padding.php index 9cade66c9..bed6b3d17 100644 --- a/WEB-INF/lib/libchart/classes/view/primitive/Padding.php +++ b/WEB-INF/lib/libchart/classes/view/primitive/Padding.php @@ -1,6 +1,6 @@ top = $top; if ($right == null) { $this->right = $top; diff --git a/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php b/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php index b6b26bd80..05b8ac420 100644 --- a/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php +++ b/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php @@ -1,6 +1,6 @@ img = $img; } diff --git a/WEB-INF/lib/libchart/classes/view/primitive/Rectangle.php b/WEB-INF/lib/libchart/classes/view/primitive/Rectangle.php index 402214ea7..265c572ca 100644 --- a/WEB-INF/lib/libchart/classes/view/primitive/Rectangle.php +++ b/WEB-INF/lib/libchart/classes/view/primitive/Rectangle.php @@ -1,6 +1,6 @@ x1 = $x1; $this->y1 = $y1; $this->x2 = $x2; diff --git a/WEB-INF/lib/libchart/classes/view/text/Text.php b/WEB-INF/lib/libchart/classes/view/text/Text.php index eeef1cfb0..ad745e0e5 100644 --- a/WEB-INF/lib/libchart/classes/view/text/Text.php +++ b/WEB-INF/lib/libchart/classes/view/text/Text.php @@ -1,6 +1,6 @@ diff --git a/initialize.php b/initialize.php index 04c61f5a5..5cba1fda8 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5331"); +define("APP_VERSION", "1.19.23.5332"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From cd6ea8fe075b7891b081ff9b3532c7d1c0627fd6 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 27 Oct 2020 21:29:47 +0000 Subject: [PATCH 075/587] Cosmetic. Fixed encoding in libchart comments. --- WEB-INF/lib/libchart/classes/libchart.php | 2 +- WEB-INF/lib/libchart/classes/model/DataSet.php | 4 ++-- WEB-INF/lib/libchart/classes/model/Point.php | 4 ++-- WEB-INF/lib/libchart/classes/model/XYDataSet.php | 4 ++-- WEB-INF/lib/libchart/classes/model/XYSeriesDataSet.php | 4 ++-- WEB-INF/lib/libchart/classes/view/axis/Axis.php | 4 ++-- WEB-INF/lib/libchart/classes/view/axis/Bound.php | 4 ++-- WEB-INF/lib/libchart/classes/view/caption/Caption.php | 4 ++-- WEB-INF/lib/libchart/classes/view/chart/BarChart.php | 4 ++-- WEB-INF/lib/libchart/classes/view/chart/Chart.php | 4 ++-- .../lib/libchart/classes/view/chart/HorizontalBarChart.php | 4 ++-- WEB-INF/lib/libchart/classes/view/chart/LineChart.php | 4 ++-- WEB-INF/lib/libchart/classes/view/chart/PieChart.php | 4 ++-- WEB-INF/lib/libchart/classes/view/chart/VerticalBarChart.php | 4 ++-- WEB-INF/lib/libchart/classes/view/color/Color.php | 4 ++-- WEB-INF/lib/libchart/classes/view/color/ColorSet.php | 4 ++-- WEB-INF/lib/libchart/classes/view/color/Palette.php | 4 ++-- WEB-INF/lib/libchart/classes/view/plot/Plot.php | 4 ++-- WEB-INF/lib/libchart/classes/view/primitive/Padding.php | 4 ++-- WEB-INF/lib/libchart/classes/view/primitive/Primitive.php | 4 ++-- WEB-INF/lib/libchart/classes/view/primitive/Rectangle.php | 4 ++-- WEB-INF/lib/libchart/classes/view/text/Text.php | 4 ++-- 22 files changed, 43 insertions(+), 43 deletions(-) diff --git a/WEB-INF/lib/libchart/classes/libchart.php b/WEB-INF/lib/libchart/classes/libchart.php index 5fc668d79..3d1cd5369 100644 --- a/WEB-INF/lib/libchart/classes/libchart.php +++ b/WEB-INF/lib/libchart/classes/libchart.php @@ -1,6 +1,6 @@ Date: Wed, 28 Oct 2020 19:51:36 +0000 Subject: [PATCH 076/587] Removed a PHP warning on reports.php for 0 inactive users. --- initialize.php | 2 +- reports.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/initialize.php b/initialize.php index 5cba1fda8..56deb3b7a 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5332"); +define("APP_VERSION", "1.19.23.5333"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/reports.php b/reports.php index 94b837cc1..5a4977b7a 100644 --- a/reports.php +++ b/reports.php @@ -229,7 +229,7 @@ } } } - $row_count = ceil(count($user_list_active)/3); + $row_count = is_array($user_list_active) ? ceil(count($user_list_active)/3) : 1; $form->addInput(array('type'=>'checkboxgroup', 'name'=>'users_active', 'data'=>$user_list_active, @@ -246,7 +246,7 @@ } } } - $row_count = ceil(count($user_list_inactive)/3); + $row_count = is_array($user_list_inactive) ? ceil(count($user_list_inactive)/3) : 1; $form->addInput(array('type'=>'checkboxgroup', 'name'=>'users_inactive', 'data'=>$user_list_inactive, From e4863b6338a4d6aad4fd7f779e54d9f01d6c9901 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 28 Oct 2020 20:38:43 +0000 Subject: [PATCH 077/587] Defined a default value in TTUser::getConfigInt() function. --- WEB-INF/lib/ttUser.class.php | 4 ++-- initialize.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/WEB-INF/lib/ttUser.class.php b/WEB-INF/lib/ttUser.class.php index c1b771a2d..72b829d31 100644 --- a/WEB-INF/lib/ttUser.class.php +++ b/WEB-INF/lib/ttUser.class.php @@ -297,8 +297,8 @@ function getConfigOption($name) { return $config->getDefinedValue($name); } - // getConfigInt retruns an integer value defined in a group, or false. - function getConfigInt($name, $defaultVal) { + // getConfigInt returns an integer value defined in a group, or false. + function getConfigInt($name, $defaultVal = 0) { $config = new ttConfigHelper($this->getConfig()); return $config->getIntValue($name, $defaultVal); } diff --git a/initialize.php b/initialize.php index 56deb3b7a..5e00b1a9e 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5333"); +define("APP_VERSION", "1.19.23.5334"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 9637ca6a2b3c3f7c69b1026ea1e8353049f7570a Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 28 Oct 2020 20:49:57 +0000 Subject: [PATCH 078/587] Some more progress on fixing PHP warnings. --- WEB-INF/lib/form/DateField.class.php | 2 +- initialize.php | 2 +- password_reset.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/WEB-INF/lib/form/DateField.class.php b/WEB-INF/lib/form/DateField.class.php index 18a3ec475..f3513c480 100644 --- a/WEB-INF/lib/form/DateField.class.php +++ b/WEB-INF/lib/form/DateField.class.php @@ -406,7 +406,7 @@ function adjustiFrame(pickerDiv, iFrameDiv) { $html .= " value=\"".htmlspecialchars($this->getValue())."\""; $html .= ">"; - if (DIR_NAME) + if (defined('DIR_NAME')) $app_root = '/'.DIR_NAME; $html .= " name."');\">\n"; diff --git a/initialize.php b/initialize.php index 5e00b1a9e..f1164ff3b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5334"); +define("APP_VERSION", "1.19.23.5335"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/password_reset.php b/password_reset.php index 01e04f3a1..ba3547132 100644 --- a/password_reset.php +++ b/password_reset.php @@ -105,7 +105,7 @@ $http = 'http'; $cl_subject = $user_i18n->get('form.reset_password.email_subject'); - if (DIR_NAME) + if (defined('DIR_NAME')) $pass_edit_url = $http.'://'.$_SERVER['HTTP_HOST'].'/'.DIR_NAME.'/password_change.php?ref='.$temp_ref; else $pass_edit_url = $http.'://'.$_SERVER['HTTP_HOST'].'/password_change.php?ref='.$temp_ref; From 47747a5be6169bb6b4722229bdefc5bb59deca5c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 28 Oct 2020 21:15:01 +0000 Subject: [PATCH 079/587] More progress on removing conditions for PHP warnings. --- initialize.php | 2 +- notification_add.php | 2 +- notification_edit.php | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/initialize.php b/initialize.php index f1164ff3b..398fc4f0b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5335"); +define("APP_VERSION", "1.19.23.5336"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/notification_add.php b/notification_add.php index 8b0f96b56..b7f743256 100644 --- a/notification_add.php +++ b/notification_add.php @@ -97,7 +97,7 @@ if ($err->no()) { // Calculate next execution time. - $next = tdCron::getNextOccurrence($cl_cron_spec, mktime()); + $next = tdCron::getNextOccurrence($cl_cron_spec, time()); if (ttNotificationHelper::insert(array( 'cron_spec' => $cl_cron_spec, diff --git a/notification_edit.php b/notification_edit.php index 975b313a8..a07d25d8e 100644 --- a/notification_edit.php +++ b/notification_edit.php @@ -110,8 +110,7 @@ if ($err->no()) { // Calculate next execution time. - $next = tdCron::getNextOccurrence($cl_cron_spec, mktime()); - + $next = tdCron::getNextOccurrence($cl_cron_spec, time()); if (ttNotificationHelper::update(array( 'id' => $notification_id, 'cron_spec' => $cl_cron_spec, From 65be2016ceb19b366a9bea9c92001cab7c71ba14 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 29 Oct 2020 13:36:21 +0000 Subject: [PATCH 080/587] Fixed division by zero problem in pie charts. --- WEB-INF/lib/ttChartHelper.class.php | 4 ++-- initialize.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/WEB-INF/lib/ttChartHelper.class.php b/WEB-INF/lib/ttChartHelper.class.php index 31d35e3fd..60c9897cb 100644 --- a/WEB-INF/lib/ttChartHelper.class.php +++ b/WEB-INF/lib/ttChartHelper.class.php @@ -86,8 +86,8 @@ static function getTotals($user_id, $chart_type, $selected_date, $interval_type) $res = $mdb2->query($sql); if (!is_a($res, 'PEAR_Error')) { while ($val = $res->fetchRow()) { - if ($val['time'] >= 0) // Only positive totals make sense in pie charts. Skip negatives entirely. - $result[] = array('name'=>$val['name'],'time'=>$val['time']); // name - project name, time - total for project in seconds. + if ($val['time'] > 0) // Only positive totals make sense in pie charts. Skip negatives entirely. + $result[] = array('name'=>$val['name'],'time'=>$val['time']); // name - entity name, time - total for entity in seconds. } } diff --git a/initialize.php b/initialize.php index 398fc4f0b..8a771556b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5336"); +define("APP_VERSION", "1.19.23.5337"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From e0093c5c4bd0ac8d9d6a6aadfc101c5deb3ab50e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 29 Oct 2020 14:06:56 +0000 Subject: [PATCH 081/587] Addressed a condition for PHP warning. --- WEB-INF/lib/ttFavReportHelper.class.php | 32 ++++--------------------- initialize.php | 2 +- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/WEB-INF/lib/ttFavReportHelper.class.php b/WEB-INF/lib/ttFavReportHelper.class.php index 2707fd2b1..bf2309dcf 100644 --- a/WEB-INF/lib/ttFavReportHelper.class.php +++ b/WEB-INF/lib/ttFavReportHelper.class.php @@ -1,30 +1,6 @@ Date: Thu, 29 Oct 2020 14:17:26 +0000 Subject: [PATCH 082/587] Addressed a PHP warning. --- WEB-INF/lib/ttFavReportHelper.class.php | 3 ++- initialize.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/WEB-INF/lib/ttFavReportHelper.class.php b/WEB-INF/lib/ttFavReportHelper.class.php index bf2309dcf..b4f917a4a 100644 --- a/WEB-INF/lib/ttFavReportHelper.class.php +++ b/WEB-INF/lib/ttFavReportHelper.class.php @@ -416,7 +416,8 @@ static function loadReport(&$bean) { $custom_field_attrs[$checkbox_field_name] = null; } } - $attrs = array_merge($attrs, $custom_field_attrs); + if (is_array($custom_field_attrs)) + $attrs = array_merge($attrs, $custom_field_attrs); $bean->setAttributes($attrs); } } diff --git a/initialize.php b/initialize.php index a69cc1447..2e8f5dc23 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5338"); +define("APP_VERSION", "1.19.23.5339"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From f008878420aa3031e9369654eba5d2af978e3ae6 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 13:28:41 +0000 Subject: [PATCH 083/587] Removed a redirect to mobile pages as we now have mobile time entry working. --- index.php | 28 +--------------------------- initialize.php | 2 +- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/index.php b/index.php index cabc7060b..8c4471d1e 100644 --- a/index.php +++ b/index.php @@ -38,29 +38,7 @@ exit(); } } - -// Redirect to time.php or mobile/time.php for other roles. - -// Regexp to determine mobile browser was taken from detectmobilebrowsers.com on Aug 24, 2012. -$useragent = $_SERVER['HTTP_USER_AGENT']; -$mobileBrowser = preg_match('/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4)); - -if ($mobileBrowser) { -?> - - - - - - - - @@ -73,7 +51,3 @@

    Your browser does not support JavaScript. Time Tracker will not work without it.

    - - diff --git a/initialize.php b/initialize.php index 2e8f5dc23..02aaa37a4 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5339"); +define("APP_VERSION", "1.19.23.5340"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 26a6ddc4e3f5e904a807149c3aeea98b4fa09a8f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 13:40:23 +0000 Subject: [PATCH 084/587] Cosmetic. --- index.php | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/index.php b/index.php index 8c4471d1e..e2f13c2a3 100644 --- a/index.php +++ b/index.php @@ -1,30 +1,6 @@ Date: Fri, 30 Oct 2020 13:58:22 +0000 Subject: [PATCH 085/587] Cosmetic change to noscript output message. --- index.php | 3 +-- initialize.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index e2f13c2a3..c74f2688b 100644 --- a/index.php +++ b/index.php @@ -23,7 +23,6 @@ location.href = "time.php?date="+(new Date()).strftime(''); diff --git a/initialize.php b/initialize.php index 02aaa37a4..964246e27 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5340"); +define("APP_VERSION", "1.19.23.5341"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 70fec9233dc81524441d2bb19abbf9375b89599e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 15:34:51 +0000 Subject: [PATCH 086/587] Made projects.php page mobile-friendly. --- WEB-INF/templates/projects2.tpl | 93 +++++++++++++++++++++++++++++++++ default.css | 8 ++- initialize.php | 2 +- projects.php | 32 ++---------- projects1.php | 58 ++++++++++++++++++++ 5 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 WEB-INF/templates/projects2.tpl create mode 100644 projects1.php diff --git a/WEB-INF/templates/projects2.tpl b/WEB-INF/templates/projects2.tpl new file mode 100644 index 000000000..9b8de40c4 --- /dev/null +++ b/WEB-INF/templates/projects2.tpl @@ -0,0 +1,93 @@ + + +{if $user->can('manage_projects')} + {if $inactive_projects} +
    {$i18n.form.projects.active_projects}
    + {/if} + {if $active_projects} + + + + + {if $show_files} + + {/if} + + + + {foreach $active_projects as $project} + + + + {if $show_files} + {if $project.has_files} + + {else} + + {/if} + {/if} + + + + {/foreach} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}
    + {/if} +
    + {if $inactive_projects} +
    {$i18n.form.projects.inactive_projects}
    + + + + + {if $show_files} + + {/if} + + + + {foreach $inactive_projects as $project} + + + + {if $show_files} + {if $project.has_files} + + {else} + + {/if} + {/if} + + + + {/foreach} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}
    +
    + {/if} +{else} + + + + + {if $show_files} + + {/if} + + {if $active_projects} + {foreach $active_projects as $project} + + + + {if $show_files} + {if $project.has_files} + + {else} + + {/if} + {/if} + + {/foreach} + {/if} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}{$i18n.label.files} 
    +{/if} diff --git a/default.css b/default.css index 278305591..4a8782cac 100644 --- a/default.css +++ b/default.css @@ -253,7 +253,7 @@ input.password-field { width: 210px; margin-top: 1rem; margin-left: auto; - margin-right: auto + margin-right: auto; } .large-screen-calendar { @@ -315,6 +315,12 @@ input.password-field { margin-bottom: 1rem; } +.section-header { + font-weight: bold; + margin-left: auto; + margin-right: auto; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/initialize.php b/initialize.php index 964246e27..e33fd924c 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5341"); +define("APP_VERSION", "1.19.23.5342"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/projects.php b/projects.php index 0075c038f..e9a0b5dcf 100644 --- a/projects.php +++ b/projects.php @@ -1,30 +1,6 @@ assign('inactive_projects', $inactive_projects); $smarty->assign('show_files', $showFiles); $smarty->assign('title', $i18n->get('title.projects')); -$smarty->assign('content_page_name', 'projects.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'projects2.tpl'); +$smarty->display('index2.tpl'); diff --git a/projects1.php b/projects1.php new file mode 100644 index 000000000..0075c038f --- /dev/null +++ b/projects1.php @@ -0,0 +1,58 @@ +getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { + header('Location: feature_disabled.php'); + exit(); +} +// End of access checks. + +$showFiles = $user->isPluginEnabled('at'); + +if($user->can('manage_projects')) { + $active_projects = ttGroupHelper::getActiveProjects($showFiles); + $inactive_projects = ttGroupHelper::getInactiveProjects($showFiles); +} else { + $options['include_files'] = $showFiles; + $active_projects = $user->getAssignedProjects($options); +} + +$smarty->assign('active_projects', $active_projects); +$smarty->assign('inactive_projects', $inactive_projects); +$smarty->assign('show_files', $showFiles); +$smarty->assign('title', $i18n->get('title.projects')); +$smarty->assign('content_page_name', 'projects.tpl'); +$smarty->display('index.tpl'); From e059663ffec3db4c7ec8eacfa19689b3a1dbf7b1 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 16:42:05 +0000 Subject: [PATCH 087/587] A style fix for buttons. --- default.css | 6 ++++++ initialize.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index 4a8782cac..804a06a66 100644 --- a/default.css +++ b/default.css @@ -221,6 +221,12 @@ input[type=submit] { appearance: none; } +input[type=button] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + input.text-field { width: 220px; } diff --git a/initialize.php b/initialize.php index e33fd924c..7ef3d111b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5342"); +define("APP_VERSION", "1.19.23.5343"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 931f93dc014e76520ecafa38a67c5da185c6adce Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 16:54:42 +0000 Subject: [PATCH 088/587] Made project_delete.php mobile-friendly. --- WEB-INF/templates/project_delete2.tpl | 4 ++++ initialize.php | 2 +- project_delete.php | 32 ++++----------------------- 3 files changed, 9 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/project_delete2.tpl diff --git a/WEB-INF/templates/project_delete2.tpl b/WEB-INF/templates/project_delete2.tpl new file mode 100644 index 000000000..7c84c0223 --- /dev/null +++ b/WEB-INF/templates/project_delete2.tpl @@ -0,0 +1,4 @@ +{$forms.projectDeleteForm.open} +
    {$project_to_delete|escape}
    +
    {$forms.projectDeleteForm.btn_delete.control} {$forms.projectDeleteForm.btn_cancel.control}
    +{$forms.projectDeleteForm.close} diff --git a/initialize.php b/initialize.php index 7ef3d111b..83b50b327 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5343"); +define("APP_VERSION", "1.19.23.5344"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/project_delete.php b/project_delete.php index 3b165a33d..2d6ca2895 100644 --- a/project_delete.php +++ b/project_delete.php @@ -1,30 +1,6 @@ assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.projectDeleteForm.btn_cancel.focus()"'); $smarty->assign('title', $i18n->get('title.delete_project')); -$smarty->assign('content_page_name', 'project_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'project_delete2.tpl'); +$smarty->display('index2.tpl'); From 1350cb94ee1015611396771d560a0204ce500175 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 18:28:21 +0000 Subject: [PATCH 089/587] Recoded project_add.php to be mobile friendly. --- WEB-INF/templates/project_add2.tpl | 46 +++++++++++ WEB-INF/templates/register2.tpl | 1 + initialize.php | 2 +- project_add.php | 36 ++------- project_add1.php | 118 +++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 31 deletions(-) create mode 100644 WEB-INF/templates/project_add2.tpl create mode 100644 project_add1.php diff --git a/WEB-INF/templates/project_add2.tpl b/WEB-INF/templates/project_add2.tpl new file mode 100644 index 000000000..401fd26ac --- /dev/null +++ b/WEB-INF/templates/project_add2.tpl @@ -0,0 +1,46 @@ +{$forms.projectForm.open} + + + + + + + + + + + + + +{if $show_files} + + + + + + +{/if} +{if $show_users} + + + + + + +{/if} +{if $show_tasks} + + + + + + +{/if} + + + + + + +
    {$forms.projectForm.project_name.control}
    {$forms.projectForm.description.control}
    {$forms.projectForm.newfile.control}
    {$forms.projectForm.users.control}
    {$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
    {$forms.projectForm.btn_add.control}
    +{$forms.projectForm.close} diff --git a/WEB-INF/templates/register2.tpl b/WEB-INF/templates/register2.tpl index 5584fde39..1262a4c02 100644 --- a/WEB-INF/templates/register2.tpl +++ b/WEB-INF/templates/register2.tpl @@ -55,5 +55,6 @@
    {$forms.groupForm.btn_submit.control}
    {$forms.groupForm.close} \ No newline at end of file diff --git a/initialize.php b/initialize.php index 83b50b327..9bd298cb8 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5344"); +define("APP_VERSION", "1.19.23.5345"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/project_add.php b/project_add.php index 5768d5fb5..1b326b627 100644 --- a/project_add.php +++ b/project_add.php @@ -1,30 +1,6 @@ addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); if ($showFiles) $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); $form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); @@ -114,5 +90,5 @@ $smarty->assign('show_users', count($users) > 0); $smarty->assign('show_tasks', $show_tasks); $smarty->assign('title', $i18n->get('title.add_project')); -$smarty->assign('content_page_name', 'project_add.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'project_add2.tpl'); +$smarty->display('index2.tpl'); diff --git a/project_add1.php b/project_add1.php new file mode 100644 index 000000000..5768d5fb5 --- /dev/null +++ b/project_add1.php @@ -0,0 +1,118 @@ +getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { + header('Location: feature_disabled.php'); + exit(); +} +// End of access checks. + +$showFiles = $user->isPluginEnabled('at'); +$users = ttGroupHelper::getActiveUsers(); +foreach ($users as $user_item) + $all_users[$user_item['id']] = $user_item['name']; + +$tasks = ttGroupHelper::getActiveTasks(); +foreach ($tasks as $task_item) + $all_tasks[$task_item['id']] = $task_item['name']; +$show_tasks = MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && count($tasks) > 0; + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('project_name')); + $cl_description = trim($request->getParameter('description')); + $cl_users = $request->getParameter('users', array()); + $cl_tasks = $request->getParameter('tasks', array()); +} else { + foreach ($users as $user_item) + $cl_users[] = $user_item['id']; + foreach ($tasks as $task_item) + $cl_tasks[] = $task_item['id']; +} + +$form = new Form('projectForm'); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','style'=>'width: 250px;','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +if ($showFiles) + $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); +$form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); +if ($show_tasks) + $form->addInput(array('type'=>'checkboxgroup','name'=>'tasks','data'=>$all_tasks,'layout'=>'H','value'=>$cl_tasks)); +$form->addInput(array('type'=>'submit','name'=>'btn_add','value'=>$i18n->get('button.add'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); + if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); + if (!ttGroupHelper::validateCheckboxGroupInput($cl_users, 'tt_users')) $err->add($i18n->get('error.field'), $i18n->get('label.users')); + if (!ttGroupHelper::validateCheckboxGroupInput($cl_tasks, 'tt_tasks')) $err->add($i18n->get('error.field'), $i18n->get('label.tasks')); + + if ($err->no()) { + if (!ttProjectHelper::getProjectByName($cl_name)) { + $id = ttProjectHelper::insert(array('name' => $cl_name, + 'description' => $cl_description, + 'users' => $cl_users, + 'tasks' => $cl_tasks, + 'status' => ACTIVE)); + + // Put a new file in storage if we have it. + if ($id && $showFiles && $_FILES['newfile']['name']) { + $fileHelper = new ttFileHelper($err); + $fields = array('entity_type'=>'project', + 'entity_id' => $id, + 'file_name' => $_FILES['newfile']['name']); + $fileHelper->putFile($fields); + } + if ($id) { + header('Location: projects.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } +} // isPost + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('onload', 'onLoad="document.projectForm.project_name.focus()"'); +$smarty->assign('show_files', $showFiles); +$smarty->assign('show_users', count($users) > 0); +$smarty->assign('show_tasks', $show_tasks); +$smarty->assign('title', $i18n->get('title.add_project')); +$smarty->assign('content_page_name', 'project_add.tpl'); +$smarty->display('index.tpl'); From d768f2767e22ae1bca4af601143ba4f3c65e174c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 18:34:18 +0000 Subject: [PATCH 090/587] Removed not needed label tags. --- WEB-INF/templates/project_add2.tpl | 8 ++++---- initialize.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/WEB-INF/templates/project_add2.tpl b/WEB-INF/templates/project_add2.tpl index 401fd26ac..9eba40d90 100644 --- a/WEB-INF/templates/project_add2.tpl +++ b/WEB-INF/templates/project_add2.tpl @@ -21,17 +21,17 @@
    {$i18n.label.users}:
    {$i18n.label.users}: {$forms.projectForm.users.control}
    {$i18n.label.tasks}:
    {$i18n.label.tasks}: {$forms.projectForm.tasks.control}
    + + + + + + + + + + + + + + + + + + +{if $show_users} + + + + + + +{/if} +{if $show_tasks} + + + + + + +{/if} + +
    {$forms.projectForm.project_name.control}
    {$forms.projectForm.description.control}
    {$forms.projectForm.status.control}
    {$i18n.label.users}:
    {$i18n.label.users}:{$forms.projectForm.users.control}
    {$i18n.label.tasks}:
    {$i18n.label.tasks}:{$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
    +
    {$forms.projectForm.btn_save.control} {$forms.projectForm.btn_copy.control}
    +{$forms.projectForm.close} diff --git a/initialize.php b/initialize.php index 4b39a7fa2..50887d050 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5346"); +define("APP_VERSION", "1.19.23.5347"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/project_edit.php b/project_edit.php index e1792e48c..cbb2c1f9b 100644 --- a/project_edit.php +++ b/project_edit.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_project_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); $form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); @@ -132,5 +108,5 @@ $smarty->assign('show_users', count($users) > 0); $smarty->assign('show_tasks', $show_tasks); $smarty->assign('title', $i18n->get('title.edit_project')); -$smarty->assign('content_page_name', 'project_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'project_edit2.tpl'); +$smarty->display('index2.tpl'); diff --git a/project_edit1.php b/project_edit1.php new file mode 100644 index 000000000..e1792e48c --- /dev/null +++ b/project_edit1.php @@ -0,0 +1,136 @@ +getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { + header('Location: feature_disabled.php'); + exit(); +} +$cl_project_id = (int)$request->getParameter('id'); +$project = ttProjectHelper::get($cl_project_id); +if (!$project) { + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +$users = ttGroupHelper::getActiveUsers(); +foreach ($users as $user_item) + $all_users[$user_item['id']] = $user_item['name']; + +$tasks = ttGroupHelper::getActiveTasks(); +foreach ($tasks as $task_item) + $all_tasks[$task_item['id']] = $task_item['name']; +$show_tasks = MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && count($tasks) > 0; + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('project_name')); + $cl_description = trim($request->getParameter('description')); + $cl_status = $request->getParameter('status'); + $cl_users = $request->getParameter('users', array()); + $cl_tasks = $request->getParameter('tasks', array()); +} else { + $cl_name = $project['name']; + $cl_description = $project['description']; + $cl_status = $project['status']; + $cl_users = ttProjectHelper::getAssignedUsers($cl_project_id); + $cl_tasks = explode(',', $project['tasks']); +} + +$form = new Form('projectForm'); +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_project_id)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','style'=>'width: 250px;','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, + 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); +$form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); +if ($show_tasks) + $form->addInput(array('type'=>'checkboxgroup','name'=>'tasks','data'=>$all_tasks,'layout'=>'H','value'=>$cl_tasks)); +$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); +$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); + if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); + if (!ttGroupHelper::validateCheckboxGroupInput($cl_users, 'tt_users')) $err->add($i18n->get('error.field'), $i18n->get('label.users')); + if (!ttGroupHelper::validateCheckboxGroupInput($cl_tasks, 'tt_tasks')) $err->add($i18n->get('error.field'), $i18n->get('label.tasks')); + + if ($err->no()) { + if ($request->getParameter('btn_save')) { + $existing_project = ttProjectHelper::getProjectByName($cl_name); + if (!$existing_project || ($cl_project_id == $existing_project['id'])) { + // Update project information. + if (ttProjectHelper::update(array( + 'id' => $cl_project_id, + 'name' => $cl_name, + 'description' => $cl_description, + 'status' => $cl_status, + 'users' => $cl_users, + 'tasks' => $cl_tasks))) { + header('Location: projects.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } + + if ($request->getParameter('btn_copy')) { + if (!ttProjectHelper::getProjectByName($cl_name)) { + if (ttProjectHelper::insert(array('name' => $cl_name, + 'description' => $cl_description, + 'users' => $cl_users, + 'tasks' => $cl_tasks, + 'status' => ACTIVE))) { + header('Location: projects.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } + } +} // isPost + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('onload', 'onLoad="document.projectForm.project_name.focus()"'); +$smarty->assign('show_users', count($users) > 0); +$smarty->assign('show_tasks', $show_tasks); +$smarty->assign('title', $i18n->get('title.edit_project')); +$smarty->assign('content_page_name', 'project_edit.tpl'); +$smarty->display('index.tpl'); From c034f76bfe0c5fa14c90eb03ce27930b305f6524 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 30 Oct 2020 19:14:17 +0000 Subject: [PATCH 092/587] Eliminated one more PHP warning. --- WEB-INF/lib/ttReportHelper.class.php | 28 +++++++++++++++------------- initialize.php | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index e090af6f4..294225e0c 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -635,19 +635,21 @@ static function putInSession($report_items) { unset($_SESSION['report_item_ids']); unset($_SESSION['report_item_expense_ids']); - // Iterate through records and build 2 comma-separated lists. - foreach($report_items as $item) { - if ($item['type'] == 1) - $report_item_ids .= ','.$item['id']; - else if ($item['type'] == 2) - $report_item_expense_ids .= ','.$item['id']; - } - $report_item_ids = trim($report_item_ids, ','); - $report_item_expense_ids = trim($report_item_expense_ids, ','); - - // The lists are ready. Put them in session. - if ($report_item_ids) $_SESSION['report_item_ids'] = $report_item_ids; - if ($report_item_expense_ids) $_SESSION['report_item_expense_ids'] = $report_item_expense_ids; + if (is_array($report_items)) { + // Iterate through records and build 2 comma-separated lists. + foreach($report_items as $item) { + if ($item['type'] == 1) + $report_item_ids .= ','.$item['id']; + else if ($item['type'] == 2) + $report_item_expense_ids .= ','.$item['id']; + } + $report_item_ids = trim($report_item_ids, ','); + $report_item_expense_ids = trim($report_item_expense_ids, ','); + + // The lists are ready. Put them in session. + if ($report_item_ids) $_SESSION['report_item_ids'] = $report_item_ids; + if ($report_item_expense_ids) $_SESSION['report_item_expense_ids'] = $report_item_expense_ids; + } } // getFromSession obtains tt_log and tt_expense_items ids stored in user session. diff --git a/initialize.php b/initialize.php index 50887d050..79679dbce 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5347"); +define("APP_VERSION", "1.19.23.5348"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From d645c848d129a0dc9a7e35dc449996ee4fae63e2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 1 Nov 2020 17:56:07 +0000 Subject: [PATCH 093/587] Made users.php page mobile-friendly. --- WEB-INF/templates/projects2.tpl | 4 +- WEB-INF/templates/users2.tpl | 97 +++++++++++++++++++++++++++++++++ initialize.php | 2 +- users.php | 32 ++--------- users1.php | 69 +++++++++++++++++++++++ 5 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 WEB-INF/templates/users2.tpl create mode 100644 users1.php diff --git a/WEB-INF/templates/projects2.tpl b/WEB-INF/templates/projects2.tpl index 9b8de40c4..bb40d1430 100644 --- a/WEB-INF/templates/projects2.tpl +++ b/WEB-INF/templates/projects2.tpl @@ -3,9 +3,7 @@ {if $user->can('manage_projects')} - {if $inactive_projects} -
    {$i18n.form.projects.active_projects}
    - {/if} + {if $inactive_projects}
    {$i18n.form.projects.active_projects}
    {/if} {if $active_projects} diff --git a/WEB-INF/templates/users2.tpl b/WEB-INF/templates/users2.tpl new file mode 100644 index 000000000..816490da4 --- /dev/null +++ b/WEB-INF/templates/users2.tpl @@ -0,0 +1,97 @@ + + +{if $user->can('manage_users')} + {if $inactive_users}
    {$i18n.label.active_users}
    {/if} + {if $active_users} +
    + + + + + {if $show_quota} + + {/if} + + + + {foreach $active_users as $u} + + + + + {if $show_quota} + + {/if} + {if $u.group_id != $user->group_id || $u.rank < $user->rank || ($u.rank == $user->rank && $u.id == $user->id)} + + {if $u.id != $user->id}{else}{/if} + {else} + + + {/if} + + {/foreach} + {/if} +
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}{$i18n.label.quota}
    + {if $uncompleted_indicators} + + {/if} + {$u.name|escape} + {$u.login|escape}{$u.role_name|escape}{$u.quota_percent}{$i18n.label.edit}{$i18n.label.delete}
    +
    + {if $inactive_users} +
    {$i18n.label.inactive_users}
    + + + + + + {if $show_quota} + + {/if} + + + + {foreach $inactive_users as $u} + + + + + {if $show_quota} + + {/if} + {if $u.group_id != $user->group_id || $u.rank < $user->rank} + + + {else} + + + {/if} + + {/foreach} +
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}{$i18n.label.quota}
    {$u.name|escape}{$u.login|escape}{$u.role_name|escape}{$u.quota_percent}{$i18n.label.edit}{$i18n.label.delete}
    +
    + {/if} +{else} + + + + + + + {foreach $active_users as $u} + + + + + + {/foreach} +
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}
    + {if $uncompleted_indicators} + + {/if} + {$u.name|escape} + {$u.login|escape}{$u.role_name|escape}
    +{/if} diff --git a/initialize.php b/initialize.php index 79679dbce..9e4e77c91 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5348"); +define("APP_VERSION", "1.19.23.5349"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/users.php b/users.php index 2fbcb5d20..a0ccdc3c1 100644 --- a/users.php +++ b/users.php @@ -1,30 +1,6 @@ assign('inactive_users', $inactive_users); $smarty->assign('show_quota', $user->isPluginEnabled('mq')); $smarty->assign('title', $i18n->get('title.users')); -$smarty->assign('content_page_name', 'users.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'users2.tpl'); +$smarty->display('index2.tpl'); diff --git a/users1.php b/users1.php new file mode 100644 index 000000000..2fbcb5d20 --- /dev/null +++ b/users1.php @@ -0,0 +1,69 @@ +getMaxRankForGroup($user->getGroup()); +if ($user->can('view_users')) + $options = array('status'=>ACTIVE,'include_clients'=>true,'include_login'=>true,'include_role'=>true); +else /* if ($user->can('manage_users')) */ + $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_clients'=>true,'include_self'=>true,'include_login'=>true,'include_role'=>true); +$active_users = $user->getUsers($options); + +// Prepare a list of inactive users. +if($user->can('manage_users')) { + $options = array('status'=>INACTIVE,'max_rank'=>$rank,'include_clients'=>true,'include_login'=>true,'include_role'=>true); + $inactive_users = $user->getUsers($options); +} + +$uncompleted_indicators = $user->getConfigOption('uncompleted_indicators'); +if ($uncompleted_indicators) { + // Check each active user if they have an uncompleted time entry. + foreach ($active_users as $key => $active_user) { + $active_users[$key]['has_uncompleted_entry'] = (bool) ttTimeHelper::getUncompleted($active_user['id']); + } + $smarty->assign('uncompleted_indicators', true); +} + +$smarty->assign('active_users', $active_users); +$smarty->assign('inactive_users', $inactive_users); +$smarty->assign('show_quota', $user->isPluginEnabled('mq')); +$smarty->assign('title', $i18n->get('title.users')); +$smarty->assign('content_page_name', 'users.tpl'); +$smarty->display('index.tpl'); From 513d272520a6f807de02f961b7a0b2fef13a5468 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 1 Nov 2020 18:18:37 +0000 Subject: [PATCH 094/587] Made user_delete.php mobile friendly. --- WEB-INF/templates/user_delete2.tpl | 4 ++++ initialize.php | 2 +- user_delete.php | 32 ++++-------------------------- 3 files changed, 9 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/user_delete2.tpl diff --git a/WEB-INF/templates/user_delete2.tpl b/WEB-INF/templates/user_delete2.tpl new file mode 100644 index 000000000..3e089d29d --- /dev/null +++ b/WEB-INF/templates/user_delete2.tpl @@ -0,0 +1,4 @@ +{$forms.userDeleteForm.open} +
    {$user_to_delete|escape}
    +
    {$forms.userDeleteForm.btn_delete.control} {$forms.userDeleteForm.btn_cancel.control}
    +{$forms.userDeleteForm.close} diff --git a/initialize.php b/initialize.php index 9e4e77c91..8e626e50b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5349"); +define("APP_VERSION", "1.19.23.5350"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_delete.php b/user_delete.php index 24f84010f..99378fda4 100644 --- a/user_delete.php +++ b/user_delete.php @@ -1,30 +1,6 @@ assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('title', $i18n->get('title.delete_user')); -$smarty->assign('content_page_name', 'user_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'user_delete2.tpl'); +$smarty->display('index2.tpl'); From 9ab973e980f79c18ce4c0634d3e485d122aaaaa4 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 5 Nov 2020 20:40:29 +0000 Subject: [PATCH 095/587] Refactored user_add.php for mobile access. --- WEB-INF/templates/user_add2.tpl | 159 +++++++++++++++++++++ initialize.php | 2 +- user_add.php | 39 +---- user_add1.php | 244 ++++++++++++++++++++++++++++++++ 4 files changed, 411 insertions(+), 33 deletions(-) create mode 100644 WEB-INF/templates/user_add2.tpl create mode 100644 user_add1.php diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl new file mode 100644 index 000000000..983784f7b --- /dev/null +++ b/WEB-INF/templates/user_add2.tpl @@ -0,0 +1,159 @@ + + +{$forms.userForm.open} +{$forms.projectForm.open} + + + + + + + + + + + + + +{if !$auth_external} + + + + + + + + + + + + +{/if} + + + + + +{if $show_quota} + + + + + + +{/if} + + + + + + + + + + + + +{if $custom_fields && $custom_fields->userFields} + {foreach $custom_fields->userFields as $userField} + {assign var="control_name" value='user_field_'|cat:$userField['id']} + + + + + + + {/foreach} +{/if} + + + + + + + +{if $show_projects} + + + + + + + + +{/if} + + + + + + +
    {$forms.userForm.name.control}
    {$forms.userForm.login.control}
    {$forms.userForm.pas1.control}
    {$forms.userForm.pas2.control}
    {$forms.userForm.email.control}
    {$forms.userForm.quota_percent.control} + {$i18n.label.what_is_it} + {$i18n.label.what_is_it} +
    {$forms.userForm.role.control}
    {$forms.userForm.client.control}
    {$forms.userForm.$control_name.control}
    {$forms.userForm.rate.control}
    {$forms.userForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.userForm.btn_submit.control}
    +{$forms.userForm.close} diff --git a/initialize.php b/initialize.php index 8e626e50b..32ba423e9 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5350"); +define("APP_VERSION", "1.19.23.5351"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_add.php b/user_add.php index 0cd71b0a4..327ee8702 100644 --- a/user_add.php +++ b/user_add.php @@ -1,30 +1,6 @@ getParameter('rate_'.$p), true)) { - $project_with_rate = array(); + $project_with_rate = array(); $project_with_rate['id'] = $p; $project_with_rate['rate'] = $request->getParameter('rate_'.$p); $assigned_projects[] = $project_with_rate; @@ -97,8 +73,8 @@ } $form = new Form('userForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 300px;','value'=>$cl_name)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); if (!$auth->isPasswordExternal()) { $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); @@ -118,7 +94,6 @@ $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$userCustomFields[$userField['id']]['value'])); } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', 'data'=>CustomFields::getOptions($userField['id']), 'value'=>$userCustomFields[$userField['id']]['value'], 'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -240,5 +215,5 @@ function render(&$table, $value, $row, $column, $selected = false) { $smarty->assign('show_quota', $show_quota); $smarty->assign('show_projects', $show_projects); $smarty->assign('title', $i18n->get('title.add_user')); -$smarty->assign('content_page_name', 'user_add.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'user_add2.tpl'); +$smarty->display('index2.tpl'); diff --git a/user_add1.php b/user_add1.php new file mode 100644 index 000000000..b7c2bc7a6 --- /dev/null +++ b/user_add1.php @@ -0,0 +1,244 @@ +isPluginEnabled('mq'); +if ($user->isPluginEnabled('cl')) + $clients = ttGroupHelper::getActiveClients(); + +// Use custom fields plugin if it is enabled. +if ($user->isPluginEnabled('cf')) { + require_once('plugins/CustomFields.class.php'); + $custom_fields = new CustomFields(); + $smarty->assign('custom_fields', $custom_fields); +} + +$assigned_projects = array(); +if ($request->isPost()) { + $cl_name = trim($request->getParameter('name')); + $cl_login = trim($request->getParameter('login')); + if (!$auth->isPasswordExternal()) { + $cl_password1 = $request->getParameter('pas1'); + $cl_password2 = $request->getParameter('pas2'); + } + $cl_email = trim($request->getParameter('email')); + $cl_role_id = $request->getParameter('role'); + $cl_client_id = $request->getParameter('client'); + $cl_quota_percent = $request->getParameter('quota_percent'); + // If we have user custom fields - collect input. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $control_name = 'user_field_'.$userField['id']; + $userCustomFields[$userField['id']] = array('field_id' => $userField['id'], + 'control_name' => $control_name, + 'label' => $userField['label'], + 'type' => $userField['type'], + 'required' => $userField['required'], + 'value' => trim($request->getParameter($control_name))); + } + } + $cl_rate = $request->getParameter('rate'); + $cl_projects = $request->getParameter('projects'); + if (is_array($cl_projects)) { + foreach ($cl_projects as $p) { + if (ttValidFloat($request->getParameter('rate_'.$p), true)) { + $project_with_rate = array(); + $project_with_rate['id'] = $p; + $project_with_rate['rate'] = $request->getParameter('rate_'.$p); + $assigned_projects[] = $project_with_rate; + } else + $err->add($i18n->get('error.field'), 'rate_'.$p); + } + } +} + +$form = new Form('userForm'); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 300px;','value'=>$cl_name)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); +if (!$auth->isPasswordExternal()) { + $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); + $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); +} +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); + +$active_roles = ttTeamHelper::getActiveRolesForUser(); +$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles,'datakeys'=>array('id', 'name'))); +if ($user->isPluginEnabled('cl')) + $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); + +// If we have custom fields - add controls for them. +if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($userField['type'] == CustomFields::TYPE_TEXT) { + $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$userCustomFields[$userField['id']]['value'])); + } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { + $form->addInput(array('type'=>'combobox','name'=>$field_name, + 'style'=>'width: 250px;', + 'data'=>CustomFields::getOptions($userField['id']), + 'value'=>$userCustomFields[$userField['id']]['value'], + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + } + } +} + +$form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'rate','format'=>'.2','value'=>$cl_rate)); +if ($show_quota) + $form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'quota_percent','format'=>'.2','value'=>$cl_quota_percent)); + +$show_projects = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); +if ($show_projects) { + $projects = ttGroupHelper::getActiveProjects(); + if (count($projects) == 0) $show_projects = false; +} + +// Define classes for the projects table. +class NameCellRenderer extends DefaultCellRenderer { + function render(&$table, $value, $row, $column, $selected = false) { + $this->setOptions(array('width'=>200)); + $this->setValue(''); + return $this->toString(); + } +} +class RateCellRenderer extends DefaultCellRenderer { + function render(&$table, $value, $row, $column, $selected = false) { + global $assigned_projects; + $field = new FloatField('rate_'.$table->getValueAtName($row, 'id')); + $field->setFormName($table->getFormName()); + $field->setSize(5); + $field->setFormat('.2'); + foreach ($assigned_projects as $p) { + if ($p['id'] == $table->getValueAtName($row,'id')) $field->setValue($p['rate']); + } + $this->setValue($field->getHtml()); + return $this->toString(); + } +} +// Create projects table. +$table = new Table('projects'); +$table->setIAScript('setDefaultRate'); +$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); +$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); +$table->setData($projects); +$table->setKeyField('id'); +$table->setValue($cl_projects); +$table->addColumn(new TableColumn('name', $i18n->get('label.project'), new NameCellRenderer())); +$table->addColumn(new TableColumn('p_rate', $i18n->get('form.users.rate'), new RateCellRenderer())); +$form->addInputElement($table); + +$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.submit'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.person_name')); + if (!ttValidString($cl_login)) $err->add($i18n->get('error.field'), $i18n->get('label.login')); + if (!$auth->isPasswordExternal()) { + if (!ttValidString($cl_password1)) $err->add($i18n->get('error.field'), $i18n->get('label.password')); + if (!ttValidString($cl_password2)) $err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); + if ($cl_password1 !== $cl_password2) + $err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); + } + if (!ttValidEmail($cl_email, true)) $err->add($i18n->get('error.field'), $i18n->get('label.email')); + // Require selection of a client for a client role. + if ($user->isPluginEnabled('cl') && ttRoleHelper::isClientRole($cl_role_id) && !$cl_client_id) $err->add($i18n->get('error.client')); + if (!ttValidFloat($cl_quota_percent, true)) $err->add($i18n->get('error.field'), $i18n->get('label.quota')); + // Validate input in user custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($userCustomFields as $userField) { + // Validation is the same for text and dropdown fields. + if (!ttValidString($userField['value'], !$userField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($userField['label'])); + } + } + if (!ttValidFloat($cl_rate, true)) $err->add($i18n->get('error.field'), $i18n->get('form.users.default_rate')); + if (!ttUserHelper::canAdd()) $err->add($i18n->get('error.user_count')); + + if ($err->no()) { + if (!ttUserHelper::getUserByLogin($cl_login)) { + $fields = array( + 'name' => $cl_name, + 'login' => $cl_login, + 'password' => $cl_password1, + 'rate' => $cl_rate, + 'quota_percent' => $cl_quota_percent, + 'group_id' => $user->getGroup(), + 'org_id' => $user->org_id, + 'role_id' => $cl_role_id, + 'client_id' => $cl_client_id, + 'projects' => $assigned_projects, + 'email' => $cl_email); + $user_id = ttUserHelper::insert($fields); + + // Insert user custom fields if we have them. + $result = true; + if ($user_id && $custom_fields && $custom_fields->userFields) { + $result = $custom_fields->insertEntityFields(CustomFields::ENTITY_USER, $user_id, $userCustomFields); + } + + if ($user_id && $result) { + if (!$user->exists()) { + // We added a user to an empty subgroup. Set new user as on behalf user. + // Needed for user-based things to work (such as notifications config). + $user->setOnBehalfUser($user_id); + } + header('Location: users.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.user_exists')); + } +} // isPost + +$smarty->assign('auth_external', $auth->isPasswordExternal()); +$smarty->assign('active_roles', $active_roles); +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); +$smarty->assign('show_quota', $show_quota); +$smarty->assign('show_projects', $show_projects); +$smarty->assign('title', $i18n->get('title.add_user')); +$smarty->assign('content_page_name', 'user_add.tpl'); +$smarty->display('index.tpl'); From c2ccfd3379ff6702126583fb272b9b4dddaac4b2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 5 Nov 2020 21:03:18 +0000 Subject: [PATCH 096/587] Usability improvements on user_add.php. --- WEB-INF/templates/user_add2.tpl | 10 ++++++++-- initialize.php | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index 983784f7b..b1ae40d1b 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -34,6 +34,7 @@ function setDefaultRate(element) { function handleClientControl() { var selectedRoleId = document.getElementById("role").value; var clientControl = document.getElementById("client"); + var clientBlock = document.getElementById("client_block"); var nonClientBlock = document.getElementById("non_client_block"); var projectsControl = document.getElementById("projects_control"); @@ -43,6 +44,7 @@ function handleClientControl() { var isClient = roles[i][1]; if (isClient == 1) { clientControl.style.visibility = "visible"; + clientBlock.style.display = ""; nonClientBlock.style.display = "none"; projectsControl.style.display = "none"; @@ -55,6 +57,7 @@ function handleClientControl() { } else { clientControl.value = ""; clientControl.style.visibility = "hidden"; + clientBlock.style.display = "none"; nonClientBlock.style.display = ""; projectsControl.style.display = ""; } @@ -109,17 +112,20 @@ function handleClientControl() {
    {$forms.userForm.role.control}
    {$forms.userForm.client.control}
    @@ -101,17 +100,6 @@ function handleClientControl() { -{if $show_quota} - - - - - - -{/if} @@ -127,6 +115,17 @@ function handleClientControl() { +{if $show_quota} + + + + + + +{/if} {if $custom_fields && $custom_fields->userFields} {foreach $custom_fields->userFields as $userField} {assign var="control_name" value='user_field_'|cat:$userField['id']} diff --git a/WEB-INF/templates/user_edit2.tpl b/WEB-INF/templates/user_edit2.tpl new file mode 100644 index 000000000..6339b9734 --- /dev/null +++ b/WEB-INF/templates/user_edit2.tpl @@ -0,0 +1,202 @@ + + +{$forms.userForm.open} +
    {$forms.userForm.email.control}
    {$forms.userForm.quota_percent.control} - {$i18n.label.what_is_it} - {$i18n.label.what_is_it} -
    {$forms.userForm.quota_percent.control} + {$i18n.label.what_is_it} + {$i18n.label.what_is_it} +
    + + + + + + + + + + + + +{if !$auth_external} + + + + + + + + + + + + +{/if} + + + + + +{if $user->id != $user_id} + + + + + + + + + + + + + + + + + + + + +{/if} +{if $user->id == $user_id} + + + + + + +{/if} + +{if $show_quota} + + + + + + +{/if} +{if $custom_fields && $custom_fields->userFields} + {foreach $custom_fields->userFields as $userField} + {assign var="control_name" value='user_field_'|cat:$userField['id']} + + + + + + + {/foreach} +{/if} + + + + + + + +{if $show_projects} + + + + + + + + +{/if} + + + + + + +
    {$forms.userForm.name.control}
    {$forms.userForm.login.control}
    {$forms.userForm.pas1.control}
    {$forms.userForm.pas2.control}
    {$forms.userForm.email.control}
    {$forms.userForm.role.control}
    {$forms.userForm.client.control}
    {$forms.userForm.status.control}
    {$user->role_name} {if $can_swap}{$i18n.form.user_edit.swap_roles}{/if}
    {$forms.userForm.quota_percent.control} + {$i18n.label.what_is_it} + {$i18n.label.what_is_it} +
    {$forms.userForm.$control_name.control}
    {$forms.userForm.rate.control}
    {$forms.userForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.userForm.btn_submit.control}
    +{$forms.userForm.close} diff --git a/initialize.php b/initialize.php index c50180255..553382e95 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5352"); +define("APP_VERSION", "1.19.23.5353"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_edit.php b/user_edit.php index d74ae2785..493cb8d4d 100644 --- a/user_edit.php +++ b/user_edit.php @@ -1,30 +1,6 @@ addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 300px;','value'=>$cl_name)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); if (!$auth->isPasswordExternal()) { $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); } -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','style'=>'width: 300px;','value'=>$cl_email)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); $active_roles = ttTeamHelper::getActiveRolesForUser(); $form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles, 'datakeys'=>array('id', 'name'))); @@ -154,7 +130,6 @@ $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$userCustomFields[$userField['id']]['value'])); } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', 'data'=>CustomFields::getOptions($userField['id']), 'value'=>$userCustomFields[$userField['id']]['value'], 'empty'=>array(''=>$i18n->get('dropdown.select')))); @@ -304,5 +279,5 @@ function render(&$table, $value, $row, $column, $selected = false) { $smarty->assign('show_projects', $show_projects); $smarty->assign('user_id', $user_id); $smarty->assign('title', $i18n->get('title.edit_user')); -$smarty->assign('content_page_name', 'user_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'user_edit2.tpl'); +$smarty->display('index2.tpl'); diff --git a/user_edit1.php b/user_edit1.php new file mode 100644 index 000000000..d74ae2785 --- /dev/null +++ b/user_edit1.php @@ -0,0 +1,308 @@ +getParameter('id'); +$user_details = $user->getUserDetails($user_id); +if (!$user_details) { + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +$show_quota = $user->isPluginEnabled('mq'); +if ($user->isPluginEnabled('cl')) + $clients = ttGroupHelper::getActiveClients(); + +// Use custom fields plugin if it is enabled. +if ($user->isPluginEnabled('cf')) { + require_once('plugins/CustomFields.class.php'); + $custom_fields = new CustomFields(); + $smarty->assign('custom_fields', $custom_fields); +} + +$show_projects = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); +if ($show_projects) { + $projects = ttGroupHelper::getActiveProjects(); + if (count($projects) == 0) $show_projects = false; +} +$assigned_projects = array(); + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('name')); + $cl_login = trim($request->getParameter('login')); + if (!$auth->isPasswordExternal()) { + $cl_password1 = $request->getParameter('pas1'); + $cl_password2 = $request->getParameter('pas2'); + } + $cl_email = trim($request->getParameter('email')); + $cl_role_id = $request->getParameter('role'); + $cl_client_id = $request->getParameter('client'); + $cl_status = $request->getParameter('status'); + $cl_quota_percent = $request->getParameter('quota_percent'); + // If we have user custom fields - collect input. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $control_name = 'user_field_'.$userField['id']; + $userCustomFields[$userField['id']] = array('field_id' => $userField['id'], + 'control_name' => $control_name, + 'label' => $userField['label'], + 'type' => $userField['type'], + 'required' => $userField['required'], + 'value' => trim($request->getParameter($control_name))); + } + } + $cl_rate = $request->getParameter('rate'); + $cl_projects = $request->getParameter('projects'); + if (is_array($cl_projects)) { + foreach ($cl_projects as $p) { + if (ttValidFloat($request->getParameter('rate_'.$p), true)) { + $project_with_rate = array(); + $project_with_rate['id'] = $p; + $project_with_rate['rate'] = $request->getParameter('rate_'.$p); + $assigned_projects[] = $project_with_rate; + } else + $err->add($i18n->get('error.field'), 'rate_'.$p); + } + } +} else { + $cl_name = $user_details['name']; + $cl_login = $user_details['login']; + $cl_email = $user_details['email']; + $cl_quota_percent = str_replace('.', $user->getDecimalMark(), $user_details['quota_percent']); + // If we have user custom fields - collect values from database. + if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $control_name = 'user_field_'.$userField['id']; + $userCustomFields[$userField['id']] = array('field_id' => $userField['id'], + 'control_name' => $control_name, + 'label' => $userField['label'], + 'type' => $userField['type'], + 'required' => $userField['required'], + 'value' => $custom_fields->getEntityFieldValue(CustomFields::ENTITY_USER, $user_id, $userField['id'], $userField['type'])); + } + } + $cl_rate = str_replace('.', $user->getDecimalMark(), $user_details['rate']); + $cl_role_id = $user_details['role_id']; + $cl_client_id = $user_details['client_id']; + $cl_status = $user_details['status']; + $cl_projects = array(); + $assigned_projects = ttProjectHelper::getAssignedProjects($user_id); + foreach($assigned_projects as $p) { + $cl_projects[] = $p['id']; + } +} + +$form = new Form('userForm'); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 300px;','value'=>$cl_name)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); +if (!$auth->isPasswordExternal()) { + $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); + $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); +} +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','style'=>'width: 300px;','value'=>$cl_email)); + +$active_roles = ttTeamHelper::getActiveRolesForUser(); +$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles, 'datakeys'=>array('id', 'name'))); +if ($user->isPluginEnabled('cl')) + $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); + +// If we have custom fields - add controls for them. +if ($custom_fields && $custom_fields->userFields) { + foreach ($custom_fields->userFields as $userField) { + $field_name = 'user_field_'.$userField['id']; + if ($userField['type'] == CustomFields::TYPE_TEXT) { + $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$userCustomFields[$userField['id']]['value'])); + } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { + $form->addInput(array('type'=>'combobox','name'=>$field_name, + 'style'=>'width: 250px;', + 'data'=>CustomFields::getOptions($userField['id']), + 'value'=>$userCustomFields[$userField['id']]['value'], + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + } + } +} + +$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, + 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); +$form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'rate','format'=>'.2','value'=>$cl_rate)); +if ($show_quota) + $form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'quota_percent','format'=>'.2','value'=>$cl_quota_percent)); + +// Define classes for the projects table. +class NameCellRenderer extends DefaultCellRenderer { + function render(&$table, $value, $row, $column, $selected = false) { + $this->setOptions(array('width'=>200)); + $this->setValue(''); + return $this->toString(); + } +} +class RateCellRenderer extends DefaultCellRenderer { + function render(&$table, $value, $row, $column, $selected = false) { + global $assigned_projects; + + $field = new FloatField('rate_'.$table->getValueAtName($row,'id')); + $field->setFormName($table->getFormName()); + $field->setSize(5); + $field->setFormat('.2'); + foreach ($assigned_projects as $p) { + if ($p['id'] == $table->getValueAtName($row,'id')) $field->setValue($p['rate']); + } + $this->setValue($field->getHtml()); + return $this->toString(); + } +} +// Create projects table. +$table = new Table('projects'); +$table->setIAScript('setRate'); +$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); +$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); +$table->setData($projects); +$table->setKeyField('id'); +$table->setValue($cl_projects); +$table->addColumn(new TableColumn('name', $i18n->get('label.project'), new NameCellRenderer())); +$table->addColumn(new TableColumn('p_rate', $i18n->get('form.users.rate'), new RateCellRenderer())); +$form->addInputElement($table); + +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$user_id)); +$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.save'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.person_name')); + if (!ttValidString($cl_login)) $err->add($i18n->get('error.field'), $i18n->get('label.login')); + if (!$auth->isPasswordExternal() && ($cl_password1 || $cl_password2)) { + if (!ttValidString($cl_password1)) $err->add($i18n->get('error.field'), $i18n->get('label.password')); + if (!ttValidString($cl_password2)) $err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); + if ($cl_password1 !== $cl_password2) + $err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); + } + if (!ttValidEmail($cl_email, true)) $err->add($i18n->get('error.field'), $i18n->get('label.email')); + // Require selection of a client for a client role. + if ($user->isPluginEnabled('cl') && ttRoleHelper::isClientRole($cl_role_id) && !$cl_client_id) $err->add($i18n->get('error.client')); + if (!ttValidFloat($cl_quota_percent, true)) $err->add($i18n->get('error.field'), $i18n->get('label.quota')); + // Validate input in user custom fields. + if ($custom_fields && $custom_fields->userFields) { + foreach ($userCustomFields as $userField) { + // Validation is the same for text and dropdown fields. + if (!ttValidString($userField['value'], !$userField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($userField['label'])); + } + } + if (!ttValidFloat($cl_rate, true)) $err->add($i18n->get('error.field'), $i18n->get('form.users.default_rate')); + + if ($err->no()) { + $existing_user = ttUserHelper::getUserByLogin($cl_login); + if (!$existing_user || ($user_id == $existing_user['id'])) { + + $fields = array( + 'name' => $cl_name, + 'login' => $cl_login, + 'password' => $cl_password1, + 'email' => $cl_email, + 'status' => $cl_status, + 'rate' => $cl_rate, + 'quota_percent' => $cl_quota_percent, + 'projects' => $assigned_projects); + if (in_array('manage_users', $user->rights) && $cl_role_id) { + $fields['role_id'] = $cl_role_id; + $fields['client_id'] = $cl_client_id; + } + + $result = ttUserHelper::update($user_id, $fields); + // Update user custom fields if we have them. + if ($result && $custom_fields && $custom_fields->userFields) { + $result = $custom_fields->updateEntityFields(CustomFields::ENTITY_USER, $user_id, $userCustomFields); + } + + if ($result) { + // If our own login changed, set new one in cookie to remember it. + if (($user_id == $user->id) && ($user->login != $cl_login)) { + setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); + } + + // In case the name of the "on behalf" user has changed - set it in session. + if (($user->behalf_id == $user_id) && ($user->behalf_name != $cl_name)) { + $_SESSION['behalf_name'] = $cl_name; + } + + // If we deactivated our own account, do housekeeping and logout. + if ($user->id == $user_id && !is_null($cl_status) && $cl_status == INACTIVE) { + // Remove LOGIN_COOKIE_NAME cookie that stores login name. + unset($_COOKIE[LOGIN_COOKIE_NAME]); + setcookie(LOGIN_COOKIE_NAME, NULL, -1); + + $auth->doLogout(); + header('Location: login.php'); + exit(); + } + + header('Location: users.php'); + exit(); + + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.user_exists')); + } +} // isPost + +$can_swap = false; +if ($user->id == $user_id && $user->can('swap_roles')) { + $users_for_swap = ttTeamHelper::getUsersForSwap(); + if (is_array($users_for_swap) && sizeof($users_for_swap) > 0) + $can_swap = true; +} + +$rates = ttProjectHelper::getRates($user_id); +$smarty->assign('rates', $rates); + +$smarty->assign('auth_external', $auth->isPasswordExternal()); +$smarty->assign('active_roles', $active_roles); +$smarty->assign('can_swap', $can_swap); +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); +$smarty->assign('show_quota', $show_quota); +$smarty->assign('show_projects', $show_projects); +$smarty->assign('user_id', $user_id); +$smarty->assign('title', $i18n->get('title.edit_user')); +$smarty->assign('content_page_name', 'user_edit.tpl'); +$smarty->display('index.tpl'); From 96487108634653cab85a047e425096e9a28e1517 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 10 Nov 2020 22:05:00 +0000 Subject: [PATCH 098/587] Made tasks.php page mobile-friendly. --- WEB-INF/templates/tasks2.tpl | 70 ++++++++++++++++++++++++++++++++ initialize.php | 2 +- tasks.php | 32 ++------------- tasks1.php | 77 ++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/tasks2.tpl create mode 100644 tasks1.php diff --git a/WEB-INF/templates/tasks2.tpl b/WEB-INF/templates/tasks2.tpl new file mode 100644 index 000000000..ac53362eb --- /dev/null +++ b/WEB-INF/templates/tasks2.tpl @@ -0,0 +1,70 @@ + + +{$forms.tasksForm.open} +{if $user->can('manage_tasks')} + + + + + + +
    {$forms.tasksForm.task_required.control} {$i18n.label.what_is_it}{$forms.tasksForm.btn_save.control}
    + {if $inactive_tasks}
    {$i18n.form.tasks.active_tasks}
    {/if} + {if $active_tasks} + + + + + + + + {foreach $active_tasks as $task} + + + + + + + {/foreach} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}{$i18n.label.edit}{$i18n.label.delete}
    + {/if} +
    + {if $inactive_tasks} +
    {$i18n.form.tasks.inactive_tasks}
    + + + + + + + + {foreach $inactive_tasks as $task} + + + + + + + {/foreach} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}{$i18n.label.edit}{$i18n.label.delete}
    +
    + {/if} +{else} + + + + + + {if $active_tasks} + {foreach $active_tasks as $task} + + + + + {/foreach} + {/if} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}
    +{/if} +{$forms.tasksForm.close} diff --git a/initialize.php b/initialize.php index 553382e95..966061772 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5353"); +define("APP_VERSION", "1.19.23.5354"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/tasks.php b/tasks.php index 2e13ead5c..464af6159 100644 --- a/tasks.php +++ b/tasks.php @@ -1,30 +1,6 @@ assign('active_tasks', $active_tasks); $smarty->assign('inactive_tasks', $inactive_tasks); $smarty->assign('title', $i18n->get('title.tasks')); -$smarty->assign('content_page_name', 'tasks.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'tasks2.tpl'); +$smarty->display('index2.tpl'); diff --git a/tasks1.php b/tasks1.php new file mode 100644 index 000000000..2e13ead5c --- /dev/null +++ b/tasks1.php @@ -0,0 +1,77 @@ +getTrackingMode()) { + header('Location: feature_disabled.php'); + exit(); +} +// End of access checks. + +$config = $user->getConfigHelper(); + +if ($request->isPost()) { + $cl_task_required = $request->getParameter('task_required'); +} else { + $cl_task_required = $config->getDefinedValue('task_required'); +} + +if($user->can('manage_tasks')) { + $active_tasks = ttGroupHelper::getActiveTasks(); + $inactive_tasks = ttGroupHelper::getInactiveTasks(); +} else + $active_tasks = $user->getAssignedTasks(); + +$form = new Form('tasksForm'); +$form->addInput(array('type'=>'checkbox','name'=>'task_required','value'=>$cl_task_required)); +$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); + +if ($request->isPost()) { + if ($request->getParameter('btn_save')) { + // Save button clicked. Update config. + $config->setDefinedValue('task_required', $cl_task_required); + if (!$user->updateGroup(array('config' => $config->getConfig()))) { + $err->add($i18n->get('error.db')); + } + } +} + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('active_tasks', $active_tasks); +$smarty->assign('inactive_tasks', $inactive_tasks); +$smarty->assign('title', $i18n->get('title.tasks')); +$smarty->assign('content_page_name', 'tasks.tpl'); +$smarty->display('index.tpl'); From adb4472cfd550a4a8fdd9fd7327b9673fac6f862 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 12 Nov 2020 17:47:23 +0000 Subject: [PATCH 099/587] Made task_delete.php mobile-friendly. --- WEB-INF/templates/task_delete2.tpl | 4 ++++ initialize.php | 2 +- task_delete.php | 32 ++++-------------------------- 3 files changed, 9 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/task_delete2.tpl diff --git a/WEB-INF/templates/task_delete2.tpl b/WEB-INF/templates/task_delete2.tpl new file mode 100644 index 000000000..70044b74a --- /dev/null +++ b/WEB-INF/templates/task_delete2.tpl @@ -0,0 +1,4 @@ +{$forms.taskDeleteForm.open} +
    {$task_to_delete|escape}
    +
    {$forms.taskDeleteForm.btn_delete.control} {$forms.taskDeleteForm.btn_cancel.control}
    +{$forms.taskDeleteForm.close} diff --git a/initialize.php b/initialize.php index 966061772..d14e50d59 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5354"); +define("APP_VERSION", "1.19.23.5355"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/task_delete.php b/task_delete.php index bd0eec717..61f5e23ff 100644 --- a/task_delete.php +++ b/task_delete.php @@ -1,30 +1,6 @@ assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.taskDeleteForm.btn_cancel.focus()"'); $smarty->assign('title', $i18n->get('title.delete_task')); -$smarty->assign('content_page_name', 'task_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'task_delete2.tpl'); +$smarty->display('index2.tpl'); From 5ccad87a6c07d30981f10f3519eb85306b8eda33 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 12 Nov 2020 19:26:20 +0000 Subject: [PATCH 100/587] Made task_add.php mobile-friendly. --- WEB-INF/templates/task_add2.tpl | 30 +++++++++++ initialize.php | 2 +- task_add.php | 36 +++---------- task_add1.php | 89 +++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 31 deletions(-) create mode 100644 WEB-INF/templates/task_add2.tpl create mode 100644 task_add1.php diff --git a/WEB-INF/templates/task_add2.tpl b/WEB-INF/templates/task_add2.tpl new file mode 100644 index 000000000..4bede3e31 --- /dev/null +++ b/WEB-INF/templates/task_add2.tpl @@ -0,0 +1,30 @@ +{$forms.taskForm.open} + + + + + + + + + + + + + +{if $show_projects} + + + + + + +{/if} + + + + + + +
    {$forms.taskForm.name.control}
    {$forms.taskForm.description.control}
    {$i18n.label.projects}:
    {$i18n.label.projects}:{$forms.taskForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.taskForm.btn_submit.control}
    +{$forms.taskForm.close} diff --git a/initialize.php b/initialize.php index d14e50d59..6b404d998 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5355"); +define("APP_VERSION", "1.19.23.5356"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/task_add.php b/task_add.php index 078bd5ca1..852ac378e 100644 --- a/task_add.php +++ b/task_add.php @@ -1,30 +1,6 @@ addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); @@ -85,5 +61,5 @@ $smarty->assign('show_projects', count($projects) > 0); $smarty->assign('onload', 'onLoad="document.taskForm.name.focus()"'); $smarty->assign('title', $i18n->get('title.add_task')); -$smarty->assign('content_page_name', 'task_add.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'task_add2.tpl'); +$smarty->display('index2.tpl'); diff --git a/task_add1.php b/task_add1.php new file mode 100644 index 000000000..078bd5ca1 --- /dev/null +++ b/task_add1.php @@ -0,0 +1,89 @@ +getTrackingMode()) { + header('Location: feature_disabled.php'); + exit(); +} +// End of access checks. + +$projects = ttGroupHelper::getActiveProjects(); + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('name')); + $cl_description = trim($request->getParameter('description')); + $cl_projects = $request->getParameter('projects'); +} else { + foreach ($projects as $project_item) + $cl_projects[] = $project_item['id']; +} + +$form = new Form('taskForm'); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 250px;','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); +$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); + if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); + + if ($err->no()) { + if (!ttTaskHelper::getTaskByName($cl_name)) { + if (ttTaskHelper::insert(array( + 'name' => $cl_name, + 'description' => $cl_description, + 'status' => ACTIVE, + 'projects' => $cl_projects))) { + header('Location: tasks.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } +} // isPost + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('show_projects', count($projects) > 0); +$smarty->assign('onload', 'onLoad="document.taskForm.name.focus()"'); +$smarty->assign('title', $i18n->get('title.add_task')); +$smarty->assign('content_page_name', 'task_add.tpl'); +$smarty->display('index.tpl'); From 8824bd2332368f1d463d72f95e6b085cdea49138 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 12 Nov 2020 19:45:49 +0000 Subject: [PATCH 101/587] Made task_edit.php mobile-friendly. --- WEB-INF/templates/task_edit2.tpl | 33 +++++++++ initialize.php | 2 +- task_edit.php | 36 ++------- task_edit1.php | 122 +++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+), 31 deletions(-) create mode 100644 WEB-INF/templates/task_edit2.tpl create mode 100644 task_edit1.php diff --git a/WEB-INF/templates/task_edit2.tpl b/WEB-INF/templates/task_edit2.tpl new file mode 100644 index 000000000..0ec709851 --- /dev/null +++ b/WEB-INF/templates/task_edit2.tpl @@ -0,0 +1,33 @@ +{$forms.taskForm.open} + + + + + + + + + + + + + + + + + + + +{if $show_projects} + + + + + + +{/if} + + +
    {$forms.taskForm.name.control}
    {$forms.taskForm.description.control}
    {$forms.taskForm.status.control}
    {$i18n.label.projects}:
    {$i18n.label.projects}:{$forms.taskForm.projects.control}
    {$i18n.label.required_fields}
    +
    {$forms.taskForm.btn_save.control} {$forms.taskForm.btn_copy.control}
    +{$forms.taskForm.close} diff --git a/initialize.php b/initialize.php index 6b404d998..12427a800 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5356"); +define("APP_VERSION", "1.19.23.5357"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/task_edit.php b/task_edit.php index 10410c4b3..307beb0b5 100644 --- a/task_edit.php +++ b/task_edit.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_task_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); @@ -118,5 +94,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('show_projects', count($projects) > 0); $smarty->assign('title', $i18n->get('title.edit_task')); -$smarty->assign('content_page_name', 'task_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'task_edit2.tpl'); +$smarty->display('index2.tpl'); diff --git a/task_edit1.php b/task_edit1.php new file mode 100644 index 000000000..10410c4b3 --- /dev/null +++ b/task_edit1.php @@ -0,0 +1,122 @@ +getTrackingMode()) { + header('Location: feature_disabled.php'); + exit(); +} +$cl_task_id = (int)$request->getParameter('id'); +$task = ttTaskHelper::get($cl_task_id); +if (!$task) { + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +$projects = ttGroupHelper::getActiveProjects(); + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('name')); + $cl_description = trim($request->getParameter('description')); + $cl_status = $request->getParameter('status'); + $cl_projects = $request->getParameter('projects'); +} else { + $cl_name = $task['name']; + $cl_description = $task['description']; + $cl_status = $task['status']; + $assigned_projects = ttTaskHelper::getAssignedProjects($cl_task_id); + foreach ($assigned_projects as $project_item) + $cl_projects[] = $project_item['id']; +} + +$form = new Form('taskForm'); +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_task_id)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 250px;','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, + 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); +$form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); +$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); +$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); + if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); + + if ($err->no()) { + if ($request->getParameter('btn_save')) { + $existing_task = ttTaskHelper::getTaskByName($cl_name); + if (!$existing_task || ($cl_task_id == $existing_task['id'])) { + // Update task information. + if (ttTaskHelper::update(array( + 'task_id' => $cl_task_id, + 'name' => $cl_name, + 'description' => $cl_description, + 'status' => $cl_status, + 'projects' => $cl_projects))) { + header('Location: tasks.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } + + if ($request->getParameter('btn_copy')) { + if (!ttTaskHelper::getTaskByName($cl_name)) { + if (ttTaskHelper::insert(array( + 'name' => $cl_name, + 'description' => $cl_description, + 'status' => $cl_status, + 'projects' => $cl_projects))) { + header('Location: tasks.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } + } +} // isPost + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('show_projects', count($projects) > 0); +$smarty->assign('title', $i18n->get('title.edit_task')); +$smarty->assign('content_page_name', 'task_edit.tpl'); +$smarty->display('index.tpl'); From 39ad8ee6a434ab91f5e0751f02fa5b6f4bc4fb3a Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 12 Nov 2020 21:07:45 +0000 Subject: [PATCH 102/587] Made clients.php mobile-friendly. --- WEB-INF/templates/clients2.tpl | 59 ++++++++++++++++++++++++++++++++++ clients.php | 32 +++--------------- clients1.php | 55 +++++++++++++++++++++++++++++++ initialize.php | 2 +- 4 files changed, 119 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/clients2.tpl create mode 100644 clients1.php diff --git a/WEB-INF/templates/clients2.tpl b/WEB-INF/templates/clients2.tpl new file mode 100644 index 000000000..1ec69df2f --- /dev/null +++ b/WEB-INF/templates/clients2.tpl @@ -0,0 +1,59 @@ + + +{if $user->can('manage_clients')} + {if $inactive_clients}
    {$i18n.form.clients.active_clients}
    {/if} + {if $active_clients} + + + + + + + + {foreach $active_clients as $client} + + + + + + + {/foreach} + {/if} +
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}{$i18n.label.edit}{$i18n.label.delete}
    +
    + {if $inactive_clients} +
    {$i18n.form.clients.inactive_clients}
    + + + + + + + + {foreach $inactive_clients as $client} + + + + + + + {/foreach} +
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}{$i18n.label.edit}{$i18n.label.delete}
    +
    + {/if} +{else} + + + + + + {foreach $active_clients as $client} + + + + + {/foreach} +
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}
    +{/if} diff --git a/clients.php b/clients.php index a299d3061..77ade9c7b 100644 --- a/clients.php +++ b/clients.php @@ -1,30 +1,6 @@ assign('active_clients', $active_clients); $smarty->assign('inactive_clients', $inactive_clients); $smarty->assign('title', $i18n->get('title.clients')); -$smarty->assign('content_page_name', 'clients.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'clients2.tpl'); +$smarty->display('index2.tpl'); diff --git a/clients1.php b/clients1.php new file mode 100644 index 000000000..a299d3061 --- /dev/null +++ b/clients1.php @@ -0,0 +1,55 @@ +isPluginEnabled('cl')) { + header('Location: feature_disabled.php'); + exit(); +} +// End of access checks. + +if($user->can('manage_clients')) { + $active_clients = ttGroupHelper::getActiveClients(true); + $inactive_clients = ttGroupHelper::getInactiveClients(true); +} else + $active_clients = $user->getAssignedClients(); + +$smarty->assign('active_clients', $active_clients); +$smarty->assign('inactive_clients', $inactive_clients); +$smarty->assign('title', $i18n->get('title.clients')); +$smarty->assign('content_page_name', 'clients.tpl'); +$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index 12427a800..576a3c2ad 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5357"); +define("APP_VERSION", "1.19.23.5358"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From adb3536504bf9859d9e40657bd879da92437e924 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 16:10:51 +0000 Subject: [PATCH 103/587] Made client_delete.php mobile-friendly. --- WEB-INF/templates/client_delete2.tpl | 16 ++++++ client_delete.php | 32 ++---------- client_delete1.php | 78 ++++++++++++++++++++++++++++ default.css | 1 + initialize.php | 2 +- 5 files changed, 100 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/client_delete2.tpl create mode 100644 client_delete1.php diff --git a/WEB-INF/templates/client_delete2.tpl b/WEB-INF/templates/client_delete2.tpl new file mode 100644 index 000000000..bc583ea66 --- /dev/null +++ b/WEB-INF/templates/client_delete2.tpl @@ -0,0 +1,16 @@ +{$forms.clientDeleteForm.open} + + + + + + + + + + + + +
    {$i18n.form.client.client_to_delete}:
    {$i18n.form.client.client_to_delete}:
    {$client_to_delete|escape}
    {$i18n.form.client.client_entries}:
    {$i18n.form.client.client_entries}:{$forms.clientDeleteForm.delete_client_entries.control}
    +
    {$forms.clientDeleteForm.btn_delete.control} {$forms.clientDeleteForm.btn_cancel.control}
    +{$forms.clientDeleteForm.close} diff --git a/client_delete.php b/client_delete.php index a5f00656e..147f2db54 100644 --- a/client_delete.php +++ b/client_delete.php @@ -1,30 +1,6 @@ assign('client_to_delete', $client_to_delete); $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('title', $i18n->get('title.delete_client')); -$smarty->assign('content_page_name', 'client_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'client_delete2.tpl'); +$smarty->display('index2.tpl'); diff --git a/client_delete1.php b/client_delete1.php new file mode 100644 index 000000000..a5f00656e --- /dev/null +++ b/client_delete1.php @@ -0,0 +1,78 @@ +isPluginEnabled('cl')) { + header('Location: feature_disabled.php'); + exit(); +} +$id = (int)$request->getParameter('id'); +$client = ttClientHelper::getClient($id); +if (!$client) { + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +$client_to_delete = $client['name']; + +$form = new Form('clientDeleteForm'); +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$id)); +$form->addInput(array('type'=>'combobox','name'=>'delete_client_entries', + 'data'=>array('0'=>$i18n->get('dropdown.do_not_delete'),'1'=>$i18n->get('dropdown.delete')))); +$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); +$form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); + +if ($request->isPost()) { + if ($request->getParameter('btn_delete')) { + if (ttClientHelper::delete($id, $request->getParameter('delete_client_entries'))) { + header('Location: clients.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } + + if ($request->getParameter('btn_cancel')) { + header('Location: clients.php'); + exit(); + } +} // isPost + +$smarty->assign('client_to_delete', $client_to_delete); +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('title', $i18n->get('title.delete_client')); +$smarty->assign('content_page_name', 'client_delete.tpl'); +$smarty->display('index.tpl'); diff --git a/default.css b/default.css index 804a06a66..fdf1d168f 100644 --- a/default.css +++ b/default.css @@ -323,6 +323,7 @@ input.password-field { .section-header { font-weight: bold; + text-align: center; margin-left: auto; margin-right: auto; } diff --git a/initialize.php b/initialize.php index 576a3c2ad..aae530f1f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5358"); +define("APP_VERSION", "1.19.23.5359"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ea7fdda737e3f00350025971031845259c71244d Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 17:12:51 +0000 Subject: [PATCH 104/587] Made client_add.php mobile-friendly. --- WEB-INF/templates/client_add2.tpl | 36 ++++++++++++ client_add.php | 36 ++---------- client_add1.php | 94 +++++++++++++++++++++++++++++++ initialize.php | 2 +- 4 files changed, 137 insertions(+), 31 deletions(-) create mode 100644 WEB-INF/templates/client_add2.tpl create mode 100644 client_add1.php diff --git a/WEB-INF/templates/client_add2.tpl b/WEB-INF/templates/client_add2.tpl new file mode 100644 index 000000000..9ffdfa203 --- /dev/null +++ b/WEB-INF/templates/client_add2.tpl @@ -0,0 +1,36 @@ +{$forms.clientForm.open} + + + + + + + + + + + + + + + + + + + + + +{if $show_projects} + + + + + + +{/if} + + + + +
    {$forms.clientForm.name.control}
    {$forms.clientForm.address.control}
    {$forms.clientForm.tax.control} (0{$user->getDecimalMark()}00)
    {$i18n.label.required_fields}
    {$i18n.label.projects}:
    {$i18n.label.projects}:{$forms.clientForm.projects.control}
    {$forms.clientForm.btn_submit.control}
    +{$forms.clientForm.close} diff --git a/client_add.php b/client_add.php index 820a32fde..114e89ea0 100644 --- a/client_add.php +++ b/client_add.php @@ -1,30 +1,6 @@ getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; $form = new Form('clientForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 350px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','style'=>'width: 350px; height: 80px;','value'=>$cl_address)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','value'=>$cl_address)); $form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); if ($show_projects) $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'layout'=>'H','datakeys'=>array('id','name'),'value'=>$cl_projects)); @@ -90,5 +66,5 @@ $smarty->assign('onload', 'onLoad="document.clientForm.name.focus()"'); $smarty->assign('show_projects', $show_projects); $smarty->assign('title', $i18n->get('title.add_client')); -$smarty->assign('content_page_name', 'client_add.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'client_add2.tpl'); +$smarty->display('index2.tpl'); diff --git a/client_add1.php b/client_add1.php new file mode 100644 index 000000000..820a32fde --- /dev/null +++ b/client_add1.php @@ -0,0 +1,94 @@ +isPluginEnabled('cl')) { + header('Location: feature_disabled.php'); + exit(); +} + +$projects = ttGroupHelper::getActiveProjects(); + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('name')); + $cl_address = trim($request->getParameter('address')); + $cl_tax = $request->getParameter('tax'); + $cl_projects = $request->getParameter('projects'); +} else { + // Do not assign all projects to a new client by default. This should help to reduce clutter. + // foreach ($projects as $project_item) + // $cl_projects[] = $project_item['id']; +} + +$show_projects = (MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; + +$form = new Form('clientForm'); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 350px;','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','style'=>'width: 350px; height: 80px;','value'=>$cl_address)); +$form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); +if ($show_projects) + $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'layout'=>'H','datakeys'=>array('id','name'),'value'=>$cl_projects)); +$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.client_name')); + if (!ttValidString($cl_address, true)) $err->add($i18n->get('error.field'), $i18n->get('label.client_address')); + if (!ttValidFloat($cl_tax, true)) $err->add($i18n->get('error.field'), $i18n->get('label.tax')); + + if ($err->no()) { + if (!ttClientHelper::getClientByName($cl_name)) { + if (ttClientHelper::insert(array('name' => $cl_name, + 'address' => $cl_address, + 'tax' => $cl_tax, + 'projects' => $cl_projects, + 'status' => ACTIVE))) { + header('Location: clients.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } +} // isPost + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('onload', 'onLoad="document.clientForm.name.focus()"'); +$smarty->assign('show_projects', $show_projects); +$smarty->assign('title', $i18n->get('title.add_client')); +$smarty->assign('content_page_name', 'client_add.tpl'); +$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index aae530f1f..f55ede5ae 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5359"); +define("APP_VERSION", "1.19.23.5360"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ae6d97fb4d813a58cb073b501a4e643d91882ea9 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 17:57:09 +0000 Subject: [PATCH 105/587] Made client_edit.php mobile-friendly. --- WEB-INF/templates/client_edit2.tpl | 39 +++++++++ client_edit.php | 36 ++------ client_edit1.php | 131 +++++++++++++++++++++++++++++ initialize.php | 2 +- 4 files changed, 177 insertions(+), 31 deletions(-) create mode 100644 WEB-INF/templates/client_edit2.tpl create mode 100644 client_edit1.php diff --git a/WEB-INF/templates/client_edit2.tpl b/WEB-INF/templates/client_edit2.tpl new file mode 100644 index 000000000..d29635de4 --- /dev/null +++ b/WEB-INF/templates/client_edit2.tpl @@ -0,0 +1,39 @@ +{$forms.clientForm.open} + + + + + + + + + + + + + + + + + + + + + + + + + + + +{if $show_projects} + + + + + + +{/if} +
    {$forms.clientForm.name.control}
    {$forms.clientForm.address.control}
    {$forms.clientForm.tax.control} (0{$user->getDecimalMark()}00)
    {$forms.clientForm.status.control}
    {$i18n.label.required_fields}
    {$i18n.label.projects}:
    {$i18n.label.projects}:{$forms.clientForm.projects.control}
    +
    {$forms.clientForm.btn_save.control} {$forms.clientForm.btn_copy.control}
    +{$forms.clientForm.close} diff --git a/client_edit.php b/client_edit.php index 7b572ea7c..2924346bf 100644 --- a/client_edit.php +++ b/client_edit.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'text','name'=>'name','maxlength'=>'100','style'=>'width: 350px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','style'=>'width: 350px; height: 80px;','value'=>$cl_address)); +$form->addInput(array('type'=>'text','name'=>'name','maxlength'=>'100','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','value'=>$cl_address)); $form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); $form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); @@ -127,5 +103,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('show_projects', $show_projects); $smarty->assign('title', $i18n->get('title.edit_client')); -$smarty->assign('content_page_name', 'client_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'client_edit2.tpl'); +$smarty->display('index2.tpl'); diff --git a/client_edit1.php b/client_edit1.php new file mode 100644 index 000000000..7b572ea7c --- /dev/null +++ b/client_edit1.php @@ -0,0 +1,131 @@ +isPluginEnabled('cl')) { + header('Location: feature_disabled.php'); + exit(); +} +$cl_id = (int)$request->getParameter('id'); +$client = ttClientHelper::getClient($cl_id, true); +if (!$client) { + header('Location: access_denied.php'); + exit(); +} +// End of access checks. + +$projects = ttGroupHelper::getActiveProjects(); + +if ($request->isPost()) { + $cl_name = trim($request->getParameter('name')); + $cl_address = trim($request->getParameter('address')); + $cl_tax = trim($request->getParameter('tax')); + $cl_status = $request->getParameter('status'); + $cl_projects = $request->getParameter('projects'); +} else { + $cl_name = $client['name']; + $cl_address = $client['address']; + $cl_tax = $client['tax']; + $cl_status = $client['status']; + $assigned_projects = ttClientHelper::getAssignedProjects($cl_id); + foreach($assigned_projects as $project_item) { + $cl_projects[] = $project_item['id']; + } +} + +$show_projects = (MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; + +$form = new Form('clientForm'); +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); +$form->addInput(array('type'=>'text','name'=>'name','maxlength'=>'100','style'=>'width: 350px;','value'=>$cl_name)); +$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','style'=>'width: 350px; height: 80px;','value'=>$cl_address)); +$form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); +$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, + 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); +if ($show_projects) + $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'datakeys'=>array('id','name'),'layout'=>'H','value'=>$cl_projects)); +$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); +$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); + +if ($request->isPost()) { + // Validate user input. + if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.client_name')); + if (!ttValidString($cl_address, true)) $err->add($i18n->get('error.field'), $i18n->get('label.client_address')); + if (!ttValidFloat($cl_tax, true)) $err->add($i18n->get('error.field'), $i18n->get('label.tax')); + + if ($err->no()) { + if ($request->getParameter('btn_save')) { + $client = ttClientHelper::getClientByName($cl_name); + if (($client && ($cl_id == $client['id'])) || !$client) { + if (ttClientHelper::update(array( + 'id' => $cl_id, + 'name' => $cl_name, + 'address' => $cl_address, + 'tax' => $cl_tax, + 'status' => $cl_status, + 'projects' => $cl_projects))) { + header('Location: clients.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } + + if ($request->getParameter('btn_copy')) { + if (!ttClientHelper::getClientByName($cl_name)) { + if (ttClientHelper::insert(array('name' => $cl_name, + 'address' => $cl_address, + 'tax' => $cl_tax, + 'status' => $cl_status, + 'projects' => $cl_projects))) { + header('Location: clients.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } else + $err->add($i18n->get('error.object_exists')); + } + } +} // isPost + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('show_projects', $show_projects); +$smarty->assign('title', $i18n->get('title.edit_client')); +$smarty->assign('content_page_name', 'client_edit.tpl'); +$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index f55ede5ae..deaefa540 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5360"); +define("APP_VERSION", "1.19.23.5361"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ec328a91e21844d6e6e6923bd25d6521ebef16f8 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 20:20:22 +0000 Subject: [PATCH 106/587] Refactored expenses.php for mobile access. --- WEB-INF/templates/expenses2.tpl | 238 ++++++++++++++++++++++++++++++ default.css | 10 ++ expenses.php | 59 +++----- expenses1.php | 251 ++++++++++++++++++++++++++++++++ initialize.php | 2 +- 5 files changed, 521 insertions(+), 39 deletions(-) create mode 100644 WEB-INF/templates/expenses2.tpl create mode 100644 expenses1.php diff --git a/WEB-INF/templates/expenses2.tpl b/WEB-INF/templates/expenses2.tpl new file mode 100644 index 000000000..7af327838 --- /dev/null +++ b/WEB-INF/templates/expenses2.tpl @@ -0,0 +1,238 @@ + + +{$forms.expensesForm.open} +
    {$forms.expensesForm.date.control}
    + + +{if $user_dropdown} + + + + + + +{/if} +{if $user->isPluginEnabled('cl')} + + + + + + +{/if} +{if $show_project} + + + + + + +{/if} +{if $predefined_expenses} + + + + + + + + + + + + +{/if} + + + + + + + + + + + + +{if $show_files} + + + + + + +{/if} + + + +
    {$forms.expensesForm.date.control}
    {$forms.expensesForm.user.control}
    {$forms.expensesForm.client.control}
    {$forms.expensesForm.project.control}
    {$forms.expensesForm.predefined_expense.control}
    {$forms.expensesForm.quantity.control}
    {$forms.expensesForm.item_name.control}
    {$forms.expensesForm.cost.control}
    {$forms.expensesForm.newfile.control}
    {$forms.expensesForm.btn_submit.control}
    +{$forms.expensesForm.close} + +{if $expense_items} +
    + + + {if $user->isPluginEnabled('cl')} + + {/if} + {if $show_project} + + {/if} + + + {if $show_files} + + {/if} + + + + {foreach $expense_items as $item} + + {if $user->isPluginEnabled('cl')} + + {/if} + {if $show_project} + + {/if} + + + {if $show_files} + {if $item.has_files} + + {else} + + {/if} + {/if} + + + + {/foreach} +
    {$i18n.label.client}{$i18n.label.project}{$i18n.label.item}{$i18n.label.cost}
    {$item.client|escape}{$item.project|escape}{$item.item|escape}{$item.cost}{$i18n.label.files}{$i18n.label.files} + {if $item.approved || $item.invoice_id} +   + {else} + {$i18n.label.edit} + {/if} + + {if $item.approved || $item.invoice_id} +   + {else} + {$i18n.label.delete} + {/if} +
    +
    +
    {$i18n.label.day_total}: {$user->getCurrency()|escape} {$day_total}
    +{/if} + diff --git a/default.css b/default.css index fdf1d168f..1d0f4c1e4 100644 --- a/default.css +++ b/default.css @@ -280,6 +280,16 @@ input.password-field { resize: none; } +.day-totals { + margin-bottom: 1rem; +} + +.day-totals-col2 { + padding-left: .5rem; + padding-right: .5rem; + text-align: right; +} + .day-totals-col1 { text-align: left; padding-left: .5rem; diff --git a/expenses.php b/expenses.php index 7959bb311..170f0cd3b 100644 --- a/expenses.php +++ b/expenses.php @@ -1,30 +1,6 @@ can('track_expenses')) { $rank = $user->getMaxRankForGroup($user->getGroup()); @@ -108,11 +85,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'this.form.user_changed.value=1;this.form.submit();', 'name'=>'user', - 'style'=>'width: 250px;', 'value'=>$user_id, 'data'=>$user_list, 'datakeys'=>array('id','name'))); $form->addInput(array('type'=>'hidden','name'=>'user_changed')); + $largeScreenCalendarRowSpan += 2; $smarty->assign('user_dropdown', 1); } } @@ -123,12 +100,12 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$active_clients, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); // Note: in other modes the client list is filtered to relevant clients only. See below. + $largeScreenCalendarRowSpan += 2; } if ($show_project) { @@ -136,16 +113,16 @@ $project_list = $user->getAssignedProjects(); $form->addInput(array('type'=>'combobox', 'name'=>'project', - 'style'=>'width: 250px;', 'value'=>$cl_project, 'data'=>$project_list, 'datakeys'=>array('id','name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $largeScreenCalendarRowSpan += 2; // Dropdown for clients if the clients plugin is enabled. if ($user->isPluginEnabled('cl')) { $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. + // We need an array of assigned project ids to do some trimming. foreach($project_list as $project) $projects_assigned_to_user[] = $project['id']; @@ -162,11 +139,11 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'fillProjectDropdown(this.value);', 'name'=>'client', - 'style'=>'width: 250px;', 'value'=>$cl_client, 'data'=>$client_list, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $largeScreenCalendarRowSpan += 2; } } // If predefined expenses are configured, add controls to select an expense and quantity. @@ -175,17 +152,22 @@ $form->addInput(array('type'=>'combobox', 'onchange'=>'recalculateCost();', 'name'=>'predefined_expense', - 'style'=>'width: 250px;', 'value'=>$cl_predefined_expense, 'data'=>$predefined_expenses, 'datakeys'=>array('id', 'name'), 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); + $largeScreenCalendarRowSpan += 2; + $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','value'=>$cl_quantity)); + $largeScreenCalendarRowSpan += 2; } -$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','style'=>'width: 250px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_item_name)); -$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); -if ($showFiles) +$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','value'=>$cl_item_name)); +$largeScreenCalendarRowSpan += 2; +$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','value'=>$cl_cost)); +$largeScreenCalendarRowSpan += 2; +if ($showFiles) { $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); + $largeScreenCalendarRowSpan += 2; +} $form->addInput(array('type'=>'calendar','name'=>'date','highlight'=>'expenses','value'=>$cl_date)); // calendar $form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_submit click. $form->addInput(array('type'=>'submit','name'=>'btn_submit','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.submit'))); @@ -237,6 +219,7 @@ } } +$smarty->assign('large_screen_calendar_row_span', $largeScreenCalendarRowSpan); $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('show_project', $show_project); $smarty->assign('show_files', $showFiles); @@ -247,5 +230,5 @@ $smarty->assign('project_list', $project_list); $smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); $smarty->assign('title', $i18n->get('title.expenses')); -$smarty->assign('content_page_name', 'expenses.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'expenses2.tpl'); +$smarty->display('index2.tpl'); diff --git a/expenses1.php b/expenses1.php new file mode 100644 index 000000000..cd930a8b8 --- /dev/null +++ b/expenses1.php @@ -0,0 +1,251 @@ +isPluginEnabled('ex')) { + header('Location: feature_disabled.php'); + exit(); +} +if (!$user->exists()) { + header('Location: access_denied.php'); // Nobody to enter expenses for. + exit(); +} +if ($user->behalf_id && (!$user->can('track_expenses') || !$user->checkBehalfId())) { + header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. + exit(); +} +if (!$user->behalf_id && !$user->can('track_own_expenses') && !$user->adjustBehalfId()) { + header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to work on behalf. + exit(); +} +if ($request->isPost() && $request->getParameter('user')) { + if (!$user->isUserValid($request->getParameter('user'))) { + header('Location: access_denied.php'); // Wrong user id on post. + exit(); + } +} +// End of access checks. + +// Determine user for which we display this page. +$userChanged = $request->getParameter('user_changed'); +if ($request->isPost() && $userChanged) { + $user_id = $request->getParameter('user'); + $user->setOnBehalfUser($user_id); +} else { + $user_id = $user->getUser(); +} + +// Initialize and store date in session. +$cl_date = $request->getParameter('date', @$_SESSION['date']); +$selected_date = new DateAndTime(DB_DATEFORMAT, $cl_date); +if($selected_date->isError()) + $selected_date = new DateAndTime(DB_DATEFORMAT); +if(!$cl_date) + $cl_date = $selected_date->toString(DB_DATEFORMAT); +$_SESSION['date'] = $cl_date; + +$tracking_mode = $user->getTrackingMode(); +$show_project = MODE_PROJECTS == $tracking_mode || MODE_PROJECTS_AND_TASKS == $tracking_mode; +$showFiles = $user->isPluginEnabled('at'); + +// Initialize variables. +$cl_client = $request->getParameter('client', ($request->isPost() ? null : @$_SESSION['client'])); +$_SESSION['client'] = $cl_client; +$cl_project = $request->getParameter('project', ($request->isPost() ? null : @$_SESSION['project'])); +$_SESSION['project'] = $cl_project; +$cl_item_name = $request->getParameter('item_name'); +$cl_cost = $request->getParameter('cost'); + +// Elements of expensesForm. +$form = new Form('expensesForm'); + +if ($user->can('track_expenses')) { + $rank = $user->getMaxRankForGroup($user->getGroup()); + if ($user->can('track_own_expenses')) + $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); + else + $options = array('status'=>ACTIVE,'max_rank'=>$rank); + $user_list = $user->getUsers($options); + if (count($user_list) >= 1) { + $form->addInput(array('type'=>'combobox', + 'onchange'=>'this.form.user_changed.value=1;this.form.submit();', + 'name'=>'user', + 'style'=>'width: 250px;', + 'value'=>$user_id, + 'data'=>$user_list, + 'datakeys'=>array('id','name'))); + $form->addInput(array('type'=>'hidden','name'=>'user_changed')); + $smarty->assign('user_dropdown', 1); + } +} + +// Dropdown for clients in MODE_TIME. Use all active clients. +if (MODE_TIME == $tracking_mode && $user->isPluginEnabled('cl')) { + $active_clients = ttGroupHelper::getActiveClients(true); + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillProjectDropdown(this.value);', + 'name'=>'client', + 'style'=>'width: 250px;', + 'value'=>$cl_client, + 'data'=>$active_clients, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + // Note: in other modes the client list is filtered to relevant clients only. See below. +} + +if ($show_project) { + // Dropdown for projects assigned to user. + $project_list = $user->getAssignedProjects(); + $form->addInput(array('type'=>'combobox', + 'name'=>'project', + 'style'=>'width: 250px;', + 'value'=>$cl_project, + 'data'=>$project_list, + 'datakeys'=>array('id','name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + + // Dropdown for clients if the clients plugin is enabled. + if ($user->isPluginEnabled('cl')) { + $active_clients = ttGroupHelper::getActiveClients(true); + // We need an array of assigned project ids to do some trimming. + foreach($project_list as $project) + $projects_assigned_to_user[] = $project['id']; + + // Build a client list out of active clients. Use only clients that are relevant to user. + // Also trim their associated project list to only assigned projects (to user). + foreach($active_clients as $client) { + $projects_assigned_to_client = explode(',', $client['projects']); + $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); + if ($intersection) { + $client['projects'] = implode(',', $intersection); + $client_list[] = $client; + } + } + $form->addInput(array('type'=>'combobox', + 'onchange'=>'fillProjectDropdown(this.value);', + 'name'=>'client', + 'style'=>'width: 250px;', + 'value'=>$cl_client, + 'data'=>$client_list, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + } +} +// If predefined expenses are configured, add controls to select an expense and quantity. +$predefined_expenses = ttGroupHelper::getPredefinedExpenses(); +if ($predefined_expenses) { + $form->addInput(array('type'=>'combobox', + 'onchange'=>'recalculateCost();', + 'name'=>'predefined_expense', + 'style'=>'width: 250px;', + 'value'=>$cl_predefined_expense, + 'data'=>$predefined_expenses, + 'datakeys'=>array('id', 'name'), + 'empty'=>array(''=>$i18n->get('dropdown.select')))); + $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); +} +$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','style'=>'width: 250px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_item_name)); +$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); +if ($showFiles) + $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); +$form->addInput(array('type'=>'calendar','name'=>'date','highlight'=>'expenses','value'=>$cl_date)); // calendar +$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_submit click. +$form->addInput(array('type'=>'submit','name'=>'btn_submit','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.submit'))); + +// Submit. +if ($request->isPost()) { + if ($request->getParameter('btn_submit')) { + // Validate user input. + if ($user->isPluginEnabled('cl') && $user->isOptionEnabled('client_required') && !$cl_client) + $err->add($i18n->get('error.client')); + if ($show_project && !$cl_project) + $err->add($i18n->get('error.project')); + if (!ttValidString($cl_item_name)) $err->add($i18n->get('error.field'), $i18n->get('label.comment')); + if (!ttValidFloat($cl_cost)) $err->add($i18n->get('error.field'), $i18n->get('label.cost')); + + // Prohibit creating entries in future. + if (!$user->isOptionEnabled('future_entries')) { + $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); + if ($selected_date->after($browser_today)) + $err->add($i18n->get('error.future_date')); + } + if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); + // Finished validating input data. + + // Prohibit creating entries in locked range. + if ($user->isDateLocked($selected_date)) + $err->add($i18n->get('error.range_locked')); + + // Insert record. + if ($err->no()) { + $id = ttExpenseHelper::insert(array('date'=>$cl_date,'client_id'=>$cl_client, + 'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'status'=>1)); + + // Put a new file in storage if we have it. + if ($id && $showFiles && $_FILES['newfile']['name']) { + $fileHelper = new ttFileHelper($err); + $fields = array('entity_type'=>'expense', + 'entity_id' => $id, + 'file_name' => $_FILES['newfile']['name']); + $fileHelper->putFile($fields); + } + + if ($id) { + header('Location: expenses.php'); + exit(); + } else + $err->add($i18n->get('error.db')); + } + } +} + +$smarty->assign('forms', array($form->getName()=>$form->toArray())); +$smarty->assign('show_project', $show_project); +$smarty->assign('show_files', $showFiles); +$smarty->assign('day_total', ttExpenseHelper::getTotalForDay($cl_date)); +$smarty->assign('expense_items', ttExpenseHelper::getItems($cl_date, $showFiles)); +$smarty->assign('predefined_expenses', $predefined_expenses); +$smarty->assign('client_list', $client_list); +$smarty->assign('project_list', $project_list); +$smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); +$smarty->assign('title', $i18n->get('title.expenses')); +$smarty->assign('content_page_name', 'expenses.tpl'); +$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index deaefa540..6fb811b4d 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5361"); +define("APP_VERSION", "1.19.23.5362"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From f334b09b00b1cbd97d41ef9a656c8b6c209e1fd5 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 13 Nov 2020 21:03:12 +0000 Subject: [PATCH 107/587] Made expense_delete.php mobile-friendly. --- WEB-INF/templates/expense_delete2.tpl | 25 ++++++++ WEB-INF/templates/time_delete2.tpl | 2 +- expense_delete.php | 32 ++-------- expense_delete1.php | 88 +++++++++++++++++++++++++++ initialize.php | 2 +- 5 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 WEB-INF/templates/expense_delete2.tpl create mode 100644 expense_delete1.php diff --git a/WEB-INF/templates/expense_delete2.tpl b/WEB-INF/templates/expense_delete2.tpl new file mode 100644 index 000000000..9b9bab838 --- /dev/null +++ b/WEB-INF/templates/expense_delete2.tpl @@ -0,0 +1,25 @@ +{$forms.expenseItemForm.open} + + +{if $user->isPluginEnabled('cl')} + +{/if} +{if $show_project} + +{/if} + + + + +{if $user->isPluginEnabled('cl')} + +{/if} +{if $show_project} + +{/if} + + + +
    {$i18n.label.client}{$i18n.label.project}{$i18n.label.item}{$i18n.label.cost}
    {$expense_item.client_name|escape}{$expense_item.project_name|escape}{$expense_item.name|escape}{$expense_item.cost}
    +
    {$forms.expenseItemForm.delete_button.control} {$forms.expenseItemForm.cancel_button.control}
    +{$forms.expenseItemForm.close} diff --git a/WEB-INF/templates/time_delete2.tpl b/WEB-INF/templates/time_delete2.tpl index 9d51fcc62..20acb783c 100644 --- a/WEB-INF/templates/time_delete2.tpl +++ b/WEB-INF/templates/time_delete2.tpl @@ -8,7 +8,7 @@
    {$i18n.label.task}{$i18n.label.start} + {$i18n.label.start} {$i18n.label.finish}
    + +{if $user->isPluginEnabled('cl')} + + + + + + +{/if} +{if $show_project} + + + + + + +{/if} +{if $predefined_expenses} + + + + + + + + + + + + +{/if} + + + + + + + + + + + + +{if ($user->can('manage_invoices') && $user->isPluginEnabled('ps'))} + + + + +{/if} + + + + + + +
    {$forms.expenseItemForm.client.control}
    {$forms.expenseItemForm.project.control}
    {$forms.expenseItemForm.predefined_expense.control}
    {$forms.expenseItemForm.quantity.control}
    {$forms.expenseItemForm.item_name.control}
    {$forms.expenseItemForm.cost.control} {$user->getCurrency()|escape}
    {$forms.expenseItemForm.date.control}
    +
    {$forms.expenseItemForm.btn_save.control} {$forms.expenseItemForm.btn_copy.control} {$forms.expenseItemForm.btn_delete.control}
    +{$forms.expenseItemForm.close} diff --git a/WEB-INF/templates/expenses2.tpl b/WEB-INF/templates/expenses2.tpl index 7af327838..d996bca19 100644 --- a/WEB-INF/templates/expenses2.tpl +++ b/WEB-INF/templates/expenses2.tpl @@ -154,9 +154,9 @@ function recalculateCost() {
    {$forms.expensesForm.item_name.control}
    + + + + + +
    {$forms.swapForm.swap_with.control}
    +
    {$forms.swapForm.btn_submit.control} {$forms.swapForm.btn_cancel.control}
    +{$forms.swapForm.close} diff --git a/access_denied.php b/access_denied.php index 7d804f550..7025d8739 100644 --- a/access_denied.php +++ b/access_denied.php @@ -1,30 +1,6 @@ addInput(array('type'=>'combobox','name'=>'swap_with','style'=>'width: 250px;','data'=>$users_for_swap,'datakeys'=>array('id','name'))); +$form->addInput(array('type'=>'combobox','name'=>'swap_with','data'=>$users_for_swap,'datakeys'=>array('id','name'))); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.submit'))); $form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); @@ -73,5 +49,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.swapForm.btn_cancel.focus()"'); $smarty->assign('title', $i18n->get('title.swap_roles')); -$smarty->assign('content_page_name', 'swap_roles.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'swap_roles2.tpl'); +$smarty->display('index2.tpl'); From 625469926ef09b25833cb89ced879a3e636355e7 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 15:16:47 +0000 Subject: [PATCH 119/587] Added redirects for legacy mobile pages. --- initialize.php | 2 +- mobile/login.php | 6 ++++++ mobile/time.php | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/initialize.php b/initialize.php index 5cb71612b..dadd4e831 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5372"); +define("APP_VERSION", "1.19.23.5373"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/login.php b/mobile/login.php index fb574767a..4d5b7d5ea 100644 --- a/mobile/login.php +++ b/mobile/login.php @@ -31,6 +31,12 @@ import('ttOrgHelper'); import('ttUser'); +// Mobile pages are no longer separate. Redirect to main page. +header('Location: ../login.php'); +exit(); +// Below is no longer used code. + + if ($request->isPost()) { $cl_login = $request->getParameter('login'); } else { diff --git a/mobile/time.php b/mobile/time.php index 0bdfcfaa4..ee4d81883 100644 --- a/mobile/time.php +++ b/mobile/time.php @@ -35,6 +35,10 @@ import('ttTimeHelper'); import('DateAndTime'); +header('Location: ../time.php'); +exit(); + + // Access checks. if (!ttAccessAllowed('track_own_time')) { header('Location: access_denied.php'); From 3f65e97f033387892f98618b772043a77dc6d4b1 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 17:46:53 +0000 Subject: [PATCH 120/587] Fixed presentation of controls on tasks.php page. --- WEB-INF/templates/tasks2.tpl | 2 ++ default.css | 6 ------ initialize.php | 2 +- mobile/time.php | 3 ++- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/WEB-INF/templates/tasks2.tpl b/WEB-INF/templates/tasks2.tpl index ac53362eb..9c206bcc7 100644 --- a/WEB-INF/templates/tasks2.tpl +++ b/WEB-INF/templates/tasks2.tpl @@ -4,6 +4,7 @@ {$forms.tasksForm.open} {if $user->can('manage_tasks')} +
    @@ -11,6 +12,7 @@
    {$forms.tasksForm.task_required.control}{$forms.tasksForm.btn_save.control}
    +
    {if $inactive_tasks}
    {$i18n.form.tasks.active_tasks}
    {/if} {if $active_tasks} diff --git a/default.css b/default.css index 1d0f4c1e4..3873051e6 100644 --- a/default.css +++ b/default.css @@ -284,12 +284,6 @@ input.password-field { margin-bottom: 1rem; } -.day-totals-col2 { - padding-left: .5rem; - padding-right: .5rem; - text-align: right; -} - .day-totals-col1 { text-align: left; padding-left: .5rem; diff --git a/initialize.php b/initialize.php index dadd4e831..3aa3ec314 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5373"); +define("APP_VERSION", "1.19.23.5374"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/time.php b/mobile/time.php index ee4d81883..d623de564 100644 --- a/mobile/time.php +++ b/mobile/time.php @@ -35,9 +35,10 @@ import('ttTimeHelper'); import('DateAndTime'); +// Mobile pages are no longer separate. Redirect to main page. header('Location: ../time.php'); exit(); - +// Below is no longer used code. // Access checks. if (!ttAccessAllowed('track_own_time')) { From c94a0cbc3a0ad58464e3e3fe1861ab605a383877 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 24 Nov 2020 19:04:22 +0000 Subject: [PATCH 121/587] Refactored time_files.php for mobile access. --- WEB-INF/templates/entity_files2.tpl | 43 +++++++++++++++++++++++++++++ initialize.php | 2 +- time.php | 28 ++----------------- time_delete.php | 28 ++----------------- time_edit.php | 28 ++----------------- time_files.php | 34 ++++------------------- 6 files changed, 55 insertions(+), 108 deletions(-) create mode 100644 WEB-INF/templates/entity_files2.tpl diff --git a/WEB-INF/templates/entity_files2.tpl b/WEB-INF/templates/entity_files2.tpl new file mode 100644 index 000000000..9d48e24c1 --- /dev/null +++ b/WEB-INF/templates/entity_files2.tpl @@ -0,0 +1,43 @@ +{if $files} +
    + + + + + + + {foreach $files as $file} + + + + {if $can_edit} + + + {/if} + + {/foreach} +
    {$i18n.label.thing_name}{$i18n.label.description}
    {$file.name|escape}{$file.description|escape}{$i18n.label.edit}{$i18n.label.delete}
    +{/if} + +{if $can_edit} +{$forms.fileUploadForm.open} + + + + + + + + + + + + + +
    {$forms.fileUploadForm.newfile.control}
    {$forms.fileUploadForm.description.control}
    +
    {$forms.fileUploadForm.btn_submit.control}
    +{$forms.fileUploadForm.close} +{/if} + + + diff --git a/initialize.php b/initialize.php index 3aa3ec314..1b0d371db 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5374"); +define("APP_VERSION", "1.19.23.5375"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time.php b/time.php index af9df005f..27c21d431 100644 --- a/time.php +++ b/time.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); if ($request->isPost()) { @@ -85,5 +61,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('files', $files); $smarty->assign('title', $i18n->get('title.time_files')); -$smarty->assign('content_page_name', 'entity_files.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'entity_files2.tpl'); +$smarty->display('index2.tpl'); From 9dd5a7bd035b5dc59b8ab1c6094306b31e99e5ed Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 25 Nov 2020 14:53:01 +0000 Subject: [PATCH 122/587] Some style improvements. --- WEB-INF/templates/client_add2.tpl | 4 ++-- WEB-INF/templates/client_edit2.tpl | 2 +- WEB-INF/templates/login.db2.tpl | 2 +- WEB-INF/templates/login.ldap2.tpl | 2 +- WEB-INF/templates/password_change2.tpl | 4 ++-- WEB-INF/templates/project_add2.tpl | 12 +++++------ WEB-INF/templates/project_edit2.tpl | 8 ++++---- WEB-INF/templates/register2.tpl | 5 +++-- WEB-INF/templates/task_add2.tpl | 8 ++++---- WEB-INF/templates/task_edit2.tpl | 8 ++++---- WEB-INF/templates/user_add2.tpl | 4 ++-- WEB-INF/templates/user_edit2.tpl | 4 ++-- initialize.php | 2 +- register.php | 28 ++------------------------ 14 files changed, 35 insertions(+), 58 deletions(-) diff --git a/WEB-INF/templates/client_add2.tpl b/WEB-INF/templates/client_add2.tpl index 9ffdfa203..e22081ef4 100644 --- a/WEB-INF/templates/client_add2.tpl +++ b/WEB-INF/templates/client_add2.tpl @@ -19,7 +19,7 @@
    {$i18n.label.required_fields}
    {$i18n.label.projects}:
    {$forms.clientForm.btn_submit.control}
    {$forms.clientForm.close} diff --git a/WEB-INF/templates/client_edit2.tpl b/WEB-INF/templates/client_edit2.tpl index d29635de4..935c6a1e5 100644 --- a/WEB-INF/templates/client_edit2.tpl +++ b/WEB-INF/templates/client_edit2.tpl @@ -25,7 +25,7 @@
    {$i18n.label.required_fields}
    {$i18n.label.projects}:
    {$i18n.form.login.forgot_password}
    {$forms.loginForm.btn_login.control}
    {$i18n.form.login.forgot_password}
    {$forms.loginForm.btn_login.control}
    @@ -14,7 +14,7 @@ - + diff --git a/WEB-INF/templates/project_add2.tpl b/WEB-INF/templates/project_add2.tpl index 9eba40d90..c0385423b 100644 --- a/WEB-INF/templates/project_add2.tpl +++ b/WEB-INF/templates/project_add2.tpl @@ -11,14 +11,14 @@ - + {if $show_files} - + {/if} {if $show_users} @@ -26,7 +26,7 @@ - + {/if} {if $show_tasks} @@ -34,13 +34,13 @@ - + {/if} - + - +
    {$forms.newPasswordForm.password2.control}
    {$i18n.label.required_fields}
    {$forms.newPasswordForm.btn_save.control}
    {$forms.projectForm.description.control}
    {$forms.projectForm.newfile.control}
    {$i18n.label.users}:
    {$i18n.label.users}: {$forms.projectForm.users.control}
    {$i18n.label.tasks}:
    {$i18n.label.tasks}: {$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
    {$forms.projectForm.btn_add.control}
    {$forms.projectForm.close} diff --git a/WEB-INF/templates/project_edit2.tpl b/WEB-INF/templates/project_edit2.tpl index 8bffb048d..6a7b034c7 100644 --- a/WEB-INF/templates/project_edit2.tpl +++ b/WEB-INF/templates/project_edit2.tpl @@ -11,20 +11,20 @@
    {$forms.projectForm.description.control}
    {$forms.projectForm.status.control}
    {$i18n.label.users}:
    {$i18n.label.users}: {$forms.projectForm.users.control}
    {$i18n.label.tasks}:
    {$i18n.label.tasks}: {$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
    diff --git a/WEB-INF/templates/register2.tpl b/WEB-INF/templates/register2.tpl index 1262a4c02..35309f855 100644 --- a/WEB-INF/templates/register2.tpl +++ b/WEB-INF/templates/register2.tpl @@ -45,16 +45,17 @@ {$forms.groupForm.password2.control} +
    {$forms.groupForm.manager_email.control} {$i18n.label.required_fields} -
    +
    {$forms.groupForm.btn_submit.control} -
    +
    {$forms.groupForm.close} \ No newline at end of file diff --git a/WEB-INF/templates/task_add2.tpl b/WEB-INF/templates/task_add2.tpl index 4bede3e31..9de211172 100644 --- a/WEB-INF/templates/task_add2.tpl +++ b/WEB-INF/templates/task_add2.tpl @@ -11,20 +11,20 @@ {$forms.taskForm.description.control} -
    +
    {if $show_projects} {$i18n.label.projects}: {$i18n.label.projects}: {$forms.taskForm.projects.control} -
    +
    {/if} {$i18n.label.required_fields} -
    +
    {$forms.taskForm.btn_submit.control} -
    +
    {$forms.taskForm.close} diff --git a/WEB-INF/templates/task_edit2.tpl b/WEB-INF/templates/task_edit2.tpl index 0ec709851..e0a15e693 100644 --- a/WEB-INF/templates/task_edit2.tpl +++ b/WEB-INF/templates/task_edit2.tpl @@ -11,23 +11,23 @@ {$forms.taskForm.description.control} -
    +
    {$forms.taskForm.status.control} -
    +
    {if $show_projects} {$i18n.label.projects}: {$i18n.label.projects}: {$forms.taskForm.projects.control} -
    +
    {/if} {$i18n.label.required_fields} -
    +
    {$forms.taskForm.btn_save.control} {$forms.taskForm.btn_copy.control}
    {$forms.taskForm.close} diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index 6adc5f7cd..dfb4bfa19 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -153,10 +153,10 @@ function handleClientRole() { {/if} {$i18n.label.required_fields} -
    +
    {$forms.userForm.btn_submit.control} -
    +
    {$forms.userForm.close} diff --git a/WEB-INF/templates/user_edit2.tpl b/WEB-INF/templates/user_edit2.tpl index ecc0a838e..8a3507e7b 100644 --- a/WEB-INF/templates/user_edit2.tpl +++ b/WEB-INF/templates/user_edit2.tpl @@ -191,10 +191,10 @@ function handleClientRole() { {/if} {$i18n.label.required_fields} -
    +
    {$forms.userForm.btn_submit.control} -
    +
    {$forms.userForm.close} diff --git a/initialize.php b/initialize.php index 1b0d371db..d50b940b3 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5375"); +define("APP_VERSION", "1.19.23.5376"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/register.php b/register.php index a036c26d4..3430d4366 100644 --- a/register.php +++ b/register.php @@ -1,30 +1,6 @@ Date: Wed, 25 Nov 2020 15:08:27 +0000 Subject: [PATCH 123/587] Improved styling of the description field. --- default.css | 13 +++++++++++++ initialize.php | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index 3873051e6..a1784c5bc 100644 --- a/default.css +++ b/default.css @@ -239,6 +239,19 @@ input.password-field { width: 237px; } +#description { + width: 220px; + border-radius: 4px; + border: 1px solid #c9c9c9; + padding: .4rem; +} + +#description:focus { + background-color: yellow; + border: 1px solid black; + outline: none; +} + .chart-image { width: 300px; height: 300px; diff --git a/initialize.php b/initialize.php index d50b940b3..3de6ba486 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5376"); +define("APP_VERSION", "1.19.23.5377"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ccd704eabdc20299faffe089feeb555b292ca7b4 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 25 Nov 2020 15:47:43 +0000 Subject: [PATCH 124/587] Improving style of file upload control. --- default.css | 7 +++++++ initialize.php | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index a1784c5bc..5e1334bc8 100644 --- a/default.css +++ b/default.css @@ -235,6 +235,13 @@ input.password-field { width: 220px; } +input[type=file] { + width: 220px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + .dropdown-field { width: 237px; } diff --git a/initialize.php b/initialize.php index 3de6ba486..092bf840f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5377"); +define("APP_VERSION", "1.19.23.5378"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 1bbfcb4c137b50a8019151aeeef9b51c711409d4 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 25 Nov 2020 16:25:29 +0000 Subject: [PATCH 125/587] Some more progress on styles. --- WEB-INF/lib/form/PasswordField.class.php | 28 ++---------------------- default.css | 13 +++++------ initialize.php | 2 +- 3 files changed, 8 insertions(+), 35 deletions(-) diff --git a/WEB-INF/lib/form/PasswordField.class.php b/WEB-INF/lib/form/PasswordField.class.php index 579be5edb..ff6802c90 100644 --- a/WEB-INF/lib/form/PasswordField.class.php +++ b/WEB-INF/lib/form/PasswordField.class.php @@ -1,30 +1,6 @@ Date: Wed, 25 Nov 2020 16:41:48 +0000 Subject: [PATCH 126/587] Improved style of the note field. --- default.css | 9 +++++++++ initialize.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index e2b634693..da21649f7 100644 --- a/default.css +++ b/default.css @@ -295,6 +295,15 @@ input[type="file"] { margin: 0; height: 4rem; resize: none; + border-radius: 4px; + border: 1px solid #c9c9c9; + padding: .4rem; +} + +#note:focus { + background-color: yellow; + border: 1px solid black; + outline: none; } .day-totals { diff --git a/initialize.php b/initialize.php index 5b6cc1cb3..c98543252 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5379"); +define("APP_VERSION", "1.19.23.5380"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 7322bce85707960781c50df141e1c78cac7b675f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 25 Nov 2020 17:26:45 +0000 Subject: [PATCH 127/587] Improved spacing between menu items on site-map.php. --- WEB-INF/templates/site_map.tpl | 76 +++++++++++++++++----------------- default.css | 9 ++++ initialize.php | 2 +- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/WEB-INF/templates/site_map.tpl b/WEB-INF/templates/site_map.tpl index 48b8d40c1..c951f2b99 100644 --- a/WEB-INF/templates/site_map.tpl +++ b/WEB-INF/templates/site_map.tpl @@ -1,90 +1,90 @@ {if $authenticated} {if $user->can('administer_site')} {* sub menu for admin *} -

    - {$i18n.menu.groups}
    - {$i18n.menu.options}
    +

    + + {if isTrue('WORK_SERVER_ADMINISTRATION')} - {$i18n.label.work}
    + {/if} -

    +
    {* end of sub menu for admin *} {* main menu for admin *} -

    - {$i18n.menu.logout}
    - {$i18n.menu.forum}
    - {$i18n.menu.help}
    -

    + {* end of main menu for admin *} {else} {* sub menu for authorized user *} -

    +

    {if $user->exists() && ($user->can('track_own_time') || $user->can('track_time'))} - {$i18n.menu.time}
    + {if $user->isPluginEnabled('wv') && $user->isOptionEnabled('week_menu')} - {$i18n.menu.week}
    + {/if} {/if} {if $user->exists() && $user->isPluginEnabled('ex') && ($user->can('track_own_expenses') || $user->can('track_expenses'))} - {$i18n.menu.expenses}
    + {/if} {if $user->exists() && ($user->can('view_own_reports') || $user->can('view_reports') || $user->can('view_all_reports') || $user->can('view_client_reports'))} - {$i18n.menu.reports}
    + {/if} {if $user->exists() && $user->isPluginEnabled('ts') && ($user->can('track_own_time') || $user->can('track_time'))} - {$i18n.menu.timesheets}
    + {/if} {if $user->exists() && $user->isPluginEnabled('iv') && ($user->can('manage_invoices') || $user->can('view_client_invoices'))} - {$i18n.title.invoices}
    + {/if} {if ($user->exists() && $user->isPluginEnabled('ch') && ($user->can('view_own_charts') || $user->can('view_charts'))) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() || $user->isPluginEnabled('cl'))} - {$i18n.menu.charts}
    + {/if} {if ($user->can('view_own_projects') || $user->can('manage_projects')) && (constant('MODE_PROJECTS') == $user->getTrackingMode() || constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode())} - {$i18n.menu.projects}
    + {/if} {if (constant('MODE_PROJECTS_AND_TASKS') == $user->getTrackingMode() && ($user->can('view_own_tasks') || $user->can('manage_tasks')))} - {$i18n.menu.tasks}
    + {/if} {if $user->can('view_users') || $user->can('manage_users')} - {$i18n.menu.users}
    + {/if} {if $user->isPluginEnabled('cl') && ($user->can('view_own_clients') || $user->can('manage_clients'))} - {$i18n.menu.clients}
    + {/if} {if $user->can('export_data')} - {$i18n.menu.export}
    + {/if} -

    +
    {* end of sub menu for authorized user *} {* main menu for authorized user *} -

    - {$i18n.menu.logout}
    +

    + {if $user->exists() && $user->can('manage_own_settings')} - {$i18n.menu.profile}
    + {/if} {if $user->can('manage_basic_settings')} - {$i18n.menu.group}
    + {/if} {if $user->can('manage_features')} - {$i18n.menu.plugins}
    + {/if} - {$i18n.menu.forum}
    - {$i18n.menu.help}
    -

    + + +
    {* end of main menu for authorized user *} {/if} {else} {* main menu for non authorized user *} -

    - {$i18n.menu.login}
    +

    + {if isTrue('MULTIORG_MODE') && constant('AUTH_MODULE') == 'db'} - {$i18n.menu.register}
    + {/if} - {$i18n.menu.forum}
    - {$i18n.menu.help}
    -

    + + +
    {* end of main menu for non authorized user *} {/if} diff --git a/default.css b/default.css index da21649f7..820382bdf 100644 --- a/default.css +++ b/default.css @@ -358,6 +358,15 @@ input[type="file"] { margin-right: auto; } +.sitemap-item-group { + margin-top: 2rem; + margin-bottom: 2rem; +} + +.sitemap-item { + margin: .4rem; +} + @media screen and (max-width: 600px) { .large-screen-label { diff --git a/initialize.php b/initialize.php index c98543252..f2b193e74 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5380"); +define("APP_VERSION", "1.19.23.5381"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 56c1de5a9c853ad16a350c36669901f3acfa26c9 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 25 Nov 2020 18:17:27 +0000 Subject: [PATCH 128/587] Cosmetic. Added copytight notices on refactored templates. --- WEB-INF/templates/client_add2.tpl | 3 +++ WEB-INF/templates/client_delete2.tpl | 3 +++ WEB-INF/templates/client_edit2.tpl | 3 +++ WEB-INF/templates/clients2.tpl | 3 +++ WEB-INF/templates/entity_files2.tpl | 3 +++ WEB-INF/templates/expense_delete2.tpl | 3 +++ WEB-INF/templates/expense_edit2.tpl | 3 +++ WEB-INF/templates/expenses2.tpl | 3 +++ WEB-INF/templates/login.db2.tpl | 3 +++ WEB-INF/templates/login.ldap2.tpl | 3 +++ WEB-INF/templates/login2.tpl | 3 +++ WEB-INF/templates/password_change2.tpl | 3 +++ WEB-INF/templates/password_reset2.tpl | 3 +++ WEB-INF/templates/project_add2.tpl | 3 +++ WEB-INF/templates/project_delete2.tpl | 3 +++ WEB-INF/templates/project_edit2.tpl | 3 +++ WEB-INF/templates/register2.tpl | 3 +++ WEB-INF/templates/swap_roles2.tpl | 3 +++ WEB-INF/templates/task_add2.tpl | 3 +++ WEB-INF/templates/task_delete2.tpl | 3 +++ WEB-INF/templates/task_edit2.tpl | 3 +++ WEB-INF/templates/tasks2.tpl | 3 +++ WEB-INF/templates/time2.tpl | 3 +++ WEB-INF/templates/time_delete2.tpl | 3 +++ WEB-INF/templates/time_edit2.tpl | 3 +++ WEB-INF/templates/user_add2.tpl | 3 +++ WEB-INF/templates/user_delete2.tpl | 3 +++ WEB-INF/templates/user_edit2.tpl | 3 +++ WEB-INF/templates/users2.tpl | 3 +++ initialize.php | 2 +- 30 files changed, 88 insertions(+), 1 deletion(-) diff --git a/WEB-INF/templates/client_add2.tpl b/WEB-INF/templates/client_add2.tpl index e22081ef4..5fe001b23 100644 --- a/WEB-INF/templates/client_add2.tpl +++ b/WEB-INF/templates/client_add2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {$forms.clientForm.open} diff --git a/WEB-INF/templates/client_delete2.tpl b/WEB-INF/templates/client_delete2.tpl index bc583ea66..47506f79b 100644 --- a/WEB-INF/templates/client_delete2.tpl +++ b/WEB-INF/templates/client_delete2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {$forms.clientDeleteForm.open}
    diff --git a/WEB-INF/templates/client_edit2.tpl b/WEB-INF/templates/client_edit2.tpl index 935c6a1e5..91f2b1c39 100644 --- a/WEB-INF/templates/client_edit2.tpl +++ b/WEB-INF/templates/client_edit2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {$forms.clientForm.open}
    {$i18n.form.client.client_to_delete}:
    diff --git a/WEB-INF/templates/clients2.tpl b/WEB-INF/templates/clients2.tpl index 1ec69df2f..9f7d4064b 100644 --- a/WEB-INF/templates/clients2.tpl +++ b/WEB-INF/templates/clients2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + diff --git a/WEB-INF/templates/entity_files2.tpl b/WEB-INF/templates/entity_files2.tpl index 9d48e24c1..d6b892b38 100644 --- a/WEB-INF/templates/entity_files2.tpl +++ b/WEB-INF/templates/entity_files2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {if $files}
    diff --git a/WEB-INF/templates/expense_delete2.tpl b/WEB-INF/templates/expense_delete2.tpl index 9b9bab838..a9ea04d10 100644 --- a/WEB-INF/templates/expense_delete2.tpl +++ b/WEB-INF/templates/expense_delete2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {$forms.expenseItemForm.open}
    diff --git a/WEB-INF/templates/expense_edit2.tpl b/WEB-INF/templates/expense_edit2.tpl index 3cea79482..ec921e007 100644 --- a/WEB-INF/templates/expense_edit2.tpl +++ b/WEB-INF/templates/expense_edit2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 33aa428e7..487bff7cf 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {include file="time_script.tpl"} {if $show_navigation} diff --git a/WEB-INF/templates/time_delete2.tpl b/WEB-INF/templates/time_delete2.tpl index 20acb783c..59d9039d1 100644 --- a/WEB-INF/templates/time_delete2.tpl +++ b/WEB-INF/templates/time_delete2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {$forms.timeRecordForm.open}
    diff --git a/WEB-INF/templates/time_edit2.tpl b/WEB-INF/templates/time_edit2.tpl index dc3d78cd0..8a25c43cf 100644 --- a/WEB-INF/templates/time_edit2.tpl +++ b/WEB-INF/templates/time_edit2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + {include file="time_script.tpl"} {* Conditional include of confirmSave handler. *} diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index dfb4bfa19..ad421b9e8 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -1,3 +1,6 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + diff --git a/initialize.php b/initialize.php index f2b193e74..42b94a865 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5381"); +define("APP_VERSION", "1.19.23.5382"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 25202d51cbcbe494fb4a5a30cf90687736d64342 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 25 Nov 2020 18:25:02 +0000 Subject: [PATCH 129/587] Cleanup. Removed no longer used legacy mobile client pages and templates. --- WEB-INF/templates/mobile/client_add.tpl | 37 ------ WEB-INF/templates/mobile/client_delete.tpl | 25 ---- WEB-INF/templates/mobile/client_edit.tpl | 41 ------- WEB-INF/templates/mobile/clients.tpl | 66 ---------- WEB-INF/templates/mobile/header.tpl | 3 - initialize.php | 2 +- mobile/client_add.php | 94 -------------- mobile/client_delete.php | 78 ------------ mobile/client_edit.php | 135 --------------------- mobile/clients.php | 54 --------- 10 files changed, 1 insertion(+), 534 deletions(-) delete mode 100644 WEB-INF/templates/mobile/client_add.tpl delete mode 100644 WEB-INF/templates/mobile/client_delete.tpl delete mode 100644 WEB-INF/templates/mobile/client_edit.tpl delete mode 100644 WEB-INF/templates/mobile/clients.tpl delete mode 100644 mobile/client_add.php delete mode 100644 mobile/client_delete.php delete mode 100644 mobile/client_edit.php delete mode 100644 mobile/clients.php diff --git a/WEB-INF/templates/mobile/client_add.tpl b/WEB-INF/templates/mobile/client_add.tpl deleted file mode 100644 index db10ede45..000000000 --- a/WEB-INF/templates/mobile/client_add.tpl +++ /dev/null @@ -1,37 +0,0 @@ -{$forms.clientForm.open} -
    - - - -
    - - - - - - - - - - - - - - - - - - -{if $show_projects} - - - - - -{/if} - - - -
    {$i18n.label.client_name} (*):{$forms.clientForm.name.control}
    {$i18n.label.client_address}:{$forms.clientForm.address.control}
    {$i18n.label.tax}, %:{$forms.clientForm.tax.control} (0{$user->getDecimalMark()}00)
    {$i18n.label.required_fields}
     
    {$i18n.label.projects}:{$forms.clientForm.projects.control}
     
    {$forms.clientForm.btn_submit.control}
    -
    -{$forms.clientForm.close} diff --git a/WEB-INF/templates/mobile/client_delete.tpl b/WEB-INF/templates/mobile/client_delete.tpl deleted file mode 100644 index f40b94c12..000000000 --- a/WEB-INF/templates/mobile/client_delete.tpl +++ /dev/null @@ -1,25 +0,0 @@ -{$forms.clientDeleteForm.open} - - - - -
    - - - - - - - - - - - - - - - - -
    {$i18n.form.client.client_to_delete}:{$client_to_delete|escape}
    {$i18n.form.client.client_entries}:{$forms.clientDeleteForm.delete_client_entries.control}
     
    {$forms.clientDeleteForm.btn_delete.control}  {$forms.clientDeleteForm.btn_cancel.control}
    -
    -{$forms.clientDeleteForm.close} diff --git a/WEB-INF/templates/mobile/client_edit.tpl b/WEB-INF/templates/mobile/client_edit.tpl deleted file mode 100644 index 4f70ced7a..000000000 --- a/WEB-INF/templates/mobile/client_edit.tpl +++ /dev/null @@ -1,41 +0,0 @@ -{$forms.clientForm.open} - - - - -
    - - - - - - - - - - - - - - - - - - - - - - -{if $show_projects} - - - - -{/if} - - - - -
    {$i18n.label.client_name} (*):{$forms.clientForm.name.control}
    {$i18n.label.client_address}:{$forms.clientForm.address.control}
    {$i18n.label.tax}, %:{$forms.clientForm.tax.control} (0{$user->decimal_mark}00)
    {$i18n.label.status}:{$forms.clientForm.status.control}
    {$i18n.label.required_fields}
     
    {$i18n.label.projects}:{$forms.clientForm.projects.control}
     
    {$forms.clientForm.btn_save.control} {$forms.clientForm.btn_copy.control} {$forms.clientForm.btn_delete.control}
    -
    -{$forms.clientForm.close} diff --git a/WEB-INF/templates/mobile/clients.tpl b/WEB-INF/templates/mobile/clients.tpl deleted file mode 100644 index 34f53a919..000000000 --- a/WEB-INF/templates/mobile/clients.tpl +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -
    -{if $user->can('manage_clients')} - - {if $inactive_clients} - - {/if} - - - - - {foreach $active_clients as $client} - - - - - {/foreach} -
    {$i18n.form.clients.active_clients}
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}
    - - - -

    - - {if $inactive_clients} - - - - - - - {foreach $inactive_clients as $client} - - - - - {/foreach} -
    {$i18n.form.clients.inactive_clients}
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}
    - - - -

    - {/if} -{else} - - - - - - {if $active_clients} - {foreach $active_clients as $client} - - - - - {/foreach} - {/if} -
    {$i18n.label.thing_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}
    -{/if} -
    diff --git a/WEB-INF/templates/mobile/header.tpl b/WEB-INF/templates/mobile/header.tpl index ccea5e7e1..d4cf2c53b 100644 --- a/WEB-INF/templates/mobile/header.tpl +++ b/WEB-INF/templates/mobile/header.tpl @@ -91,9 +91,6 @@ {/if} {if $user->can('view_users') || $user->can('manage_users')} {$i18n.menu.users} - {/if} - {if $user->isPluginEnabled('cl') && ($user->can('view_own_clients') || $user->can('manage_clients'))} - {$i18n.menu.clients} {/if} diff --git a/initialize.php b/initialize.php index 42b94a865..4e41c7ea3 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5382"); +define("APP_VERSION", "1.19.23.5383"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/client_add.php b/mobile/client_add.php deleted file mode 100644 index 2050204a6..000000000 --- a/mobile/client_add.php +++ /dev/null @@ -1,94 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_address = trim($request->getParameter('address')); - $cl_tax = $request->getParameter('tax'); - $cl_projects = $request->getParameter('projects'); -} else { - // Do not assign all projects to a new client by default. This should help to reduce clutter. - // foreach ($projects as $project_item) - // $cl_projects[] = $project_item['id']; -} - -$show_projects = (MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; - -$form = new Form('clientForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','class'=>'mobile-textarea','value'=>$cl_address)); -$form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); -if ($show_projects) - $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'layout'=>'H','datakeys'=>array('id','name'),'value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.client_name')); - if (!ttValidString($cl_address, true)) $err->add($i18n->get('error.field'), $i18n->get('label.client_address')); - if (!ttValidFloat($cl_tax, true)) $err->add($i18n->get('error.field'), $i18n->get('label.tax')); - - if ($err->no()) { - if (!ttClientHelper::getClientByName($cl_name)) { - if (ttClientHelper::insert(array('name' => $cl_name, - 'address' => $cl_address, - 'tax' => $cl_tax, - 'projects' => $cl_projects, - 'status' => ACTIVE))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.clientForm.name.focus()"'); -$smarty->assign('show_projects',$show_projects); -$smarty->assign('title', $i18n->get('title.add_client')); -$smarty->assign('content_page_name', 'mobile/client_add.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/client_delete.php b/mobile/client_delete.php deleted file mode 100644 index 8e05ccde8..000000000 --- a/mobile/client_delete.php +++ /dev/null @@ -1,78 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} -$id = (int)$request->getParameter('id'); -$client = ttClientHelper::getClient($id); -if (!$client) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$client_to_delete = $client['name']; - -$form = new Form('clientDeleteForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$id)); -$form->addInput(array('type'=>'combobox','name'=>'delete_client_entries', - 'data'=>array('0'=>$i18n->get('dropdown.do_not_delete'),'1'=>$i18n->get('dropdown.delete')))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_delete')) { - if (ttClientHelper::delete($id, $request->getParameter('delete_client_entries'))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } - - if ($request->getParameter('btn_cancel')) { - header('Location: clients.php'); - exit(); - } -} // isPost - -$smarty->assign('client_to_delete', $client_to_delete); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('title', $i18n->get('title.delete_client')); -$smarty->assign('content_page_name', 'mobile/client_delete.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/client_edit.php b/mobile/client_edit.php deleted file mode 100644 index ab8686509..000000000 --- a/mobile/client_edit.php +++ /dev/null @@ -1,135 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_id = (int)$request->getParameter('id'); -$client = ttClientHelper::getClient($cl_id, true); -if (!$client) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_address = trim($request->getParameter('address')); - $cl_tax = trim($request->getParameter('tax')); - $cl_status = $request->getParameter('status'); - $cl_projects = $request->getParameter('projects'); -} else { - $cl_name = $client['name']; - $cl_address = $client['address']; - $cl_tax = $client['tax']; - $cl_status = $client['status']; - $assigned_projects = ttClientHelper::getAssignedProjects($cl_id); - foreach($assigned_projects as $project_item) { - $cl_projects[] = $project_item['id']; - } -} - -$show_projects = (MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; - -$form = new Form('clientForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'text','name'=>'name','maxlength'=>'100','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','class'=>'mobile-textarea','value'=>$cl_address)); -$form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -if ($show_projects) - $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'datakeys'=>array('id','name'),'layout'=>'H','value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.client_name')); - if (!ttValidString($cl_address, true)) $err->add($i18n->get('error.field'), $i18n->get('label.client_address')); - if (!ttValidFloat($cl_tax, true)) $err->add($i18n->get('error.field'), $i18n->get('label.tax')); - - if ($err->no()) { - if ($request->getParameter('btn_save')) { - $client = ttClientHelper::getClientByName($cl_name); - if (($client && ($cl_id == $client['id'])) || !$client) { - if (ttClientHelper::update(array('id' => $cl_id, - 'name' => $cl_name, - 'address' => $cl_address, - 'tax' => $cl_tax, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_copy')) { - if (!ttClientHelper::getClientByName($cl_name)) { - if (ttClientHelper::insert(array('name' => $cl_name, - 'address' => $cl_address, - 'tax' => $cl_tax, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_delete')) { - header("Location: client_delete.php?id=$cl_id"); - exit(); - } - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('title', $i18n->get('title.edit_client')); -$smarty->assign('content_page_name', 'mobile/client_edit.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/clients.php b/mobile/clients.php deleted file mode 100644 index d1e6b38f3..000000000 --- a/mobile/clients.php +++ /dev/null @@ -1,54 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -if($user->can('manage_clients')) { - $active_clients = ttGroupHelper::getActiveClients(true); - $inactive_clients = ttGroupHelper::getInactiveClients(true); -} else - $active_clients = $user->getAssignedClients(); - -$smarty->assign('active_clients', $active_clients); -$smarty->assign('inactive_clients', $inactive_clients); -$smarty->assign('title', $i18n->get('title.clients')); -$smarty->assign('content_page_name', 'mobile/clients.tpl'); -$smarty->display('mobile/index.tpl'); From fa0a08caa353fd5e2667780c7bb42eb763ad1b02 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 26 Nov 2020 16:36:43 +0000 Subject: [PATCH 130/587] Cosmetic changes in translation files. --- README.md | 2 +- WEB-INF/resources/ca.lang.php | 34 +++++------------------------- WEB-INF/resources/cs.lang.php | 34 +++++------------------------- WEB-INF/resources/da.lang.php | 34 +++++------------------------- WEB-INF/resources/de.lang.php | 28 ++----------------------- WEB-INF/resources/en.lang.php | 34 +++++------------------------- WEB-INF/resources/es.lang.php | 36 ++++++-------------------------- WEB-INF/resources/et.lang.php | 28 ++----------------------- WEB-INF/resources/fa.lang.php | 34 +++++------------------------- WEB-INF/resources/fi.lang.php | 33 +++++------------------------ WEB-INF/resources/fr.lang.php | 32 ++++------------------------ WEB-INF/resources/gr.lang.php | 28 ++----------------------- WEB-INF/resources/he.lang.php | 28 ++----------------------- WEB-INF/resources/hu.lang.php | 28 ++----------------------- WEB-INF/resources/it.lang.php | 28 ++----------------------- WEB-INF/resources/ja.lang.php | 28 ++----------------------- WEB-INF/resources/ko.lang.php | 28 ++----------------------- WEB-INF/resources/nl.lang.php | 28 ++----------------------- WEB-INF/resources/no.lang.php | 28 ++----------------------- WEB-INF/resources/pl.lang.php | 28 ++----------------------- WEB-INF/resources/pt-br.lang.php | 28 ++----------------------- WEB-INF/resources/pt.lang.php | 28 ++----------------------- WEB-INF/resources/ro.lang.php | 28 ++----------------------- WEB-INF/resources/ru.lang.php | 28 ++----------------------- WEB-INF/resources/sk.lang.php | 28 ++----------------------- WEB-INF/resources/sl.lang.php | 28 ++----------------------- WEB-INF/resources/sr.lang.php | 28 ++----------------------- WEB-INF/resources/sv.lang.php | 28 ++----------------------- WEB-INF/resources/tr.lang.php | 28 ++----------------------- WEB-INF/resources/zh-cn.lang.php | 28 ++----------------------- WEB-INF/resources/zh-tw.lang.php | 34 +++++------------------------- initialize.php | 2 +- mobile/index.php | 5 ++--- 33 files changed, 91 insertions(+), 811 deletions(-) diff --git a/README.md b/README.md index f3b7987ef..cf2f8601f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Anuko Time Tracker ## About -Anuko [Time Tracker](https://www.anuko.com/time-tracker/index.htm) is a simple, easy to use, open source, web-based time tracking application written in PHP. It allows you to track the time that employees or colleagues spend working on projects and tasks. It needs a web server such as Apache, IIS, etc. to run on, and a database to keep the data in, such as MySQL. +Anuko [Time Tracker](https://www.anuko.com/time-tracker/index.htm) is an open source, web-based time tracking application written in PHP. It allows you to track the time that employees or colleagues spend working on projects and tasks. It needs a web server such as Apache, IIS, etc. to run on, and a database to keep the data in, such as MySQL. ## Free Hosting [Anuko](https://www.anuko.com) provides [free hosting](https://www.anuko.com/time-tracker/free-hosting/index.htm) of Time Tracker to individuals and small groups up to 5 users. To start using Time Tracker immediately, create a group at https://timetracker.anuko.com diff --git a/WEB-INF/resources/ca.lang.php b/WEB-INF/resources/ca.lang.php index de6e0df96..34421e73d 100644 --- a/WEB-INF/resources/ca.lang.php +++ b/WEB-INF/resources/ca.lang.php @@ -1,30 +1,6 @@ '¿Ha oblidat la seva paraula de pas?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'S\\\'ha enviat la petició de restablir paraula de pas.', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Sol·licitud de restabliment de la paraula de pas de Anuko Time Tracker', // TODO: translate the following. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Per restablir la paraula de pas, si us plau escrigui-la i faci clic en guardar.', @@ -649,7 +625,7 @@ 'form.mail.to' => 'Per a', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'Factura enviada.', diff --git a/WEB-INF/resources/cs.lang.php b/WEB-INF/resources/cs.lang.php index 92411b33b..199a96faf 100644 --- a/WEB-INF/resources/cs.lang.php +++ b/WEB-INF/resources/cs.lang.php @@ -1,30 +1,6 @@ 'Zapomenuté heslo?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Zaslán požadavek k vymazání hesla.', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko Time Tracker požadavek na vymazání hesla', // TODO: translate the following. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. @@ -662,7 +638,7 @@ 'form.mail.to' => 'Komu', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'Faktura odeslána.', diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 3ab49c39e..88b5324fb 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -1,30 +1,6 @@ 'Nulstilling af adgangskode er sendt på email.', 'form.reset_password.email_subject' => 'Anuko Time Tracker - Anmodning om nulstilling af adgangskode', // TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Hej\n\nNogen, IP %s, har bedt om at få nulstillet din adgangskode. Tryk på linket hvis du vil have nulstillet din adgangskode.\n\n%s\n\nAnuko Time Tracker er et nemt, let at bruge, open source tidsregistrerings system. Besøg https://www.anuko.com for mere information.\n\n", +'form.reset_password.email_body' => "Hej\n\nNogen, IP %s, har bedt om at få nulstillet din adgangskode. Tryk på linket hvis du vil have nulstillet din adgangskode.\n\n%s\n\nAnuko Time Tracker er et open source tidsregistrerings system. Besøg https://www.anuko.com for mere information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Skriv en ny adgangskode og tryk Gem.', @@ -626,7 +602,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Til', 'form.mail.report_subject' => 'Tidsregistrerings Rapport', -'form.mail.footer' => 'Anuko Time Tracker er et simpelt, let at bruge, open source
    tidsregistrerings system. Besøg www.anuko.com for mere information.', +'form.mail.footer' => 'Anuko Time Tracker er et open source
    tidsregistrerings system. Besøg www.anuko.com for mere information.', 'form.mail.report_sent' => 'Rapport sendt.', 'form.mail.invoice_sent' => 'Faktura sendt.', diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index 7db6f93bb..be1ede828 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -1,30 +1,6 @@ 'Forgot password?', -'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Password reset request sent by email.', 'form.reset_password.email_subject' => 'Anuko Time Tracker password reset request', -'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Type new password and click on Save.', @@ -587,7 +563,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'To', 'form.mail.report_subject' => 'Time Tracker Report', -'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'Invoice sent.', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index 0c1d2c6b9..e7df23ad6 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -1,30 +1,6 @@ '¿Olvido su contraseña?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. // TODO: check / improve translation of form.reset_password.message. @@ -486,9 +462,9 @@ 'form.reset_password.email_subject' => 'Solicitud de reestablecimiento de la contraseña de Anuko Time Tracker', // Note to translators: the ending of this string needs to be translated. // TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Querido usuario, Alguien, IP %s, solicitó reestablecer su contraseña de Anuko Time Tracker. Por favor visite este enlace si quiere reestablecer su contraseña.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +'form.reset_password.email_body' => "Querido usuario, Alguien, IP %s, solicitó reestablecer su contraseña de Anuko Time Tracker. Por favor visite este enlace si quiere reestablecer su contraseña.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: improve translation of form.change_password.tip. @@ -664,7 +640,7 @@ // TODO: translate form.mail.report_subject. // 'form.mail.report_subject' => 'Time Tracker Report', // Note to translators: the following strings need to be translated. -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'Factura enviada.', diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index b6b442441..e2c63ef91 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -1,30 +1,6 @@ 'بازیابی رمز عبور؟', // TODO: translate form.login.about. -'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'درخواست بازیابی رمزعبور به ایمیل فرستاده شد.', @@ -481,7 +457,7 @@ // 'form.reset_password.email_subject' => 'Anuko Time Tracker password reset request', 'form.reset_password.email_subject' => 'درخواست بازیابی رمزعبور فرستاده شد', // TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Older translation is below. // 'form.reset_password.email_body' => "کاربران گرامی\n\n یک نفر، شاید خودتان، درخواست بازیابی رمزعبور نرم افزار رهگیری زمان شما را داشته است.لطفا برای تغییر رمزعبور روی لینک زیر کلیک کنید: \n\n%s\n\n", @@ -649,7 +625,7 @@ 'form.mail.to' => 'به', 'form.mail.report_subject' => 'گزارش تایم شیت', // TODO: translate form.mail.footer. -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', 'form.mail.report_sent' => 'گزارش ارسال شد.', 'form.mail.invoice_sent' => 'فاکتور ارسال شد.', diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index 753dcf8ce..42af8047e 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -1,30 +1,6 @@ 'Salasanan nollauspyyntöviesti lähetetty.', 'form.reset_password.email_subject' => 'Anuko Time Tracker -salasanan nollauspyyntö', -// TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Hyvä käyttäjä,\n\nJoku, IP %s, on pyytänyt nollaamaan Anuko Time Tracker -ohjelman salasanasi. Jos haluat nollata salasanasi, käy sivulla \n\n%s\n\nAnuko Time Tracker on yksinkertainen ja helppokäyttöinen vapaan koodin tuntiseurantaohjelmisto. Lisätietoja sivulla https://www.anuko.com.\n\n", @@ -631,6 +607,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Vastaanottaja', 'form.mail.report_subject' => 'Time Tracker -raportti', +// TODO: English string for form.mail.footer changed. Re-translate. 'form.mail.footer' => 'Anuko Time Tracker on yksinkertainen ja helppokäyttöinen vapaan koodin tuntiseurantaohjelmisto. Lisätietoja sivulla www.anuko.com.', 'form.mail.report_sent' => 'Raportti lähetetty.', 'form.mail.invoice_sent' => 'Lasku lähetetty.', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index ca00e9471..46116db12 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -1,30 +1,6 @@ 'Une demande de réinitialisation du mot de passe a été envoyé par courriel.', 'form.reset_password.email_subject' => 'Demande de réinitialisation de mot de passe Anuko Time Tracker', -// TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Cher utilisateur,\n\nQuelqu\'un, IP %s, avez demandé une réinitialisation de votre mot de passe. Veuillez de suivre ce lien pour le réinitialiser\n\n%s\n\nAnuko Time Tracker est un système de gestion du temps, open source, simple et facile à utiliser. Visitez https://www.anuko.com pour plus d\'informations.\n\n", diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index ba630f269..5e3ee8ee8 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -1,30 +1,6 @@ '忘記密碼?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => '密碼重設請求已經發送。', // TODO: Add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko時間追蹤器密碼重設請求', // TODO: translate the following. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. @@ -647,7 +623,7 @@ 'form.mail.to' => '到', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => '發票已送出。', diff --git a/initialize.php b/initialize.php index 4e41c7ea3..ae59bd0db 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5383"); +define("APP_VERSION", "1.19.23.5384"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/index.php b/mobile/index.php index fa3f04c46..8fc64b35e 100644 --- a/mobile/index.php +++ b/mobile/index.php @@ -44,10 +44,9 @@ From 6f4cf24936570945a4809d8cfc33acb42c952813 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 26 Nov 2020 17:17:34 +0000 Subject: [PATCH 131/587] Cosmetic improvements in translation files. --- WEB-INF/resources/da.lang.php | 2 +- WEB-INF/resources/de.lang.php | 2 +- WEB-INF/resources/et.lang.php | 2 +- WEB-INF/resources/fi.lang.php | 3 ++- WEB-INF/resources/fr.lang.php | 2 +- WEB-INF/resources/gr.lang.php | 2 +- WEB-INF/resources/he.lang.php | 2 ++ WEB-INF/resources/hu.lang.php | 2 +- WEB-INF/resources/it.lang.php | 2 +- WEB-INF/resources/ja.lang.php | 2 +- WEB-INF/resources/ko.lang.php | 2 +- WEB-INF/resources/nl.lang.php | 2 ++ WEB-INF/resources/no.lang.php | 2 ++ WEB-INF/resources/pl.lang.php | 2 +- WEB-INF/resources/pt-br.lang.php | 2 +- WEB-INF/resources/pt.lang.php | 2 +- WEB-INF/resources/ro.lang.php | 2 +- WEB-INF/resources/ru.lang.php | 2 +- WEB-INF/resources/sk.lang.php | 2 +- WEB-INF/resources/sl.lang.php | 2 +- WEB-INF/resources/sr.lang.php | 2 ++ WEB-INF/resources/sv.lang.php | 2 ++ WEB-INF/resources/tr.lang.php | 2 +- WEB-INF/resources/zh-cn.lang.php | 2 ++ initialize.php | 2 +- 25 files changed, 32 insertions(+), 19 deletions(-) diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 88b5324fb..040405503 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -431,7 +431,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Har du glemt din adgangskode?', -'form.login.about' => 'Anuko Time Tracker er et nemt, let at bruge, open source tidsregistrerings system.', +'form.login.about' => 'Anuko Time Tracker er et open source tidsregistrerings system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Nulstilling af adgangskode er sendt på email.', diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index be1ede828..2268692bb 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -422,7 +422,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Passwort vergessen?', -'form.login.about' => 'Anuko Time Tracker ist ein einfaches, leicht zu bedienendes, Open-Source Zeiterfassungssystem.', +'form.login.about' => 'Anuko Time Tracker ist ein Open-Source Zeiterfassungssystem.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Anfrage zur Zurücksetzung des Passwortes wurde per E-mail gesendet.', diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index e2c63ef91..30f697cbd 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -439,7 +439,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Unustasid salasõna?', -'form.login.about' => 'Anuko Time Tracker on lihtne, lihtsalt kasutatav ja avatud lähtekoodiga ajaarvestussüsteem.', +'form.login.about' => 'Anuko Time Tracker on avatud lähtekoodiga ajaarvestussüsteem.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Salasõna tühistamise teade on saadetud e-postile.', diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index 42af8047e..034ea6ae0 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -436,7 +436,8 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Salasana unohtunut?', -'form.login.about' => 'Anuko Time Tracker on yksinkertainen ja helppokäyttöinen vapaan koodin tuntiseurantaohjelmisto.', + // TODO: check translation of form.login.about - is open source "vapaan koodin"? +'form.login.about' => 'Anuko Time Tracker on vapaan koodin tuntiseurantaohjelmisto.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Salasanan nollauspyyntöviesti lähetetty.', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index 46116db12..44ba9b2bb 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -428,7 +428,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Mot de passe oublié?', -'form.login.about' => 'Anuko Time Tracker est un système de gestion du temps, open source, simple et facile à utiliser.', +'form.login.about' => 'Anuko Time Tracker est un système de gestion du temps, open source.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Une demande de réinitialisation du mot de passe a été envoyé par courriel.', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index 5e3ee8ee8..29404a831 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -428,7 +428,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Ξεχάσατε τον κωδικό πρόσβασης;', -'form.login.about' => 'Anuko Time Tracker είναι ένα απλό, εύχρηστο, ανοικτού κώδικα σύστημα παρακολούθησης χρόνου.', +'form.login.about' => 'Anuko Time Tracker είναι ένα ανοικτού κώδικα σύστημα παρακολούθησης χρόνου.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Το αίτημα επαναφοράς κωδικού πρόσβασης αποστέλλεται μέσω ηλεκτρονικού ταχυδρομείου.', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index 1460943e2..2bc6129d9 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -453,6 +453,8 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'שכחת סיסמה?', + // TODO: re-translate form.login.about as it has changed. + // 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', 'form.login.about' => 'Anuko Time Tracker הינה מערכת פשוטה, קלה לשימוש וחינמית לניהול זמן.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index 509034524..98a566d10 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -450,7 +450,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Elfelejtetted a jelszót?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. // TODO: translate the following. diff --git a/WEB-INF/resources/it.lang.php b/WEB-INF/resources/it.lang.php index 1626913ec..1b7f56e46 100644 --- a/WEB-INF/resources/it.lang.php +++ b/WEB-INF/resources/it.lang.php @@ -438,7 +438,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Password dimenticata?', -'form.login.about' => 'Anuko Time Tracker è un sistema semplice e open source per registrare i tempi di lavoro.', +'form.login.about' => 'Anuko Time Tracker è un sistema open source per registrare i tempi di lavoro.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Richiesta di reset password inviata via mail.', diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index b73f3ea83..aae1528cc 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -451,7 +451,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'パスワードを忘れましたか?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => '送信したパスワードの初期化の要求。', // TODO: add "by email" to match the English string. diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index e7430b6ee..6794c57e7 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -455,7 +455,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => '암호를 잊으셨습니까?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => '송신한 암호 재설정 요청.', // TODO: add "by email" to match the English string. diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 959822057..8b2e557ea 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -390,6 +390,8 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Wachtwoord vergeten?', + // TODO: re-translate form.login.about as it has changed. + // 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', 'form.login.about' => 'Anuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index ed392d932..77d43637f 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -450,6 +450,8 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Glemt passordet?', + // TODO: re-translate form.login.about as it has changed. + // 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', 'form.login.about' => 'Anuko Time Tracker er et enkelt, brukervennlig tidsregistreringssystem basert på åpen kildekode.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index 5f67ff40f..b617314db 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -439,7 +439,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Nie pamiętasz hasła?', -'form.login.about' => 'Anuko Time Tracker jest prostym, łatwym w użyciu, otwartoźródłowym systemem śledzenia czasu.', +'form.login.about' => 'Anuko Time Tracker jest otwartoźródłowym systemem śledzenia czasu.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Instrukcje zmiany hasła zostały wysłane na adres e-mail połączony z kontem.', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index 3fb2f3aed..95e9d1060 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -434,7 +434,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Esqueceu a senha?', -'form.login.about' => 'Anuko Time Tracker é um sistema, simples, de fácil uso, de código aberto, de rastreamento do tempo.', +'form.login.about' => 'Anuko Time Tracker é um sistema de código aberto de rastreamento do tempo.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Pedido para resetar a senha enviado por e-mail.', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index fab8af4cf..dd72ab4b6 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -434,7 +434,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Esqueceu a senha?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. // TODO: translate the following. diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index 32edb49e9..55731aa05 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -454,7 +454,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Parola pierduta?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Cererea de resetare a parolei a fost trimisa.', // TODO: add "by email" to match the English string. diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index 3268f0878..dd6c1e1c8 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -391,7 +391,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Забыли пароль?', -'form.login.about' => 'Anuko Time Tracker - это открытая (open source), простая и лёгкая в использовании система трекинга рабочего времени.', +'form.login.about' => 'Anuko Time Tracker - это открытая (open source) система трекинга рабочего времени.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Запрос на сброс пароля отослан по e-mail.', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index 90f500e0c..95a025a7a 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -443,7 +443,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Zabudnuté heslo?', -'form.login.about' => 'Anuko Time Tracker je jednoduchý a ľahko použiteľný systém na sledovanie času s otvoreným zdrojovým kódom.', +'form.login.about' => 'Anuko Time Tracker je systém na sledovanie času s otvoreným zdrojovým kódom.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Žiadosť o obnovenie hesla bola odoslaná e-mailom.', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index 2e1004810..eb8bd99dd 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -426,7 +426,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. // TODO: translate the following. // 'form.login.forgot_password' => 'Forgot password?', -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Zahteva za razveljavitev gesla je bila poslana.', // TODO: add "by email" to match the English string. diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index f67e81334..a80f0e67a 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -437,6 +437,8 @@ // Forma prijave. Pogledajte primer na https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Zaboravili ste lozinku?', + // TODO: re-translate form.login.about as it has changed. + // 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', 'form.login.about' => 'Anuko Time Tracker je jednostavan i lak za korišćenje za praćenje radnog vremena.', // Izmena forme za lozinku. Pogledajte primer na https://timetracker.anuko.com/password_reset.php. diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index fc1c7bd62..6bae583a7 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -436,6 +436,8 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Glömt lösenordet?', + // TODO: re-translate form.login.about as it has changed. + // 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', 'form.login.about' => 'Anuko Time Tracker är en lättanvänd applikation byggd med öppen källkod som enkelt låter dig spåra och hålla koll på arbetstider.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index f1c164c62..3ba51a116 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -462,7 +462,7 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Parolanızı unuttunuz mu?', // TODO: translate the following. -// 'form.login.about' => 'Anuko Time Tracker is a simple, easy to use, open source time tracking system.', +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Parola sıfırlama talebi yollandı.', // TODO: add "by email" to match the English string. diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index c10942223..7eb54073a 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -442,6 +442,8 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => '忘记密码?', +// TODO: re-translate form.login.about as it has changed. +// 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', 'form.login.about' => 'Anuko Time Tracker 是一种简单、易用、开放源代码的实时跟踪系统。', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. diff --git a/initialize.php b/initialize.php index ae59bd0db..1f219134f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5384"); +define("APP_VERSION", "1.19.23.5385"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 2de5567b129e8190b9c1f9d80d9cedc5b6c5d37d Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 26 Nov 2020 18:10:00 +0000 Subject: [PATCH 132/587] Some more refactoring in translation files. --- WEB-INF/resources/de.lang.php | 2 +- WEB-INF/resources/es.lang.php | 2 +- WEB-INF/resources/et.lang.php | 2 +- WEB-INF/resources/fa.lang.php | 2 +- WEB-INF/resources/fi.lang.php | 2 +- WEB-INF/resources/fr.lang.php | 2 +- WEB-INF/resources/gr.lang.php | 2 +- WEB-INF/resources/he.lang.php | 4 ++-- WEB-INF/resources/hu.lang.php | 2 +- WEB-INF/resources/ja.lang.php | 6 +++--- WEB-INF/resources/ko.lang.php | 2 +- WEB-INF/resources/nl.lang.php | 2 ++ WEB-INF/resources/no.lang.php | 4 ++-- WEB-INF/resources/pl.lang.php | 4 ++-- WEB-INF/resources/pt-br.lang.php | 4 ++-- WEB-INF/resources/pt.lang.php | 2 +- WEB-INF/resources/ro.lang.php | 6 +++--- WEB-INF/resources/ru.lang.php | 2 +- WEB-INF/resources/sk.lang.php | 4 ++-- WEB-INF/resources/sl.lang.php | 6 +++--- WEB-INF/resources/sr.lang.php | 4 ++-- WEB-INF/resources/sv.lang.php | 4 ++-- WEB-INF/resources/tr.lang.php | 6 +++--- WEB-INF/resources/zh-cn.lang.php | 2 +- initialize.php | 2 +- 25 files changed, 41 insertions(+), 39 deletions(-) diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index 2268692bb..13626d9e6 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -427,7 +427,7 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Anfrage zur Zurücksetzung des Passwortes wurde per E-mail gesendet.', 'form.reset_password.email_subject' => 'Anuko Time Tracker Anfrage zur Zurücksetzung des Passwortes', -'form.reset_password.email_body' => "Sehr geehrter Nutzer,\n\nEin Benutzer mit der IP %s hat vor Kurzem die Zurücksetzung Ihres Passworts für Anuko Time Tracker Passwort angefordert. Bitte rufen Sie diesen Link auf wenn Sie Ihr Passwort zurücksetzen möchten.\n\n%s\n\nAnuko Time Tracker ist ein einfaches, leicht zu bedienendes, Open-Source Zeiterfassungs-System. Besuchen Sie https://www.anuko.com für weitere Informationen.\n\n", +'form.reset_password.email_body' => "Sehr geehrter Nutzer,\n\nEin Benutzer mit der IP %s hat vor Kurzem die Zurücksetzung Ihres Passworts für Anuko Time Tracker Passwort angefordert. Bitte rufen Sie diesen Link auf wenn Sie Ihr Passwort zurücksetzen möchten.\n\n%s\n\nAnuko Time Tracker ist ein Open-Source Zeiterfassungs-System. Besuchen Sie https://www.anuko.com für weitere Informationen.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Um das Passwort zurückzusetzen, geben Sie ein Neues ein und klicken dann auf Speichern.', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index e7df23ad6..05c24948c 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -461,7 +461,7 @@ 'form.reset_password.message' => 'Se ha enviado la petición de reestablecer contraseña.', 'form.reset_password.email_subject' => 'Solicitud de reestablecimiento de la contraseña de Anuko Time Tracker', // Note to translators: the ending of this string needs to be translated. -// TODO: English string has changed. "from IP added. Re-translate the beginning. +// TODO: English string has changed. "from IP added. Re-translate. // 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Querido usuario, Alguien, IP %s, solicitó reestablecer su contraseña de Anuko Time Tracker. Por favor visite este enlace si quiere reestablecer su contraseña.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index 30f697cbd..d938cf079 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -444,7 +444,7 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Salasõna tühistamise teade on saadetud e-postile.', 'form.reset_password.email_subject' => 'Anuko Time Tracker, parooli tühistamise nõue', -'form.reset_password.email_body' => "Lugupeetud Kasutaja,\n\nIP-lt %s on nõutud Teie salasõna lähtestamist. Palun avage allolev link, kui soovite oma parooli lähtestada.\n\n%s\n\nAnuko Time Tracker on lihtne, lihtsalt kasutatav ja avatud lähtekoodiga ajaarvestussüsteem. Lisainfo saamiseks külastage https://www.anuko.com lehekülge.\n\n", +'form.reset_password.email_body' => "Lugupeetud Kasutaja,\n\nIP-lt %s on nõutud Teie salasõna lähtestamist. Palun avage allolev link, kui soovite oma parooli lähtestada.\n\n%s\n\nAnuko Time Tracker on avatud lähtekoodiga ajaarvestussüsteem. Lisainfo saamiseks külastage https://www.anuko.com lehekülge.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Kirjuta siia oma uus parool ja salvesta.', diff --git a/WEB-INF/resources/fa.lang.php b/WEB-INF/resources/fa.lang.php index 0d578b64c..0fca34586 100644 --- a/WEB-INF/resources/fa.lang.php +++ b/WEB-INF/resources/fa.lang.php @@ -456,7 +456,7 @@ // TODO: check translation of form.reset_password.email_subject. This is the subject for email message for password reset. Below is the English original. // 'form.reset_password.email_subject' => 'Anuko Time Tracker password reset request', 'form.reset_password.email_subject' => 'درخواست بازیابی رمزعبور فرستاده شد', -// TODO: English string has changed. "from IP added. Re-translate the beginning. +// TODO: English string has changed. Re-translate. // 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Older translation is below. // 'form.reset_password.email_body' => "کاربران گرامی\n\n یک نفر، شاید خودتان، درخواست بازیابی رمزعبور نرم افزار رهگیری زمان شما را داشته است.لطفا برای تغییر رمزعبور روی لینک زیر کلیک کنید: \n\n%s\n\n", diff --git a/WEB-INF/resources/fi.lang.php b/WEB-INF/resources/fi.lang.php index 034ea6ae0..eaad8a293 100644 --- a/WEB-INF/resources/fi.lang.php +++ b/WEB-INF/resources/fi.lang.php @@ -445,7 +445,7 @@ // TODO: English string has changed. Re-translate. // 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Hyvä käyttäjä,\n\nJoku, IP %s, on pyytänyt nollaamaan Anuko Time Tracker -ohjelman salasanasi. Jos haluat nollata salasanasi, käy sivulla \n\n%s\n\nAnuko Time Tracker on yksinkertainen ja helppokäyttöinen vapaan koodin tuntiseurantaohjelmisto. Lisätietoja sivulla https://www.anuko.com.\n\n", +'form.reset_password.email_body' => "Hyvä käyttäjä,\n\nJoku, IP %s, on pyytänyt nollaamaan Anuko Time Tracker -ohjelman salasanasi. Jos haluat nollata salasanasi, käy sivulla \n\n%s\n\nAnuko Time Tracker on vapaan koodin tuntiseurantaohjelmisto. Lisätietoja sivulla https://www.anuko.com.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Syötä uusi salasana ja osoita Tallenna.', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index 44ba9b2bb..3d4845cc0 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -436,7 +436,7 @@ // TODO: English string has changed. Re-translate. // 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Cher utilisateur,\n\nQuelqu\'un, IP %s, avez demandé une réinitialisation de votre mot de passe. Veuillez de suivre ce lien pour le réinitialiser\n\n%s\n\nAnuko Time Tracker est un système de gestion du temps, open source, simple et facile à utiliser. Visitez https://www.anuko.com pour plus d\'informations.\n\n", +'form.reset_password.email_body' => "Cher utilisateur,\n\nQuelqu\'un, IP %s, avez demandé une réinitialisation de votre mot de passe. Veuillez de suivre ce lien pour le réinitialiser\n\n%s\n\nAnuko Time Tracker est un système de gestion du temps, open source. Visitez https://www.anuko.com pour plus d\'informations.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Saisissez votre nouveau mot de passe et cliquez sur Sauvegarder.', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index 29404a831..61b06f6bd 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -433,7 +433,7 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Το αίτημα επαναφοράς κωδικού πρόσβασης αποστέλλεται μέσω ηλεκτρονικού ταχυδρομείου.', 'form.reset_password.email_subject' => 'Αίτημα επαναφοράς κωδικού Anuko Time Tracker', -'form.reset_password.email_body' => "Αγαπητέ χρήστη,\n\nΚάποιος από την IP %s ζήτησε επαναφορά του κωδικού πρόσβασης στο Anuko Time Tracker. Πατήστε στον ακόλουθο σύνδεσμο για επαναφορά του κωδικού σας.\n\n%s\n\nΤο Anuko Time Tracker είναι ένα απλό, εύχρηστο, ανοικτού κώδικα σύστημα παρακολούθησης χρόνου. Επισκεφθείτε τη διεύθυνση https://www.anuko.com για περισσότερες πληροφορίες.\n\n", +'form.reset_password.email_body' => "Αγαπητέ χρήστη,\n\nΚάποιος από την IP %s ζήτησε επαναφορά του κωδικού πρόσβασης στο Anuko Time Tracker. Πατήστε στον ακόλουθο σύνδεσμο για επαναφορά του κωδικού σας.\n\n%s\n\nΤο Anuko Time Tracker είναι ένα ανοικτού κώδικα σύστημα παρακολούθησης χρόνου. Επισκεφθείτε τη διεύθυνση https://www.anuko.com για περισσότερες πληροφορίες.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Πληκτρολογήστε νέο κωδικό πρόσβασης και κάντε κλικ στην επιλογή Αποθήκευση.', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index 2bc6129d9..b8459e8b7 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -460,8 +460,8 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'הבקשה לאיפוס בסיסמה נשלחה בדואר אלקטרוני.', 'form.reset_password.email_subject' => 'בקשה לאיפוס סיסמה למערכת Anuko Time Tracker', -// TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Older translation is below. // 'form.reset_password.email_body' => "משתמש יקר,\n\n התקבלה בקשה לאיפוס סיסמתך. נא ללחוץ על קישור זה אם ברצונך לאפס את הסיסמה.\n\n%s\n\n. Anuko Time Tracker הינה מערכת לניהול זמן פשוטה וחינמית. בקר באתרנו בכתובת https://www.anuko.com לפרטים נוספים.\n\n", diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index 98a566d10..a4fe12023 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -456,7 +456,7 @@ // TODO: translate the following. // 'form.reset_password.message' => 'Password reset request sent by email.', // 'form.reset_password.email_subject' => 'Anuko Time Tracker password reset request', -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index aae1528cc..07db51091 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -457,10 +457,10 @@ 'form.reset_password.message' => '送信したパスワードの初期化の要求。', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko Time Trackerのパスワードの初期化の要求', // TODO: translate the ending of this string. -// TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Older translation is below. -// 'form.reset_password.email_body' => "尊敬なるお客様、\n\n誰から(多分あなた)あなたのAnuko Time Trackerのパスワードの初期化が要求されました。あなたのパスワードを初期化しようとこのリンクを押してください。\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "尊敬なるお客様、\n\n誰から(多分あなた)あなたのAnuko Time Trackerのパスワードの初期化が要求されました。あなたのパスワードを初期化しようとこのリンクを押してください。\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index 6794c57e7..975719ebd 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -461,7 +461,7 @@ 'form.reset_password.message' => '송신한 암호 재설정 요청.', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko Time Tracker 암호 재설정 요청', // TODO: translate the following. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 8b2e557ea..ac8431264 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -397,6 +397,8 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Het verzoek om het wachtwoord te herstellen is verzonden per email.', 'form.reset_password.email_subject' => 'Anuko Time Tracker wachtwoord herstel verzoek', +// TODO: retranslate form.reset_password.email_body as the string has changed. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", 'form.reset_password.email_body' => "Geachte medewerker,\n\nIemand, met IP adres %s, heeft verzocht uw wachtwoord in Anuko Time Tracker te herstellen. Klik op deze link als u uw wachtwoord wil wijzigen.\n\n%s\n\nAnuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem. Bezoek https://www.anuko.com voor meer informatie.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index 77d43637f..eb406d0f9 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -458,8 +458,8 @@ // TODO: translate the following. // 'form.reset_password.message' => 'Password reset request sent by email.', // 'form.reset_password.email_subject' => 'Anuko Time Tracker password reset request', -// TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Kjære bruker,\n\nNoen, IP %s, bad om å få ditt Anuko Time Tracker password resatt. Vær vennlig å besøk denne lenken dersom du ønsker at passordet ditt skal resettes.\n\n%s\n\nAnuko Time Tracker er et enkelt og brukervennlig system for tidsregistrering basert på åpen kildekode. Les mer på https://www.anuko.com.\n\n", diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index b617314db..79952ff56 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -445,9 +445,9 @@ 'form.reset_password.message' => 'Instrukcje zmiany hasła zostały wysłane na adres e-mail połączony z kontem.', 'form.reset_password.email_subject' => 'Anuko Time Tracker - żądanie zmiany hasła', // TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Drogi Użytkowniku,\n\nktoś, IP %s, poprosił o zmianę hasła w aplikacji Anuko Time Tracker. Aby ustawić nowe hasło, proszę kliknąć na poniższy link lub go skopiować i otworzyć w oknie przeglądarki WWW.\n\n%s\n\nJeśli to nie Ty poprosiłeś o zmianę hasła, zignoruj tą wiadomość.\n\nAnuko Time Tracker jest prostym, łatwym w użyciu, otwartoźródłowym systemem do śledzenia czasu. Odwiedź https://www.anuko.com aby uzyskać więcej informacji.\n\n", +'form.reset_password.email_body' => "Drogi Użytkowniku,\n\nktoś, IP %s, poprosił o zmianę hasła w aplikacji Anuko Time Tracker. Aby ustawić nowe hasło, proszę kliknąć na poniższy link lub go skopiować i otworzyć w oknie przeglądarki WWW.\n\n%s\n\nJeśli to nie Ty poprosiłeś o zmianę hasła, zignoruj tą wiadomość.\n\nAnuko Time Tracker jest otwartoźródłowym systemem do śledzenia czasu. Odwiedź https://www.anuko.com aby uzyskać więcej informacji.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Wpisz nowe hasło i kliknij Zapisz.', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index 95e9d1060..9f446ce5f 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -440,9 +440,9 @@ 'form.reset_password.message' => 'Pedido para resetar a senha enviado por e-mail.', 'form.reset_password.email_subject' => 'Pedido de alteração de senha no Anuko Time Tracker', // TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Prezado usuário,\n\nAlguém, IP %s, solicitou o reset da sua senha do Anuko Time Tracker. Entre nete link para resetar a sua senha.\n\n%s\n\nAnuko Time Tracker é um sistema, simples, de fácil uso, de código abertois, de rastreamento do tempo. Visite https://www.anuko.com para mais informações.\n\n", +'form.reset_password.email_body' => "Prezado usuário,\n\nAlguém, IP %s, solicitou o reset da sua senha do Anuko Time Tracker. Entre nete link para resetar a sua senha.\n\n%s\n\nAnuko Time Tracker é um sistema de código abertois, de rastreamento do tempo. Visite https://www.anuko.com para mais informações.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Entre com a nova senha e clique em Salvar.', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index dd72ab4b6..b0ae4794a 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -440,7 +440,7 @@ // TODO: translate the following. // 'form.reset_password.message' => 'Password reset request sent by email.', // 'form.reset_password.email_subject' => 'Anuko Time Tracker password reset request', -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index 55731aa05..2ca785263 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -459,10 +459,10 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Cererea de resetare a parolei a fost trimisa.', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko Time Tracker - cerere de resetare a parolei', -// TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Draga Utilizator,\n\nCineva, IP %s, a cerut resetarea parolei pentru contul Anuko Time Tracker. Te rog, viziteaza acesta legatura daca doresti sa iti resetezi parola.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +'form.reset_password.email_body' => "Draga Utilizator,\n\nCineva, IP %s, a cerut resetarea parolei pentru contul Anuko Time Tracker. Te rog, viziteaza acesta legatura daca doresti sa iti resetezi parola.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index dd6c1e1c8..53cb89b10 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -396,7 +396,7 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Запрос на сброс пароля отослан по e-mail.', 'form.reset_password.email_subject' => 'Сброс пароля к Anuko Time Tracker', -'form.reset_password.email_body' => "Уважаемый пользователь,\n\nКто-то c IP %s попросил сбросить ваш пароль к системе Anuko Time Tracker. Пройдите по данной ссылке для сброса пароля.\n\n%s\n\nAnuko Time Tracker - это открытая (open source), простая и лёгкая в использовании система трекинга рабочего времени. Подробности - на сайте https://www.anuko.com.", +'form.reset_password.email_body' => "Уважаемый пользователь,\n\nКто-то c IP %s попросил сбросить ваш пароль к системе Anuko Time Tracker. Пройдите по данной ссылке для сброса пароля.\n\n%s\n\nAnuko Time Tracker - это открытая (open source) система трекинга рабочего времени. Подробности - на сайте https://www.anuko.com.", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Впечатайте новый пароль и нажмите Cохранить.', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index 95a025a7a..56023db5a 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -449,9 +449,9 @@ 'form.reset_password.message' => 'Žiadosť o obnovenie hesla bola odoslaná e-mailom.', 'form.reset_password.email_subject' => 'Žiadosť o obnovenie hesla do Anuko Time Tracker', // TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Vážený používateľ,\n\nniekto, IP %s, si vyžiadal obnovenie vášho hesla do Anuko Time Tracker. Prosím kliknite na nasledujúcu linku, ak si prajete obnoviť heslo.\n\n%s\n\nAnuko Time Tracker je jednoduchý a ľahko použiteľný systém na sledovanie času s otvoreným zdrojovým kódom. Navštívte https://www.anuko.com pre viac informácií.\n\n", +'form.reset_password.email_body' => "Vážený používateľ,\n\nniekto, IP %s, si vyžiadal obnovenie vášho hesla do Anuko Time Tracker. Prosím kliknite na nasledujúcu linku, ak si prajete obnoviť heslo.\n\n%s\n\nAnuko Time Tracker je systém na sledovanie času s otvoreným zdrojovým kódom. Navštívte https://www.anuko.com pre viac informácií.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Zadajte nové heslo a kliknite na Uložiť.', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index eb8bd99dd..ae6ec81c3 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -432,10 +432,10 @@ 'form.reset_password.message' => 'Zahteva za razveljavitev gesla je bila poslana.', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko Time Tracker zahteva za razveljavitev gesla', // TODO: translate the ending of this string properly. -// TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. "from IP" added. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Spoštovani uporabnik,\n\nNekdo, IP %s, je zahteval razveljavitev vašega Anuko Time Tracker gesla. Prosimo obiščite to povezavo, če želite razveljaviti vaše geslo.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +'form.reset_password.email_body' => "Spoštovani uporabnik,\n\nNekdo, IP %s, je zahteval razveljavitev vašega Anuko Time Tracker gesla. Prosimo obiščite to povezavo, če želite razveljaviti vaše geslo.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index a80f0e67a..abfb0d7bd 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -444,8 +444,8 @@ // Izmena forme za lozinku. Pogledajte primer na https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Zahtev za izmenu lozinke je poslat mejlom.', 'form.reset_password.email_subject' => 'Anuko Time Tracker zahtev za izmenu lozinke', -// TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Poštovani korisniče,\n\nneko, IP %s, ste poslali zahtev za izmenu lozinke na Anuko Time Tracker nalogu. Molimo da pratite link ako želite da izmenite lozinku.\n\n%s\n\nAnuko Time Tracker je jednostavan i lak za korišćenje za praćenje radnog vremena. Posetite nas na https://www.anuko.com za više informacija.\n\n", diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index 6bae583a7..17af93fd8 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -443,8 +443,8 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Begäran om att återställa lösenordet skickades via e-post.', 'form.reset_password.email_subject' => 'Återställning av lösenord för Anuko Time Tracker begärd', -// TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Kära användare,\n\Någon, IP %s, begärde att ditt lösenord för Anuko Time Tracker skulle återställas. Vänligen besök den här länken ifall du vill återställa ditt lösenord.\n\n%s\n\nAnuko Time Tracker är en lättanvänd applikation byggd med öppen källkod som enkelt låter dig spåra och hålla koll på arbetstider. Besök https://www.anuko.com för mer information.\n\n", diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index 3ba51a116..3b98e0a50 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -468,10 +468,10 @@ 'form.reset_password.message' => 'Parola sıfırlama talebi yollandı.', // TODO: add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko Time Tracker parola sıfırlama talebi', // TODO: translate the ending of the following. -// TODO: English string has changed. "from IP" added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Sayın Kullanıcı,\n\nBirisi, IP %s, Anuko Time Tracker parolanızın sıfırlanmasını istedi. Parolanızı sıfırlamak isterseniz lütfen bu bağlantıyı takip edin.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +'form.reset_password.email_body' => "Sayın Kullanıcı,\n\nBirisi, IP %s, Anuko Time Tracker parolanızın sıfırlanmasını istedi. Parolanızı sıfırlamak isterseniz lütfen bu bağlantıyı takip edin.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index 7eb54073a..5500155fc 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -450,7 +450,7 @@ 'form.reset_password.message' => '密码重设请求已经发送。', // TODO: Add "by email" to match the English string. 'form.reset_password.email_subject' => 'Anuko时间追踪器密码重设请求', // TODO: translate the following. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. // TODO: translate the following. diff --git a/initialize.php b/initialize.php index 1f219134f..6384b0dad 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5385"); +define("APP_VERSION", "1.19.23.5386"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ad140616820e9fae649e4adeef3663ddee6e48ea Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Thu, 26 Nov 2020 19:19:45 +0000 Subject: [PATCH 133/587] Minor improvements in translation files. --- WEB-INF/resources/da.lang.php | 2 +- WEB-INF/resources/de.lang.php | 2 +- WEB-INF/resources/es.lang.php | 2 +- WEB-INF/resources/et.lang.php | 2 +- WEB-INF/resources/fr.lang.php | 2 +- WEB-INF/resources/gr.lang.php | 2 +- WEB-INF/resources/he.lang.php | 2 ++ WEB-INF/resources/hu.lang.php | 2 +- WEB-INF/resources/it.lang.php | 8 ++++---- WEB-INF/resources/ja.lang.php | 2 +- WEB-INF/resources/ko.lang.php | 2 +- WEB-INF/resources/nl.lang.php | 2 ++ WEB-INF/resources/no.lang.php | 2 +- WEB-INF/resources/pl.lang.php | 2 +- WEB-INF/resources/pt-br.lang.php | 2 +- WEB-INF/resources/pt.lang.php | 2 +- WEB-INF/resources/ro.lang.php | 2 +- WEB-INF/resources/ru.lang.php | 2 +- WEB-INF/resources/sk.lang.php | 2 +- WEB-INF/resources/sl.lang.php | 2 +- WEB-INF/resources/sr.lang.php | 2 ++ WEB-INF/resources/sv.lang.php | 2 ++ WEB-INF/resources/tr.lang.php | 2 +- WEB-INF/resources/zh-cn.lang.php | 2 +- initialize.php | 2 +- 25 files changed, 32 insertions(+), 24 deletions(-) diff --git a/WEB-INF/resources/da.lang.php b/WEB-INF/resources/da.lang.php index 040405503..efdacc370 100644 --- a/WEB-INF/resources/da.lang.php +++ b/WEB-INF/resources/da.lang.php @@ -436,7 +436,7 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Nulstilling af adgangskode er sendt på email.', 'form.reset_password.email_subject' => 'Anuko Time Tracker - Anmodning om nulstilling af adgangskode', -// TODO: English string has changed. "from IP added. Re-translate the beginning. +// TODO: English string has changed. Re-translate the beginning. // 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Hej\n\nNogen, IP %s, har bedt om at få nulstillet din adgangskode. Tryk på linket hvis du vil have nulstillet din adgangskode.\n\n%s\n\nAnuko Time Tracker er et open source tidsregistrerings system. Besøg https://www.anuko.com for mere information.\n\n", diff --git a/WEB-INF/resources/de.lang.php b/WEB-INF/resources/de.lang.php index 13626d9e6..e41d92b09 100644 --- a/WEB-INF/resources/de.lang.php +++ b/WEB-INF/resources/de.lang.php @@ -580,7 +580,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'An', 'form.mail.report_subject' => 'Time Tracker Bericht', -'form.mail.footer' => 'Anuko Time Tracker ist ein einfaches, leicht zu bedienendes, Open-Source
    Zeitverwaltungs-System. Besuchen Sie www.anuko.com für weitere Informationen.', +'form.mail.footer' => 'Anuko Time Tracker ist ein Open-Source
    Zeitverwaltungs-System. Besuchen Sie www.anuko.com für weitere Informationen.', 'form.mail.report_sent' => 'Der Bericht wurde gesendet.', 'form.mail.invoice_sent' => 'Die Rechnung wurde gesendet.', diff --git a/WEB-INF/resources/es.lang.php b/WEB-INF/resources/es.lang.php index 05c24948c..9df814845 100644 --- a/WEB-INF/resources/es.lang.php +++ b/WEB-INF/resources/es.lang.php @@ -461,7 +461,7 @@ 'form.reset_password.message' => 'Se ha enviado la petición de reestablecer contraseña.', 'form.reset_password.email_subject' => 'Solicitud de reestablecimiento de la contraseña de Anuko Time Tracker', // Note to translators: the ending of this string needs to be translated. -// TODO: English string has changed. "from IP added. Re-translate. +// TODO: English string has changed. Re-translate. // 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. 'form.reset_password.email_body' => "Querido usuario, Alguien, IP %s, solicitó reestablecer su contraseña de Anuko Time Tracker. Por favor visite este enlace si quiere reestablecer su contraseña.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", diff --git a/WEB-INF/resources/et.lang.php b/WEB-INF/resources/et.lang.php index d938cf079..7638ade63 100644 --- a/WEB-INF/resources/et.lang.php +++ b/WEB-INF/resources/et.lang.php @@ -610,7 +610,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Kellele', 'form.mail.report_subject' => 'Time Tracker raport', -'form.mail.footer' => 'Anuko Time Tracker on lihtne, lihtsalt kasutatav ja avatud lähtekoodiga
    ajaarvestussüsteem. Lisainfo saamiseks külastage www.anuko.com lehekülge.', +'form.mail.footer' => 'Anuko Time Tracker on avatud lähtekoodiga
    ajaarvestussüsteem. Lisainfo saamiseks külastage www.anuko.com lehekülge.', 'form.mail.report_sent' => 'Raport on saadetud.', 'form.mail.invoice_sent' => 'Arve on saadetud.', diff --git a/WEB-INF/resources/fr.lang.php b/WEB-INF/resources/fr.lang.php index 3d4845cc0..771ed18e3 100644 --- a/WEB-INF/resources/fr.lang.php +++ b/WEB-INF/resources/fr.lang.php @@ -598,7 +598,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'À', 'form.mail.report_subject' => 'Rapport Time Tracker', -'form.mail.footer' => 'Anuko Time Tracker est un système de gestion du temps, open source, simple et facile à utiliser. Visitez www.anuko.com pour plus d\\\'informations.', +'form.mail.footer' => 'Anuko Time Tracker est un système de gestion du temps, open source. Visitez www.anuko.com pour plus d\\\'informations.', 'form.mail.report_sent' => 'Le rapport a été envoyé.', 'form.mail.invoice_sent' => 'La facture a été envoyée.', diff --git a/WEB-INF/resources/gr.lang.php b/WEB-INF/resources/gr.lang.php index 61b06f6bd..e9003045c 100644 --- a/WEB-INF/resources/gr.lang.php +++ b/WEB-INF/resources/gr.lang.php @@ -590,7 +590,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Προς', 'form.mail.report_subject' => 'Time Tracker αναφορά', -'form.mail.footer' => 'Το Anuko Time Tracker είναι ένα απλό, εύχρηστο, ανοικτού κώδικα σύστημα παρακολούθησης χρόνου. Επισκεφθείτε τη διεύθυνση www.anuko.com για περισσότερες πληροφορίες.', +'form.mail.footer' => 'Το Anuko Time Tracker είναι ένα ανοικτού κώδικα σύστημα παρακολούθησης χρόνου. Επισκεφθείτε τη διεύθυνση www.anuko.com για περισσότερες πληροφορίες.', 'form.mail.report_sent' => 'Η αναφορά στάλθηκε.', 'form.mail.invoice_sent' => 'Το τιμολόγιο στάλθηκε.', diff --git a/WEB-INF/resources/he.lang.php b/WEB-INF/resources/he.lang.php index b8459e8b7..032e01bf0 100644 --- a/WEB-INF/resources/he.lang.php +++ b/WEB-INF/resources/he.lang.php @@ -628,6 +628,8 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'אל', 'form.mail.report_subject' => 'דוח Time Tracker', +// TODO: retranslate form.mail.footer as the English string has changed. +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', 'form.mail.footer' => 'Anuko Time Tracker הינה מערכת פשוטה, קלה לשימוש וחינמית לניהול זמן. בקר באתר www.anuko.com לפרטים נוספים.', 'form.mail.report_sent' => 'הדוח נשלח.', 'form.mail.invoice_sent' => 'החשבונית נשלחה.', diff --git a/WEB-INF/resources/hu.lang.php b/WEB-INF/resources/hu.lang.php index a4fe12023..1909682fb 100644 --- a/WEB-INF/resources/hu.lang.php +++ b/WEB-INF/resources/hu.lang.php @@ -630,7 +630,7 @@ 'form.mail.to' => 'Címzett', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'A számla elküldve.', diff --git a/WEB-INF/resources/it.lang.php b/WEB-INF/resources/it.lang.php index 1b7f56e46..35035d3e9 100644 --- a/WEB-INF/resources/it.lang.php +++ b/WEB-INF/resources/it.lang.php @@ -443,10 +443,10 @@ // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Richiesta di reset password inviata via mail.', 'form.reset_password.email_subject' => 'Richiesta reset password per Anuko Time Tracker', -// TODO: English string has changed. "from IP added. Re-translate the beginning. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is a simple, easy to use, open source time tracking system. Visit https://www.anuko.com for more information.\n\n", +// TODO: English string has changed. Re-translate the beginning. +// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", // "IP %s" probably sounds awkward. -'form.reset_password.email_body' => "Caro utente,\n\n qualcuno, IP %s, ha richiesto di reimpostare la tua password per Anuko Time Tracker. Per favore visita questo link per reimpostare la tua password.\n\n%s\n\nAnuko Time Tracker è un sistema semplice e open source per registrare i tempi di lavoro. Visita https://www.anuko.com per maggiori informazioni.\n\n", +'form.reset_password.email_body' => "Caro utente,\n\n qualcuno, IP %s, ha richiesto di reimpostare la tua password per Anuko Time Tracker. Per favore visita questo link per reimpostare la tua password.\n\n%s\n\nAnuko Time Tracker è un sistema open source per registrare i tempi di lavoro. Visita https://www.anuko.com per maggiori informazioni.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Digita una nuova password e clicca su Salva.', @@ -605,7 +605,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'A', 'form.mail.report_subject' => 'Rapporto Time Tracker', -'form.mail.footer' => 'Anuko Time Tracker è un sistema semplice e open source
    per registrare i tempi di lavoro. Visita www.anuko.com per maggiori informazioni.', +'form.mail.footer' => 'Anuko Time Tracker è un sistema open source
    per registrare i tempi di lavoro. Visita www.anuko.com per maggiori informazioni.', 'form.mail.report_sent' => 'Rapporto inviato.', 'form.mail.invoice_sent' => 'Fattura inviata.', diff --git a/WEB-INF/resources/ja.lang.php b/WEB-INF/resources/ja.lang.php index 07db51091..0ba848ba0 100644 --- a/WEB-INF/resources/ja.lang.php +++ b/WEB-INF/resources/ja.lang.php @@ -633,7 +633,7 @@ 'form.mail.to' => 'まで', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => '送信した送り状。', diff --git a/WEB-INF/resources/ko.lang.php b/WEB-INF/resources/ko.lang.php index 975719ebd..975e42169 100644 --- a/WEB-INF/resources/ko.lang.php +++ b/WEB-INF/resources/ko.lang.php @@ -631,7 +631,7 @@ 'form.mail.to' => '까지', // TODO: is this correct? The meaning is that we send an email TO this person. // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => '송신한 송장.', diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index ac8431264..6d51082c7 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -546,6 +546,8 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Aan', 'form.mail.report_subject' => 'Time Tracker rapport', +// TODO: retranslate form.mail.footer as the English string has changed. +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', 'form.mail.footer' => 'Anuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem. Bezoek www.anuko.com voor meer informatie.', 'form.mail.report_sent' => 'Rapport is verzonden.', 'form.mail.invoice_sent' => 'Factuur is verzonden.', diff --git a/WEB-INF/resources/no.lang.php b/WEB-INF/resources/no.lang.php index eb406d0f9..cfaf305b5 100644 --- a/WEB-INF/resources/no.lang.php +++ b/WEB-INF/resources/no.lang.php @@ -632,7 +632,7 @@ 'form.mail.to' => 'Til', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', // 'form.mail.invoice_sent' => 'Invoice sent.', diff --git a/WEB-INF/resources/pl.lang.php b/WEB-INF/resources/pl.lang.php index 79952ff56..24664d693 100644 --- a/WEB-INF/resources/pl.lang.php +++ b/WEB-INF/resources/pl.lang.php @@ -610,7 +610,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Do', 'form.mail.report_subject' => 'Raport Time Tracker', -'form.mail.footer' => 'Anuko Time Tracker jest prostym, łatwym w użyciu, otwartoźródłowym
    systemem śledzenia czasu. Odwiedź www.anuko.com, aby uzyskać więcej informacji.', +'form.mail.footer' => 'Anuko Time Tracker jest otwartoźródłowym
    systemem śledzenia czasu. Odwiedź www.anuko.com, aby uzyskać więcej informacji.', 'form.mail.report_sent' => 'Wysłano raport', 'form.mail.invoice_sent' => 'Wysłano fakturę', diff --git a/WEB-INF/resources/pt-br.lang.php b/WEB-INF/resources/pt-br.lang.php index 9f446ce5f..e41cf26c3 100644 --- a/WEB-INF/resources/pt-br.lang.php +++ b/WEB-INF/resources/pt-br.lang.php @@ -605,7 +605,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Para', 'form.mail.report_subject' => 'Relatório do Time Tracker', -'form.mail.footer' => 'Anuko Time Tracker é um sistema, simples, de fácil uso, de código aberto,
    de rastreamento do tempo. Visite www.anuko.com para mais informações.', +'form.mail.footer' => 'Anuko Time Tracker é um sistema de código aberto,
    de rastreamento do tempo. Visite www.anuko.com para mais informações.', 'form.mail.report_sent' => 'Relatório enviado.', 'form.mail.invoice_sent' => 'Fatura enviada.', diff --git a/WEB-INF/resources/pt.lang.php b/WEB-INF/resources/pt.lang.php index b0ae4794a..13912a44d 100644 --- a/WEB-INF/resources/pt.lang.php +++ b/WEB-INF/resources/pt.lang.php @@ -612,7 +612,7 @@ 'form.mail.to' => 'Para', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', // 'form.mail.invoice_sent' => 'Invoice sent.', diff --git a/WEB-INF/resources/ro.lang.php b/WEB-INF/resources/ro.lang.php index 2ca785263..0c531ad11 100644 --- a/WEB-INF/resources/ro.lang.php +++ b/WEB-INF/resources/ro.lang.php @@ -633,7 +633,7 @@ 'form.mail.to' => 'Catre', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'Factura trimisa.', diff --git a/WEB-INF/resources/ru.lang.php b/WEB-INF/resources/ru.lang.php index 53cb89b10..835b90048 100644 --- a/WEB-INF/resources/ru.lang.php +++ b/WEB-INF/resources/ru.lang.php @@ -543,7 +543,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Кому', 'form.mail.report_subject' => 'Time Tracker отчёт', -'form.mail.footer' => 'Anuko Time Tracker - это открытая (open source), простая и лёгкая в использовании система трекинга рабочего времени. Подробности на сайте www.anuko.com.', +'form.mail.footer' => 'Anuko Time Tracker - это открытая (open source) система трекинга рабочего времени. Подробности на сайте www.anuko.com.', 'form.mail.report_sent' => 'Отчёт отправлен.', 'form.mail.invoice_sent' => 'Счёт отправлен.', diff --git a/WEB-INF/resources/sk.lang.php b/WEB-INF/resources/sk.lang.php index 56023db5a..57c14a7db 100644 --- a/WEB-INF/resources/sk.lang.php +++ b/WEB-INF/resources/sk.lang.php @@ -615,7 +615,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Komu', 'form.mail.report_subject' => 'Time Tracker zostava', -'form.mail.footer' => 'Anuko Time Tracker je jednoduchý a ľahko použiteľný systém na sledovanie času s otvoreným zdrojovým kódom.
    Navštívte www.anuko.com pre viac informácií.', +'form.mail.footer' => 'Anuko Time Tracker je systém na sledovanie času s otvoreným zdrojovým kódom.
    Navštívte www.anuko.com pre viac informácií.', 'form.mail.report_sent' => 'Zostava odoslaná.', 'form.mail.invoice_sent' => 'Faktúra odoslaná.', diff --git a/WEB-INF/resources/sl.lang.php b/WEB-INF/resources/sl.lang.php index ae6ec81c3..32e200f81 100644 --- a/WEB-INF/resources/sl.lang.php +++ b/WEB-INF/resources/sl.lang.php @@ -606,7 +606,7 @@ 'form.mail.to' => 'Za', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', // 'form.mail.invoice_sent' => 'Invoice sent.', diff --git a/WEB-INF/resources/sr.lang.php b/WEB-INF/resources/sr.lang.php index abfb0d7bd..38cf8565b 100644 --- a/WEB-INF/resources/sr.lang.php +++ b/WEB-INF/resources/sr.lang.php @@ -610,6 +610,8 @@ // Forma mejla. Pogledajte primer na https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Za', 'form.mail.report_subject' => 'Evidencija vremena', +// TODO: retranslate form.mail.footer as the English string has changed. +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', 'form.mail.footer' => 'Anuko Time Tracker je jednostavan i lak za korišćenje za praćenje
    radnog vremena. Posetite www.anuko.com za više informacija.', 'form.mail.report_sent' => 'Izveštaj poslat.', 'form.mail.invoice_sent' => 'Račun poslat.', diff --git a/WEB-INF/resources/sv.lang.php b/WEB-INF/resources/sv.lang.php index 17af93fd8..fe05e89a7 100644 --- a/WEB-INF/resources/sv.lang.php +++ b/WEB-INF/resources/sv.lang.php @@ -609,6 +609,8 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Till', 'form.mail.report_subject' => 'Tidsrapport', +// TODO: retranslate form.mail.footer as the English string has changed. +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', 'form.mail.footer' => 'Anuko Time Tracker är en lättanvänd applikation byggd med öppen källkod för att enkelt spåra och hålla koll på arbetstider. Besök www.anuko.com för mer information.', 'form.mail.report_sent' => 'Rapporten skickades.', 'form.mail.invoice_sent' => 'Fakturan skickades.', diff --git a/WEB-INF/resources/tr.lang.php b/WEB-INF/resources/tr.lang.php index 3b98e0a50..777440e88 100644 --- a/WEB-INF/resources/tr.lang.php +++ b/WEB-INF/resources/tr.lang.php @@ -646,7 +646,7 @@ 'form.mail.to' => 'Kime', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => 'Fatura yollandı.', diff --git a/WEB-INF/resources/zh-cn.lang.php b/WEB-INF/resources/zh-cn.lang.php index 5500155fc..01e639bdd 100644 --- a/WEB-INF/resources/zh-cn.lang.php +++ b/WEB-INF/resources/zh-cn.lang.php @@ -620,7 +620,7 @@ 'form.mail.to' => '到', // TODO: translate the following. // 'form.mail.report_subject' => 'Time Tracker Report', -// 'form.mail.footer' => 'Anuko Time Tracker is a simple, easy to use, open source
    time tracking system. Visit www.anuko.com for more information.', +// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', // 'form.mail.report_sent' => 'Report sent.', 'form.mail.invoice_sent' => '发票已送出。', diff --git a/initialize.php b/initialize.php index 6384b0dad..52148e8b1 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5386"); +define("APP_VERSION", "1.19.23.5387"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 0ac7c8645b11b61d51a1da55685112c8ba7d97b5 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 15:29:40 +0000 Subject: [PATCH 134/587] Added separators on some forms to improve UI. --- WEB-INF/templates/client_add2.tpl | 1 + WEB-INF/templates/client_edit2.tpl | 1 + WEB-INF/templates/project_add2.tpl | 2 ++ WEB-INF/templates/project_edit2.tpl | 2 ++ WEB-INF/templates/task_add2.tpl | 1 + WEB-INF/templates/task_edit2.tpl | 1 + initialize.php | 2 +- 7 files changed, 9 insertions(+), 1 deletion(-) diff --git a/WEB-INF/templates/client_add2.tpl b/WEB-INF/templates/client_add2.tpl index 5fe001b23..2704a133c 100644 --- a/WEB-INF/templates/client_add2.tpl +++ b/WEB-INF/templates/client_add2.tpl @@ -24,6 +24,7 @@ License: See license.txt *} {$i18n.label.required_fields}
    {if $show_projects} +
    {$i18n.label.projects}: {$i18n.label.projects}: diff --git a/WEB-INF/templates/client_edit2.tpl b/WEB-INF/templates/client_edit2.tpl index 91f2b1c39..67b79ecdf 100644 --- a/WEB-INF/templates/client_edit2.tpl +++ b/WEB-INF/templates/client_edit2.tpl @@ -30,6 +30,7 @@ License: See license.txt *} {$i18n.label.required_fields}
    {if $show_projects} +
    {$i18n.label.projects}: {$i18n.label.projects}: diff --git a/WEB-INF/templates/project_add2.tpl b/WEB-INF/templates/project_add2.tpl index 4f2c14286..cd900cf36 100644 --- a/WEB-INF/templates/project_add2.tpl +++ b/WEB-INF/templates/project_add2.tpl @@ -24,6 +24,7 @@ License: See license.txt *}
    {/if} {if $show_users} +
    {$i18n.label.users}: {$i18n.label.users}: @@ -32,6 +33,7 @@ License: See license.txt *}
    {/if} {if $show_tasks} +
    {$i18n.label.tasks}: {$i18n.label.tasks}: diff --git a/WEB-INF/templates/project_edit2.tpl b/WEB-INF/templates/project_edit2.tpl index 8ce9ae9c7..f7b23a9ac 100644 --- a/WEB-INF/templates/project_edit2.tpl +++ b/WEB-INF/templates/project_edit2.tpl @@ -22,6 +22,7 @@ License: See license.txt *}
    {if $show_users} +
    {$i18n.label.users}: {$i18n.label.users}: @@ -30,6 +31,7 @@ License: See license.txt *}
    {/if} {if $show_tasks} +
    {$i18n.label.tasks}: {$i18n.label.tasks}: diff --git a/WEB-INF/templates/task_add2.tpl b/WEB-INF/templates/task_add2.tpl index 534c9525e..1b1c4e42e 100644 --- a/WEB-INF/templates/task_add2.tpl +++ b/WEB-INF/templates/task_add2.tpl @@ -16,6 +16,7 @@ License: See license.txt *}
    {if $show_projects} +
    {$i18n.label.projects}: {$i18n.label.projects}: diff --git a/WEB-INF/templates/task_edit2.tpl b/WEB-INF/templates/task_edit2.tpl index e66a93e10..9292ad151 100644 --- a/WEB-INF/templates/task_edit2.tpl +++ b/WEB-INF/templates/task_edit2.tpl @@ -22,6 +22,7 @@ License: See license.txt *}
    {if $show_projects} +
    {$i18n.label.projects}: {$i18n.label.projects}: diff --git a/initialize.php b/initialize.php index 52148e8b1..2d5f9964d 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5387"); +define("APP_VERSION", "1.19.23.5388"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 1a9ec2adbc3adb32a857f2300ade94da1af8a37f Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 16:19:46 +0000 Subject: [PATCH 135/587] Styles client address field. --- default.css | 4 ++-- initialize.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/default.css b/default.css index 820382bdf..40d085f01 100644 --- a/default.css +++ b/default.css @@ -243,14 +243,14 @@ input[type="file"] { width: 237px; } -#description { +#description, #address { width: 220px; border-radius: 4px; border: 1px solid #c9c9c9; padding: .4rem; } -#description:focus { +#description:focus, #address:focus { background-color: yellow; border: 1px solid black; outline: none; diff --git a/initialize.php b/initialize.php index 2d5f9964d..472e4f37f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5388"); +define("APP_VERSION", "1.19.23.5389"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 706fa5628098a513ab667ed8f3261e89310ad3b1 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 16:25:15 +0000 Subject: [PATCH 136/587] Styled item_name field for expenses. --- default.css | 4 ++-- initialize.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/default.css b/default.css index 40d085f01..fea2e8da5 100644 --- a/default.css +++ b/default.css @@ -243,14 +243,14 @@ input[type="file"] { width: 237px; } -#description, #address { +#description, #address, #item_name { width: 220px; border-radius: 4px; border: 1px solid #c9c9c9; padding: .4rem; } -#description:focus, #address:focus { +#description:focus, #address:focus, #item_name:focus { background-color: yellow; border: 1px solid black; outline: none; diff --git a/initialize.php b/initialize.php index 472e4f37f..837759f2b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5389"); +define("APP_VERSION", "1.19.23.5390"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From fef326c0478e77feff6a5b14dad4450b172e8017 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 16:58:05 +0000 Subject: [PATCH 137/587] Improved x-scrollable-table styles to alternate rows background. --- WEB-INF/templates/entity_files2.tpl | 3 ++- default.css | 6 ++++-- initialize.php | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/WEB-INF/templates/entity_files2.tpl b/WEB-INF/templates/entity_files2.tpl index d6b892b38..07a46443d 100644 --- a/WEB-INF/templates/entity_files2.tpl +++ b/WEB-INF/templates/entity_files2.tpl @@ -23,6 +23,7 @@ License: See license.txt *} {/if} {if $can_edit} +
    {$forms.fileUploadForm.open} @@ -37,8 +38,8 @@ License: See license.txt *} +
    {$forms.fileUploadForm.description.control}
    {$forms.fileUploadForm.btn_submit.control}
    -
    {$forms.fileUploadForm.btn_submit.control}
    {$forms.fileUploadForm.close} {/if} diff --git a/default.css b/default.css index fea2e8da5..8079296aa 100644 --- a/default.css +++ b/default.css @@ -128,8 +128,7 @@ div.page-hint { margin-top: .5rem; margin-left: auto; margin-right: auto; - padding: .5rem; - background-color: #f0f0f0; + border-collapse: collapse; } .x-scrollable-table th { @@ -140,6 +139,9 @@ div.page-hint { padding: .25rem; } +.x-scrollable-table tr:nth-child(even) {background: #ffffff} +.x-scrollable-table tr:nth-child(odd) {background: #f5f5f5} + .text-cell { text-align: left; } diff --git a/initialize.php b/initialize.php index 837759f2b..2cd8198bb 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5390"); +define("APP_VERSION", "1.19.23.5391"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 83fc6da0ea7e7e2ef1e23653e9d442efa303c32e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 18:36:05 +0000 Subject: [PATCH 138/587] Some style fixes for calendar and x-scrollable-table. --- default.css | 5 +++++ initialize.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index 8079296aa..c4f8ac542 100644 --- a/default.css +++ b/default.css @@ -133,6 +133,7 @@ div.page-hint { .x-scrollable-table th { white-space: nowrap; + padding: .25rem; } .x-scrollable-table td { @@ -281,6 +282,10 @@ input[type="file"] { margin-right: auto; } +.small-screen-calendar a:focus, .large-screen-calendar a:focus { + outline: none; +} + .large-screen-calendar { display: block; width: 210px; diff --git a/initialize.php b/initialize.php index 2cd8198bb..627153414 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5391"); +define("APP_VERSION", "1.19.23.5392"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ad9d244216139d0c9e0aec21a00905eb3198a897 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 20:35:20 +0000 Subject: [PATCH 139/587] Fixed an issue with incorrect column span. --- initialize.php | 2 +- time.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/initialize.php b/initialize.php index 627153414..79d1105fe 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5392"); +define("APP_VERSION", "1.19.23.5393"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time.php b/time.php index 27c21d431..6bd10ad53 100644 --- a/time.php +++ b/time.php @@ -86,8 +86,7 @@ } if ($showProject) $colspan++; if ($showTask) $colspan++; - if ($showStart) $colspan++; - if ($showFinish) $colspan++; + if ($showStart) $colspan += 2; // Another for show finish. $colspan++; // There is always a duration. if ($showFiles) $colspan++; $colspan++; // There is always an edit column. From 9d37ef6efab76fa1f94cb7b534f6c31cb2d227f0 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 27 Nov 2020 21:02:08 +0000 Subject: [PATCH 140/587] Improved UI for user pages. --- WEB-INF/templates/user_add2.tpl | 1 + WEB-INF/templates/user_edit2.tpl | 1 + default.css | 4 ++++ initialize.php | 2 +- user_add.php | 1 + user_edit.php | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/WEB-INF/templates/user_add2.tpl b/WEB-INF/templates/user_add2.tpl index ad421b9e8..7413fd2a2 100644 --- a/WEB-INF/templates/user_add2.tpl +++ b/WEB-INF/templates/user_add2.tpl @@ -147,6 +147,7 @@ function handleClientRole() { {if $show_projects} +
    diff --git a/WEB-INF/templates/user_edit2.tpl b/WEB-INF/templates/user_edit2.tpl index 107891777..5adad2e9f 100644 --- a/WEB-INF/templates/user_edit2.tpl +++ b/WEB-INF/templates/user_edit2.tpl @@ -185,6 +185,7 @@ function handleClientRole() { {if $show_projects} +
    diff --git a/default.css b/default.css index c4f8ac542..8159cab08 100644 --- a/default.css +++ b/default.css @@ -234,6 +234,10 @@ input[type="text"] { width: 220px; } +input[type="text"].project-rate-field { + width: 100px; +} + input[type="password"] { width: 220px; } diff --git a/initialize.php b/initialize.php index 79d1105fe..68f36434c 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5393"); +define("APP_VERSION", "1.19.23.5394"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_add.php b/user_add.php index e87fed752..046ecdb87 100644 --- a/user_add.php +++ b/user_add.php @@ -123,6 +123,7 @@ class RateCellRenderer extends DefaultCellRenderer { function render(&$table, $value, $row, $column, $selected = false) { global $assigned_projects; $field = new FloatField('rate_'.$table->getValueAtName($row, 'id')); + $field->setCssClass('project-rate-field'); $field->setFormName($table->getFormName()); $field->setSize(5); $field->setFormat('.2'); diff --git a/user_edit.php b/user_edit.php index 17c8292e3..be0f13e26 100644 --- a/user_edit.php +++ b/user_edit.php @@ -156,6 +156,7 @@ function render(&$table, $value, $row, $column, $selected = false) { global $assigned_projects; $field = new FloatField('rate_'.$table->getValueAtName($row,'id')); + $field->setCssClass('project-rate-field'); $field->setFormName($table->getFormName()); $field->setSize(5); $field->setFormat('.2'); From 26058d1c778fba9ecdbef81453eaf64ed13f3607 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 29 Nov 2020 23:36:30 +0000 Subject: [PATCH 141/587] Improved presentation of project rates table. --- WEB-INF/lib/form/Table.class.php | 9 ++++----- default.css | 6 +++++- initialize.php | 2 +- user_edit.php | 5 +++-- week.php | 3 ++- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/WEB-INF/lib/form/Table.class.php b/WEB-INF/lib/form/Table.class.php index 7bcd78be8..1995b7dea 100644 --- a/WEB-INF/lib/form/Table.class.php +++ b/WEB-INF/lib/form/Table.class.php @@ -47,10 +47,9 @@ class Table extends FormElement { var $mHeaderOptions = array(); var $mProccessed = false; - function __construct($name, $cssClass = null) { + function __construct($name) { $this->class = 'Table'; $this->name = $name; - $this->cssClass = $cssClass; } function setKeyField($value) { @@ -123,15 +122,15 @@ function getHtml() { if ($this->mInteractive) $html .= $this->_addJavaScript(); $html .= "cssClass) { - $html .= " class=\"".$this->cssClass."\""; + if ($this->css_class) { + $html .= " class=\"".$this->css_class."\""; } if (count($this->mTableOptions) > 0) { foreach ($this->mTableOptions as $k=>$v) { $html .= " $k=\"$v\""; } } else { - $html .= " border=\"1\""; + // $html .= " border=\"1\""; } if ($this->mWidth!="") $html .= " width=\"".$this->mWidth."\""; $html .= ">\n"; diff --git a/default.css b/default.css index 8159cab08..2a6b06382 100644 --- a/default.css +++ b/default.css @@ -108,6 +108,10 @@ div.page-hint { margin-top: 1rem; } +.project-rate-table { + width: 300px; +} + .centered-table { margin-top: .5rem; margin-left: auto; @@ -235,7 +239,7 @@ input[type="text"] { } input[type="text"].project-rate-field { - width: 100px; + width: 50px; } input[type="password"] { diff --git a/initialize.php b/initialize.php index 68f36434c..ca81befef 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5394"); +define("APP_VERSION", "1.19.23.5395"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_edit.php b/user_edit.php index be0f13e26..b0868c4e5 100644 --- a/user_edit.php +++ b/user_edit.php @@ -146,7 +146,7 @@ // Define classes for the projects table. class NameCellRenderer extends DefaultCellRenderer { function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200)); + //$this->setOptions(array('width'=>200)); $this->setValue(''); return $this->toString(); } @@ -169,8 +169,9 @@ function render(&$table, $value, $row, $column, $selected = false) { } // Create projects table. $table = new Table('projects'); +$table->setCssClass('project-rate-table'); $table->setIAScript('setRate'); -$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); +//$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); $table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); $table->setData($projects); $table->setKeyField('id'); diff --git a/week.php b/week.php index d86e0c99c..fee395d66 100644 --- a/week.php +++ b/week.php @@ -275,7 +275,8 @@ function render(&$table, $value, $row, $column, $selected = false) { } // Create week_durations table. -$table = new Table('week_durations', 'week_view_table'); +$table = new Table('week_durations'); +// $table->setCssClass('week_view_table'); // Currently not used. Fix this. $table->setTableOptions(array('width'=>'100%','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); $table->setRowOptions(array('class'=>'tableHeaderCentered')); $table->setData($dataArray); From 374853526cac28b5b38fc96638601eb550058564 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 1 Dec 2020 18:23:14 +0000 Subject: [PATCH 142/587] Resuming work on styles. --- WEB-INF/lib/form/Table.class.php | 3 +-- initialize.php | 2 +- user_edit.php | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/WEB-INF/lib/form/Table.class.php b/WEB-INF/lib/form/Table.class.php index 1995b7dea..c83d90bd8 100644 --- a/WEB-INF/lib/form/Table.class.php +++ b/WEB-INF/lib/form/Table.class.php @@ -129,9 +129,8 @@ function getHtml() { foreach ($this->mTableOptions as $k=>$v) { $html .= " $k=\"$v\""; } - } else { - // $html .= " border=\"1\""; } + if ($this->mWidth!="") $html .= " width=\"".$this->mWidth."\""; $html .= ">\n"; diff --git a/initialize.php b/initialize.php index ca81befef..daa1b0522 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5395"); +define("APP_VERSION", "1.19.23.5396"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_edit.php b/user_edit.php index b0868c4e5..c270243ad 100644 --- a/user_edit.php +++ b/user_edit.php @@ -171,8 +171,6 @@ function render(&$table, $value, $row, $column, $selected = false) { $table = new Table('projects'); $table->setCssClass('project-rate-table'); $table->setIAScript('setRate'); -//$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); $table->setData($projects); $table->setKeyField('id'); $table->setValue($cl_projects); From 5d1667d8de0bf0583234d750d2123f5c40962246 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 1 Dec 2020 18:33:13 +0000 Subject: [PATCH 143/587] Improved styles on user_add.php. --- default.css | 5 +++++ initialize.php | 2 +- user_add.php | 4 +--- user_edit.php | 2 -- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/default.css b/default.css index 2a6b06382..2aa8335f8 100644 --- a/default.css +++ b/default.css @@ -110,6 +110,11 @@ div.page-hint { .project-rate-table { width: 300px; + border-collapse: collapse; +} + +.project-rate-table td { + padding: .2rem; } .centered-table { diff --git a/initialize.php b/initialize.php index daa1b0522..aced0690c 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5396"); +define("APP_VERSION", "1.19.23.5397"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/user_add.php b/user_add.php index 046ecdb87..7b7b72ed8 100644 --- a/user_add.php +++ b/user_add.php @@ -114,7 +114,6 @@ // Define classes for the projects table. class NameCellRenderer extends DefaultCellRenderer { function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200)); $this->setValue(''); return $this->toString(); } @@ -136,9 +135,8 @@ function render(&$table, $value, $row, $column, $selected = false) { } // Create projects table. $table = new Table('projects'); +$table->setCssClass('project-rate-table'); $table->setIAScript('setDefaultRate'); -$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); $table->setData($projects); $table->setKeyField('id'); $table->setValue($cl_projects); diff --git a/user_edit.php b/user_edit.php index c270243ad..b1f1e65e2 100644 --- a/user_edit.php +++ b/user_edit.php @@ -146,7 +146,6 @@ // Define classes for the projects table. class NameCellRenderer extends DefaultCellRenderer { function render(&$table, $value, $row, $column, $selected = false) { - //$this->setOptions(array('width'=>200)); $this->setValue(''); return $this->toString(); } @@ -154,7 +153,6 @@ function render(&$table, $value, $row, $column, $selected = false) { class RateCellRenderer extends DefaultCellRenderer { function render(&$table, $value, $row, $column, $selected = false) { global $assigned_projects; - $field = new FloatField('rate_'.$table->getValueAtName($row,'id')); $field->setCssClass('project-rate-field'); $field->setFormName($table->getFormName()); From 529edc11b2f3476cae0a976ff40bdd5b62e4cbd2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 1 Dec 2020 22:03:35 +0000 Subject: [PATCH 144/587] Some cleanup and commenting in css. --- WEB-INF/templates/charts2.tpl | 4 +- default.css | 92 ++++++++++++++++++++++------------- initialize.php | 2 +- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/WEB-INF/templates/charts2.tpl b/WEB-INF/templates/charts2.tpl index 7f4c3844a..6e9f1756d 100644 --- a/WEB-INF/templates/charts2.tpl +++ b/WEB-INF/templates/charts2.tpl @@ -53,7 +53,7 @@ function adjustTodayLinks() { -
    + {section name=i loop=$totals} {if $smarty.section.i.index <= 12} @@ -68,7 +68,7 @@ function adjustTodayLinks() {
    -
    + {section name=i loop=$totals} {if $smarty.section.i.index <= 12} diff --git a/default.css b/default.css index 2aa8335f8..2262acf67 100644 --- a/default.css +++ b/default.css @@ -8,57 +8,53 @@ body { background-color: white; } +/* logo on top of pages */ div.logo { padding: .5rem; text-align: center; background-color: #a6ccf7; } +/* top menu bar for large screens */ div.top-menu-large-screen { background-color: black; display: block; } -.top-submenu-large-screen { +/* submenu for large screens */ +div.top-submenu-large-screen { background-color: #d9d9d9; display: block; } +/* top menu for small screens */ div.top-menu-small-screen { background-color: black; display: none; } -div.top-menu-small-screen a { +/* top menu items */ +div.top-menu-large-screen a, div.top-menu-small-screen a { font-size: 1rem; font-weight: bold; color: white; margin: .1rem .2rem .1rem .2rem; } -div.top-menu-large-screen a { - font-size: 1rem; - font-weight: bold; - color: white; - margin: .1rem .2rem .1rem .2rem; -} - -.top-menu-table { - margin-left: auto; - margin-right: auto; -} - -.top-submenu-table { +/* top menu tables */ +.top-menu-table, .top-submenu-table { margin-left: auto; margin-right: auto; } +/* top submenu items */ .top-submenu-large-screen a { font-size: 1rem; color: #444444; margin: .1rem .2rem .1rem .2rem; } +/* page title div */ div.page-title { font-size: 12pt; font-weight: bold; @@ -69,45 +65,60 @@ div.page-title { margin-bottom: .2rem; } +/* user details div */ div.user-details { text-align: center; padding: .2rem; } +/* page errors div */ .page-errors { margin-top: .5rem; text-align: center; color: red; } +/* page messages div */ .page-messages { margin-top: .5rem; text-align: center; color: blue; } +/* page content div */ .page-content { text-align: center; } +/* vertical separator for controls on forms for both large and small screens */ .form-control-separator { height: .5rem; } +/* vertical separator for controls on small screens */ +.small-screen-form-control-separator { + height: .25rem; + display: none; +} + +/* "about" text div on login page */ div#LoginAboutText { padding: 1rem; margin-left:auto; margin-right:auto; } +/* default domain text div for ldap login */ #ldapDefaultDomain { color: #777777; } +/* page hint div to display on top of some pages to clarify things */ div.page-hint { margin-top: 1rem; } +/* project rate table for user add and user edit pages */ .project-rate-table { width: 300px; border-collapse: collapse; @@ -117,21 +128,15 @@ div.page-hint { padding: .2rem; } +/* a table to display controls centered horizontally */ .centered-table { + display: inline-block; margin-top: .5rem; margin-left: auto; margin-right: auto; - display: inline-block; -} - -.chart-list { - border-spacing: .2rem; -} - -.record-list { - margin: 1rem; } +/* a table to hold things that may not fit into available screen width */ .x-scrollable-table { display: inline-block; margin-top: .5rem; @@ -152,40 +157,59 @@ div.page-hint { .x-scrollable-table tr:nth-child(even) {background: #ffffff} .x-scrollable-table tr:nth-child(odd) {background: #f5f5f5} +/* a text cell in tables */ .text-cell { text-align: left; } +/* time cell in tables */ .time-cell { text-align: right; } +/* text cell for note header when we display notes on separate rows */ .note-header-cell { text-align: right; } +/* control labels for large screens */ .large-screen-label { text-align: right; vertical-align: middle; display: table-cell; } -.large-screen-chart-list { +/* control labels for small screens */ +.small-screen-label { + text-align: left; + display: none; +} + +/* list of items displayed in a chart on large screens */ +.large-screen-chart-items-list { display: table-cell; } -.small-screen-chart-list { +/* list of items displayed in a chart on small screens */ +.small-screen-chart-items-list { display: none; } -.small-screen-label { - text-align: left; - display: none; +/* a div to display a chart in */ +div.chart { + padding-left: 1rem; + padding-right: 1rem; } -.small-screen-form-control-separator { - height: .25rem; - display: none; + + +/* TODO: work in progress below... */ +.chart-list { + border-spacing: .2rem; +} + +.record-list { + margin: 1rem; } .page-content input { @@ -393,11 +417,11 @@ input[type="file"] { display: none; } - .large-screen-chart-list { + .large-screen-chart-items-list { display: none; } - .small-screen-chart-list { + .small-screen-chart-items-list { display: table-cell; } diff --git a/initialize.php b/initialize.php index aced0690c..c33acb839 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5397"); +define("APP_VERSION", "1.19.23.5398"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 13bc4e28d73abdc10b4c02f264161719b6bc7866 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 2 Dec 2020 18:32:30 +0000 Subject: [PATCH 145/587] Some cleanup and commenting in styles. --- WEB-INF/templates/charts2.tpl | 4 ++-- default.css | 10 ++++++---- initialize.php | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/WEB-INF/templates/charts2.tpl b/WEB-INF/templates/charts2.tpl index 6e9f1756d..ff15ea8f2 100644 --- a/WEB-INF/templates/charts2.tpl +++ b/WEB-INF/templates/charts2.tpl @@ -54,7 +54,7 @@ function adjustTodayLinks() {
    - +
    {section name=i loop=$totals} {if $smarty.section.i.index <= 12} @@ -69,7 +69,7 @@ function adjustTodayLinks() {
    {$totals[i].name|escape}
    - +
    {section name=i loop=$totals} {if $smarty.section.i.index <= 12} diff --git a/default.css b/default.css index 2262acf67..518f200db 100644 --- a/default.css +++ b/default.css @@ -145,15 +145,18 @@ div.page-hint { border-collapse: collapse; } +/* th in x-scrollable-table */ .x-scrollable-table th { white-space: nowrap; padding: .25rem; } +/* td in x-scrollable-table */ .x-scrollable-table td { padding: .25rem; } +/* alternating row background in x-scrollable-table */ .x-scrollable-table tr:nth-child(even) {background: #ffffff} .x-scrollable-table tr:nth-child(odd) {background: #f5f5f5} @@ -201,13 +204,12 @@ div.chart { padding-right: 1rem; } - - -/* TODO: work in progress below... */ -.chart-list { +/* a table to annotate items from chart picture */ +.chart-items-list-table { border-spacing: .2rem; } +/* TODO: work in progress below */ .record-list { margin: 1rem; } diff --git a/initialize.php b/initialize.php index c33acb839..0f49c474f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5398"); +define("APP_VERSION", "1.19.23.5399"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 000093299c75e46866bcccc6fd42a4092dd8a0ef Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 15:22:32 +0000 Subject: [PATCH 146/587] Put some more comments in default.css. --- default.css | 26 ++++++++++++++++++-------- initialize.php | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/default.css b/default.css index 518f200db..619426ef1 100644 --- a/default.css +++ b/default.css @@ -209,38 +209,48 @@ div.chart { border-spacing: .2rem; } -/* TODO: work in progress below */ -.record-list { +/* a div to display a list of records in */ +div.record-list { margin: 1rem; } +/* input controls */ .page-content input { border-radius: 4px; border: 1px solid #c9c9c9; padding: .4rem; } -.td-with-input { - text-align: left; -} - +/* input controls with focus on them */ .page-content input:focus { background-color: yellow; border: 1px solid black; outline: none; } -.contribute-msg { +/* a table cell containing input control */ +.td-with-input { + text-align: left; +} + +/* div containing how to contribute message */ +div.contribute-msg { text-align: center; margin-top: 2rem; padding: .2rem; background-color: #eeeeee; } -.version-and-copyright { + +/* div containing app version and copyright info */ +div.version-and-copyright { text-align: center; padding: .5rem; } + + + +/* TODO: work in progress below */ .centered-table td img { vertical-align: middle; } diff --git a/initialize.php b/initialize.php index 0f49c474f..82cc5d7df 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5399"); +define("APP_VERSION", "1.19.23.5400"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 82fa8f93e9a8c5cffd16db0303b9ca18ec6cd25b Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 16:59:01 +0000 Subject: [PATCH 147/587] Added more comments in default.css. --- default.css | 131 ++++++++++++++++++++++++++++++------------------- initialize.php | 2 +- 2 files changed, 82 insertions(+), 51 deletions(-) diff --git a/default.css b/default.css index 619426ef1..30160902b 100644 --- a/default.css +++ b/default.css @@ -247,82 +247,95 @@ div.version-and-copyright { padding: .5rem; } - - - -/* TODO: work in progress below */ +/* img in td in centered-table, ex: now icons */ .centered-table td img { vertical-align: middle; } -.what-is-it-img { +/* span for what is it icon image */ +span.what-is-it-img { display: none; } -.what-is-it-text { +/* span for what is it text */ +span.what-is-it-text { display: inline-block; } -input[type="submit"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} - -input[type="button"] { +/* buttons */ +input[type="submit"], input[type="button"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; } -input[type="text"] { +/* input controls */ +input[type="text"], input[type="password"], input[type="file"] { width: 220px; } +/* project rate input control */ input[type="text"].project-rate-field { width: 50px; } -input[type="password"] { - width: 220px; +/* dropdown control */ +.dropdown-field { + width: 236px; } -input[type="file"] { +/* textareas for fields */ +#description, #address, #item_name { width: 220px; + border-radius: 4px; + border: 1px solid #c9c9c9; + padding: .4rem; } -.dropdown-field { - width: 237px; +/* textareas with focus */ +#description:focus, #address:focus, #item_name:focus { + background-color: yellow; + border: 1px solid black; + outline: none; } -#description, #address, #item_name { - width: 220px; +/* textarea for note field */ +#note { + width: 100%; + margin: 0; + height: 4rem; + resize: none; border-radius: 4px; border: 1px solid #c9c9c9; padding: .4rem; } -#description:focus, #address:focus, #item_name:focus { +/* note field with focus */ +#note:focus { background-color: yellow; border: 1px solid black; outline: none; } +/* chart image */ .chart-image { width: 300px; height: 300px; } +/* chart color cell for annotations */ .chart-color-cell { width: .4rem; height: 1rem; } +/* chart description cell for annotations */ .chart-description-cell { text-align: left; padding-left: .25rem; } +/* calendar for small screens */ .small-screen-calendar { display: none; width: 210px; @@ -331,10 +344,12 @@ input[type="file"] { margin-right: auto; } +/* calendars with focus */ .small-screen-calendar a:focus, .large-screen-calendar a:focus { outline: none; } +/* calendar for large screens */ .large-screen-calendar { display: block; width: 210px; @@ -342,143 +357,159 @@ input[type="file"] { margin-top: 1rem; } +/* label for checkboxes */ .checkbox-label { float: left; } -#note { - width: 100%; - margin: 0; - height: 4rem; - resize: none; - border-radius: 4px; - border: 1px solid #c9c9c9; - padding: .4rem; -} - -#note:focus { - background-color: yellow; - border: 1px solid black; - outline: none; -} - -.day-totals { +/* div for day totals */ +div.day-totals { margin-bottom: 1rem; + width: 100%; } +/* column 1 for day totals */ .day-totals-col1 { text-align: left; padding-left: .5rem; padding-right: .5rem; } +/* column 2 for day totals */ .day-totals-col2 { padding-left: .5rem; padding-right: .5rem; text-align: right; } +/* not billable items */ .not-billable { - color: #ff6666; + color: red; } -.remaining-quota { +/* remaining quota span */ +span.remaining-quota { color: red; } -.remaining-quota-balance { +/* remaining quota balance span */ +span.remaining-quota-balance { color: red; } -.over-quota { +/* over quota span */ +span.over-quota { color: green; } -.over-quota-balance { +/* over quota balance span */ +span.over-quota-balance { color: green; } -.optional-nav { +/* div for optional navigation, ex: week view */ +div.optional-nav { margin-top: .5rem; } +/* div for a set of buttons, ex: save, copy, delete */ .button-set { margin-top: .5rem; margin-bottom: 1rem; } -.section-header { +/* section header div */ +div.section-header { font-weight: bold; text-align: center; margin-left: auto; margin-right: auto; } -.sitemap-item-group { +/* div for a group of items in site map */ +div.sitemap-item-group { margin-top: 2rem; margin-bottom: 2rem; } -.sitemap-item { +/* div for a single item in site map */ +div.sitemap-item { margin: .4rem; } +/* media rules for small screens */ @media screen and (max-width: 600px) { + /* hide large screen labels */ .large-screen-label { display: none; } + /* hide large screen chart annotations */ .large-screen-chart-items-list { display: none; } + /* show small screen chart annotations */ .small-screen-chart-items-list { display: table-cell; } + /* show small screen labels */ .small-screen-label { display: block; } + /* show small screen calendar */ .small-screen-calendar { display: block; } + /* hide large screen calendar */ .large-screen-calendar { display: none; } + /* show small screen form control separators */ .small-screen-form-control-separator { display: block; } - .what-is-it-img { + /* show what is it icons */ + span.what-is-it-img { display: inline-block; } - .what-is-it-text { + /* hide what is it text */ + span.what-is-it-text { display: none; } + /* hide how to contribute message */ div.contribute-msg { display: none; } + /* hide version and copyright */ div.version-and-copyright { display: none; } } +/* media rules for menus on small screens */ @media screen and (max-width: 1170px) { + + /* show small screen menu */ div.top-menu-small-screen { display: block; } + /* hide large screen menu */ div.top-menu-large-screen { display: none; } + /* hide large screen submenu */ div.top-submenu-large-screen { display: none; } diff --git a/initialize.php b/initialize.php index 82cc5d7df..2978e7a1b 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5400"); +define("APP_VERSION", "1.19.23.5401"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 05988b6d9bf9be8fc5f64f55cc9c61e602058638 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 17:43:38 +0000 Subject: [PATCH 148/587] Removed no longer used files. --- charts1.php | 227 -------------------- clients1.php | 55 ----- default.css | 4 - expense_delete1.php | 88 -------- expense_edit1.php | 243 --------------------- expenses1.php | 251 ---------------------- initialize.php | 2 +- project_add1.php | 118 ----------- project_edit1.php | 136 ------------ projects1.php | 58 ----- task_add1.php | 89 -------- task_edit1.php | 122 ----------- tasks1.php | 77 ------- time1.php | 506 -------------------------------------------- user_add1.php | 244 --------------------- user_edit1.php | 308 --------------------------- users1.php | 69 ------ 17 files changed, 1 insertion(+), 2596 deletions(-) delete mode 100644 charts1.php delete mode 100644 clients1.php delete mode 100644 expense_delete1.php delete mode 100644 expense_edit1.php delete mode 100644 expenses1.php delete mode 100644 project_add1.php delete mode 100644 project_edit1.php delete mode 100644 projects1.php delete mode 100644 task_add1.php delete mode 100644 task_edit1.php delete mode 100644 tasks1.php delete mode 100644 time1.php delete mode 100644 user_add1.php delete mode 100644 user_edit1.php delete mode 100644 users1.php diff --git a/charts1.php b/charts1.php deleted file mode 100644 index 3b4ce15a1..000000000 --- a/charts1.php +++ /dev/null @@ -1,227 +0,0 @@ -isPluginEnabled('ch')) { - header('Location: feature_disabled.php'); - exit(); -} -if (!$user->exists()) { - header('Location: access_denied.php'); // Nobody to display a chart for. - exit(); -} -if ($user->behalf_id && (!$user->can('view_charts') || !$user->checkBehalfId())) { - header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. - exit(); -} -if (!$user->behalf_id && !$user->can('view_own_charts') && !$user->adjustBehalfId()) { - header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to view on behalf. - exit(); -} -if ($request->isPost() && $request->getParameter('user')) { - if (!$user->isUserValid($request->getParameter('user'))) { - header('Location: access_denied.php'); // Wrong user id on post. - exit(); - } -} -// End of access checks. - -// Determine user for which we display this page. -$userChanged = $request->getParameter('user_changed'); -if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); - $user->setOnBehalfUser($user_id); -} else { - $user_id = $user->getUser(); -} - -$uc = new ttUserConfig(); -$tracking_mode = $user->getTrackingMode(); - -// Initialize and store date in session. -$cl_date = $request->getParameter('date', @$_SESSION['date']); -if(!$cl_date) { - $now = new DateAndTime(DB_DATEFORMAT); - $cl_date = $now->toString(DB_DATEFORMAT); -} -$_SESSION['date'] = $cl_date; - -if ($request->isPost()) { - $cl_interval = $request->getParameter('interval'); - if (!$cl_interval) $cl_interval = INTERVAL_THIS_MONTH; - $_SESSION['chart_interval'] = $cl_interval; - $uc->setValue(SYSC_CHART_INTERVAL, $cl_interval); - - $cl_type = $request->getParameter('type'); - if (!$cl_type) $cl_type = ttChartHelper::adjustType($cl_type); - $_SESSION['chart_type'] = $cl_type; - $uc->setValue(SYSC_CHART_TYPE, $cl_type); -} else { - // Initialize chart interval. - $cl_interval = $_SESSION['chart_interval']; - if (!$cl_interval) $cl_interval = $uc->getValue(SYSC_CHART_INTERVAL); - if (!$cl_interval) $cl_interval = INTERVAL_THIS_MONTH; - $_SESSION['chart_interval'] = $cl_interval; - - // Initialize chart type. - $cl_type = $_SESSION['chart_type']; - if (!$cl_type) $cl_type = $uc->getValue(SYSC_CHART_TYPE); - $cl_type = ttChartHelper::adjustType($cl_type); - $_SESSION['chart_type'] = $cl_type; -} - -// Elements of chartForm. -$chart_form = new Form('chartForm'); - -// User dropdown. Changes the user "on behalf" of whom we are working. -if ($user->can('view_charts')) { - $rank = $user->getMaxRankForGroup($user->getGroup()); - if ($user->can('view_own_charts')) - $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); - else - $options = array('status'=>ACTIVE,'max_rank'=>$rank); - $user_list = $user->getUsers($options); - if (count($user_list) >= 1) { - $chart_form->addInput(array('type'=>'combobox', - 'onchange'=>'this.form.user_changed.value=1;this.form.submit();', - 'name'=>'user', - 'value'=>$user_id, - 'data'=>$user_list, - 'datakeys'=>array('id','name'), - )); - $chart_form->addInput(array('type'=>'hidden','name'=>'user_changed')); - $smarty->assign('user_dropdown', 1); - } -} - -// Chart interval options. -$intervals = array(); -$intervals[INTERVAL_THIS_DAY] = $i18n->get('dropdown.selected_day'); -$intervals[INTERVAL_THIS_WEEK] = $i18n->get('dropdown.selected_week'); -$intervals[INTERVAL_THIS_MONTH] = $i18n->get('dropdown.selected_month'); -$intervals[INTERVAL_THIS_YEAR] = $i18n->get('dropdown.selected_year'); -$intervals[INTERVAL_ALL_TIME] = $i18n->get('dropdown.all_time'); - -// Chart interval dropdown. -$chart_form->addInput(array('type' => 'combobox', - 'onchange' => 'this.form.submit();', - 'name' => 'interval', - 'value' => $cl_interval, - 'data' => $intervals -)); - -// Chart type options. -$chart_selector = (MODE_PROJECTS_AND_TASKS == $tracking_mode || $user->isPluginEnabled('cl')); -if ($chart_selector) { - $types = array(); - if (MODE_PROJECTS == $tracking_mode || MODE_PROJECTS_AND_TASKS == $tracking_mode) - $types[CHART_PROJECTS] = $i18n->get('dropdown.projects'); - if (MODE_PROJECTS_AND_TASKS == $tracking_mode) - $types[CHART_TASKS] = $i18n->get('dropdown.tasks'); - if ($user->isPluginEnabled('cl')) - $types[CHART_CLIENTS] = $i18n->get('dropdown.clients'); - - // Add chart type dropdown. - $chart_form->addInput(array('type' => 'combobox', - 'onchange' => 'this.form.submit();', - 'name' => 'type', - 'value' => $cl_type, - 'data' => $types - )); -} - -// Calendar. -$chart_form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar - -// Get data for our chart. -$totals = ttChartHelper::getTotals($user_id, $cl_type, $cl_date, $cl_interval); -$smarty->assign('totals', $totals); - -// Prepare chart for drawing. -/* - * We use libchart.php library to draw chart images. It can draw chart labels, too (embed in the image). - * But quality of such auto-scaled text is not good. Therefore, we only use libchart to draw a pie-chart picture with - * auto-calculated percentage markers around it. We print labels (to the side of the picture) ourselves, - * using the same colors libchart is using. For labels printout, the $totals array (which is used for picture points) - * is also passed to charts.tpl Smarty template. - * - * To make all of the above possible with only one database call to obtain $totals we have to print the chart image - * to a file here (see code below). Once the image is available as a .png file, the charts.tpl can render it. - * - * PieChartEx class is a little extension to libchart-provided PieChart class. It allows us to print the chart - * without title, logo, and labels. - */ -$chart = new PieChartEx(300, 300); -$data_set = new XYDataSet(); -foreach($totals as $total) { - $data_set->addPoint(new Point( $total['name'], $total['time'])); -} -$chart->setDataSet($data_set); - -// Prepare a file name. -$img_dir = TEMPLATE_DIR.'_c/'; // Directory. -$file_name = uniqid('chart_').'.png'; // Short file name. Unique ID here is to avoid problems with browser caching. -$img_ref = 'WEB-INF/templates_c/'.$file_name; // Image reference for html. -$file_name = $img_dir.$file_name; // Full file name. - -// Clean up the file system from older images. -$img_files = glob($img_dir.'chart_*.png'); -if (is_array($img_files)) { - foreach($img_files as $file) { - // If file creation time is older than 1 minute, delete it. - if (filemtime($file) < (time() - 60)) { - unlink($file); - } - } -} - -// Write chart image to file system. -$chart->renderEx(array('fileName'=>$file_name,'hideLogo'=>true,'hideTitle'=>true,'hideLabel'=>true)); -// At this point libchart usage is complete and we have chart image on disk. - -$smarty->assign('img_file_name', $img_ref); -$smarty->assign('chart_selector', $chart_selector); -$smarty->assign('forms', array($chart_form->getName() => $chart_form->toArray())); -$smarty->assign('title', $i18n->get('title.charts')); -$smarty->assign('content_page_name', 'charts.tpl'); -$smarty->display('index.tpl'); diff --git a/clients1.php b/clients1.php deleted file mode 100644 index a299d3061..000000000 --- a/clients1.php +++ /dev/null @@ -1,55 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -if($user->can('manage_clients')) { - $active_clients = ttGroupHelper::getActiveClients(true); - $inactive_clients = ttGroupHelper::getInactiveClients(true); -} else - $active_clients = $user->getAssignedClients(); - -$smarty->assign('active_clients', $active_clients); -$smarty->assign('inactive_clients', $inactive_clients); -$smarty->assign('title', $i18n->get('title.clients')); -$smarty->assign('content_page_name', 'clients.tpl'); -$smarty->display('index.tpl'); diff --git a/default.css b/default.css index 30160902b..595967e64 100644 --- a/default.css +++ b/default.css @@ -515,10 +515,6 @@ div.sitemap-item { } } - - - - /* TODO: below are legacy styles. Review as work on mobile-friendly pages continues. */ a { color: blue; text-decoration: none; } diff --git a/expense_delete1.php b/expense_delete1.php deleted file mode 100644 index 788fb59fa..000000000 --- a/expense_delete1.php +++ /dev/null @@ -1,88 +0,0 @@ -isPluginEnabled('ex')) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_id = (int)$request->getParameter('id'); -// Get the expense item we are deleting. -$expense_item = ttExpenseHelper::getItem($cl_id); -if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { - // Prohibit deleting not ours, approved, or invoiced items. - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -if ($request->isPost()) { - if ($request->getParameter('delete_button')) { // Delete button pressed. - - // Determine if it is okay to delete the record. - $item_date = new DateAndTime(DB_DATEFORMAT, $expense_item['date']); - if ($user->isDateLocked($item_date)) - $err->add($i18n->get('error.range_locked')); - - if ($err->no()) { - // Mark the record as deleted. - if (ttExpenseHelper::markDeleted($cl_id)) { - header('Location: expenses.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } - } - if ($request->getParameter('cancel_button')) { // Cancel button pressed. - header('Location: expenses.php'); - exit(); - } -} // isPost - -$form = new Form('expenseItemForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'submit','name'=>'delete_button','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'cancel_button','value'=>$i18n->get('button.cancel'))); - -$show_project = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); - -$smarty->assign('forms', array($form->getName() => $form->toArray())); -$smarty->assign('expense_item', $expense_item); -$smarty->assign('show_project', $show_project); -$smarty->assign('title', $i18n->get('title.delete_expense')); -$smarty->assign('content_page_name', 'expense_delete.tpl'); -$smarty->display('index.tpl'); diff --git a/expense_edit1.php b/expense_edit1.php deleted file mode 100644 index d8b452d56..000000000 --- a/expense_edit1.php +++ /dev/null @@ -1,243 +0,0 @@ -isPluginEnabled('ex')) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_id = (int)$request->getParameter('id'); -// Get the expense item we are editing. -$expense_item = ttExpenseHelper::getItem($cl_id); -if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { - // Prohibit editing not ours, approved, or invoiced items. - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$item_date = new DateAndTime(DB_DATEFORMAT, $expense_item['date']); -$confirm_save = $user->getConfigOption('confirm_save'); -$trackingMode = $user->getTrackingMode(); -$show_project = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; - -// Initialize variables. -$cl_date = $cl_client = $cl_project = $cl_item_name = $cl_cost = null; -if ($request->isPost()) { - $cl_date = trim($request->getParameter('date')); - $cl_client = $request->getParameter('client'); - $cl_project = $request->getParameter('project'); - $cl_item_name = trim($request->getParameter('item_name')); - $cl_cost = trim($request->getParameter('cost')); - if ($user->isPluginEnabled('ps')) - $cl_paid = $request->getParameter('paid'); -} else { - $cl_date = $item_date->toString($user->getDateFormat()); - $cl_client = $expense_item['client_id']; - $cl_project = $expense_item['project_id']; - $cl_item_name = $expense_item['name']; - $cl_cost = $expense_item['cost']; - $cl_paid = $expense_item['paid']; -} - -// Initialize elements of 'expenseItemForm'. -$form = new Form('expenseItemForm'); - -// Dropdown for clients in MODE_TIME. Use all active clients. -if (MODE_TIME == $trackingMode && $user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$active_clients, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - // Note: in other modes the client list is filtered to relevant clients only. See below. -} - -if ($show_project) { - // Dropdown for projects assigned to user. - $project_list = $user->getAssignedProjects(); - $form->addInput(array('type'=>'combobox', - 'name'=>'project', - 'style'=>'width: 250px;', - 'value'=>$cl_project, - 'data'=>$project_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - - // Dropdown for clients if the clients plugin is enabled. - if ($user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. - foreach($project_list as $project) - $projects_assigned_to_user[] = $project['id']; - - // Build a client list out of active clients. Use only clients that are relevant to user. - // Also trim their associated project list to only assigned projects (to user). - foreach($active_clients as $client) { - $projects_assigned_to_client = explode(',', $client['projects']); - $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); - if ($intersection) { - $client['projects'] = implode(',', $intersection); - $client_list[] = $client; - } - } - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$client_list, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } -} -// If predefined expenses are configured, add controls to select an expense and quantity. -$predefined_expenses = ttGroupHelper::getPredefinedExpenses(); -if ($predefined_expenses) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'recalculateCost();', - 'name'=>'predefined_expense', - 'style'=>'width: 250px;', - 'value'=>$cl_predefined_expense, - 'data'=>$predefined_expenses, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); -} -$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','style'=>'width: 250px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_item_name)); -$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); -if ($user->can('manage_invoices') && $user->isPluginEnabled('ps')) - $form->addInput(array('type'=>'checkbox','name'=>'paid','value'=>$cl_paid)); -$form->addInput(array('type'=>'datefield','name'=>'date','maxlength'=>'20','value'=>$cl_date)); -// Hidden control for record id. -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_save or btn_copy click. -$on_click_action = 'browser_today.value=get_date();'; -$form->addInput(array('type'=>'submit','name'=>'btn_copy','onclick'=>$on_click_action,'value'=>$i18n->get('button.copy'))); -if ($confirm_save) $on_click_action .= 'return(confirmSave());'; -$form->addInput(array('type'=>'submit','name'=>'btn_save','onclick'=>$on_click_action,'value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - -if ($request->isPost()) { - // Validate user input. - if ($user->isPluginEnabled('cl') && $user->isOptionEnabled('client_required') && !$cl_client) - $err->add($i18n->get('error.client')); - if ($show_project && !$cl_project) - $err->add($i18n->get('error.project')); - if (!ttValidString($cl_item_name)) $err->add($i18n->get('error.field'), $i18n->get('label.item')); - if (!ttValidFloat($cl_cost)) $err->add($i18n->get('error.field'), $i18n->get('label.cost')); - if (!ttValidDate($cl_date)) $err->add($i18n->get('error.field'), $i18n->get('label.date')); - - // This is a new date for the expense item. - $new_date = new DateAndTime($user->getDateFormat(), $cl_date); - - // Prohibit creating entries in future. - if (!$user->isOptionEnabled('future_entries')) { - $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); - if ($new_date->after($browser_today)) - $err->add($i18n->get('error.future_date')); - } - if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); - // Finished validating user input. - - // Save record. - if ($request->getParameter('btn_save')) { - // We need to: - // 1) Prohibit updating locked entries (that are in locked range). - // 2) Prohibit saving unlocked entries into locked range. - - // Now, step by step. - // 1) Prohibit saving locked entries in any form. - if ($user->isDateLocked($item_date)) - $err->add($i18n->get('error.range_locked')); - - // 2) Prohibit saving unlocked entries into locked range. - if ($err->no() && $user->isDateLocked($new_date)) - $err->add($i18n->get('error.range_locked')); - - // Now, an update. - if ($err->no()) { - if (ttExpenseHelper::update(array('id'=>$cl_id,'date'=>$new_date->toString(DB_DATEFORMAT), - 'client_id'=>$cl_client,'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'paid'=>$cl_paid))) { - header('Location: expenses.php?date='.$new_date->toString(DB_DATEFORMAT)); - exit(); - } - } - } - - // Save as new record. - if ($request->getParameter('btn_copy')) { - // We need to prohibit saving into locked interval. - if ($user->isDateLocked($new_date)) - $err->add($i18n->get('error.range_locked')); - - // Now, a new insert. - if ($err->no()) { - if (ttExpenseHelper::insert(array('date'=>$new_date->toString(DB_DATEFORMAT),'client_id'=>$cl_client, - 'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'status'=>1))) { - header('Location: expenses.php?date='.$new_date->toString(DB_DATEFORMAT)); - exit(); - } else - $err->add($i18n->get('error.db')); - } - } - - if ($request->getParameter('btn_delete')) { - header("Location: expense_delete.php?id=$cl_id"); - exit(); - } -} // isPost - -if ($confirm_save) { - $smarty->assign('confirm_save', true); - $smarty->assign('entry_date', $cl_date); -} -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_project', $show_project); -$smarty->assign('predefined_expenses', $predefined_expenses); -$smarty->assign('client_list', $client_list); -$smarty->assign('project_list', $project_list); -$smarty->assign('task_list', $task_list); -$smarty->assign('title', $i18n->get('title.edit_expense')); -$smarty->assign('content_page_name', 'expense_edit.tpl'); -$smarty->display('index.tpl'); diff --git a/expenses1.php b/expenses1.php deleted file mode 100644 index cd930a8b8..000000000 --- a/expenses1.php +++ /dev/null @@ -1,251 +0,0 @@ -isPluginEnabled('ex')) { - header('Location: feature_disabled.php'); - exit(); -} -if (!$user->exists()) { - header('Location: access_denied.php'); // Nobody to enter expenses for. - exit(); -} -if ($user->behalf_id && (!$user->can('track_expenses') || !$user->checkBehalfId())) { - header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. - exit(); -} -if (!$user->behalf_id && !$user->can('track_own_expenses') && !$user->adjustBehalfId()) { - header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to work on behalf. - exit(); -} -if ($request->isPost() && $request->getParameter('user')) { - if (!$user->isUserValid($request->getParameter('user'))) { - header('Location: access_denied.php'); // Wrong user id on post. - exit(); - } -} -// End of access checks. - -// Determine user for which we display this page. -$userChanged = $request->getParameter('user_changed'); -if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); - $user->setOnBehalfUser($user_id); -} else { - $user_id = $user->getUser(); -} - -// Initialize and store date in session. -$cl_date = $request->getParameter('date', @$_SESSION['date']); -$selected_date = new DateAndTime(DB_DATEFORMAT, $cl_date); -if($selected_date->isError()) - $selected_date = new DateAndTime(DB_DATEFORMAT); -if(!$cl_date) - $cl_date = $selected_date->toString(DB_DATEFORMAT); -$_SESSION['date'] = $cl_date; - -$tracking_mode = $user->getTrackingMode(); -$show_project = MODE_PROJECTS == $tracking_mode || MODE_PROJECTS_AND_TASKS == $tracking_mode; -$showFiles = $user->isPluginEnabled('at'); - -// Initialize variables. -$cl_client = $request->getParameter('client', ($request->isPost() ? null : @$_SESSION['client'])); -$_SESSION['client'] = $cl_client; -$cl_project = $request->getParameter('project', ($request->isPost() ? null : @$_SESSION['project'])); -$_SESSION['project'] = $cl_project; -$cl_item_name = $request->getParameter('item_name'); -$cl_cost = $request->getParameter('cost'); - -// Elements of expensesForm. -$form = new Form('expensesForm'); - -if ($user->can('track_expenses')) { - $rank = $user->getMaxRankForGroup($user->getGroup()); - if ($user->can('track_own_expenses')) - $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); - else - $options = array('status'=>ACTIVE,'max_rank'=>$rank); - $user_list = $user->getUsers($options); - if (count($user_list) >= 1) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'this.form.user_changed.value=1;this.form.submit();', - 'name'=>'user', - 'style'=>'width: 250px;', - 'value'=>$user_id, - 'data'=>$user_list, - 'datakeys'=>array('id','name'))); - $form->addInput(array('type'=>'hidden','name'=>'user_changed')); - $smarty->assign('user_dropdown', 1); - } -} - -// Dropdown for clients in MODE_TIME. Use all active clients. -if (MODE_TIME == $tracking_mode && $user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$active_clients, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - // Note: in other modes the client list is filtered to relevant clients only. See below. -} - -if ($show_project) { - // Dropdown for projects assigned to user. - $project_list = $user->getAssignedProjects(); - $form->addInput(array('type'=>'combobox', - 'name'=>'project', - 'style'=>'width: 250px;', - 'value'=>$cl_project, - 'data'=>$project_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - - // Dropdown for clients if the clients plugin is enabled. - if ($user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. - foreach($project_list as $project) - $projects_assigned_to_user[] = $project['id']; - - // Build a client list out of active clients. Use only clients that are relevant to user. - // Also trim their associated project list to only assigned projects (to user). - foreach($active_clients as $client) { - $projects_assigned_to_client = explode(',', $client['projects']); - $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); - if ($intersection) { - $client['projects'] = implode(',', $intersection); - $client_list[] = $client; - } - } - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$client_list, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } -} -// If predefined expenses are configured, add controls to select an expense and quantity. -$predefined_expenses = ttGroupHelper::getPredefinedExpenses(); -if ($predefined_expenses) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'recalculateCost();', - 'name'=>'predefined_expense', - 'style'=>'width: 250px;', - 'value'=>$cl_predefined_expense, - 'data'=>$predefined_expenses, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); -} -$form->addInput(array('type'=>'textarea','maxlength'=>'800','name'=>'item_name','style'=>'width: 250px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_item_name)); -$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); -if ($showFiles) - $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); -$form->addInput(array('type'=>'calendar','name'=>'date','highlight'=>'expenses','value'=>$cl_date)); // calendar -$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_submit click. -$form->addInput(array('type'=>'submit','name'=>'btn_submit','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.submit'))); - -// Submit. -if ($request->isPost()) { - if ($request->getParameter('btn_submit')) { - // Validate user input. - if ($user->isPluginEnabled('cl') && $user->isOptionEnabled('client_required') && !$cl_client) - $err->add($i18n->get('error.client')); - if ($show_project && !$cl_project) - $err->add($i18n->get('error.project')); - if (!ttValidString($cl_item_name)) $err->add($i18n->get('error.field'), $i18n->get('label.comment')); - if (!ttValidFloat($cl_cost)) $err->add($i18n->get('error.field'), $i18n->get('label.cost')); - - // Prohibit creating entries in future. - if (!$user->isOptionEnabled('future_entries')) { - $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); - if ($selected_date->after($browser_today)) - $err->add($i18n->get('error.future_date')); - } - if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); - // Finished validating input data. - - // Prohibit creating entries in locked range. - if ($user->isDateLocked($selected_date)) - $err->add($i18n->get('error.range_locked')); - - // Insert record. - if ($err->no()) { - $id = ttExpenseHelper::insert(array('date'=>$cl_date,'client_id'=>$cl_client, - 'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'status'=>1)); - - // Put a new file in storage if we have it. - if ($id && $showFiles && $_FILES['newfile']['name']) { - $fileHelper = new ttFileHelper($err); - $fields = array('entity_type'=>'expense', - 'entity_id' => $id, - 'file_name' => $_FILES['newfile']['name']); - $fileHelper->putFile($fields); - } - - if ($id) { - header('Location: expenses.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } - } -} - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_project', $show_project); -$smarty->assign('show_files', $showFiles); -$smarty->assign('day_total', ttExpenseHelper::getTotalForDay($cl_date)); -$smarty->assign('expense_items', ttExpenseHelper::getItems($cl_date, $showFiles)); -$smarty->assign('predefined_expenses', $predefined_expenses); -$smarty->assign('client_list', $client_list); -$smarty->assign('project_list', $project_list); -$smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); -$smarty->assign('title', $i18n->get('title.expenses')); -$smarty->assign('content_page_name', 'expenses.tpl'); -$smarty->display('index.tpl'); diff --git a/initialize.php b/initialize.php index 2978e7a1b..f176802f5 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5401"); +define("APP_VERSION", "1.19.23.5402"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/project_add1.php b/project_add1.php deleted file mode 100644 index 5768d5fb5..000000000 --- a/project_add1.php +++ /dev/null @@ -1,118 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -$showFiles = $user->isPluginEnabled('at'); -$users = ttGroupHelper::getActiveUsers(); -foreach ($users as $user_item) - $all_users[$user_item['id']] = $user_item['name']; - -$tasks = ttGroupHelper::getActiveTasks(); -foreach ($tasks as $task_item) - $all_tasks[$task_item['id']] = $task_item['name']; -$show_tasks = MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && count($tasks) > 0; - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('project_name')); - $cl_description = trim($request->getParameter('description')); - $cl_users = $request->getParameter('users', array()); - $cl_tasks = $request->getParameter('tasks', array()); -} else { - foreach ($users as $user_item) - $cl_users[] = $user_item['id']; - foreach ($tasks as $task_item) - $cl_tasks[] = $task_item['id']; -} - -$form = new Form('projectForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); -if ($showFiles) - $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); -$form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); -if ($show_tasks) - $form->addInput(array('type'=>'checkboxgroup','name'=>'tasks','data'=>$all_tasks,'layout'=>'H','value'=>$cl_tasks)); -$form->addInput(array('type'=>'submit','name'=>'btn_add','value'=>$i18n->get('button.add'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_users, 'tt_users')) $err->add($i18n->get('error.field'), $i18n->get('label.users')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_tasks, 'tt_tasks')) $err->add($i18n->get('error.field'), $i18n->get('label.tasks')); - - if ($err->no()) { - if (!ttProjectHelper::getProjectByName($cl_name)) { - $id = ttProjectHelper::insert(array('name' => $cl_name, - 'description' => $cl_description, - 'users' => $cl_users, - 'tasks' => $cl_tasks, - 'status' => ACTIVE)); - - // Put a new file in storage if we have it. - if ($id && $showFiles && $_FILES['newfile']['name']) { - $fileHelper = new ttFileHelper($err); - $fields = array('entity_type'=>'project', - 'entity_id' => $id, - 'file_name' => $_FILES['newfile']['name']); - $fileHelper->putFile($fields); - } - if ($id) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.projectForm.project_name.focus()"'); -$smarty->assign('show_files', $showFiles); -$smarty->assign('show_users', count($users) > 0); -$smarty->assign('show_tasks', $show_tasks); -$smarty->assign('title', $i18n->get('title.add_project')); -$smarty->assign('content_page_name', 'project_add.tpl'); -$smarty->display('index.tpl'); diff --git a/project_edit1.php b/project_edit1.php deleted file mode 100644 index e1792e48c..000000000 --- a/project_edit1.php +++ /dev/null @@ -1,136 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_project_id = (int)$request->getParameter('id'); -$project = ttProjectHelper::get($cl_project_id); -if (!$project) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$users = ttGroupHelper::getActiveUsers(); -foreach ($users as $user_item) - $all_users[$user_item['id']] = $user_item['name']; - -$tasks = ttGroupHelper::getActiveTasks(); -foreach ($tasks as $task_item) - $all_tasks[$task_item['id']] = $task_item['name']; -$show_tasks = MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && count($tasks) > 0; - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('project_name')); - $cl_description = trim($request->getParameter('description')); - $cl_status = $request->getParameter('status'); - $cl_users = $request->getParameter('users', array()); - $cl_tasks = $request->getParameter('tasks', array()); -} else { - $cl_name = $project['name']; - $cl_description = $project['description']; - $cl_status = $project['status']; - $cl_users = ttProjectHelper::getAssignedUsers($cl_project_id); - $cl_tasks = explode(',', $project['tasks']); -} - -$form = new Form('projectForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_project_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -$form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); -if ($show_tasks) - $form->addInput(array('type'=>'checkboxgroup','name'=>'tasks','data'=>$all_tasks,'layout'=>'H','value'=>$cl_tasks)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_users, 'tt_users')) $err->add($i18n->get('error.field'), $i18n->get('label.users')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_tasks, 'tt_tasks')) $err->add($i18n->get('error.field'), $i18n->get('label.tasks')); - - if ($err->no()) { - if ($request->getParameter('btn_save')) { - $existing_project = ttProjectHelper::getProjectByName($cl_name); - if (!$existing_project || ($cl_project_id == $existing_project['id'])) { - // Update project information. - if (ttProjectHelper::update(array( - 'id' => $cl_project_id, - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => $cl_status, - 'users' => $cl_users, - 'tasks' => $cl_tasks))) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_copy')) { - if (!ttProjectHelper::getProjectByName($cl_name)) { - if (ttProjectHelper::insert(array('name' => $cl_name, - 'description' => $cl_description, - 'users' => $cl_users, - 'tasks' => $cl_tasks, - 'status' => ACTIVE))) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.projectForm.project_name.focus()"'); -$smarty->assign('show_users', count($users) > 0); -$smarty->assign('show_tasks', $show_tasks); -$smarty->assign('title', $i18n->get('title.edit_project')); -$smarty->assign('content_page_name', 'project_edit.tpl'); -$smarty->display('index.tpl'); diff --git a/projects1.php b/projects1.php deleted file mode 100644 index 0075c038f..000000000 --- a/projects1.php +++ /dev/null @@ -1,58 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -$showFiles = $user->isPluginEnabled('at'); - -if($user->can('manage_projects')) { - $active_projects = ttGroupHelper::getActiveProjects($showFiles); - $inactive_projects = ttGroupHelper::getInactiveProjects($showFiles); -} else { - $options['include_files'] = $showFiles; - $active_projects = $user->getAssignedProjects($options); -} - -$smarty->assign('active_projects', $active_projects); -$smarty->assign('inactive_projects', $inactive_projects); -$smarty->assign('show_files', $showFiles); -$smarty->assign('title', $i18n->get('title.projects')); -$smarty->assign('content_page_name', 'projects.tpl'); -$smarty->display('index.tpl'); diff --git a/task_add1.php b/task_add1.php deleted file mode 100644 index 078bd5ca1..000000000 --- a/task_add1.php +++ /dev/null @@ -1,89 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_description = trim($request->getParameter('description')); - $cl_projects = $request->getParameter('projects'); -} else { - foreach ($projects as $project_item) - $cl_projects[] = $project_item['id']; -} - -$form = new Form('taskForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); -$form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - - if ($err->no()) { - if (!ttTaskHelper::getTaskByName($cl_name)) { - if (ttTaskHelper::insert(array( - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => ACTIVE, - 'projects' => $cl_projects))) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_projects', count($projects) > 0); -$smarty->assign('onload', 'onLoad="document.taskForm.name.focus()"'); -$smarty->assign('title', $i18n->get('title.add_task')); -$smarty->assign('content_page_name', 'task_add.tpl'); -$smarty->display('index.tpl'); diff --git a/task_edit1.php b/task_edit1.php deleted file mode 100644 index 10410c4b3..000000000 --- a/task_edit1.php +++ /dev/null @@ -1,122 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_task_id = (int)$request->getParameter('id'); -$task = ttTaskHelper::get($cl_task_id); -if (!$task) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_description = trim($request->getParameter('description')); - $cl_status = $request->getParameter('status'); - $cl_projects = $request->getParameter('projects'); -} else { - $cl_name = $task['name']; - $cl_description = $task['description']; - $cl_status = $task['status']; - $assigned_projects = ttTaskHelper::getAssignedProjects($cl_task_id); - foreach ($assigned_projects as $project_item) - $cl_projects[] = $project_item['id']; -} - -$form = new Form('taskForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_task_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 250px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -$form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - - if ($err->no()) { - if ($request->getParameter('btn_save')) { - $existing_task = ttTaskHelper::getTaskByName($cl_name); - if (!$existing_task || ($cl_task_id == $existing_task['id'])) { - // Update task information. - if (ttTaskHelper::update(array( - 'task_id' => $cl_task_id, - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_copy')) { - if (!ttTaskHelper::getTaskByName($cl_name)) { - if (ttTaskHelper::insert(array( - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_projects', count($projects) > 0); -$smarty->assign('title', $i18n->get('title.edit_task')); -$smarty->assign('content_page_name', 'task_edit.tpl'); -$smarty->display('index.tpl'); diff --git a/tasks1.php b/tasks1.php deleted file mode 100644 index 2e13ead5c..000000000 --- a/tasks1.php +++ /dev/null @@ -1,77 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -$config = $user->getConfigHelper(); - -if ($request->isPost()) { - $cl_task_required = $request->getParameter('task_required'); -} else { - $cl_task_required = $config->getDefinedValue('task_required'); -} - -if($user->can('manage_tasks')) { - $active_tasks = ttGroupHelper::getActiveTasks(); - $inactive_tasks = ttGroupHelper::getInactiveTasks(); -} else - $active_tasks = $user->getAssignedTasks(); - -$form = new Form('tasksForm'); -$form->addInput(array('type'=>'checkbox','name'=>'task_required','value'=>$cl_task_required)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_save')) { - // Save button clicked. Update config. - $config->setDefinedValue('task_required', $cl_task_required); - if (!$user->updateGroup(array('config' => $config->getConfig()))) { - $err->add($i18n->get('error.db')); - } - } -} - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('active_tasks', $active_tasks); -$smarty->assign('inactive_tasks', $inactive_tasks); -$smarty->assign('title', $i18n->get('title.tasks')); -$smarty->assign('content_page_name', 'tasks.tpl'); -$smarty->display('index.tpl'); diff --git a/time1.php b/time1.php deleted file mode 100644 index b249f05b7..000000000 --- a/time1.php +++ /dev/null @@ -1,506 +0,0 @@ -behalf_id && (!$user->can('track_time') || !$user->checkBehalfId())) { - header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. - exit(); -} -if (!$user->behalf_id && !$user->can('track_own_time') && !$user->adjustBehalfId()) { - header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to work on behalf. - exit(); -} -if ($request->isPost()) { - $userChanged = $request->getParameter('user_changed'); // Reused in multiple places below. - if ($userChanged && !($user->can('track_time') && $user->isUserValid($request->getParameter('user')))) { - header('Location: access_denied.php'); // User changed, but no right or wrong user id. - exit(); - } -} -// End of access checks. - -// Determine user for whom we display this page. -if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); - $user->setOnBehalfUser($user_id); -} else { - $user_id = $user->getUser(); -} - -$group_id = $user->getGroup(); -$config = new ttConfigHelper($user->getConfig()); - -$showClient = $user->isPluginEnabled('cl'); -$showBillable = $user->isPluginEnabled('iv'); -$trackingMode = $user->getTrackingMode(); -$showProject = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; -$showTask = MODE_PROJECTS_AND_TASKS == $trackingMode; -if ($showTask) $taskRequired = $config->getDefinedValue('task_required'); -$recordType = $user->getRecordType(); -$showStart = TYPE_START_FINISH == $recordType || TYPE_ALL == $recordType; -$showDuration = TYPE_DURATION == $recordType || TYPE_ALL == $recordType; -$showFiles = $user->isPluginEnabled('at'); -$showRecordCustomFields = $user->isOptionEnabled('record_custom_fields'); - -// Initialize and store date in session. -$cl_date = $request->getParameter('date', @$_SESSION['date']); -$selected_date = new DateAndTime(DB_DATEFORMAT, $cl_date); -if($selected_date->isError()) - $selected_date = new DateAndTime(DB_DATEFORMAT); -if(!$cl_date) - $cl_date = $selected_date->toString(DB_DATEFORMAT); -$_SESSION['date'] = $cl_date; - -// Use custom fields plugin if it is enabled. -if ($user->isPluginEnabled('cf')) { - require_once('plugins/CustomFields.class.php'); - $custom_fields = new CustomFields(); - $smarty->assign('custom_fields', $custom_fields); -} - -$showNoteColumn = !$config->getDefinedValue('time_note_on_separate_row'); -$showNoteRow = $config->getDefinedValue('time_note_on_separate_row'); -if ($showNoteRow) { - // Determine column span for note field. - $colspan = 0; - if ($showClient) $colspan++; - if ($showRecordCustomFields && $custom_fields && $custom_fields->timeFields) { - foreach ($custom_fields->timeFields as $timeField) { - $colspan++; - } - } - if ($showProject) $colspan++; - if ($showTask) $colspan++; - if ($showStart) $colspan++; - if ($showFinish) $colspan++; - $colspan++; // There is always a duration. - if ($showFiles) $colspan++; - $colspan++; // There is always an edit column. - // $colspan++; // There is always a delete column. - // $colspan--; // Remove one column for label. - $smarty->assign('colspan', $colspan); -} - -if ($user->isPluginEnabled('mq')){ - require_once('plugins/MonthlyQuota.class.php'); - $quota = new MonthlyQuota(); - $month_quota_minutes = $quota->getUserQuota($selected_date->mYear, $selected_date->mMonth); - $quota_minutes_from_1st = $quota->getUserQuotaFrom1st($selected_date); - $month_total = ttTimeHelper::getTimeForMonth($selected_date); - $month_total_minutes = ttTimeHelper::toMinutes($month_total); - $balance_left = $quota_minutes_from_1st - $month_total_minutes; - $minutes_left = $month_quota_minutes - $month_total_minutes; - - $smarty->assign('month_total', $month_total); - $smarty->assign('month_quota', ttTimeHelper::toAbsDuration($month_quota_minutes)); - $smarty->assign('over_balance', $balance_left < 0); - $smarty->assign('balance_remaining', ttTimeHelper::toAbsDuration($balance_left)); - $smarty->assign('over_quota', $minutes_left < 0); - $smarty->assign('quota_remaining', ttTimeHelper::toAbsDuration($minutes_left)); -} - -// Initialize variables. -$cl_start = trim($request->getParameter('start')); -$cl_finish = trim($request->getParameter('finish')); -$cl_duration = trim($request->getParameter('duration')); -$cl_note = trim($request->getParameter('note')); -$cl_billable = 1; -if ($showBillable) { - if ($request->isPost()) { - $cl_billable = $request->getParameter('billable'); - $_SESSION['billable'] = (int) $cl_billable; - } else - if (isset($_SESSION['billable'])) - $cl_billable = $_SESSION['billable']; -} -$cl_client = $request->getParameter('client', ($request->isPost() ? null : @$_SESSION['client'])); -$_SESSION['client'] = $cl_client; -$cl_project = $request->getParameter('project', ($request->isPost() ? null : @$_SESSION['project'])); -$_SESSION['project'] = $cl_project; -$cl_task = $request->getParameter('task', ($request->isPost() ? null : @$_SESSION['task'])); -$_SESSION['task'] = $cl_task; - -// Handle time custom fields. -$timeCustomFields = array(); -if ($custom_fields && $custom_fields->timeFields) { - foreach ($custom_fields->timeFields as $timeField) { - $control_name = 'time_field_'.$timeField['id']; - $cl_control_name = $request->getParameter($control_name, ($request->isPost() ? null : @$_SESSION[$control_name])); - $_SESSION[$control_name] = $cl_control_name; - $timeCustomFields[$timeField['id']] = array('field_id' => $timeField['id'], - 'control_name' => $control_name, - 'label' => $timeField['label'], - 'type' => $timeField['type'], - 'required' => $timeField['required'], - 'value' => trim($cl_control_name)); - } -} - -// Elements of timeRecordForm. -$form = new Form('timeRecordForm'); - -// Dropdown for user and a hidden control to indicate user change. -if ($user->can('track_time')) { - $rank = $user->getMaxRankForGroup($group_id); - if ($user->can('track_own_time')) - $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); - else - $options = array('status'=>ACTIVE,'max_rank'=>$rank); - $user_list = $user->getUsers($options); - if (count($user_list) >= 1) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'document.timeRecordForm.user_changed.value=1;document.timeRecordForm.submit();', - 'name'=>'user', - 'style'=>'width: 250px;', - 'value'=>$user_id, - 'data'=>$user_list, - 'datakeys'=>array('id','name'))); - $form->addInput(array('type'=>'hidden','name'=>'user_changed')); - $smarty->assign('user_dropdown', 1); - } -} - -// Dropdown for clients in MODE_TIME. Use all active clients. -// Note: for other tracking modes the control is added further below. -if (MODE_TIME == $trackingMode && $showClient) { - $active_clients = ttGroupHelper::getActiveClients(true); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$active_clients, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - // Note: in other modes the client list is filtered to relevant clients only. See below. -} - -// Billable checkbox. -if ($showBillable) - $form->addInput(array('type'=>'checkbox','name'=>'billable','value'=>$cl_billable)); - -// If we have time custom fields - add controls for them. -if ($custom_fields && $custom_fields->timeFields) { - foreach ($custom_fields->timeFields as $timeField) { - $field_name = 'time_field_'.$timeField['id']; - if ($timeField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'style'=>'width: 250px;','value'=>$timeCustomFields[$timeField['id']]['value'])); - } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { - $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', - 'data'=>CustomFields::getOptions($timeField['id']), - 'value'=>$timeCustomFields[$timeField['id']]['value'], - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } - } -} - -// If we show project dropdown, add controls for project and client. -if ($showProject) { - // Dropdown for projects assigned to user. - $options['include_templates'] = $user->isPluginEnabled('tp') && $config->getDefinedValue('bind_templates_with_projects'); - $project_list = $user->getAssignedProjects($options); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', - 'name'=>'project', - 'style'=>'width: 250px;', - 'value'=>$cl_project, - 'data'=>$project_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - - // Client dropdown. - if ($showClient) { - $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. - foreach($project_list as $project) - $projects_assigned_to_user[] = $project['id']; - - // Build a client list out of active clients. Use only clients that are relevant to user. - // Also trim their associated project list to only assigned projects (to user). - foreach($active_clients as $client) { - $projects_assigned_to_client = explode(',', $client['projects']); - if (is_array($projects_assigned_to_client) && is_array($projects_assigned_to_user)) - $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); - if ($intersection) { - $client['projects'] = implode(',', $intersection); - $client_list[] = $client; - } - } - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$client_list, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } -} - -// Task dropdown. -if ($showTask) { - $task_list = ttGroupHelper::getActiveTasks(); - $form->addInput(array('type'=>'combobox', - 'name'=>'task', - 'style'=>'width: 250px;', - 'value'=>$cl_task, - 'data'=>$task_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); -} - -// Start and finish controls. -if ($showStart) { - $form->addInput(array('type'=>'text','name'=>'start','value'=>$cl_start,'onchange'=>"formDisable('start');")); - $form->addInput(array('type'=>'text','name'=>'finish','value'=>$cl_finish,'onchange'=>"formDisable('finish');")); - if ($user->punch_mode && !$user->canOverridePunchMode()) { - // Make the start and finish fields read-only. - $form->getElement('start')->setEnabled(false); - $form->getElement('finish')->setEnabled(false); - } -} - -// Duration control. -if ($showDuration) - $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); - -// File upload control. -if ($showFiles) - $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); - -// If we have templates, add a dropdown to select one. -if ($user->isPluginEnabled('tp')){ - $template_list = ttGroupHelper::getActiveTemplates(); - if (count($template_list) >= 1) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillNote(this.value);', - 'name'=>'template', - 'style'=>'width: 250px;', - 'data'=>$template_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $smarty->assign('template_dropdown', 1); - $smarty->assign('bind_templates_with_projects', $config->getDefinedValue('bind_templates_with_projects')); - $smarty->assign('prepopulate_note', $config->getDefinedValue('prepopulate_note')); - $smarty->assign('template_list', $template_list); - } -} - -// Note control. -if (!defined('NOTE_INPUT_HEIGHT')) - define('NOTE_INPUT_HEIGHT', 40); -$form->addInput(array('type'=>'textarea','name'=>'note','style'=>'width: 600px; height:'.NOTE_INPUT_HEIGHT.'px;','value'=>$cl_note)); - -// Calendar. -$form->addInput(array('type'=>'calendar','name'=>'date','value'=>$cl_date)); // calendar - -// A hidden control for today's date from user's browser. -$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_submit click. - -// Submit button. -$form->addInput(array('type'=>'submit','name'=>'btn_submit','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.submit'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_submit')) { - // Submit button clicked. - // Validate user input. - if ($showClient && $user->isOptionEnabled('client_required') && !$cl_client) - $err->add($i18n->get('error.client')); - // Validate input in time custom fields. - if ($custom_fields && $custom_fields->timeFields) { - foreach ($timeCustomFields as $timeField) { - // Validation is the same for text and dropdown fields. - if (!ttValidString($timeField['value'], !$timeField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($timeField['label'])); - } - } - if ($showProject) { - if (!$cl_project) $err->add($i18n->get('error.project')); - } - if ($showTask && $taskRequired) { - if (!$cl_task) $err->add($i18n->get('error.task')); - } - if (strlen($cl_duration) == 0) { - if ($cl_start || $cl_finish) { - if (!ttTimeHelper::isValidTime($cl_start)) - $err->add($i18n->get('error.field'), $i18n->get('label.start')); - if ($cl_finish) { - if (!ttTimeHelper::isValidTime($cl_finish)) - $err->add($i18n->get('error.field'), $i18n->get('label.finish')); - if (!ttTimeHelper::isValidInterval($cl_start, $cl_finish)) - $err->add($i18n->get('error.interval'), $i18n->get('label.finish'), $i18n->get('label.start')); - } - } else { - if ($showStart) { - $err->add($i18n->get('error.empty'), $i18n->get('label.start')); - $err->add($i18n->get('error.empty'), $i18n->get('label.finish')); - } - if ($showDuration) - $err->add($i18n->get('error.empty'), $i18n->get('label.duration')); - } - } else { - if (false === ttTimeHelper::postedDurationToMinutes($cl_duration)) - $err->add($i18n->get('error.field'), $i18n->get('label.duration')); - } - if (!ttValidString($cl_note, true)) $err->add($i18n->get('error.field'), $i18n->get('label.note')); - if ($user->isPluginEnabled('tp') && !ttValidTemplateText($cl_note)) { - $err->add($i18n->get('error.field'), $i18n->get('label.note')); - } - if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); - // Finished validating user input. - - // Prohibit creating entries in future. - if (!$user->isOptionEnabled('future_entries')) { - $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); - if ($selected_date->after($browser_today)) - $err->add($i18n->get('error.future_date')); - } - - // Prohibit creating entries in locked range. - if ($user->isDateLocked($selected_date)) - $err->add($i18n->get('error.range_locked')); - - // Prohibit creating another uncompleted record. - if ($err->no()) { - if (($not_completed_rec = ttTimeHelper::getUncompleted($user_id)) && (($cl_finish == '') && ($cl_duration == ''))) - $err->add($i18n->get('error.uncompleted_exists')." ".$i18n->get('error.goto_uncompleted').""); - } - - // Prohibit creating an overlapping record. - if ($err->no()) { - if (ttTimeHelper::overlaps($user_id, $cl_date, $cl_start, $cl_finish)) - $err->add($i18n->get('error.overlap')); - } - - // Insert record. - if ($err->no()) { - $id = ttTimeHelper::insert(array( - 'date' => $cl_date, - 'client' => $cl_client, - 'project' => $cl_project, - 'task' => $cl_task, - 'start' => $cl_start, - 'finish' => $cl_finish, - 'duration' => $cl_duration, - 'note' => $cl_note, - 'billable' => $cl_billable)); - - // Insert time custom fields if we have them. - $result = true; - if ($id && $custom_fields && $custom_fields->timeFields) { - $result = $custom_fields->insertTimeFields($id, $timeCustomFields); - } - - // Put a new file in storage if we have it. - if ($id && $showFiles && $_FILES['newfile']['name']) { - $fileHelper = new ttFileHelper($err); - $fields = array('entity_type'=>'time', - 'entity_id' => $id, - 'file_name' => $_FILES['newfile']['name']); - $fileHelper->putFile($fields); - } - - if ($id && $result && $err->no()) { - header('Location: time.php'); - exit(); - } - $err->add($i18n->get('error.db')); - } - } elseif ($request->getParameter('btn_stop')) { - // Stop button pressed to finish an uncompleted record. - $record_id = $request->getParameter('record_id'); - $record = ttTimeHelper::getRecord($record_id); - $browser_date = $request->getParameter('browser_date'); - $browser_time = $request->getParameter('browser_time'); - - // Can we complete this record? - if ($record['date'] == $browser_date // closing today's record - && ttTimeHelper::isValidInterval($record['start'], $browser_time) // finish time is greater than start time - && !ttTimeHelper::overlaps($user_id, $browser_date, $record['start'], $browser_time)) { // no overlap - $res = ttTimeHelper::update(array( - 'id'=>$record['id'], - 'date'=>$record['date'], - 'client'=>$record['client_id'], - 'project'=>$record['project_id'], - 'task'=>$record['task_id'], - 'start'=>$record['start'], - 'finish'=>$browser_time, - 'note'=>$record['comment'], - 'billable'=>$record['billable'])); - if (!$res) - $err->add($i18n->get('error.db')); - } else { - // Cannot complete, redirect for manual edit. - header('Location: time_edit.php?id='.$record_id); - exit(); - } - } -} // isPost - -$week_total = ttTimeHelper::getTimeForWeek($selected_date); -$timeRecords = ttTimeHelper::getRecords($cl_date, $showFiles); - -$smarty->assign('selected_date', $selected_date); -$smarty->assign('week_total', $week_total); -$smarty->assign('day_total', ttTimeHelper::getTimeForDay($cl_date)); -$smarty->assign('time_records', $timeRecords); -$smarty->assign('show_record_custom_fields', $showRecordCustomFields); -$smarty->assign('show_navigation', $user->isPluginEnabled('wv') && !$user->isOptionEnabled('week_menu')); -$smarty->assign('show_client', $showClient); -$smarty->assign('show_billable', $showBillable); -$smarty->assign('show_project', $showProject); -$smarty->assign('show_task', $showTask); -$smarty->assign('task_required', $taskRequired); -$smarty->assign('show_start', $showStart); -$smarty->assign('show_duration', $showDuration); -$smarty->assign('show_note_column', $showNoteColumn); -$smarty->assign('show_note_row', $showNoteRow); -$smarty->assign('show_files', $showFiles); -$smarty->assign('client_list', $client_list); -$smarty->assign('project_list', $project_list); -$smarty->assign('task_list', $task_list); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="fillDropdowns();prepopulateNote();"'); -$smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); -$smarty->assign('title', $i18n->get('title.time')); -$smarty->assign('content_page_name', 'time.tpl'); -$smarty->display('index.tpl'); diff --git a/user_add1.php b/user_add1.php deleted file mode 100644 index b7c2bc7a6..000000000 --- a/user_add1.php +++ /dev/null @@ -1,244 +0,0 @@ -isPluginEnabled('mq'); -if ($user->isPluginEnabled('cl')) - $clients = ttGroupHelper::getActiveClients(); - -// Use custom fields plugin if it is enabled. -if ($user->isPluginEnabled('cf')) { - require_once('plugins/CustomFields.class.php'); - $custom_fields = new CustomFields(); - $smarty->assign('custom_fields', $custom_fields); -} - -$assigned_projects = array(); -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_login = trim($request->getParameter('login')); - if (!$auth->isPasswordExternal()) { - $cl_password1 = $request->getParameter('pas1'); - $cl_password2 = $request->getParameter('pas2'); - } - $cl_email = trim($request->getParameter('email')); - $cl_role_id = $request->getParameter('role'); - $cl_client_id = $request->getParameter('client'); - $cl_quota_percent = $request->getParameter('quota_percent'); - // If we have user custom fields - collect input. - if ($custom_fields && $custom_fields->userFields) { - foreach ($custom_fields->userFields as $userField) { - $control_name = 'user_field_'.$userField['id']; - $userCustomFields[$userField['id']] = array('field_id' => $userField['id'], - 'control_name' => $control_name, - 'label' => $userField['label'], - 'type' => $userField['type'], - 'required' => $userField['required'], - 'value' => trim($request->getParameter($control_name))); - } - } - $cl_rate = $request->getParameter('rate'); - $cl_projects = $request->getParameter('projects'); - if (is_array($cl_projects)) { - foreach ($cl_projects as $p) { - if (ttValidFloat($request->getParameter('rate_'.$p), true)) { - $project_with_rate = array(); - $project_with_rate['id'] = $p; - $project_with_rate['rate'] = $request->getParameter('rate_'.$p); - $assigned_projects[] = $project_with_rate; - } else - $err->add($i18n->get('error.field'), 'rate_'.$p); - } - } -} - -$form = new Form('userForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 300px;','value'=>$cl_name)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); -if (!$auth->isPasswordExternal()) { - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); -} -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); - -$active_roles = ttTeamHelper::getActiveRolesForUser(); -$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles,'datakeys'=>array('id', 'name'))); -if ($user->isPluginEnabled('cl')) - $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); - -// If we have custom fields - add controls for them. -if ($custom_fields && $custom_fields->userFields) { - foreach ($custom_fields->userFields as $userField) { - $field_name = 'user_field_'.$userField['id']; - if ($userField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$userCustomFields[$userField['id']]['value'])); - } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { - $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', - 'data'=>CustomFields::getOptions($userField['id']), - 'value'=>$userCustomFields[$userField['id']]['value'], - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } - } -} - -$form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'rate','format'=>'.2','value'=>$cl_rate)); -if ($show_quota) - $form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'quota_percent','format'=>'.2','value'=>$cl_quota_percent)); - -$show_projects = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); -if ($show_projects) { - $projects = ttGroupHelper::getActiveProjects(); - if (count($projects) == 0) $show_projects = false; -} - -// Define classes for the projects table. -class NameCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200)); - $this->setValue(''); - return $this->toString(); - } -} -class RateCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - global $assigned_projects; - $field = new FloatField('rate_'.$table->getValueAtName($row, 'id')); - $field->setFormName($table->getFormName()); - $field->setSize(5); - $field->setFormat('.2'); - foreach ($assigned_projects as $p) { - if ($p['id'] == $table->getValueAtName($row,'id')) $field->setValue($p['rate']); - } - $this->setValue($field->getHtml()); - return $this->toString(); - } -} -// Create projects table. -$table = new Table('projects'); -$table->setIAScript('setDefaultRate'); -$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); -$table->setData($projects); -$table->setKeyField('id'); -$table->setValue($cl_projects); -$table->addColumn(new TableColumn('name', $i18n->get('label.project'), new NameCellRenderer())); -$table->addColumn(new TableColumn('p_rate', $i18n->get('form.users.rate'), new RateCellRenderer())); -$form->addInputElement($table); - -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.submit'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.person_name')); - if (!ttValidString($cl_login)) $err->add($i18n->get('error.field'), $i18n->get('label.login')); - if (!$auth->isPasswordExternal()) { - if (!ttValidString($cl_password1)) $err->add($i18n->get('error.field'), $i18n->get('label.password')); - if (!ttValidString($cl_password2)) $err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); - if ($cl_password1 !== $cl_password2) - $err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); - } - if (!ttValidEmail($cl_email, true)) $err->add($i18n->get('error.field'), $i18n->get('label.email')); - // Require selection of a client for a client role. - if ($user->isPluginEnabled('cl') && ttRoleHelper::isClientRole($cl_role_id) && !$cl_client_id) $err->add($i18n->get('error.client')); - if (!ttValidFloat($cl_quota_percent, true)) $err->add($i18n->get('error.field'), $i18n->get('label.quota')); - // Validate input in user custom fields. - if ($custom_fields && $custom_fields->userFields) { - foreach ($userCustomFields as $userField) { - // Validation is the same for text and dropdown fields. - if (!ttValidString($userField['value'], !$userField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($userField['label'])); - } - } - if (!ttValidFloat($cl_rate, true)) $err->add($i18n->get('error.field'), $i18n->get('form.users.default_rate')); - if (!ttUserHelper::canAdd()) $err->add($i18n->get('error.user_count')); - - if ($err->no()) { - if (!ttUserHelper::getUserByLogin($cl_login)) { - $fields = array( - 'name' => $cl_name, - 'login' => $cl_login, - 'password' => $cl_password1, - 'rate' => $cl_rate, - 'quota_percent' => $cl_quota_percent, - 'group_id' => $user->getGroup(), - 'org_id' => $user->org_id, - 'role_id' => $cl_role_id, - 'client_id' => $cl_client_id, - 'projects' => $assigned_projects, - 'email' => $cl_email); - $user_id = ttUserHelper::insert($fields); - - // Insert user custom fields if we have them. - $result = true; - if ($user_id && $custom_fields && $custom_fields->userFields) { - $result = $custom_fields->insertEntityFields(CustomFields::ENTITY_USER, $user_id, $userCustomFields); - } - - if ($user_id && $result) { - if (!$user->exists()) { - // We added a user to an empty subgroup. Set new user as on behalf user. - // Needed for user-based things to work (such as notifications config). - $user->setOnBehalfUser($user_id); - } - header('Location: users.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.user_exists')); - } -} // isPost - -$smarty->assign('auth_external', $auth->isPasswordExternal()); -$smarty->assign('active_roles', $active_roles); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); -$smarty->assign('show_quota', $show_quota); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('title', $i18n->get('title.add_user')); -$smarty->assign('content_page_name', 'user_add.tpl'); -$smarty->display('index.tpl'); diff --git a/user_edit1.php b/user_edit1.php deleted file mode 100644 index d74ae2785..000000000 --- a/user_edit1.php +++ /dev/null @@ -1,308 +0,0 @@ -getParameter('id'); -$user_details = $user->getUserDetails($user_id); -if (!$user_details) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$show_quota = $user->isPluginEnabled('mq'); -if ($user->isPluginEnabled('cl')) - $clients = ttGroupHelper::getActiveClients(); - -// Use custom fields plugin if it is enabled. -if ($user->isPluginEnabled('cf')) { - require_once('plugins/CustomFields.class.php'); - $custom_fields = new CustomFields(); - $smarty->assign('custom_fields', $custom_fields); -} - -$show_projects = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); -if ($show_projects) { - $projects = ttGroupHelper::getActiveProjects(); - if (count($projects) == 0) $show_projects = false; -} -$assigned_projects = array(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_login = trim($request->getParameter('login')); - if (!$auth->isPasswordExternal()) { - $cl_password1 = $request->getParameter('pas1'); - $cl_password2 = $request->getParameter('pas2'); - } - $cl_email = trim($request->getParameter('email')); - $cl_role_id = $request->getParameter('role'); - $cl_client_id = $request->getParameter('client'); - $cl_status = $request->getParameter('status'); - $cl_quota_percent = $request->getParameter('quota_percent'); - // If we have user custom fields - collect input. - if ($custom_fields && $custom_fields->userFields) { - foreach ($custom_fields->userFields as $userField) { - $control_name = 'user_field_'.$userField['id']; - $userCustomFields[$userField['id']] = array('field_id' => $userField['id'], - 'control_name' => $control_name, - 'label' => $userField['label'], - 'type' => $userField['type'], - 'required' => $userField['required'], - 'value' => trim($request->getParameter($control_name))); - } - } - $cl_rate = $request->getParameter('rate'); - $cl_projects = $request->getParameter('projects'); - if (is_array($cl_projects)) { - foreach ($cl_projects as $p) { - if (ttValidFloat($request->getParameter('rate_'.$p), true)) { - $project_with_rate = array(); - $project_with_rate['id'] = $p; - $project_with_rate['rate'] = $request->getParameter('rate_'.$p); - $assigned_projects[] = $project_with_rate; - } else - $err->add($i18n->get('error.field'), 'rate_'.$p); - } - } -} else { - $cl_name = $user_details['name']; - $cl_login = $user_details['login']; - $cl_email = $user_details['email']; - $cl_quota_percent = str_replace('.', $user->getDecimalMark(), $user_details['quota_percent']); - // If we have user custom fields - collect values from database. - if ($custom_fields && $custom_fields->userFields) { - foreach ($custom_fields->userFields as $userField) { - $control_name = 'user_field_'.$userField['id']; - $userCustomFields[$userField['id']] = array('field_id' => $userField['id'], - 'control_name' => $control_name, - 'label' => $userField['label'], - 'type' => $userField['type'], - 'required' => $userField['required'], - 'value' => $custom_fields->getEntityFieldValue(CustomFields::ENTITY_USER, $user_id, $userField['id'], $userField['type'])); - } - } - $cl_rate = str_replace('.', $user->getDecimalMark(), $user_details['rate']); - $cl_role_id = $user_details['role_id']; - $cl_client_id = $user_details['client_id']; - $cl_status = $user_details['status']; - $cl_projects = array(); - $assigned_projects = ttProjectHelper::getAssignedProjects($user_id); - foreach($assigned_projects as $p) { - $cl_projects[] = $p['id']; - } -} - -$form = new Form('userForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 300px;','value'=>$cl_name)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','style'=>'width: 300px;','value'=>$cl_login)); -if (!$auth->isPasswordExternal()) { - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); -} -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','style'=>'width: 300px;','value'=>$cl_email)); - -$active_roles = ttTeamHelper::getActiveRolesForUser(); -$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles, 'datakeys'=>array('id', 'name'))); -if ($user->isPluginEnabled('cl')) - $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); - -// If we have custom fields - add controls for them. -if ($custom_fields && $custom_fields->userFields) { - foreach ($custom_fields->userFields as $userField) { - $field_name = 'user_field_'.$userField['id']; - if ($userField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$userCustomFields[$userField['id']]['value'])); - } elseif ($userField['type'] == CustomFields::TYPE_DROPDOWN) { - $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', - 'data'=>CustomFields::getOptions($userField['id']), - 'value'=>$userCustomFields[$userField['id']]['value'], - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } - } -} - -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -$form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'rate','format'=>'.2','value'=>$cl_rate)); -if ($show_quota) - $form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'quota_percent','format'=>'.2','value'=>$cl_quota_percent)); - -// Define classes for the projects table. -class NameCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200)); - $this->setValue(''); - return $this->toString(); - } -} -class RateCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - global $assigned_projects; - - $field = new FloatField('rate_'.$table->getValueAtName($row,'id')); - $field->setFormName($table->getFormName()); - $field->setSize(5); - $field->setFormat('.2'); - foreach ($assigned_projects as $p) { - if ($p['id'] == $table->getValueAtName($row,'id')) $field->setValue($p['rate']); - } - $this->setValue($field->getHtml()); - return $this->toString(); - } -} -// Create projects table. -$table = new Table('projects'); -$table->setIAScript('setRate'); -$table->setTableOptions(array('width'=>'300','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); -$table->setData($projects); -$table->setKeyField('id'); -$table->setValue($cl_projects); -$table->addColumn(new TableColumn('name', $i18n->get('label.project'), new NameCellRenderer())); -$table->addColumn(new TableColumn('p_rate', $i18n->get('form.users.rate'), new RateCellRenderer())); -$form->addInputElement($table); - -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$user_id)); -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.save'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.person_name')); - if (!ttValidString($cl_login)) $err->add($i18n->get('error.field'), $i18n->get('label.login')); - if (!$auth->isPasswordExternal() && ($cl_password1 || $cl_password2)) { - if (!ttValidString($cl_password1)) $err->add($i18n->get('error.field'), $i18n->get('label.password')); - if (!ttValidString($cl_password2)) $err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); - if ($cl_password1 !== $cl_password2) - $err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); - } - if (!ttValidEmail($cl_email, true)) $err->add($i18n->get('error.field'), $i18n->get('label.email')); - // Require selection of a client for a client role. - if ($user->isPluginEnabled('cl') && ttRoleHelper::isClientRole($cl_role_id) && !$cl_client_id) $err->add($i18n->get('error.client')); - if (!ttValidFloat($cl_quota_percent, true)) $err->add($i18n->get('error.field'), $i18n->get('label.quota')); - // Validate input in user custom fields. - if ($custom_fields && $custom_fields->userFields) { - foreach ($userCustomFields as $userField) { - // Validation is the same for text and dropdown fields. - if (!ttValidString($userField['value'], !$userField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($userField['label'])); - } - } - if (!ttValidFloat($cl_rate, true)) $err->add($i18n->get('error.field'), $i18n->get('form.users.default_rate')); - - if ($err->no()) { - $existing_user = ttUserHelper::getUserByLogin($cl_login); - if (!$existing_user || ($user_id == $existing_user['id'])) { - - $fields = array( - 'name' => $cl_name, - 'login' => $cl_login, - 'password' => $cl_password1, - 'email' => $cl_email, - 'status' => $cl_status, - 'rate' => $cl_rate, - 'quota_percent' => $cl_quota_percent, - 'projects' => $assigned_projects); - if (in_array('manage_users', $user->rights) && $cl_role_id) { - $fields['role_id'] = $cl_role_id; - $fields['client_id'] = $cl_client_id; - } - - $result = ttUserHelper::update($user_id, $fields); - // Update user custom fields if we have them. - if ($result && $custom_fields && $custom_fields->userFields) { - $result = $custom_fields->updateEntityFields(CustomFields::ENTITY_USER, $user_id, $userCustomFields); - } - - if ($result) { - // If our own login changed, set new one in cookie to remember it. - if (($user_id == $user->id) && ($user->login != $cl_login)) { - setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); - } - - // In case the name of the "on behalf" user has changed - set it in session. - if (($user->behalf_id == $user_id) && ($user->behalf_name != $cl_name)) { - $_SESSION['behalf_name'] = $cl_name; - } - - // If we deactivated our own account, do housekeeping and logout. - if ($user->id == $user_id && !is_null($cl_status) && $cl_status == INACTIVE) { - // Remove LOGIN_COOKIE_NAME cookie that stores login name. - unset($_COOKIE[LOGIN_COOKIE_NAME]); - setcookie(LOGIN_COOKIE_NAME, NULL, -1); - - $auth->doLogout(); - header('Location: login.php'); - exit(); - } - - header('Location: users.php'); - exit(); - - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.user_exists')); - } -} // isPost - -$can_swap = false; -if ($user->id == $user_id && $user->can('swap_roles')) { - $users_for_swap = ttTeamHelper::getUsersForSwap(); - if (is_array($users_for_swap) && sizeof($users_for_swap) > 0) - $can_swap = true; -} - -$rates = ttProjectHelper::getRates($user_id); -$smarty->assign('rates', $rates); - -$smarty->assign('auth_external', $auth->isPasswordExternal()); -$smarty->assign('active_roles', $active_roles); -$smarty->assign('can_swap', $can_swap); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); -$smarty->assign('show_quota', $show_quota); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('user_id', $user_id); -$smarty->assign('title', $i18n->get('title.edit_user')); -$smarty->assign('content_page_name', 'user_edit.tpl'); -$smarty->display('index.tpl'); diff --git a/users1.php b/users1.php deleted file mode 100644 index 2fbcb5d20..000000000 --- a/users1.php +++ /dev/null @@ -1,69 +0,0 @@ -getMaxRankForGroup($user->getGroup()); -if ($user->can('view_users')) - $options = array('status'=>ACTIVE,'include_clients'=>true,'include_login'=>true,'include_role'=>true); -else /* if ($user->can('manage_users')) */ - $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_clients'=>true,'include_self'=>true,'include_login'=>true,'include_role'=>true); -$active_users = $user->getUsers($options); - -// Prepare a list of inactive users. -if($user->can('manage_users')) { - $options = array('status'=>INACTIVE,'max_rank'=>$rank,'include_clients'=>true,'include_login'=>true,'include_role'=>true); - $inactive_users = $user->getUsers($options); -} - -$uncompleted_indicators = $user->getConfigOption('uncompleted_indicators'); -if ($uncompleted_indicators) { - // Check each active user if they have an uncompleted time entry. - foreach ($active_users as $key => $active_user) { - $active_users[$key]['has_uncompleted_entry'] = (bool) ttTimeHelper::getUncompleted($active_user['id']); - } - $smarty->assign('uncompleted_indicators', true); -} - -$smarty->assign('active_users', $active_users); -$smarty->assign('inactive_users', $inactive_users); -$smarty->assign('show_quota', $user->isPluginEnabled('mq')); -$smarty->assign('title', $i18n->get('title.users')); -$smarty->assign('content_page_name', 'users.tpl'); -$smarty->display('index.tpl'); From ba13f2e7523c2913c1af268ff85e3392657872f0 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 18:27:09 +0000 Subject: [PATCH 149/587] Made file_edit.php page mobile-friendly. --- WEB-INF/templates/file_edit2.tpl | 22 ++++++ client_edit1.php | 131 ------------------------------- file_edit.php | 36 ++------- initialize.php | 2 +- 4 files changed, 29 insertions(+), 162 deletions(-) create mode 100644 WEB-INF/templates/file_edit2.tpl delete mode 100644 client_edit1.php diff --git a/WEB-INF/templates/file_edit2.tpl b/WEB-INF/templates/file_edit2.tpl new file mode 100644 index 000000000..66f72cc3d --- /dev/null +++ b/WEB-INF/templates/file_edit2.tpl @@ -0,0 +1,22 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + +{$forms.fileForm.open} +
    {$totals[i].name|escape}
    + + + + + + + + + + + + + + +
    {$forms.fileForm.file_name.control}
    {$forms.fileForm.description.control}
    {$i18n.label.required_fields}
    +
    {$forms.fileForm.btn_save.control}
    +{$forms.fileForm.close} diff --git a/client_edit1.php b/client_edit1.php deleted file mode 100644 index 7b572ea7c..000000000 --- a/client_edit1.php +++ /dev/null @@ -1,131 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_id = (int)$request->getParameter('id'); -$client = ttClientHelper::getClient($cl_id, true); -if (!$client) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_address = trim($request->getParameter('address')); - $cl_tax = trim($request->getParameter('tax')); - $cl_status = $request->getParameter('status'); - $cl_projects = $request->getParameter('projects'); -} else { - $cl_name = $client['name']; - $cl_address = $client['address']; - $cl_tax = $client['tax']; - $cl_status = $client['status']; - $assigned_projects = ttClientHelper::getAssignedProjects($cl_id); - foreach($assigned_projects as $project_item) { - $cl_projects[] = $project_item['id']; - } -} - -$show_projects = (MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; - -$form = new Form('clientForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'text','name'=>'name','maxlength'=>'100','style'=>'width: 350px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','style'=>'width: 350px; height: 80px;','value'=>$cl_address)); -$form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -if ($show_projects) - $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'datakeys'=>array('id','name'),'layout'=>'H','value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.client_name')); - if (!ttValidString($cl_address, true)) $err->add($i18n->get('error.field'), $i18n->get('label.client_address')); - if (!ttValidFloat($cl_tax, true)) $err->add($i18n->get('error.field'), $i18n->get('label.tax')); - - if ($err->no()) { - if ($request->getParameter('btn_save')) { - $client = ttClientHelper::getClientByName($cl_name); - if (($client && ($cl_id == $client['id'])) || !$client) { - if (ttClientHelper::update(array( - 'id' => $cl_id, - 'name' => $cl_name, - 'address' => $cl_address, - 'tax' => $cl_tax, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_copy')) { - if (!ttClientHelper::getClientByName($cl_name)) { - if (ttClientHelper::insert(array('name' => $cl_name, - 'address' => $cl_address, - 'tax' => $cl_tax, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('title', $i18n->get('title.edit_client')); -$smarty->assign('content_page_name', 'client_edit.tpl'); -$smarty->display('index.tpl'); diff --git a/file_edit.php b/file_edit.php index d2c8f2990..745293c2e 100644 --- a/file_edit.php +++ b/file_edit.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_file_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'file_name','style'=>'width: 250px;','value'=>$cl_name)); +$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'file_name','value'=>$cl_name)); $form->getElement('file_name')->setEnabled(false); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); if ($request->isPost()) { @@ -120,5 +96,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.fileForm.description.focus()"'); $smarty->assign('title', $i18n->get('title.edit_file')); -$smarty->assign('content_page_name', 'file_edit.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'file_edit2.tpl'); +$smarty->display('index2.tpl'); diff --git a/initialize.php b/initialize.php index f176802f5..0a7d91412 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5402"); +define("APP_VERSION", "1.19.23.5403"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From b72b5fbd56be8cede708844df1fc9d19ce5e84d2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 19:46:03 +0000 Subject: [PATCH 150/587] Made file_delete.php mobile-friendly. --- WEB-INF/templates/file_delete2.tpl | 7 +++++++ file_delete.php | 32 ++++-------------------------- initialize.php | 2 +- 3 files changed, 12 insertions(+), 29 deletions(-) create mode 100644 WEB-INF/templates/file_delete2.tpl diff --git a/WEB-INF/templates/file_delete2.tpl b/WEB-INF/templates/file_delete2.tpl new file mode 100644 index 000000000..80abe01ce --- /dev/null +++ b/WEB-INF/templates/file_delete2.tpl @@ -0,0 +1,7 @@ +{* Copyright (c) Anuko International Ltd. https://www.anuko.com +License: See license.txt *} + +{$forms.fileDeleteForm.open} +
    {$file_to_delete|escape}
    +
    {$forms.fileDeleteForm.btn_delete.control} {$forms.fileDeleteForm.btn_cancel.control}
    +{$forms.fileDeleteForm.close} diff --git a/file_delete.php b/file_delete.php index ff56f118b..1b415c19b 100644 --- a/file_delete.php +++ b/file_delete.php @@ -1,30 +1,6 @@ assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('onload', 'onLoad="document.fileDeleteForm.btn_cancel.focus()"'); $smarty->assign('title', $i18n->get('title.delete_file')); -$smarty->assign('content_page_name', 'file_delete.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'file_delete2.tpl'); +$smarty->display('index2.tpl'); diff --git a/initialize.php b/initialize.php index 0a7d91412..a863d270f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5403"); +define("APP_VERSION", "1.19.23.5404"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 509a401638a0eaba661196cc38e0b3159e71db7c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 20:36:33 +0000 Subject: [PATCH 151/587] Cleanup: removed no longer used templates. --- WEB-INF/templates/charts.tpl | 37 ---- WEB-INF/templates/client_add.tpl | 37 ---- WEB-INF/templates/client_delete.tpl | 25 --- WEB-INF/templates/client_edit.tpl | 41 ----- WEB-INF/templates/clients.tpl | 74 -------- WEB-INF/templates/entity_files.tpl | 47 ------ WEB-INF/templates/expense_delete.tpl | 39 ----- WEB-INF/templates/expense_edit.tpl | 189 --------------------- WEB-INF/templates/expenses.tpl | 241 --------------------------- WEB-INF/templates/file_delete.tpl | 18 -- WEB-INF/templates/file_edit.tpl | 29 ---- WEB-INF/templates/project_add.tpl | 49 ------ WEB-INF/templates/project_delete.tpl | 18 -- WEB-INF/templates/project_edit.tpl | 47 ------ WEB-INF/templates/projects.tpl | 114 ------------- WEB-INF/templates/swap_roles.tpl | 15 -- WEB-INF/templates/task_add.tpl | 36 ---- WEB-INF/templates/task_delete.tpl | 20 --- WEB-INF/templates/task_edit.tpl | 40 ----- WEB-INF/templates/tasks.tpl | 96 ----------- WEB-INF/templates/time.tpl | 234 -------------------------- WEB-INF/templates/user_add.tpl | 134 --------------- WEB-INF/templates/user_delete.tpl | 20 --- WEB-INF/templates/user_edit.tpl | 168 ------------------- WEB-INF/templates/users.tpl | 121 -------------- expense_files.php | 34 +--- initialize.php | 2 +- project_files.php | 34 +--- timesheet_delete.php | 28 +--- timesheet_files.php | 34 +--- 30 files changed, 18 insertions(+), 2003 deletions(-) delete mode 100644 WEB-INF/templates/charts.tpl delete mode 100644 WEB-INF/templates/client_add.tpl delete mode 100644 WEB-INF/templates/client_delete.tpl delete mode 100644 WEB-INF/templates/client_edit.tpl delete mode 100644 WEB-INF/templates/clients.tpl delete mode 100644 WEB-INF/templates/entity_files.tpl delete mode 100644 WEB-INF/templates/expense_delete.tpl delete mode 100644 WEB-INF/templates/expense_edit.tpl delete mode 100644 WEB-INF/templates/expenses.tpl delete mode 100644 WEB-INF/templates/file_delete.tpl delete mode 100644 WEB-INF/templates/file_edit.tpl delete mode 100644 WEB-INF/templates/project_add.tpl delete mode 100644 WEB-INF/templates/project_delete.tpl delete mode 100644 WEB-INF/templates/project_edit.tpl delete mode 100644 WEB-INF/templates/projects.tpl delete mode 100644 WEB-INF/templates/swap_roles.tpl delete mode 100644 WEB-INF/templates/task_add.tpl delete mode 100644 WEB-INF/templates/task_delete.tpl delete mode 100644 WEB-INF/templates/task_edit.tpl delete mode 100644 WEB-INF/templates/tasks.tpl delete mode 100644 WEB-INF/templates/time.tpl delete mode 100644 WEB-INF/templates/user_add.tpl delete mode 100644 WEB-INF/templates/user_delete.tpl delete mode 100644 WEB-INF/templates/user_edit.tpl delete mode 100644 WEB-INF/templates/users.tpl diff --git a/WEB-INF/templates/charts.tpl b/WEB-INF/templates/charts.tpl deleted file mode 100644 index 8e05e1985..000000000 --- a/WEB-INF/templates/charts.tpl +++ /dev/null @@ -1,37 +0,0 @@ -

    -{$forms.chartForm.open} - - -{if $user_dropdown} - - {if $chart_selector} - - {/if} -{else} - {if $chart_selector} - - {/if} -{/if} - - -
    {$i18n.label.user}: {$forms.chartForm.user.control}{$i18n.form.charts.chart}: {$forms.chartForm.type.control}{$i18n.form.charts.chart}: {$forms.chartForm.type.control}
    - - - - - -
    - - {section name=i loop=$totals} - {if $smarty.section.i.index <= 12} - - {/if} - {/section} -
    {$totals[i].name|escape}
    -
    -

    - - - -
    {$i18n.form.charts.interval}: {$forms.chartForm.interval.control}
    {$forms.chartForm.date.control}
    -{$forms.chartForm.close} diff --git a/WEB-INF/templates/client_add.tpl b/WEB-INF/templates/client_add.tpl deleted file mode 100644 index db10ede45..000000000 --- a/WEB-INF/templates/client_add.tpl +++ /dev/null @@ -1,37 +0,0 @@ -{$forms.clientForm.open} - - - - -
    - - - - - - - - - - - - - - - - - - -{if $show_projects} - - - - - -{/if} - - - -
    {$i18n.label.client_name} (*):{$forms.clientForm.name.control}
    {$i18n.label.client_address}:{$forms.clientForm.address.control}
    {$i18n.label.tax}, %:{$forms.clientForm.tax.control} (0{$user->getDecimalMark()}00)
    {$i18n.label.required_fields}
     
    {$i18n.label.projects}:{$forms.clientForm.projects.control}
     
    {$forms.clientForm.btn_submit.control}
    -
    -{$forms.clientForm.close} diff --git a/WEB-INF/templates/client_delete.tpl b/WEB-INF/templates/client_delete.tpl deleted file mode 100644 index f40b94c12..000000000 --- a/WEB-INF/templates/client_delete.tpl +++ /dev/null @@ -1,25 +0,0 @@ -{$forms.clientDeleteForm.open} - - - - -
    - - - - - - - - - - - - - - - - -
    {$i18n.form.client.client_to_delete}:{$client_to_delete|escape}
    {$i18n.form.client.client_entries}:{$forms.clientDeleteForm.delete_client_entries.control}
     
    {$forms.clientDeleteForm.btn_delete.control}  {$forms.clientDeleteForm.btn_cancel.control}
    -
    -{$forms.clientDeleteForm.close} diff --git a/WEB-INF/templates/client_edit.tpl b/WEB-INF/templates/client_edit.tpl deleted file mode 100644 index 2abf70dc1..000000000 --- a/WEB-INF/templates/client_edit.tpl +++ /dev/null @@ -1,41 +0,0 @@ -{$forms.clientForm.open} - - - - -
    - - - - - - - - - - - - - - - - - - - - - - -{if $show_projects} - - - - -{/if} - - - - -
    {$i18n.label.client_name} (*):{$forms.clientForm.name.control}
    {$i18n.label.client_address}:{$forms.clientForm.address.control}
    {$i18n.label.tax}, %:{$forms.clientForm.tax.control} (0{$user->getDecimalMark()}00)
    {$i18n.label.status}:{$forms.clientForm.status.control}
    {$i18n.label.required_fields}
     
    {$i18n.label.projects}:{$forms.clientForm.projects.control}
     
    {$forms.clientForm.btn_save.control} {$forms.clientForm.btn_copy.control}
    -
    -{$forms.clientForm.close} diff --git a/WEB-INF/templates/clients.tpl b/WEB-INF/templates/clients.tpl deleted file mode 100644 index 07b835c87..000000000 --- a/WEB-INF/templates/clients.tpl +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - -
    -{if $user->can('manage_clients')} - - {if $inactive_clients} - - {/if} - - - - - - - {foreach $active_clients as $client} - - - - - - - {/foreach} -
    {$i18n.form.clients.active_clients}
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}{$i18n.label.edit}{$i18n.label.delete}
    - - - -

    - - {if $inactive_clients} - - - - - - - - - {foreach $inactive_clients as $client} - - - - - - - {/foreach} -
    {$i18n.form.clients.inactive_clients}
    {$i18n.label.person_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}{$i18n.label.edit}{$i18n.label.delete}
    - - - -

    - {/if} -{else} - - - - - - {if $active_clients} - {foreach $active_clients as $client} - - - - - {/foreach} - {/if} -
    {$i18n.label.thing_name}{$i18n.label.address}
    {$client.name|escape}{$client.address|escape}
    -{/if} -
    diff --git a/WEB-INF/templates/entity_files.tpl b/WEB-INF/templates/entity_files.tpl deleted file mode 100644 index ab9564852..000000000 --- a/WEB-INF/templates/entity_files.tpl +++ /dev/null @@ -1,47 +0,0 @@ - - - - -
    - - - - -{if $can_edit} - - -{/if} - -{if $files} - {foreach $files as $file} - - - - {if $can_edit} - - - {/if} - - {/foreach} -{/if} -
    {$i18n.label.thing_name}{$i18n.label.description}
    {$file.name|escape}{$file.description|escape}{$i18n.label.edit}{$i18n.label.delete}
    -
    - -{if $can_edit} -{$forms.fileUploadForm.open} - - - - -
    - - - - - - - -
    {$i18n.label.description}:{$forms.fileUploadForm.description.control}{$forms.fileUploadForm.newfile.control}
    {$forms.fileUploadForm.btn_submit.control}
    -
    -{$forms.fileUploadForm.close} -{/if} diff --git a/WEB-INF/templates/expense_delete.tpl b/WEB-INF/templates/expense_delete.tpl deleted file mode 100644 index 6e5bf12c8..000000000 --- a/WEB-INF/templates/expense_delete.tpl +++ /dev/null @@ -1,39 +0,0 @@ -{$forms.expenseItemForm.open} - - - - -
    - - -{if $user->isPluginEnabled('cl')} - -{/if} - -{if $show_project} - -{/if} - - - - -{if $user->isPluginEnabled('cl')} - -{/if} -{if $show_project} - -{/if} - - - -
    {$i18n.label.client}{$i18n.label.project}{$i18n.label.item}{$i18n.label.cost}
    {$expense_item.client_name|escape}{$expense_item.project_name|escape}{$expense_item.name|escape}{$expense_item.cost}
    - - - - - - - -
     
    {$forms.expenseItemForm.delete_button.control}  {$forms.expenseItemForm.cancel_button.control}
    -
    -{$forms.expenseItemForm.close} diff --git a/WEB-INF/templates/expense_edit.tpl b/WEB-INF/templates/expense_edit.tpl deleted file mode 100644 index 671e868cf..000000000 --- a/WEB-INF/templates/expense_edit.tpl +++ /dev/null @@ -1,189 +0,0 @@ - - -{$forms.expenseItemForm.open} - - - - -
    - - - - -
    - -{if $user->isPluginEnabled('cl')} - - - - -{/if} -{if $show_project} - - - - -{/if} -{if $predefined_expenses} - - - - - - - - -{/if} - - - - - - - - -{if ($user->can('manage_invoices') && $user->isPluginEnabled('ps'))} - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.client} {if $user->isOptionEnabled('client_required')}(*){/if}:{$forms.expenseItemForm.client.control}
    {$i18n.label.project} (*):{$forms.expenseItemForm.project.control}
    {$i18n.label.expense}:{$forms.expenseItemForm.predefined_expense.control}
    {$i18n.label.quantity}:{$forms.expenseItemForm.quantity.control}
    {$i18n.label.comment}:{$forms.expenseItemForm.item_name.control}
    {$i18n.label.cost}:{$forms.expenseItemForm.cost.control} {$user->getCurrency()|escape}
     
    {$i18n.label.date}:{$forms.expenseItemForm.date.control}
     
    {$forms.expenseItemForm.btn_save.control} {$forms.expenseItemForm.btn_copy.control} {$forms.expenseItemForm.btn_delete.control}
    -
    -
    -{$forms.expenseItemForm.close} diff --git a/WEB-INF/templates/expenses.tpl b/WEB-INF/templates/expenses.tpl deleted file mode 100644 index 3c5867279..000000000 --- a/WEB-INF/templates/expenses.tpl +++ /dev/null @@ -1,241 +0,0 @@ - - -{$forms.expensesForm.open} - - - - - -
    - -{if $user_dropdown} - - - - -{/if} -{if $user->isPluginEnabled('cl')} - - - - -{/if} -{if $show_project} - - - - -{/if} -{if $predefined_expenses} - - - - - - - - -{/if} - - - - - - - - -{if $show_files} - - - - -{/if} -
    {$i18n.label.user}:{$forms.expensesForm.user.control}
    {$i18n.label.client}{if $user->isOptionEnabled('client_required')} (*){/if}:{$forms.expensesForm.client.control}
    {$i18n.label.project} (*):{$forms.expensesForm.project.control}
    {$i18n.label.expense}:{$forms.expensesForm.predefined_expense.control}
    {$i18n.label.quantity}:{$forms.expensesForm.quantity.control}
    {$i18n.label.comment} (*):{$forms.expensesForm.item_name.control}
    {$i18n.label.cost} (*):{$forms.expensesForm.cost.control} {$user->getCurrency()|escape}
    {$i18n.label.file}:{$forms.expensesForm.newfile.control}
    -
    - - -
    {$forms.expensesForm.date.control}
    -
    - - - - - -
    {$forms.expensesForm.btn_submit.control}
    - - - - - -
    -{if $expense_items} - - - {if $user->isPluginEnabled('cl')} - - {/if} - {if $show_project} - - {/if} - - - {if $show_files} - - {/if} - - - - {foreach $expense_items as $item} - - {if $user->isPluginEnabled('cl')} - - {/if} - {if $show_project} - - {/if} - - - {if $show_files} - {if $item.has_files} - - {else} - - {/if} - {/if} - - - - {/foreach} -
    {$i18n.label.client}{$i18n.label.project}{$i18n.label.item}{$i18n.label.cost}
    {$item.client|escape}{$item.project|escape}{$item.item|escape}{$item.cost}{$i18n.label.files}{$i18n.label.files} - {if $item.approved || $item.invoice_id} -   - {else} - {$i18n.label.edit} - {/if} - - {if $item.approved || $item.invoice_id} -   - {else} - {$i18n.label.delete} - {/if} -
    - - - - -
    {$i18n.label.day_total}: {$user->getCurrency()|escape} {$day_total}
    -{/if} -
    -{$forms.expensesForm.close} diff --git a/WEB-INF/templates/file_delete.tpl b/WEB-INF/templates/file_delete.tpl deleted file mode 100644 index 81107daa5..000000000 --- a/WEB-INF/templates/file_delete.tpl +++ /dev/null @@ -1,18 +0,0 @@ -{$forms.fileDeleteForm.open} - - - - -
    - - - - - - - - - -
    {$file_to_delete|escape}
     
    {$forms.fileDeleteForm.btn_delete.control}  {$forms.fileDeleteForm.btn_cancel.control}
    -
    -{$forms.fileDeleteForm.close} diff --git a/WEB-INF/templates/file_edit.tpl b/WEB-INF/templates/file_edit.tpl deleted file mode 100644 index 697a650ce..000000000 --- a/WEB-INF/templates/file_edit.tpl +++ /dev/null @@ -1,29 +0,0 @@ -{$forms.fileForm.open} - - - - -
    - - - - - - - - - - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.fileForm.file_name.control}
    {$i18n.label.description}:{$forms.fileForm.description.control}
    {$i18n.label.required_fields}
     
    {$forms.fileForm.btn_save.control}
    -
    -{$forms.fileForm.close} diff --git a/WEB-INF/templates/project_add.tpl b/WEB-INF/templates/project_add.tpl deleted file mode 100644 index 309b13788..000000000 --- a/WEB-INF/templates/project_add.tpl +++ /dev/null @@ -1,49 +0,0 @@ -{$forms.projectForm.open} - - - - -
    - - - - - - - - - -{if $show_files} - - - - -{/if} -{if $show_users} - - - - - -{/if} -{if $show_tasks} - - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.projectForm.project_name.control}
    {$i18n.label.description}:{$forms.projectForm.description.control}
    {$i18n.label.file}:{$forms.projectForm.newfile.control}
     
    {$i18n.label.users}:{$forms.projectForm.users.control}
     
    {$i18n.label.tasks}:{$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
     
    {$forms.projectForm.btn_add.control}
    -
    -{$forms.projectForm.close} diff --git a/WEB-INF/templates/project_delete.tpl b/WEB-INF/templates/project_delete.tpl deleted file mode 100644 index 98d3e836d..000000000 --- a/WEB-INF/templates/project_delete.tpl +++ /dev/null @@ -1,18 +0,0 @@ -{$forms.projectDeleteForm.open} - - - - -
    - - - - - - - - - -
    {$project_to_delete|escape}
     
    {$forms.projectDeleteForm.btn_delete.control}  {$forms.projectDeleteForm.btn_cancel.control}
    -
    -{$forms.projectDeleteForm.close} diff --git a/WEB-INF/templates/project_edit.tpl b/WEB-INF/templates/project_edit.tpl deleted file mode 100644 index 2a2364f20..000000000 --- a/WEB-INF/templates/project_edit.tpl +++ /dev/null @@ -1,47 +0,0 @@ -{$forms.projectForm.open} - - - - -
    - - - - - - - - - - - - - -{if $show_users} - - - - - -{/if} -{if $show_tasks} - - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.projectForm.project_name.control}
    {$i18n.label.description}:{$forms.projectForm.description.control}
    {$i18n.label.status}:{$forms.projectForm.status.control}
     
    {$i18n.label.users}:{$forms.projectForm.users.control}
     
    {$i18n.label.tasks}:{$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
     
    {$forms.projectForm.btn_save.control} {$forms.projectForm.btn_copy.control}
    -
    -{$forms.projectForm.close} diff --git a/WEB-INF/templates/projects.tpl b/WEB-INF/templates/projects.tpl deleted file mode 100644 index 19bbe2373..000000000 --- a/WEB-INF/templates/projects.tpl +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - -
    -{if $user->can('manage_projects')} - - {if $inactive_projects} - - {/if} - {if $active_projects} - - - - {if $show_files} - - {/if} - - - - {foreach $active_projects as $project} - - - - {if $show_files} - {if $project.has_files} - - {else} - - {/if} - {/if} - - - - {/foreach} - {/if} -
    {$i18n.form.projects.active_projects}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}
    - - - - - -

    -
    -
    - - {if $inactive_projects} - - - - - - {if $show_files} - - {/if} - - - - {foreach $inactive_projects as $project} - - - - {if $show_files} - {if $project.has_files} - - {else} - - {/if} - {/if} - - - - {/foreach} -
    {$i18n.form.projects.inactive_projects}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}{$i18n.label.files}{$i18n.label.files}{$i18n.label.edit}{$i18n.label.delete}
    - - - - - -

    -
    -
    - {/if} -{else} - - - - - {if $show_files} - - {/if} - - {if $active_projects} - {foreach $active_projects as $project} - - - - {if $show_files} - {if $project.has_files} - - {else} - - {/if} - {/if} - - {/foreach} - {/if} -
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}{$i18n.label.files} 
    -{/if} -
    diff --git a/WEB-INF/templates/swap_roles.tpl b/WEB-INF/templates/swap_roles.tpl deleted file mode 100644 index 2d3086329..000000000 --- a/WEB-INF/templates/swap_roles.tpl +++ /dev/null @@ -1,15 +0,0 @@ -{$forms.swapForm.open} - -
    - - - - - - - - -
    {$i18n.form.swap.hint}
     
    {$i18n.form.swap.swap_with}:{$forms.swapForm.swap_with.control}
    {$forms.swapForm.btn_submit.control} {$forms.swapForm.btn_cancel.control}
    -
    -{$forms.swapForm.close} diff --git a/WEB-INF/templates/task_add.tpl b/WEB-INF/templates/task_add.tpl deleted file mode 100644 index d1892709a..000000000 --- a/WEB-INF/templates/task_add.tpl +++ /dev/null @@ -1,36 +0,0 @@ -{$forms.taskForm.open} - - - - -
    - - - - - - - - - -{if $show_projects} - - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.taskForm.name.control}
    {$i18n.label.description}:{$forms.taskForm.description.control}
     
    {$i18n.label.projects}:{$forms.taskForm.projects.control}
    {$i18n.label.required_fields}
     
    {$forms.taskForm.btn_submit.control}
    -
    -{$forms.taskForm.close} diff --git a/WEB-INF/templates/task_delete.tpl b/WEB-INF/templates/task_delete.tpl deleted file mode 100644 index 9f16d7c3a..000000000 --- a/WEB-INF/templates/task_delete.tpl +++ /dev/null @@ -1,20 +0,0 @@ -{$forms.taskDeleteForm.open} - - - - -
    - - - - - - - - - - - -
    {$task_to_delete|escape}
     
    {$forms.taskDeleteForm.btn_delete.control}  {$forms.taskDeleteForm.btn_cancel.control}
    -
    -{$forms.taskDeleteForm.close} diff --git a/WEB-INF/templates/task_edit.tpl b/WEB-INF/templates/task_edit.tpl deleted file mode 100644 index 0c2b1a555..000000000 --- a/WEB-INF/templates/task_edit.tpl +++ /dev/null @@ -1,40 +0,0 @@ -{$forms.taskForm.open} - - - - -
    - - - - - - - - - - - - - -{if $show_projects} - - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.taskForm.name.control}
    {$i18n.label.description}:{$forms.taskForm.description.control}
    {$i18n.label.status}:{$forms.taskForm.status.control}
     
    {$i18n.label.projects}:{$forms.taskForm.projects.control}
    {$i18n.label.required_fields}
     
    {$forms.taskForm.btn_save.control} {$forms.taskForm.btn_copy.control}
    -
    -{$forms.taskForm.close} diff --git a/WEB-INF/templates/tasks.tpl b/WEB-INF/templates/tasks.tpl deleted file mode 100644 index 591820199..000000000 --- a/WEB-INF/templates/tasks.tpl +++ /dev/null @@ -1,96 +0,0 @@ - - -{$forms.tasksForm.open} - - - - -
    -{if $user->can('manage_tasks')} - - - - - - - - -
    {$forms.tasksForm.task_required.control} {$i18n.label.what_is_it}
    {$forms.tasksForm.btn_save.control}
    -
    - - {if $inactive_tasks} - - {/if} - - - - - - - {if $active_tasks} - {foreach $active_tasks as $task} - - - - - - - {/foreach} - {/if} -
    {$i18n.form.tasks.active_tasks}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}{$i18n.label.edit}{$i18n.label.delete}
    - - - - - -

    -
    -
    - - {if $inactive_tasks} - - - - - - - - - {foreach $inactive_tasks as $task} - - - - - - - {/foreach} -
    {$i18n.form.tasks.inactive_tasks}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}{$i18n.label.edit}{$i18n.label.delete}
    - - - - - -

    -
    -
    - {/if} -{else} - - - - - - {if $active_tasks} - {foreach $active_tasks as $task} - - - - - {/foreach} - {/if} -
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}
    -{/if} -
    -{$forms.tasksForm.close} diff --git a/WEB-INF/templates/time.tpl b/WEB-INF/templates/time.tpl deleted file mode 100644 index 69d214127..000000000 --- a/WEB-INF/templates/time.tpl +++ /dev/null @@ -1,234 +0,0 @@ -{include file="time_script.tpl"} - - - -{$forms.timeRecordForm.open} - -{if $show_navigation} - - - -{/if} - - - - -
    - {$i18n.label.day_view} / {$i18n.label.week_view} -
    - -{if $user_dropdown} - - - - -{/if} -{if $show_client} - - - - -{/if} -{if $show_billable} - - - - -{/if} -{if $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - - - {assign var="control_name" value='time_field_'|cat:$timeField['id']} - - - {/foreach} -{/if} -{if $show_project} - - - - -{/if} -{if $show_task} - - - - -{/if} -{if $show_start} - - - - - - - - -{/if} -{if $show_duration} - - - - -{/if} -{if $show_files} - - - - -{/if} -{if $template_dropdown} - - - - -{/if} -
    {$i18n.label.user}:{$forms.timeRecordForm.user.control}
    {$i18n.label.client}{if $user->isOptionEnabled('client_required')} (*){/if}:{$forms.timeRecordForm.client.control}
     
    {$timeField['label']|escape}{if $timeField['required']} (*){/if}:{$forms.timeRecordForm.$control_name.control}
    {$i18n.label.project} (*):{$forms.timeRecordForm.project.control}
    {$i18n.label.task}{if $task_required} (*){/if}:{$forms.timeRecordForm.task.control}
    {$i18n.label.start}:{$forms.timeRecordForm.start.control} 
    {$i18n.label.finish}:{$forms.timeRecordForm.finish.control} 
    {$i18n.label.duration}:{$forms.timeRecordForm.duration.control} {if $user->getDecimalMark() == ','}{str_replace('.', ',', $i18n.form.time.duration_format)}{else}{$i18n.form.time.duration_format}{/if}
    {$i18n.label.file}:{$forms.timeRecordForm.newfile.control}
    {$i18n.label.template}:{$forms.timeRecordForm.template.control}
    -
    - - -
    {$forms.timeRecordForm.date.control}
    -
    - - - - - - - - - -
    {$i18n.label.note}:{$forms.timeRecordForm.note.control}
    {$forms.timeRecordForm.btn_submit.control}
    - - - - - -
    -{if $time_records} - - - {if $show_client} - - {/if} - {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - - {/foreach} - {/if} - {if $show_project} - - {/if} - {if $show_task} - - {/if} - {if $show_start} - - - {/if} - - {if $show_note_column} - - {/if} - {if $show_files} - - {/if} - - - - {foreach $time_records as $record} - - {if $show_client} - - {/if} - {* record custom fileds *} - {if $show_record_custom_fields && $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - {assign var="control_name" value='time_field_'|cat:$timeField['id']} - - {/foreach} - {/if} - {if $show_project} - - {/if} - {if $show_task} - - {/if} - {if $show_start} - - - {/if} - - {if $show_note_column} - - {/if} - {if $show_files} - {if $record.has_files} - - {else} - - {/if} - {/if} - - - - {if $show_note_row && $record.comment} - - - - - {/if} - {/foreach} -
    {$i18n.label.client}{$timeField['label']|escape}{$i18n.label.project}{$i18n.label.task}{$i18n.label.start}{$i18n.label.finish}{$i18n.label.duration}{$i18n.label.note}
    {$record.client|escape}{$record.$control_name|escape}{$record.project|escape}{$record.task|escape}{if $record.start}{$record.start}{else} {/if}{if $record.finish}{$record.finish}{else} {/if}{if ($record.duration == '0:00' && $record.start <> '')}{$i18n.form.time.uncompleted}{else}{$record.duration}{/if}{if $record.comment}{$record.comment|escape}{else} {/if}{$i18n.label.files}{$i18n.label.files} - {if $record.approved || $record.timesheet_id || $record.invoice_id} -   - {else} - {$i18n.label.edit} - {if ($record.duration == '0:00' && $record.start <> '')} - - - - - {/if} - {/if} - - {if $record.approved || $record.timesheet_id || $record.invoice_id} -   - {else} - {$i18n.label.delete} - {/if} -
    {$i18n.label.note}:{$record.comment|escape}
    -{/if} -
    - - - - - - - {if $user->isPluginEnabled('mq')} - - - {if $over_balance} - - {else} - - {/if} - - - - {if $over_quota} - - {else} - - {/if} - - {/if} -
    {$i18n.label.week_total}: {$week_total}{$i18n.label.day_total}: {$day_total}
    {$i18n.label.month_total}: {$month_total}{$i18n.form.time.over_balance}: {$balance_remaining}{$i18n.form.time.remaining_balance}: {$balance_remaining}
    {$i18n.label.quota}: {$month_quota}{$i18n.form.time.over_quota}: {$quota_remaining}{$i18n.form.time.remaining_quota}: {$quota_remaining}
    - -{$forms.timeRecordForm.close} diff --git a/WEB-INF/templates/user_add.tpl b/WEB-INF/templates/user_add.tpl deleted file mode 100644 index 35040f3c4..000000000 --- a/WEB-INF/templates/user_add.tpl +++ /dev/null @@ -1,134 +0,0 @@ - - -{$forms.userForm.open} - -
    - - - - - - - - -{if !$auth_external} - - - - - - - - -{/if} - - - - - - - - - -{if $show_quota} - - - - -{/if} -{if $custom_fields && $custom_fields->userFields} - {foreach $custom_fields->userFields as $userField} - - - {assign var="control_name" value='user_field_'|cat:$userField['id']} - - - {/foreach} -{/if} - - - - - -{if $show_projects} - - - - - - - -{/if} - - - - - - -
    {$i18n.label.person_name} (*):{$forms.userForm.name.control}
    {$i18n.label.login} (*):{$forms.userForm.login.control}
    {$i18n.label.password} (*):{$forms.userForm.pas1.control}
    {$i18n.label.confirm_password} (*):{$forms.userForm.pas2.control}
    {$i18n.label.email}:{$forms.userForm.email.control}
    {$i18n.form.users.role}:{$forms.userForm.role.control} {$forms.userForm.client.control}
    {$i18n.label.quota} (%):{$forms.userForm.quota_percent.control} {$i18n.label.what_is_it}
    {$userField['label']|escape}{if $userField['required']} (*){/if}:{$forms.userForm.$control_name.control}
    {$i18n.form.users.default_rate} (0{$user->getDecimalMark()}00):{$forms.userForm.rate.control}
     
    {$i18n.label.projects}:{$forms.userForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.userForm.btn_submit.control}
    -
    -{$forms.userForm.close} diff --git a/WEB-INF/templates/user_delete.tpl b/WEB-INF/templates/user_delete.tpl deleted file mode 100644 index e85d97f1f..000000000 --- a/WEB-INF/templates/user_delete.tpl +++ /dev/null @@ -1,20 +0,0 @@ -{$forms.userDeleteForm.open} - - - - -
    - - - - - - - - - - - -
    {$user_to_delete|escape}
     
    {$forms.userDeleteForm.btn_delete.control}  {$forms.userDeleteForm.btn_cancel.control}
    -
    -{$forms.userDeleteForm.close} diff --git a/WEB-INF/templates/user_edit.tpl b/WEB-INF/templates/user_edit.tpl deleted file mode 100644 index 49fa4ae50..000000000 --- a/WEB-INF/templates/user_edit.tpl +++ /dev/null @@ -1,168 +0,0 @@ - - -{$forms.userForm.open} - -
    - - - - - - - - -{if !$auth_external} - - - - - - - - -{/if} - - - - -{if $user->id != $user_id} - - - - - - - - -{/if} -{if $user->id == $user_id} - - - - -{/if} - -{if $show_quota} - - - - -{/if} -{if $custom_fields && $custom_fields->userFields} - {foreach $custom_fields->userFields as $userField} - - - {assign var="control_name" value='user_field_'|cat:$userField['id']} - - - {/foreach} -{/if} - - - - - -{if $show_projects} - - - - - - - -{/if} - - - - - - -
    {$i18n.label.person_name} (*):{$forms.userForm.name.control}
    {$i18n.label.login} (*):{$forms.userForm.login.control}
    {$i18n.label.password} (*):{$forms.userForm.pas1.control}
    {$i18n.label.confirm_password} (*):{$forms.userForm.pas2.control}
    {$i18n.label.email}:{$forms.userForm.email.control}
    {$i18n.form.users.role}:{$forms.userForm.role.control} {$forms.userForm.client.control}
    {$i18n.label.status}:{$forms.userForm.status.control}
    {$i18n.form.users.role}:{$user->role_name} {if $can_swap}{$i18n.form.user_edit.swap_roles}{/if}
    {$i18n.label.quota} (%):{$forms.userForm.quota_percent.control} {$i18n.label.what_is_it}
    {$userField['label']|escape}{if $userField['required']} (*){/if}:{$forms.userForm.$control_name.control}
    {$i18n.form.users.default_rate} (0{$user->getDecimalMark()}00):{$forms.userForm.rate.control}
     
    {$i18n.label.projects}:{$forms.userForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.userForm.btn_submit.control}
    -
    -{$forms.userForm.close} diff --git a/WEB-INF/templates/users.tpl b/WEB-INF/templates/users.tpl deleted file mode 100644 index c3f6861ea..000000000 --- a/WEB-INF/templates/users.tpl +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - -
    -{if $user->can('manage_users')} - - {if $inactive_users} - - {/if} - {if $active_users} - - - - - {if $show_quota} - - {/if} - - - - {foreach $active_users as $u} - - - - - {if $show_quota} - - {/if} - {if $u.group_id != $user->group_id || $u.rank < $user->rank || ($u.rank == $user->rank && $u.id == $user->id)} - - {if $u.id != $user->id}{else}{/if} - {else} - - - {/if} - - {/foreach} - {/if} -
    {$i18n.label.active_users}
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}{$i18n.label.quota}
    - {if $uncompleted_indicators} - - {/if} - {$u.name|escape} - {$u.login|escape}{$u.role_name|escape}{$u.quota_percent}{$i18n.label.edit}{$i18n.label.delete}
    - - - - - -

    -
    -
    - - {if $inactive_users} - - - - - - - {if $show_quota} - - {/if} - - - - {foreach $inactive_users as $u} - - - - - {if $show_quota} - - {/if} - {if $u.group_id != $user->group_id || $u.rank < $user->rank} - - - {else} - - - {/if} - - {/foreach} - -
    {$i18n.label.inactive_users}
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}{$i18n.label.quota}
    {$u.name|escape}{$u.login|escape}{$u.role_name|escape}{$u.quota_percent}{$i18n.label.edit}{$i18n.label.delete}
    - - - - - -
    -
    -
    - {/if} -{else} - - - - - - - {foreach $active_users as $u} - - - - - - {/foreach} -
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}
    - {if $uncompleted_indicators} - - {/if} - {$u.name|escape} - {$u.login|escape}{$u.role_name|escape}
    -{/if} -
    diff --git a/expense_files.php b/expense_files.php index feab9b611..5642cb383 100644 --- a/expense_files.php +++ b/expense_files.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); if ($request->isPost()) { @@ -85,5 +61,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('files', $files); $smarty->assign('title', $i18n->get('title.expense_files')); -$smarty->assign('content_page_name', 'entity_files.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'entity_files2.tpl'); +$smarty->display('index2.tpl'); diff --git a/initialize.php b/initialize.php index a863d270f..a222510c9 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5404"); +define("APP_VERSION", "1.19.23.5405"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/project_files.php b/project_files.php index 6ffe123f1..5dd816d6c 100644 --- a/project_files.php +++ b/project_files.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_project_id)); $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); if ($request->isPost()) { @@ -85,5 +61,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('files', $files); $smarty->assign('title', $i18n->get('title.project_files').': '.$project['name']); -$smarty->assign('content_page_name', 'entity_files.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'entity_files2.tpl'); +$smarty->display('index2.tpl'); diff --git a/timesheet_delete.php b/timesheet_delete.php index 5e98a6cc9..ff1e4e180 100644 --- a/timesheet_delete.php +++ b/timesheet_delete.php @@ -1,30 +1,6 @@ addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_timesheet_id)); $form->addInput(array('type'=>'upload','name'=>'newfile','value'=>$i18n->get('button.submit'))); -$form->addInput(array('type'=>'textarea','name'=>'description','style'=>'width: 250px; height: 40px;','value'=>$cl_description)); +$form->addInput(array('type'=>'textarea','name'=>'description','value'=>$cl_description)); $form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); if ($request->isPost()) { @@ -85,5 +61,5 @@ $smarty->assign('forms', array($form->getName()=>$form->toArray())); $smarty->assign('files', $files); $smarty->assign('title', $i18n->get('title.timesheet_files').': '.$timesheet['name']); -$smarty->assign('content_page_name', 'entity_files.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'entity_files2.tpl'); +$smarty->display('index2.tpl'); From 4500d03942456a4be84e82635412c0ebacf5d152 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 6 Dec 2020 21:35:10 +0000 Subject: [PATCH 152/587] Some more cleanup. --- .../{access_denied.tpl => access_denied2.tpl} | 0 .../{file_download.tpl => file_download2.tpl} | 0 access_denied.php | 2 +- client_add1.php | 94 ------------------- client_delete1.php | 78 --------------- feature_disabled.php | 32 +------ file_download.php | 4 +- initialize.php | 2 +- 8 files changed, 8 insertions(+), 204 deletions(-) rename WEB-INF/templates/{access_denied.tpl => access_denied2.tpl} (100%) rename WEB-INF/templates/{file_download.tpl => file_download2.tpl} (100%) delete mode 100644 client_add1.php delete mode 100644 client_delete1.php diff --git a/WEB-INF/templates/access_denied.tpl b/WEB-INF/templates/access_denied2.tpl similarity index 100% rename from WEB-INF/templates/access_denied.tpl rename to WEB-INF/templates/access_denied2.tpl diff --git a/WEB-INF/templates/file_download.tpl b/WEB-INF/templates/file_download2.tpl similarity index 100% rename from WEB-INF/templates/file_download.tpl rename to WEB-INF/templates/file_download2.tpl diff --git a/access_denied.php b/access_denied.php index 7025d8739..2aa3c5d77 100644 --- a/access_denied.php +++ b/access_denied.php @@ -8,5 +8,5 @@ if ($auth->isAuthenticated()) $smarty->assign('authenticated', true); // Used in header.tpl for menu display. $smarty->assign('title', $i18n->get('label.error')); -$smarty->assign('content_page_name', 'access_denied.tpl'); +$smarty->assign('content_page_name', 'access_denied2.tpl'); $smarty->display('index2.tpl'); diff --git a/client_add1.php b/client_add1.php deleted file mode 100644 index 820a32fde..000000000 --- a/client_add1.php +++ /dev/null @@ -1,94 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_address = trim($request->getParameter('address')); - $cl_tax = $request->getParameter('tax'); - $cl_projects = $request->getParameter('projects'); -} else { - // Do not assign all projects to a new client by default. This should help to reduce clutter. - // foreach ($projects as $project_item) - // $cl_projects[] = $project_item['id']; -} - -$show_projects = (MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode()) && count($projects) > 0; - -$form = new Form('clientForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','style'=>'width: 350px;','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'address','maxlength'=>'255','style'=>'width: 350px; height: 80px;','value'=>$cl_address)); -$form->addInput(array('type'=>'floatfield','name'=>'tax','size'=>'10','format'=>'.2','value'=>$cl_tax)); -if ($show_projects) - $form->addInput(array('type'=>'checkboxgroup','name'=>'projects','data'=>$projects,'layout'=>'H','datakeys'=>array('id','name'),'value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.client_name')); - if (!ttValidString($cl_address, true)) $err->add($i18n->get('error.field'), $i18n->get('label.client_address')); - if (!ttValidFloat($cl_tax, true)) $err->add($i18n->get('error.field'), $i18n->get('label.tax')); - - if ($err->no()) { - if (!ttClientHelper::getClientByName($cl_name)) { - if (ttClientHelper::insert(array('name' => $cl_name, - 'address' => $cl_address, - 'tax' => $cl_tax, - 'projects' => $cl_projects, - 'status' => ACTIVE))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.clientForm.name.focus()"'); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('title', $i18n->get('title.add_client')); -$smarty->assign('content_page_name', 'client_add.tpl'); -$smarty->display('index.tpl'); diff --git a/client_delete1.php b/client_delete1.php deleted file mode 100644 index a5f00656e..000000000 --- a/client_delete1.php +++ /dev/null @@ -1,78 +0,0 @@ -isPluginEnabled('cl')) { - header('Location: feature_disabled.php'); - exit(); -} -$id = (int)$request->getParameter('id'); -$client = ttClientHelper::getClient($id); -if (!$client) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$client_to_delete = $client['name']; - -$form = new Form('clientDeleteForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$id)); -$form->addInput(array('type'=>'combobox','name'=>'delete_client_entries', - 'data'=>array('0'=>$i18n->get('dropdown.do_not_delete'),'1'=>$i18n->get('dropdown.delete')))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_delete')) { - if (ttClientHelper::delete($id, $request->getParameter('delete_client_entries'))) { - header('Location: clients.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } - - if ($request->getParameter('btn_cancel')) { - header('Location: clients.php'); - exit(); - } -} // isPost - -$smarty->assign('client_to_delete', $client_to_delete); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('title', $i18n->get('title.delete_client')); -$smarty->assign('content_page_name', 'client_delete.tpl'); -$smarty->display('index.tpl'); diff --git a/feature_disabled.php b/feature_disabled.php index 7f0bb81f5..c04afe734 100644 --- a/feature_disabled.php +++ b/feature_disabled.php @@ -1,30 +1,6 @@ isAuthenticated()) $smarty->assign('authenticated', true); // Used in header.tpl for menu display. $smarty->assign('title', $i18n->get('label.error')); -$smarty->assign('content_page_name', 'access_denied.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'access_denied2.tpl'); +$smarty->display('index2.tpl'); diff --git a/file_download.php b/file_download.php index ac076b27e..0c323f7f3 100644 --- a/file_download.php +++ b/file_download.php @@ -83,5 +83,5 @@ } $smarty->assign('title', $i18n->get('title.download_file')); -$smarty->assign('content_page_name', 'file_download.tpl'); -$smarty->display('index.tpl'); +$smarty->assign('content_page_name', 'file_download2.tpl'); +$smarty->display('index2.tpl'); diff --git a/initialize.php b/initialize.php index a222510c9..0af6f6c3c 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5405"); +define("APP_VERSION", "1.19.23.5406"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 684c41fbf421859d01fbd7391d7bbb7fef430bc8 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 7 Dec 2020 17:28:19 +0000 Subject: [PATCH 153/587] Removed no longer used mobile pages. --- WEB-INF/templates/mobile/access_denied.tpl | 1 - WEB-INF/templates/mobile/expense_delete.tpl | 39 -- WEB-INF/templates/mobile/expense_edit.tpl | 183 -------- WEB-INF/templates/mobile/project_add.tpl | 43 -- WEB-INF/templates/mobile/project_delete.tpl | 18 - WEB-INF/templates/mobile/project_edit.tpl | 47 -- WEB-INF/templates/mobile/task_add.tpl | 33 -- WEB-INF/templates/mobile/task_delete.tpl | 20 - WEB-INF/templates/mobile/task_edit.tpl | 37 -- WEB-INF/templates/mobile/time_delete.tpl | 32 -- WEB-INF/templates/mobile/time_edit.tpl | 76 --- WEB-INF/templates/mobile/user_add.tpl | 124 ----- WEB-INF/templates/mobile/user_delete.tpl | 20 - WEB-INF/templates/mobile/user_edit.tpl | 153 ------ initialize.php | 2 +- mobile/access_denied.php | 36 -- mobile/expense_delete.php | 88 ---- mobile/expense_edit.php | 238 ---------- mobile/expenses.php | 5 + mobile/feature_disabled.php | 36 -- mobile/index.php | 5 + mobile/project_add.php | 103 ---- mobile/project_delete.php | 75 --- mobile/project_edit.php | 142 ------ mobile/projects.php | 5 + mobile/task_add.php | 87 ---- mobile/task_delete.php | 78 ---- mobile/task_edit.php | 128 ----- mobile/tasks.php | 5 + mobile/time_delete.php | 89 ---- mobile/time_edit.php | 494 -------------------- mobile/user_add.php | 186 -------- mobile/user_delete.php | 87 ---- mobile/user_edit.php | 245 ---------- mobile/users.php | 5 + 35 files changed, 26 insertions(+), 2939 deletions(-) delete mode 100644 WEB-INF/templates/mobile/access_denied.tpl delete mode 100644 WEB-INF/templates/mobile/expense_delete.tpl delete mode 100644 WEB-INF/templates/mobile/expense_edit.tpl delete mode 100644 WEB-INF/templates/mobile/project_add.tpl delete mode 100644 WEB-INF/templates/mobile/project_delete.tpl delete mode 100644 WEB-INF/templates/mobile/project_edit.tpl delete mode 100644 WEB-INF/templates/mobile/task_add.tpl delete mode 100644 WEB-INF/templates/mobile/task_delete.tpl delete mode 100644 WEB-INF/templates/mobile/task_edit.tpl delete mode 100644 WEB-INF/templates/mobile/time_delete.tpl delete mode 100644 WEB-INF/templates/mobile/time_edit.tpl delete mode 100644 WEB-INF/templates/mobile/user_add.tpl delete mode 100644 WEB-INF/templates/mobile/user_delete.tpl delete mode 100644 WEB-INF/templates/mobile/user_edit.tpl delete mode 100644 mobile/access_denied.php delete mode 100644 mobile/expense_delete.php delete mode 100644 mobile/expense_edit.php delete mode 100644 mobile/feature_disabled.php delete mode 100644 mobile/project_add.php delete mode 100644 mobile/project_delete.php delete mode 100644 mobile/project_edit.php delete mode 100644 mobile/task_add.php delete mode 100644 mobile/task_delete.php delete mode 100644 mobile/task_edit.php delete mode 100644 mobile/time_delete.php delete mode 100644 mobile/time_edit.php delete mode 100644 mobile/user_add.php delete mode 100644 mobile/user_delete.php delete mode 100644 mobile/user_edit.php diff --git a/WEB-INF/templates/mobile/access_denied.tpl b/WEB-INF/templates/mobile/access_denied.tpl deleted file mode 100644 index c341a4039..000000000 --- a/WEB-INF/templates/mobile/access_denied.tpl +++ /dev/null @@ -1 +0,0 @@ - diff --git a/WEB-INF/templates/mobile/expense_delete.tpl b/WEB-INF/templates/mobile/expense_delete.tpl deleted file mode 100644 index bd14824e2..000000000 --- a/WEB-INF/templates/mobile/expense_delete.tpl +++ /dev/null @@ -1,39 +0,0 @@ -{$forms.expenseItemForm.open} - - - - -
    - - -{if $user->isPluginEnabled('cl')} - -{/if} - -{if $show_project} - -{/if} - - - - -{if $user->isPluginEnabled('cl')} - -{/if} -{if $show_project} - -{/if} - - - -
    {$i18n.label.client}{$i18n.label.project}{$i18n.label.item}{$i18n.label.cost}
    {$expense_item.client_name|escape}{$expense_item.project_name|escape}{$expense_item.name|escape}{$expense_item.cost}
    - - - - - - - -
     
    {$forms.expenseItemForm.delete_button.control}  {$forms.expenseItemForm.cancel_button.control}
    -
    -{$forms.expenseItemForm.close} diff --git a/WEB-INF/templates/mobile/expense_edit.tpl b/WEB-INF/templates/mobile/expense_edit.tpl deleted file mode 100644 index d4834ae1a..000000000 --- a/WEB-INF/templates/mobile/expense_edit.tpl +++ /dev/null @@ -1,183 +0,0 @@ - - -{$forms.expenseItemForm.open} - - - - -
    - - - - -
    - -{if $user->isPluginEnabled('cl')} - - - - -{/if} -{if $show_project} - - - - -{/if} -{if $predefined_expenses} - - - - - - - - -{/if} - - - - - - - - - - - - - - - - - - - -
    {$i18n.label.client} {if $user->isOptionEnabled('client_required')}(*){/if}:{$forms.expenseItemForm.client.control}
    {$i18n.label.project} (*):{$forms.expenseItemForm.project.control}
    {$i18n.label.expense}:{$forms.expenseItemForm.predefined_expense.control}
    {$i18n.label.quantity}:{$forms.expenseItemForm.quantity.control}
    {$i18n.label.item}:{$forms.expenseItemForm.item_name.control}
    {$i18n.label.cost}:{$forms.expenseItemForm.cost.control} {$user->getCurrency()|escape}
    {$i18n.label.date}:{$forms.expenseItemForm.date.control}
     
    {$forms.expenseItemForm.btn_save.control} {$forms.expenseItemForm.btn_copy.control} {$forms.expenseItemForm.btn_delete.control}
    -
    -
    -{$forms.expenseItemForm.close} diff --git a/WEB-INF/templates/mobile/project_add.tpl b/WEB-INF/templates/mobile/project_add.tpl deleted file mode 100644 index d49b9a33e..000000000 --- a/WEB-INF/templates/mobile/project_add.tpl +++ /dev/null @@ -1,43 +0,0 @@ -{$forms.projectForm.open} - - - - -
    - - - - - - - - - -{if $show_users} - - - - - -{/if} -{if $show_tasks} - - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.projectForm.project_name.control}
    {$i18n.label.description}:{$forms.projectForm.description.control}
     
    {$i18n.label.users}:{$forms.projectForm.users.control}
     
    {$i18n.label.tasks}:{$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
     
    {$forms.projectForm.btn_add.control}
    -
    -{$forms.projectForm.close} diff --git a/WEB-INF/templates/mobile/project_delete.tpl b/WEB-INF/templates/mobile/project_delete.tpl deleted file mode 100644 index 98d3e836d..000000000 --- a/WEB-INF/templates/mobile/project_delete.tpl +++ /dev/null @@ -1,18 +0,0 @@ -{$forms.projectDeleteForm.open} - - - - -
    - - - - - - - - - -
    {$project_to_delete|escape}
     
    {$forms.projectDeleteForm.btn_delete.control}  {$forms.projectDeleteForm.btn_cancel.control}
    -
    -{$forms.projectDeleteForm.close} diff --git a/WEB-INF/templates/mobile/project_edit.tpl b/WEB-INF/templates/mobile/project_edit.tpl deleted file mode 100644 index 871f5c1dc..000000000 --- a/WEB-INF/templates/mobile/project_edit.tpl +++ /dev/null @@ -1,47 +0,0 @@ -{$forms.projectForm.open} - - - - -
    - - - - - - - - - - - - - -{if $show_users} - - - - - -{/if} -{if $show_tasks} - - - - - -{/if} - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.projectForm.project_name.control}
    {$i18n.label.description}:{$forms.projectForm.description.control}
    {$i18n.label.status}:{$forms.projectForm.status.control}
     
    {$i18n.label.users}:{$forms.projectForm.users.control}
     
    {$i18n.label.tasks}:{$forms.projectForm.tasks.control}
    {$i18n.label.required_fields}
     
    {$forms.projectForm.btn_save.control} {$forms.projectForm.btn_copy.control} {$forms.projectForm.btn_delete.control}
    -
    -{$forms.projectForm.close} diff --git a/WEB-INF/templates/mobile/task_add.tpl b/WEB-INF/templates/mobile/task_add.tpl deleted file mode 100644 index 68e415e1c..000000000 --- a/WEB-INF/templates/mobile/task_add.tpl +++ /dev/null @@ -1,33 +0,0 @@ -{$forms.taskForm.open} - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.taskForm.name.control}
    {$i18n.label.description}:{$forms.taskForm.description.control}
    {$i18n.label.projects}:{$forms.taskForm.projects.control}
    {$i18n.label.required_fields}
     
    {$forms.taskForm.btn_submit.control}
    -
    -{$forms.taskForm.close} diff --git a/WEB-INF/templates/mobile/task_delete.tpl b/WEB-INF/templates/mobile/task_delete.tpl deleted file mode 100644 index 9f16d7c3a..000000000 --- a/WEB-INF/templates/mobile/task_delete.tpl +++ /dev/null @@ -1,20 +0,0 @@ -{$forms.taskDeleteForm.open} - - - - -
    - - - - - - - - - - - -
    {$task_to_delete|escape}
     
    {$forms.taskDeleteForm.btn_delete.control}  {$forms.taskDeleteForm.btn_cancel.control}
    -
    -{$forms.taskDeleteForm.close} diff --git a/WEB-INF/templates/mobile/task_edit.tpl b/WEB-INF/templates/mobile/task_edit.tpl deleted file mode 100644 index f6672c739..000000000 --- a/WEB-INF/templates/mobile/task_edit.tpl +++ /dev/null @@ -1,37 +0,0 @@ -{$forms.taskForm.open} - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {$i18n.label.thing_name} (*):{$forms.taskForm.name.control}
    {$i18n.label.description}:{$forms.taskForm.description.control}
    {$i18n.label.status}:{$forms.taskForm.status.control}
    {$i18n.label.projects}:{$forms.taskForm.projects.control}
    {$i18n.label.required_fields}
     
    {$forms.taskForm.btn_save.control} {$forms.taskForm.btn_copy.control} {$forms.taskForm.btn_delete.control}
    -
    -{$forms.taskForm.close} diff --git a/WEB-INF/templates/mobile/time_delete.tpl b/WEB-INF/templates/mobile/time_delete.tpl deleted file mode 100644 index 2e3ac7fea..000000000 --- a/WEB-INF/templates/mobile/time_delete.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{$forms.timeRecordForm.open} - - - - -
    - - -{if $show_project} - -{/if} - - - - -{if $show_project} - -{/if} - - - -
    {$i18n.label.project}{$i18n.label.duration}{$i18n.label.note}
    {$time_rec.project_name|escape}{if ($time_rec.duration == '0:00' && $time_rec.start <> '')}{$i18n.form.time.uncompleted}{else}{$time_rec.duration}{/if}{if $time_rec.comment}{$time_rec.comment|escape}{else} {/if}
    - - - - - - - -
     
    {$forms.timeRecordForm.delete_button.control}  {$forms.timeRecordForm.cancel_button.control}
    -
    -{$forms.timeRecordForm.close} diff --git a/WEB-INF/templates/mobile/time_edit.tpl b/WEB-INF/templates/mobile/time_edit.tpl deleted file mode 100644 index 3025a63f7..000000000 --- a/WEB-INF/templates/mobile/time_edit.tpl +++ /dev/null @@ -1,76 +0,0 @@ -{include file="time_script.tpl"} - -{* Conditional include of confirmSave handler. *} -{if $confirm_save} - -{/if} - -{$forms.timeRecordForm.open} - - - - -
    - - - - -
    - -{if $show_client} - - -{/if} -{if $show_billable} - -{/if} -{if $show_paid_status} - -{/if} -{if $custom_fields && $custom_fields->timeFields} - {foreach $custom_fields->timeFields as $timeField} - - {assign var="control_name" value='time_field_'|cat:$timeField['id']} - - {/foreach} -{/if} -{if $show_project} - - -{/if} -{if $show_task} - - -{/if} -{if $show_start} - - - - -{/if} -{if $show_duration} - - -{/if} - - -{if $template_dropdown} - - -{/if} - - - -
    {$i18n.label.client}:
    {$forms.timeRecordForm.client.control}
    {$timeField['label']|escape}{if $timeField['required']} (*){/if}:
    {$forms.timeRecordForm.$control_name.control}
    {$i18n.label.project}:
    {$forms.timeRecordForm.project.control}
    {$i18n.label.task}{if $task_required} (*){/if}:
    {$forms.timeRecordForm.task.control}
    {$i18n.label.start}:
    {$forms.timeRecordForm.start.control} 
    {$i18n.label.finish}:
    {$forms.timeRecordForm.finish.control} 
    {$i18n.label.duration}:
    {$forms.timeRecordForm.duration.control}
    {$i18n.label.date}:
    {$forms.timeRecordForm.date.control}
    {$i18n.label.template}:
    {$forms.timeRecordForm.template.control}
    {$i18n.label.note}:
    {$forms.timeRecordForm.note.control}
    {$forms.timeRecordForm.btn_save.control} {$forms.timeRecordForm.btn_copy.control} {$forms.timeRecordForm.btn_delete.control}
    -
    -
    -{$forms.timeRecordForm.close} diff --git a/WEB-INF/templates/mobile/user_add.tpl b/WEB-INF/templates/mobile/user_add.tpl deleted file mode 100644 index 9df99ff00..000000000 --- a/WEB-INF/templates/mobile/user_add.tpl +++ /dev/null @@ -1,124 +0,0 @@ - - -{$forms.userForm.open} - -
    - - - - - - - - -{if !$auth_external} - - - - - - - - -{/if} - - - - - - - - - -{if $show_quota} - - - - -{/if} - - - - - -{if $show_projects} - - - - - - -{/if} - - - - - - -
    {$i18n.label.person_name} (*):{$forms.userForm.name.control}
    {$i18n.label.login} (*):{$forms.userForm.login.control}
    {$i18n.label.password} (*):{$forms.userForm.pas1.control}
    {$i18n.label.confirm_password} (*):{$forms.userForm.pas2.control}
    {$i18n.label.email}:{$forms.userForm.email.control}
    {$i18n.form.users.role}:{$forms.userForm.role.control} {$forms.userForm.client.control}
    {$i18n.label.quota} (%):{$forms.userForm.quota_percent.control}
    {$i18n.form.users.default_rate} (0{$user->decimal_mark}00):{$forms.userForm.rate.control}
    {$i18n.label.projects}:{$forms.userForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.userForm.btn_submit.control}
    -
    -{$forms.userForm.close} diff --git a/WEB-INF/templates/mobile/user_delete.tpl b/WEB-INF/templates/mobile/user_delete.tpl deleted file mode 100644 index e85d97f1f..000000000 --- a/WEB-INF/templates/mobile/user_delete.tpl +++ /dev/null @@ -1,20 +0,0 @@ -{$forms.userDeleteForm.open} - - - - -
    - - - - - - - - - - - -
    {$user_to_delete|escape}
     
    {$forms.userDeleteForm.btn_delete.control}  {$forms.userDeleteForm.btn_cancel.control}
    -
    -{$forms.userDeleteForm.close} diff --git a/WEB-INF/templates/mobile/user_edit.tpl b/WEB-INF/templates/mobile/user_edit.tpl deleted file mode 100644 index 03c5db2ef..000000000 --- a/WEB-INF/templates/mobile/user_edit.tpl +++ /dev/null @@ -1,153 +0,0 @@ - - - -{$forms.userForm.open} - -
    - - - - - - - - -{if !$auth_external} - - - - - - - - -{/if} - - - - -{if $user->id != $user_id} - - - - - - - - -{/if} - -{if $show_quota} - - - - -{/if} - - - - - -{if $show_projects} - - - - - - -{/if} - - - - - - -
    {$i18n.label.person_name} (*):{$forms.userForm.name.control}
    {$i18n.label.login} (*):{$forms.userForm.login.control}
    {$i18n.label.password} (*):{$forms.userForm.pas1.control}
    {$i18n.label.confirm_password} (*):{$forms.userForm.pas2.control}
    {$i18n.label.email}:{$forms.userForm.email.control}
    {$i18n.form.users.role}:{$forms.userForm.role.control} {$forms.userForm.client.control}
    {$i18n.label.status}:{$forms.userForm.status.control}
    {$i18n.label.quota} (%):{$forms.userForm.quota_percent.control}
    {$i18n.form.users.default_rate} (0{$user->decimal_mark}00):{$forms.userForm.rate.control}
    {$i18n.label.projects}:{$forms.userForm.projects.control}
    {$i18n.label.required_fields}
    {$forms.userForm.btn_submit.control} {$forms.userForm.btn_delete.control}
    - -{$forms.userForm.close} diff --git a/initialize.php b/initialize.php index 0af6f6c3c..265d13aea 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5406"); +define("APP_VERSION", "1.19.23.5407"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/access_denied.php b/mobile/access_denied.php deleted file mode 100644 index 6e7174a26..000000000 --- a/mobile/access_denied.php +++ /dev/null @@ -1,36 +0,0 @@ -add($i18n->get('error.access_denied')); -if ($auth->isAuthenticated()) $smarty->assign('authenticated', true); // Used in header.tpl for menu display. - -$smarty->assign('title', $i18n->get('label.error')); -$smarty->assign('content_page_name', 'mobile/access_denied.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/expense_delete.php b/mobile/expense_delete.php deleted file mode 100644 index 48e74dc0e..000000000 --- a/mobile/expense_delete.php +++ /dev/null @@ -1,88 +0,0 @@ -isPluginEnabled('ex')) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_id = (int)$request->getParameter('id'); -// Get the expense item we are deleting. -$expense_item = ttExpenseHelper::getItem($cl_id); -if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { - // Prohibit deleting not ours, approved, or invoiced items. - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -if ($request->isPost()) { - if ($request->getParameter('delete_button')) { // Delete button pressed. - - // Determine if it is okay to delete the record. - $item_date = new DateAndTime(DB_DATEFORMAT, $expense_item['date']); - if ($user->isDateLocked($item_date)) - $err->add($i18n->get('error.range_locked')); - - if ($err->no()) { - // Mark the record as deleted. - if (ttExpenseHelper::markDeleted($cl_id)) { - header('Location: expenses.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } - } - if ($request->getParameter('cancel_button')) { // Cancel button pressed. - header('Location: expenses.php'); - exit(); - } -} // isPost - -$form = new Form('expenseItemForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'submit','name'=>'delete_button','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'cancel_button','value'=>$i18n->get('button.cancel'))); - -$show_project = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); - -$smarty->assign('forms', array($form->getName() => $form->toArray())); -$smarty->assign('expense_item', $expense_item); -$smarty->assign('show_project', $show_project); -$smarty->assign('title', $i18n->get('title.delete_expense')); -$smarty->assign('content_page_name', 'mobile/expense_delete.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/expense_edit.php b/mobile/expense_edit.php deleted file mode 100644 index 67813a6f1..000000000 --- a/mobile/expense_edit.php +++ /dev/null @@ -1,238 +0,0 @@ -isPluginEnabled('ex')) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_id = (int)$request->getParameter('id'); -// Get the expense item we are editing. -$expense_item = ttExpenseHelper::getItem($cl_id); -if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { - // Prohibit editing not ours, approved, or invoiced items. - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$item_date = new DateAndTime(DB_DATEFORMAT, $expense_item['date']); -$confirm_save = $user->getConfigOption('confirm_save'); -$trackingMode = $user->getTrackingMode(); -$show_project = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; - -// Initialize variables. -$cl_date = $cl_client = $cl_project = $cl_item_name = $cl_cost = null; -if ($request->isPost()) { - $cl_date = trim($request->getParameter('date')); - $cl_client = $request->getParameter('client'); - $cl_project = $request->getParameter('project'); - $cl_item_name = trim($request->getParameter('item_name')); - $cl_cost = trim($request->getParameter('cost')); -} else { - $cl_date = $item_date->toString($user->getDateFormat()); - $cl_client = $expense_item['client_id']; - $cl_project = $expense_item['project_id']; - $cl_item_name = $expense_item['name']; - $cl_cost = $expense_item['cost']; -} - -// Initialize elements of 'expenseItemForm'. -$form = new Form('expenseItemForm'); - -// Dropdown for clients in MODE_TIME. Use all active clients. -if (MODE_TIME == $trackingMode && $user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$active_clients, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - // Note: in other modes the client list is filtered to relevant clients only. See below. -} - -if ($show_project) { - // Dropdown for projects assigned to user. - $project_list = $user->getAssignedProjects(); - $form->addInput(array('type'=>'combobox', - 'name'=>'project', - 'style'=>'width: 250px;', - 'value'=>$cl_project, - 'data'=>$project_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - - // Dropdown for clients if the clients plugin is enabled. - if ($user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. - foreach($project_list as $project) - $projects_assigned_to_user[] = $project['id']; - - // Build a client list out of active clients. Use only clients that are relevant to user. - // Also trim their associated project list to only assigned projects (to user). - foreach($active_clients as $client) { - $projects_assigned_to_client = explode(',', $client['projects']); - $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); - if ($intersection) { - $client['projects'] = implode(',', $intersection); - $client_list[] = $client; - } - } - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$client_list, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } -} -// If predefined expenses are configured, add controls to select an expense and quantity. -$predefined_expenses = ttGroupHelper::getPredefinedExpenses(); -if ($predefined_expenses) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'recalculateCost();', - 'name'=>'predefined_expense', - 'style'=>'width: 250px;', - 'value'=>$cl_predefined_expense, - 'data'=>$predefined_expenses, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); -} -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'item_name','style'=>'width: 250px;','value'=>$cl_item_name)); -$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); -$form->addInput(array('type'=>'datefield','name'=>'date','maxlength'=>'20','value'=>$cl_date)); -// Hidden control for record id. -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_save or btn_copy click. -$on_click_action = 'browser_today.value=get_date();'; -$form->addInput(array('type'=>'submit','name'=>'btn_copy','onclick'=>$on_click_action,'value'=>$i18n->get('button.copy'))); -if ($confirm_save) $on_click_action .= 'return(confirmSave());'; -$form->addInput(array('type'=>'submit','name'=>'btn_save','onclick'=>$on_click_action,'value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - -if ($request->isPost()) { - // Validate user input. - if ($user->isPluginEnabled('cl') && $user->isOptionEnabled('client_required') && !$cl_client) - $err->add($i18n->get('error.client')); - if ($show_project && !$cl_project) - $err->add($i18n->get('error.project')); - if (!ttValidString($cl_item_name)) $err->add($i18n->get('error.field'), $i18n->get('label.item')); - if (!ttValidFloat($cl_cost)) $err->add($i18n->get('error.field'), $i18n->get('label.cost')); - if (!ttValidDate($cl_date)) $err->add($i18n->get('error.field'), $i18n->get('label.date')); - - // This is a new date for the expense item. - $new_date = new DateAndTime($user->getDateFormat(), $cl_date); - - // Prohibit creating entries in future. - if (!$user->isOptionEnabled('future_entries')) { - $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); - if ($new_date->after($browser_today)) - $err->add($i18n->get('error.future_date')); - } - if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); - // Finished validating input data. - - // Save record. - if ($request->getParameter('btn_save')) { - // We need to: - // 1) Prohibit updating locked entries (that are in locked range). - // 2) Prohibit saving unlocked entries into locked range. - - // Now, step by step. - // 1) Prohibit saving locked entries in any form. - if ($user->isDateLocked($item_date)) - $err->add($i18n->get('error.range_locked')); - - // 2) Prohibit saving unlocked entries into locked range. - if ($err->no() && $user->isDateLocked($new_date)) - $err->add($i18n->get('error.range_locked')); - - // Now, an update. - if ($err->no()) { - if (ttExpenseHelper::update(array('id'=>$cl_id,'date'=>$new_date->toString(DB_DATEFORMAT), - 'client_id'=>$cl_client,'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost))) { - header('Location: expenses.php?date='.$new_date->toString(DB_DATEFORMAT)); - exit(); - } - } - } - - // Save as new record. - if ($request->getParameter('btn_copy')) { - // We need to prohibit saving into locked interval. - if ($user->isDateLocked($new_date)) - $err->add($i18n->get('error.range_locked')); - - // Now, a new insert. - if ($err->no()) { - if (ttExpenseHelper::insert(array('date'=>$new_date->toString(DB_DATEFORMAT),'client_id'=>$cl_client, - 'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'status'=>1))) { - header('Location: expenses.php?date='.$new_date->toString(DB_DATEFORMAT)); - exit(); - } else - $err->add($i18n->get('error.db')); - } - } - - if ($request->getParameter('btn_delete')) { - header("Location: expense_delete.php?id=$cl_id"); - exit(); - } -} // isPost - -if ($confirm_save) { - $smarty->assign('confirm_save', true); - $smarty->assign('entry_date', $cl_date); -} -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_project', $show_project); -$smarty->assign('predefined_expenses', $predefined_expenses); -$smarty->assign('client_list', $client_list); -$smarty->assign('project_list', $project_list); -$smarty->assign('task_list', $task_list); -$smarty->assign('title', $i18n->get('title.edit_expense')); -$smarty->assign('content_page_name', 'mobile/expense_edit.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/expenses.php b/mobile/expenses.php index 05d469985..463671f4a 100644 --- a/mobile/expenses.php +++ b/mobile/expenses.php @@ -34,6 +34,11 @@ import('ttTimeHelper'); import('ttExpenseHelper'); +// Mobile pages are no longer separate. Redirect to main page. +header('Location: ../expenses.php'); +exit(); +// Below is no longer used code. + // Access checks. if (!(ttAccessAllowed('track_own_expenses') || ttAccessAllowed('track_expenses'))) { header('Location: access_denied.php'); diff --git a/mobile/feature_disabled.php b/mobile/feature_disabled.php deleted file mode 100644 index cf399568e..000000000 --- a/mobile/feature_disabled.php +++ /dev/null @@ -1,36 +0,0 @@ -add($i18n->get('error.feature_disabled')); -if ($auth->isAuthenticated()) $smarty->assign('authenticated', true); // Used in header.tpl for menu display. - -$smarty->assign('title', $i18n->get('label.error')); -$smarty->assign('content_page_name', 'mobile/access_denied.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/index.php b/mobile/index.php index 8fc64b35e..88408af23 100644 --- a/mobile/index.php +++ b/mobile/index.php @@ -28,6 +28,11 @@ require_once('../initialize.php'); +// Mobile pages are no longer separate. Redirect to main page. +header('Location: ../index.php'); +exit(); +// Below is no longer used code. + // Redirects for admin and client roles. if ($auth->isAuthenticated()) { if ($user->can('administer_site')) { diff --git a/mobile/project_add.php b/mobile/project_add.php deleted file mode 100644 index c152006f3..000000000 --- a/mobile/project_add.php +++ /dev/null @@ -1,103 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -$users = ttGroupHelper::getActiveUsers(); -foreach ($users as $user_item) - $all_users[$user_item['id']] = $user_item['name']; - -$tasks = ttGroupHelper::getActiveTasks(); -foreach ($tasks as $task_item) - $all_tasks[$task_item['id']] = $task_item['name']; -$show_tasks = MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && count($tasks) > 0; - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('project_name')); - $cl_description = trim($request->getParameter('description')); - $cl_users = $request->getParameter('users', array()); - $cl_tasks = $request->getParameter('tasks', array()); -} else { - foreach ($users as $user_item) - $cl_users[] = $user_item['id']; - foreach ($tasks as $task_item) - $cl_tasks[] = $task_item['id']; -} - -$form = new Form('projectForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','class'=>'mobile-textarea','value'=>$cl_description)); -$form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); -if ($show_tasks) - $form->addInput(array('type'=>'checkboxgroup','name'=>'tasks','data'=>$all_tasks,'layout'=>'H','value'=>$cl_tasks)); -$form->addInput(array('type'=>'submit','name'=>'btn_add','value'=>$i18n->get('button.add'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_users, 'tt_users')) $err->add($i18n->get('error.field'), $i18n->get('label.users')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_tasks, 'tt_tasks')) $err->add($i18n->get('error.field'), $i18n->get('label.tasks')); - - if ($err->no()) { - if (!ttProjectHelper::getProjectByName($cl_name)) { - if (ttProjectHelper::insert(array('name' => $cl_name, - 'description' => $cl_description, - 'users' => $cl_users, - 'tasks' => $cl_tasks, - 'status' => ACTIVE))) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.projectForm.project_name.focus()"'); -$smarty->assign('show_users', count($users) > 0); -$smarty->assign('show_tasks', $show_tasks); -$smarty->assign('title', $i18n->get('title.add_project')); -$smarty->assign('content_page_name', 'mobile/project_add.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/project_delete.php b/mobile/project_delete.php deleted file mode 100644 index ac957e249..000000000 --- a/mobile/project_delete.php +++ /dev/null @@ -1,75 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_project_id = (int)$request->getParameter('id'); -$project = ttProjectHelper::get($cl_project_id); -if (!$project) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$project_to_delete = $project['name']; - -$form = new Form('projectDeleteForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_project_id)); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_delete')) { - if (ttProjectHelper::delete($cl_project_id)) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } elseif ($request->getParameter('btn_cancel')) { - header('Location: projects.php'); - exit(); - } -} // isPost - -$smarty->assign('project_to_delete', $project_to_delete); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.projectDeleteForm.btn_cancel.focus()"'); -$smarty->assign('title', $i18n->get('title.delete_project')); -$smarty->assign('content_page_name', 'mobile/project_delete.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/project_edit.php b/mobile/project_edit.php deleted file mode 100644 index 31da38903..000000000 --- a/mobile/project_edit.php +++ /dev/null @@ -1,142 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_project_id = (int)$request->getParameter('id'); -$project = ttProjectHelper::get($cl_project_id); -if (!$project) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$users = ttGroupHelper::getActiveUsers(); -foreach ($users as $user_item) - $all_users[$user_item['id']] = $user_item['name']; - -$tasks = ttGroupHelper::getActiveTasks(); -foreach ($tasks as $task_item) - $all_tasks[$task_item['id']] = $task_item['name']; -$show_tasks = MODE_PROJECTS_AND_TASKS == $user->getTrackingMode() && count($tasks) > 0; - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('project_name')); - $cl_description = trim($request->getParameter('description')); - $cl_status = $request->getParameter('status'); - $cl_users = $request->getParameter('users', array()); - $cl_tasks = $request->getParameter('tasks', array()); -} else { - $cl_name = $project['name']; - $cl_description = $project['description']; - $cl_status = $project['status']; - $cl_users = ttProjectHelper::getAssignedUsers($cl_project_id); - $cl_tasks = explode(',', $project['tasks']); -} - -$form = new Form('projectForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_project_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'project_name','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','class'=>'mobile-textarea','value'=>$cl_description)); -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -$form->addInput(array('type'=>'checkboxgroup','name'=>'users','data'=>$all_users,'layout'=>'H','value'=>$cl_users)); -if ($show_tasks) - $form->addInput(array('type'=>'checkboxgroup','name'=>'tasks','data'=>$all_tasks,'layout'=>'H','value'=>$cl_tasks)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_users, 'tt_users')) $err->add($i18n->get('error.field'), $i18n->get('label.users')); - if (!ttGroupHelper::validateCheckboxGroupInput($cl_tasks, 'tt_tasks')) $err->add($i18n->get('error.field'), $i18n->get('label.tasks')); - - if ($err->no()) { - if ($request->getParameter('btn_save')) { - $existing_project = ttProjectHelper::getProjectByName($cl_name); - if (!$existing_project || ($cl_project_id == $existing_project['id'])) { - // Update project information. - if (ttProjectHelper::update(array( - 'id' => $cl_project_id, - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => $cl_status, - 'users' => $cl_users, - 'tasks' => $cl_tasks))) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_copy')) { - if (!ttProjectHelper::getProjectByName($cl_name)) { - if (ttProjectHelper::insert(array('name' => $cl_name, - 'description' => $cl_description, - 'users' => $cl_users, - 'tasks' => $cl_tasks, - 'status' => ACTIVE))) { - header('Location: projects.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_delete')) { - header("Location: project_delete.php?id=$cl_project_id"); - exit(); - } - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.projectForm.project_name.focus()"'); -$smarty->assign('show_users', count($users) > 0); -$smarty->assign('show_tasks', $show_tasks); -$smarty->assign('title', $i18n->get('title.edit_project')); -$smarty->assign('content_page_name', 'mobile/project_edit.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/projects.php b/mobile/projects.php index 6a5ac572a..ee5d8dc18 100644 --- a/mobile/projects.php +++ b/mobile/projects.php @@ -31,6 +31,11 @@ import('ttTeamHelper'); import('ttGroupHelper'); +// Mobile pages are no longer separate. Redirect to main page. +header('Location: ../projects.php'); +exit(); +// Below is no longer used code. + // Access checks. if (!(ttAccessAllowed('view_own_projects') || ttAccessAllowed('manage_projects'))) { header('Location: access_denied.php'); diff --git a/mobile/task_add.php b/mobile/task_add.php deleted file mode 100644 index db73d1c77..000000000 --- a/mobile/task_add.php +++ /dev/null @@ -1,87 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_description = trim($request->getParameter('description')); - $cl_projects = $request->getParameter('projects'); -} else { - foreach ($projects as $project_item) - $cl_projects[] = $project_item['id']; -} - -$form = new Form('taskForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','class'=>'mobile-textarea','value'=>$cl_description)); -$form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.add'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - - if ($err->no()) { - if (!ttTaskHelper::getTaskByName($cl_name)) { - if (ttTaskHelper::insert(array( - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => ACTIVE, - 'projects' => $cl_projects))) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.taskForm.name.focus()"'); -$smarty->assign('title', $i18n->get('title.add_task')); -$smarty->assign('content_page_name', 'mobile/task_add.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/task_delete.php b/mobile/task_delete.php deleted file mode 100644 index dd0dae935..000000000 --- a/mobile/task_delete.php +++ /dev/null @@ -1,78 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_task_id = (int)$request->getParameter('id'); -$task = ttTaskHelper::get($cl_task_id); -if (!$task) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$task_to_delete = $task['name']; - -$form = new Form('taskDeleteForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_task_id)); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_delete')) { - if(ttTaskHelper::get($cl_task_id)) { - if (ttTaskHelper::delete($cl_task_id)) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.db')); - } elseif ($request->getParameter('btn_cancel')) { - header('Location: tasks.php'); - exit(); - } -} // isPost - -$smarty->assign('task_to_delete', $task_to_delete); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.taskDeleteForm.btn_cancel.focus()"'); -$smarty->assign('title', $i18n->get('title.delete_task')); -$smarty->assign('content_page_name', 'mobile/task_delete.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/task_edit.php b/mobile/task_edit.php deleted file mode 100644 index 02a947676..000000000 --- a/mobile/task_edit.php +++ /dev/null @@ -1,128 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -$cl_task_id = (int)$request->getParameter('id'); -$task = ttTaskHelper::get($cl_task_id); -if (!$task) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$projects = ttGroupHelper::getActiveProjects(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_description = trim($request->getParameter('description')); - $cl_status = $request->getParameter('status'); - $cl_projects = $request->getParameter('projects'); -} else { - $cl_name = $task['name']; - $cl_description = $task['description']; - $cl_status = $task['status']; - $assigned_projects = ttTaskHelper::getAssignedProjects($cl_task_id); - foreach ($assigned_projects as $project_item) - $cl_projects[] = $project_item['id']; -} - -$form = new Form('taskForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_task_id)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); -$form->addInput(array('type'=>'textarea','name'=>'description','class'=>'mobile-textarea','value'=>$cl_description)); -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -$form->addInput(array('type'=>'checkboxgroup','name'=>'projects','layout'=>'H','data'=>$projects,'datakeys'=>array('id','name'),'value'=>$cl_projects)); -$form->addInput(array('type'=>'submit','name'=>'btn_save','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_copy','value'=>$i18n->get('button.copy'))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.thing_name')); - if (!ttValidString($cl_description, true)) $err->add($i18n->get('error.field'), $i18n->get('label.description')); - - if ($err->no()) { - if ($request->getParameter('btn_save')) { - $existing_task = ttTaskHelper::getTaskByName($cl_name); - if (!$existing_task || ($cl_task_id == $existing_task['id'])) { - // Update task information. - if (ttTaskHelper::update(array( - 'task_id' => $cl_task_id, - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_copy')) { - if (!ttTaskHelper::getTaskByName($cl_name)) { - if (ttTaskHelper::insert(array( - 'name' => $cl_name, - 'description' => $cl_description, - 'status' => $cl_status, - 'projects' => $cl_projects))) { - header('Location: tasks.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.object_exists')); - } - - if ($request->getParameter('btn_delete')) { - header("Location: task_delete.php?id=$cl_task_id"); - exit(); - } - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('title', $i18n->get('title.edit_task')); -$smarty->assign('content_page_name', 'mobile/task_edit.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/tasks.php b/mobile/tasks.php index 2745df23a..960990166 100644 --- a/mobile/tasks.php +++ b/mobile/tasks.php @@ -30,6 +30,11 @@ import('form.Form'); import('ttGroupHelper'); +// Mobile pages are no longer separate. Redirect to main page. +header('Location: ../tasks.php'); +exit(); +// Below is no longer used code. + // Access checks. if (!(ttAccessAllowed('view_own_tasks') || ttAccessAllowed('manage_tasks'))) { header('Location: access_denied.php'); diff --git a/mobile/time_delete.php b/mobile/time_delete.php deleted file mode 100644 index e80c5c733..000000000 --- a/mobile/time_delete.php +++ /dev/null @@ -1,89 +0,0 @@ -getParameter('id'); -$time_rec = ttTimeHelper::getRecord($cl_id); -if (!$time_rec || $time_rec['approved'] || $time_rec['timesheet_id'] || $time_rec['invoice_id']) { - // Prohibit deleting not ours, approved, assigned to timesheet, or invoiced records. - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$trackingMode = $user->getTrackingMode(); -$showProject = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; - -if ($request->isPost()) { - if ($request->getParameter('delete_button')) { // Delete button pressed. - - // Determine if it's okay to delete the record. - $item_date = new DateAndTime(DB_DATEFORMAT, $time_rec['date']); - - // Determine if the record is uncompleted. - $uncompleted = ($time_rec['duration'] == '0:00'); - - if ($user->isDateLocked($item_date) && !$uncompleted) - $err->add($i18n->get('error.range_locked')); - - if ($err->no()) { - // Delete the record. - if (ttTimeHelper::delete($cl_id)) { - header('Location: time.php'); - exit(); - } else { - $err->add($i18n->get('error.db')); - } - } - } - if ($request->getParameter('cancel_button')) { // Cancel button pressed. - header('Location: time.php'); - exit(); - } -} // isPost - -$form = new Form('timeRecordForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); -$form->addInput(array('type'=>'submit','name'=>'delete_button','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'cancel_button','value'=>$i18n->get('button.cancel'))); -$smarty->assign('time_rec', $time_rec); -$smarty->assign('show_project', $showProject); -$smarty->assign('forms', array($form->getName() => $form->toArray())); -$smarty->assign('title', $i18n->get('title.delete_time_record')); -$smarty->assign('content_page_name', 'mobile/time_delete.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/time_edit.php b/mobile/time_edit.php deleted file mode 100644 index fb3a918dc..000000000 --- a/mobile/time_edit.php +++ /dev/null @@ -1,494 +0,0 @@ -getParameter('id'); -$time_rec = ttTimeHelper::getRecord($cl_id); -if (!$time_rec || $time_rec['approved'] || $time_rec['timesheet_id'] || $time_rec['invoice_id']) { - // Prohibit editing not ours, approved, assigned to timesheet, or invoiced records. - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$user_id = $user->getUser(); -$config = new ttConfigHelper($user->getConfig()); - -$showClient = $user->isPluginEnabled('cl'); -$showBillable = $user->isPluginEnabled('iv'); -$showPaidStatus = $user->isPluginEnabled('ps') && $user->can('manage_invoices'); -$trackingMode = $user->getTrackingMode(); -$showProject = MODE_PROJECTS == $trackingMode || MODE_PROJECTS_AND_TASKS == $trackingMode; -$showTask = MODE_PROJECTS_AND_TASKS == $trackingMode; -if ($showTask) $taskRequired = $config->getDefinedValue('task_required'); -$recordType = $user->getRecordType(); -$showStart = TYPE_START_FINISH == $recordType || TYPE_ALL == $recordType; -$showDuration = TYPE_DURATION == $recordType || TYPE_ALL == $recordType; - -// Use custom fields plugin if it is enabled. -if ($user->isPluginEnabled('cf')) { - require_once('../plugins/CustomFields.class.php'); - $custom_fields = new CustomFields(); - $smarty->assign('custom_fields', $custom_fields); -} - -$item_date = new DateAndTime(DB_DATEFORMAT, $time_rec['date']); -$confirm_save = $user->getConfigOption('confirm_save'); - -// Initialize variables. -$cl_start = $cl_finish = $cl_duration = $cl_date = $cl_note = $cl_project = $cl_task = $cl_billable = null; -if ($request->isPost()) { - $cl_start = trim($request->getParameter('start')); - $cl_finish = trim($request->getParameter('finish')); - $cl_duration = trim($request->getParameter('duration')); - $cl_date = $request->getParameter('date'); - $cl_note = trim($request->getParameter('note')); - // If we have user custom fields - collect input. - if ($custom_fields && $custom_fields->timeFields) { - foreach ($custom_fields->timeFields as $timeField) { - $control_name = 'time_field_'.$timeField['id']; - $timeCustomFields[$timeField['id']] = array('field_id' => $timeField['id'], - 'control_name' => $control_name, - 'label' => $timeField['label'], - 'type' => $timeField['type'], - 'required' => $timeField['required'], - 'value' => trim($request->getParameter($control_name))); - } - } - $cl_client = $request->getParameter('client'); - $cl_project = $request->getParameter('project'); - $cl_task = $request->getParameter('task'); - $cl_billable = 1; - if ($showBillable) - $cl_billable = $request->getParameter('billable'); - if ($showPaidStatus) - $cl_paid = $request->getParameter('paid'); -} else { - $cl_client = $time_rec['client_id']; - $cl_project = $time_rec['project_id']; - $cl_task = $time_rec['task_id']; - $cl_start = $time_rec['start']; - $cl_finish = $time_rec['finish']; - $cl_duration = $time_rec['duration']; - $cl_date = $item_date->toString($user->getDateFormat()); - $cl_note = $time_rec['comment']; - - // If we have time custom fields - collect values from database. - if ($custom_fields && $custom_fields->timeFields) { - foreach ($custom_fields->timeFields as $timeField) { - $control_name = 'time_field_'.$timeField['id']; - $timeCustomFields[$timeField['id']] = array('field_id' => $timeField['id'], - 'control_name' => $control_name, - 'label' => $timeField['label'], - 'type' => $timeField['type'], - 'required' => $timeField['required'], - 'value' => $custom_fields->getTimeFieldValue($cl_id, $timeField['id'], $timeField['type'])); - } - } - - $cl_billable = $time_rec['billable']; - $cl_paid = $time_rec['paid']; - - // Add an info message to the form if we are editing an uncompleted record. - if (strlen($cl_start) > 0 && $cl_start == $cl_finish && $cl_duration == '0:00') { - $cl_finish = ''; - $cl_duration = ''; - $msg->add($i18n->get('form.time_edit.uncompleted')); - } -} - -// Initialize elements of 'timeRecordForm'. -$form = new Form('timeRecordForm'); - -// Dropdown for clients in MODE_TIME. Use all active clients. -// Note: for other tracking modes the control is added further below. -if (MODE_TIME == $trackingMode && $showClient) { - $active_clients = ttGroupHelper::getActiveClients(true); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$active_clients, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - // Note: in other modes the client list is filtered to relevant clients only. See below. -} - -// Billable checkbox. -if ($showBillable) - $form->addInput(array('type'=>'checkbox','name'=>'billable','value'=>$cl_billable)); - -// Paid status checkbox. -if ($showPaidStatus) - $form->addInput(array('type'=>'checkbox','name'=>'paid','value'=>$cl_paid)); - -// If we have time custom fields - add controls for them. -if ($custom_fields && $custom_fields->timeFields) { - foreach ($custom_fields->timeFields as $timeField) { - $field_name = 'time_field_'.$timeField['id']; - if ($timeField['type'] == CustomFields::TYPE_TEXT) { - $form->addInput(array('type'=>'text','name'=>$field_name,'value'=>$timeCustomFields[$timeField['id']]['value'])); - } elseif ($timeField['type'] == CustomFields::TYPE_DROPDOWN) { - $form->addInput(array('type'=>'combobox','name'=>$field_name, - 'style'=>'width: 250px;', - 'data'=>CustomFields::getOptions($timeField['id']), - 'value'=>$timeCustomFields[$timeField['id']]['value'], - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } - } -} - -// If we show project dropdown, add controls for project and client. -if ($showProject) { - // Dropdown for projects assigned to user. - $options['include_templates'] = $user->isPluginEnabled('tp') && $config->getDefinedValue('bind_templates_with_projects'); - $project_list = $user->getAssignedProjects($options); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillTaskDropdown(this.value);fillTemplateDropdown(this.value);prepopulateNote();', - 'name'=>'project', - 'style'=>'width: 250px;', - 'value'=>$cl_project, - 'data'=>$project_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - - // Dropdown for clients if the clients plugin is enabled. - if ($showClient) { - $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. - foreach($project_list as $project) - $projects_assigned_to_user[] = $project['id']; - - // Build a client list out of active clients. Use only clients that are relevant to user. - // Also trim their associated project list to only assigned projects (to user). - foreach($active_clients as $client) { - $projects_assigned_to_client = explode(',', $client['projects']); - if (is_array($projects_assigned_to_client) && is_array($projects_assigned_to_user)) - $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); - if ($intersection) { - $client['projects'] = implode(',', $intersection); - $client_list[] = $client; - } - } - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$client_list, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } -} - -// Task dropdown. -if ($showTask) { - $task_list = ttGroupHelper::getActiveTasks(); - $form->addInput(array('type'=>'combobox', - 'name'=>'task', - 'style'=>'width: 250px;', - 'value'=>$cl_task, - 'data'=>$task_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); -} - -// Start and finish controls. -if ($showStart) { - $form->addInput(array('type'=>'text','name'=>'start','value'=>$cl_start,'onchange'=>"formDisable('start');")); - $form->addInput(array('type'=>'text','name'=>'finish','value'=>$cl_finish,'onchange'=>"formDisable('finish');")); - if ($user->punch_mode && !$user->canOverridePunchMode()) { - // Make the start and finish fields read-only. - $form->getElement('start')->setEnabled(false); - $form->getElement('finish')->setEnabled(false); - } -} - -// Duration control. -if ($showDuration) - $form->addInput(array('type'=>'text','name'=>'duration','value'=>$cl_duration,'onchange'=>"formDisable('duration');")); - -// Date field. -$form->addInput(array('type'=>'datefield','name'=>'date','maxlength'=>'20','value'=>$cl_date)); - -// If we have templates, add a dropdown to select one. -if ($user->isPluginEnabled('tp')){ - $template_list = ttGroupHelper::getActiveTemplates(); - if (count($template_list) >= 1) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillNote(this.value);', - 'name'=>'template', - 'style'=>'width: 250px;', - 'data'=>$template_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $smarty->assign('template_dropdown', 1); - $smarty->assign('bind_templates_with_projects', $config->getDefinedValue('bind_templates_with_projects')); - $smarty->assign('prepopulate_note', $config->getDefinedValue('prepopulate_note')); - $smarty->assign('template_list', $template_list); - } -} - -// Note control. -$form->addInput(array('type'=>'textarea','name'=>'note','class'=>'mobile-textarea','value'=>$cl_note)); - -// Hidden control for record id. -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_id)); - -// A hidden control for today's date from user's browser. -$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_save click. - -// Copy button. -$on_click_action = 'browser_today.value=get_date();'; -$form->addInput(array('type'=>'submit','name'=>'btn_copy','onclick'=>$on_click_action,'value'=>$i18n->get('button.copy'))); - -// Save button. -if ($confirm_save) $on_click_action .= 'return(confirmSave());'; -$form->addInput(array('type'=>'submit','name'=>'btn_save','onclick'=>$on_click_action,'value'=>$i18n->get('button.save'))); - -// Delete button. -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - -if ($request->isPost()) { - - // Validate user input. - if ($showClient && $user->isOptionEnabled('client_required') && !$cl_client) - $err->add($i18n->get('error.client')); - // Validate input in time custom fields. - if ($custom_fields && $custom_fields->timeFields) { - foreach ($timeCustomFields as $timeField) { - // Validation is the same for text and dropdown fields. - if (!ttValidString($timeField['value'], !$timeField['required'])) $err->add($i18n->get('error.field'), htmlspecialchars($timeField['label'])); - } - } - if ($showProject) { - if (!$cl_project) $err->add($i18n->get('error.project')); - } - if ($showTask && $task_required) { - if (!$cl_task) $err->add($i18n->get('error.task')); - } - if (!$cl_duration) { - if ('0' == $cl_duration) - $err->add($i18n->get('error.field'), $i18n->get('label.duration')); - elseif ($cl_start || $cl_finish) { - if (!ttTimeHelper::isValidTime($cl_start)) - $err->add($i18n->get('error.field'), $i18n->get('label.start')); - if ($cl_finish) { - if (!ttTimeHelper::isValidTime($cl_finish)) - $err->add($i18n->get('error.field'), $i18n->get('label.finish')); - if (!ttTimeHelper::isValidInterval($cl_start, $cl_finish)) - $err->add($i18n->get('error.interval'), $i18n->get('label.finish'), $i18n->get('label.start')); - } - } else { - if ($showStart) { - $err->add($i18n->get('error.empty'), $i18n->get('label.start')); - $err->add($i18n->get('error.empty'), $i18n->get('label.finish')); - } - if ($showDuration) - $err->add($i18n->get('error.empty'), $i18n->get('label.duration')); - } - } else { - if (false === ttTimeHelper::postedDurationToMinutes($cl_duration)) - $err->add($i18n->get('error.field'), $i18n->get('label.duration')); - } - if (!ttValidDate($cl_date)) $err->add($i18n->get('error.field'), $i18n->get('label.date')); - if (!ttValidString($cl_note, true)) $err->add($i18n->get('error.field'), $i18n->get('label.note')); - if ($user->isPluginEnabled('tp') && !ttValidTemplateText($cl_note)) { - $err->add($i18n->get('error.field'), $i18n->get('label.note')); - } - if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); - // Finished validating user input. - - // This is a new date for the time record. - $new_date = new DateAndTime($user->getDateFormat(), $cl_date); - - // Prohibit creating entries in future. - if (!$user->isOptionEnabled('future_entries')) { - $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); - if ($new_date->after($browser_today)) - $err->add($i18n->get('error.future_date')); - } - - // Save record. - if ($request->getParameter('btn_save')) { - // We need to: - // 1) Prohibit saving locked entries in any form. - // 2) Prohibit saving completed unlocked entries into locked range. - // 3) Prohibit saving uncompleted unlocked entries when another uncompleted entry exists. - - // Now, step by step. - if ($err->no()) { - // 1) Prohibit saving locked entries in any form. - if ($user->isDateLocked($item_date)) - $err->add($i18n->get('error.range_locked')); - - // 2) Prohibit saving completed unlocked entries into locked range. - if ($err->no() && $user->isDateLocked($new_date)) - $err->add($i18n->get('error.range_locked')); - - // 3) Prohibit saving uncompleted unlocked entries when another uncompleted entry exists. - $uncompleted = ($cl_finish == '' && $cl_duration == ''); - if ($uncompleted) { - $not_completed_rec = ttTimeHelper::getUncompleted($user_id); - if ($not_completed_rec && ($time_rec['id'] <> $not_completed_rec['id'])) { - // We have another not completed record. - $err->add($i18n->get('error.uncompleted_exists')." ".$i18n->get('error.goto_uncompleted').""); - } - } - } - - // Prohibit creating an overlapping record. - if ($err->no()) { - if (ttTimeHelper::overlaps($user_id, $new_date->toString(DB_DATEFORMAT), $cl_start, $cl_finish, $cl_id)) - $err->add($i18n->get('error.overlap')); - } - - // Now, an update. - if ($err->no()) { - $res = ttTimeHelper::update(array( - 'id'=>$cl_id, - 'date'=>$new_date->toString(DB_DATEFORMAT), - 'client'=>$cl_client, - 'project'=>$cl_project, - 'task'=>$cl_task, - 'start'=>$cl_start, - 'finish'=>$cl_finish, - 'duration'=>$cl_duration, - 'note'=>$cl_note, - 'billable'=>$cl_billable, - 'paid'=>$cl_paid)); - - // Update time custom fields if we have them. - if ($res && $custom_fields && $custom_fields->timeFields) { - $res = $custom_fields->updateTimeFields($cl_id, $timeCustomFields); - } - if ($res) - { - header('Location: time.php?date='.$new_date->toString(DB_DATEFORMAT)); - exit(); - } - } - } - - // Copy record. - if ($request->getParameter('btn_copy')) { - // We need to: - // 1) Prohibit saving into locked range. - // 2) Prohibit saving uncompleted unlocked entries when another uncompleted entry exists. - - // Now, step by step. - if ($err->no()) { - // 1) Prohibit saving into locked range. - if ($user->isDateLocked($new_date)) - $err->add($i18n->get('error.range_locked')); - - // 2) Prohibit saving uncompleted unlocked entries when another uncompleted entry exists. - $uncompleted = ($cl_finish == '' && $cl_duration == ''); - if ($uncompleted) { - $not_completed_rec = ttTimeHelper::getUncompleted($user_id); - if ($not_completed_rec) { - // We have another not completed record. - $err->add($i18n->get('error.uncompleted_exists')." ".$i18n->get('error.goto_uncompleted').""); - } - } - } - - // Prohibit creating an overlapping record. - if ($err->no()) { - if (ttTimeHelper::overlaps($user_id, $new_date->toString(DB_DATEFORMAT), $cl_start, $cl_finish)) - $err->add($i18n->get('error.overlap')); - } - - // Now, a new insert. - if ($err->no()) { - - $id = ttTimeHelper::insert(array( - 'date'=>$new_date->toString(DB_DATEFORMAT), - 'client'=>$cl_client, - 'project'=>$cl_project, - 'task'=>$cl_task, - 'start'=>$cl_start, - 'finish'=>$cl_finish, - 'duration'=>$cl_duration, - 'note'=>$cl_note, - 'billable'=>$cl_billable, - 'paid'=>$cl_paid)); - - // Insert time custom fields if we have them. - $res = true; - if ($id && $custom_fields && $custom_fields->timeFields) { - $res = $custom_fields->insertTimeFields($id, $timeCustomFields); - } - if ($id && $res) { - header('Location: time.php?date='.$new_date->toString(DB_DATEFORMAT)); - exit(); - } - $err->add($i18n->get('error.db')); - } - } - - if ($request->getParameter('btn_delete')) { - header("Location: time_delete.php?id=$cl_id"); - exit(); - } -} // isPost - -if ($confirm_save) { - $smarty->assign('confirm_save', true); - $smarty->assign('entry_date', $cl_date); -} -$smarty->assign('show_client', $showClient); -$smarty->assign('show_billable', $showBillable);+ -$smarty->assign('show_paid_status', $showPaidStatus); -$smarty->assign('show_project', $showProject); -$smarty->assign('show_task', $showTask); -$smarty->assign('task_required', $taskRequired); -$smarty->assign('show_start', $showStart); -$smarty->assign('show_duration', $showDuration); -$smarty->assign('client_list', $client_list); -$smarty->assign('project_list', $project_list); -$smarty->assign('task_list', $task_list); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="fillDropdowns()"'); -$smarty->assign('title', $i18n->get('title.edit_time_record')); -$smarty->assign('content_page_name', 'mobile/time_edit.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/user_add.php b/mobile/user_add.php deleted file mode 100644 index ed017de8a..000000000 --- a/mobile/user_add.php +++ /dev/null @@ -1,186 +0,0 @@ -isPluginEnabled('mq'); -if ($user->isPluginEnabled('cl')) - $clients = ttGroupHelper::getActiveClients(); - -$assigned_projects = array(); -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_login = trim($request->getParameter('login')); - if (!$auth->isPasswordExternal()) { - $cl_password1 = $request->getParameter('pas1'); - $cl_password2 = $request->getParameter('pas2'); - } - $cl_email = trim($request->getParameter('email')); - $cl_role_id = $request->getParameter('role'); - $cl_client_id = $request->getParameter('client'); - $cl_rate = $request->getParameter('rate'); - $cl_quota_percent = $request->getParameter('quota_percent'); - $cl_projects = $request->getParameter('projects'); - if (is_array($cl_projects)) { - foreach ($cl_projects as $p) { - if (ttValidFloat($request->getParameter('rate_'.$p), true)) { - $project_with_rate = array(); - $project_with_rate['id'] = $p; - $project_with_rate['rate'] = $request->getParameter('rate_'.$p); - $assigned_projects[] = $project_with_rate; - } else - $err->add($i18n->get('error.field'), 'rate_'.$p); - } - } -} - -$form = new Form('userForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); -if (!$auth->isPasswordExternal()) { - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); -} -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); - -$active_roles = ttTeamHelper::getActiveRolesForUser(); -$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles,'datakeys'=>array('id', 'name'))); -if ($user->isPluginEnabled('cl')) - $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); - -$form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'rate','format'=>'.2','value'=>$cl_rate)); -if ($show_quota) - $form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'quota_percent','format'=>'.2','value'=>$cl_quota_percent)); - -$show_projects = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); -if ($show_projects) { - $projects = ttGroupHelper::getActiveProjects(); - if (count($projects) == 0) $show_projects = false; -} - -// Define classes for the projects table. -class NameCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200,'valign'=>'top')); - $this->setValue(''); - return $this->toString(); - } -} -class RateCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - global $assigned_projects; - $field = new FloatField('rate_'.$table->getValueAtName($row, 'id')); - $field->setFormName($table->getFormName()); - $field->setSize(5); - $field->setFormat('.2'); - foreach ($assigned_projects as $p) { - if ($p['id'] == $table->getValueAtName($row,'id')) $field->setValue($p['rate']); - } - $this->setValue($field->getHtml()); - return $this->toString(); - } -} -// Create projects table. -$table = new Table('projects'); -$table->setIAScript('setDefaultRate'); -$table->setTableOptions(array('width'=>'250','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); -$table->setData($projects); -$table->setKeyField('id'); -$table->setValue($cl_projects); -$table->addColumn(new TableColumn('name', $i18n->get('label.project'), new NameCellRenderer())); -$table->addColumn(new TableColumn('p_rate', $i18n->get('form.users.rate'), new RateCellRenderer())); -$form->addInputElement($table); - -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.submit'))); - -if ($request->isPost()) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.person_name')); - if (!ttValidString($cl_login)) $err->add($i18n->get('error.field'), $i18n->get('label.login')); - if (!$auth->isPasswordExternal()) { - if (!ttValidString($cl_password1)) $err->add($i18n->get('error.field'), $i18n->get('label.password')); - if (!ttValidString($cl_password2)) $err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); - if ($cl_password1 !== $cl_password2) - $err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); - } - if (!ttValidEmail($cl_email, true)) $err->add($i18n->get('error.field'), $i18n->get('label.email')); - if (!ttValidFloat($cl_rate, true)) $err->add($i18n->get('error.field'), $i18n->get('form.users.default_rate')); - if (!ttValidFloat($cl_quota_percent, true)) $err->add($i18n->get('error.field'), $i18n->get('label.quota')); - if (!ttUserHelper::canAdd()) $err->add($i18n->get('error.user_count')); - - if ($err->no()) { - if (!ttUserHelper::getUserByLogin($cl_login)) { - $fields = array( - 'name' => $cl_name, - 'login' => $cl_login, - 'password' => $cl_password1, - 'rate' => $cl_rate, - 'quota_percent' => $cl_quota_percent, - 'group_id' => $user->getGroup(), - 'org_id' => $user->org_id, - 'role_id' => $cl_role_id, - 'client_id' => $cl_client_id, - 'projects' => $assigned_projects, - 'email' => $cl_email); - if (ttUserHelper::insert($fields)) { - header('Location: users.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.user_exists')); - } -} // isPost - -$smarty->assign('auth_external', $auth->isPasswordExternal()); -$smarty->assign('active_roles', $active_roles); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); -$smarty->assign('show_quota', $show_quota); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('title', $i18n->get('title.add_user')); -$smarty->assign('content_page_name', 'mobile/user_add.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/user_delete.php b/mobile/user_delete.php deleted file mode 100644 index 132f73022..000000000 --- a/mobile/user_delete.php +++ /dev/null @@ -1,87 +0,0 @@ -getParameter('id'); -$user_details = $user->getUserDetails($user_id); -if (!$user_details) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$smarty->assign('user_to_delete', $user_details['name']." (".$user_details['login'].")"); - -// Create confirmation form. -$form = new Form('userDeleteForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$user_id)); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); -$form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_delete')) { - if ($user->markUserDeleted($user_id)) { - // If we deleted the "on behalf" user reset its info in session. - if ($user_id == $user->behalf_id) { - unset($_SESSION['behalf_id']); - unset($_SESSION['behalf_name']); - } - // If we deleted our own account, do housekeeping and logout. - if ($user->id == $user_id) { - // Remove LOGIN_COOKIE_NAME cookie that stores login name. - unset($_COOKIE[LOGIN_COOKIE_NAME]); - setcookie(LOGIN_COOKIE_NAME, NULL, -1); - - $auth->doLogout(); - header('Location: login.php'); - } else { - header('Location: users.php'); - } - exit(); - } else { - $err->add($i18n->get('error.db')); - } - } - if ($request->getParameter('btn_cancel')) { - header('Location: users.php'); - exit(); - } -} // isPost - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('title', $i18n->get('title.delete_user')); -$smarty->assign('content_page_name', 'mobile/user_delete.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/user_edit.php b/mobile/user_edit.php deleted file mode 100644 index 58de5e8ab..000000000 --- a/mobile/user_edit.php +++ /dev/null @@ -1,245 +0,0 @@ -getParameter('id'); -$user_details = $user->getUserDetails($user_id); -if (!$user_details) { - header('Location: access_denied.php'); - exit(); -} -// End of access checks. - -$show_quota = $user->isPluginEnabled('mq'); -if ($user->isPluginEnabled('cl')) - $clients = ttGroupHelper::getActiveClients(); - -$show_projects = MODE_PROJECTS == $user->getTrackingMode() || MODE_PROJECTS_AND_TASKS == $user->getTrackingMode(); -if ($show_projects) { - $projects = ttGroupHelper::getActiveProjects(); - if (count($projects) == 0) $show_projects = false; -} -$assigned_projects = array(); - -if ($request->isPost()) { - $cl_name = trim($request->getParameter('name')); - $cl_login = trim($request->getParameter('login')); - if (!$auth->isPasswordExternal()) { - $cl_password1 = $request->getParameter('pas1'); - $cl_password2 = $request->getParameter('pas2'); - } - $cl_email = trim($request->getParameter('email')); - $cl_role_id = $request->getParameter('role'); - $cl_client_id = $request->getParameter('client'); - $cl_status = $request->getParameter('status'); - $cl_rate = $request->getParameter('rate'); - $cl_quota_percent = $request->getParameter('quota_percent'); - $cl_projects = $request->getParameter('projects'); - if (is_array($cl_projects)) { - foreach ($cl_projects as $p) { - if (ttValidFloat($request->getParameter('rate_'.$p), true)) { - $project_with_rate = array(); - $project_with_rate['id'] = $p; - $project_with_rate['rate'] = $request->getParameter('rate_'.$p); - $assigned_projects[] = $project_with_rate; - } else - $err->add($i18n->get('error.field'), 'rate_'.$p); - } - } -} else { - $cl_name = $user_details['name']; - $cl_login = $user_details['login']; - $cl_email = $user_details['email']; - $cl_rate = str_replace('.', $user->getDecimalMark(), $user_details['rate']); - $cl_quota_percent = str_replace('.', $user->getDecimalMark(), $user_details['quota_percent']); - $cl_role_id = $user_details['role_id']; - $cl_client_id = $user_details['client_id']; - $cl_status = $user_details['status']; - $cl_projects = array(); - $assigned_projects = ttProjectHelper::getAssignedProjects($user_id); - foreach($assigned_projects as $p) { - $cl_projects[] = $p['id']; - } -} - -$form = new Form('userForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'name','value'=>$cl_name)); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); -if (!$auth->isPasswordExternal()) { - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas1','value'=>$cl_password1)); - $form->addInput(array('type'=>'password','maxlength'=>'30','name'=>'pas2','value'=>$cl_password2)); -} -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'email','value'=>$cl_email)); - -$active_roles = ttTeamHelper::getActiveRolesForUser(); -$form->addInput(array('type'=>'combobox','onchange'=>'handleClientControl()','name'=>'role','value'=>$cl_role_id,'data'=>$active_roles,'datakeys'=>array('id', 'name'))); -if ($user->isPluginEnabled('cl')) - $form->addInput(array('type'=>'combobox','name'=>'client','value'=>$cl_client_id,'data'=>$clients,'datakeys'=>array('id', 'name'),'empty'=>array(''=>$i18n->get('dropdown.select')))); - -$form->addInput(array('type'=>'combobox','name'=>'status','value'=>$cl_status, - 'data'=>array(ACTIVE=>$i18n->get('dropdown.status_active'),INACTIVE=>$i18n->get('dropdown.status_inactive')))); -$form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'rate','format'=>'.2','value'=>$cl_rate)); -if ($show_quota) - $form->addInput(array('type'=>'floatfield','maxlength'=>'10','name'=>'quota_percent','format'=>'.2','value'=>$cl_quota_percent)); - -// Define classes for the projects table. -class NameCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - $this->setOptions(array('width'=>200,'valign'=>'top')); - $this->setValue(''); - return $this->toString(); - } -} -class RateCellRenderer extends DefaultCellRenderer { - function render(&$table, $value, $row, $column, $selected = false) { - global $assigned_projects; - $field = new FloatField('rate_'.$table->getValueAtName($row,'id')); - $field->setFormName($table->getFormName()); - $field->setSize(5); - $field->setFormat('.2'); - foreach ($assigned_projects as $p) { - if ($p['id'] == $table->getValueAtName($row,'id')) $field->setValue($p['rate']); - } - $this->setValue($field->getHtml()); - return $this->toString(); - } -} -// Create projects table. -$table = new Table('projects'); -$table->setIAScript('setRate'); -$table->setTableOptions(array('width'=>'250','cellspacing'=>'1','cellpadding'=>'3','border'=>'0')); -$table->setRowOptions(array('valign'=>'top','class'=>'tableHeader')); -$table->setData($projects); -$table->setKeyField('id'); -$table->setValue($cl_projects); -$table->addColumn(new TableColumn('name', $i18n->get('label.project'), new NameCellRenderer())); -$table->addColumn(new TableColumn('p_rate', $i18n->get('form.users.rate'), new RateCellRenderer())); -$form->addInputElement($table); - -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$user_id)); -$form->addInput(array('type'=>'submit','name'=>'btn_submit','value'=>$i18n->get('button.save'))); -$form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); - -if ($request->isPost()) { - if ($request->getParameter('btn_submit')) { - // Validate user input. - if (!ttValidString($cl_name)) $err->add($i18n->get('error.field'), $i18n->get('label.person_name')); - if (!ttValidString($cl_login)) $err->add($i18n->get('error.field'), $i18n->get('label.login')); - if (!$auth->isPasswordExternal() && ($cl_password1 || $cl_password2)) { - if (!ttValidString($cl_password1)) $err->add($i18n->get('error.field'), $i18n->get('label.password')); - if (!ttValidString($cl_password2)) $err->add($i18n->get('error.field'), $i18n->get('label.confirm_password')); - if ($cl_password1 !== $cl_password2) - $err->add($i18n->get('error.not_equal'), $i18n->get('label.password'), $i18n->get('label.confirm_password')); - } - if (!ttValidEmail($cl_email, true)) $err->add($i18n->get('error.field'), $i18n->get('label.email')); - if (!ttValidFloat($cl_rate, true)) $err->add($i18n->get('error.field'), $i18n->get('form.users.default_rate')); - if (!ttValidFloat($cl_quota_percent, true)) $err->add($i18n->get('error.field'), $i18n->get('label.quota')); - - if ($err->no()) { - $existing_user = ttUserHelper::getUserByLogin($cl_login); - if (!$existing_user || ($user_id == $existing_user['id'])) { - - $fields = array( - 'name' => $cl_name, - 'login' => $cl_login, - 'password' => $cl_password1, - 'email' => $cl_email, - 'status' => $cl_status, - 'rate' => $cl_rate, - 'quota_percent' => $cl_quota_percent, - 'projects' => $assigned_projects); - if (in_array('manage_users', $user->rights)) { - $fields['role_id'] = $cl_role_id; - $fields['client_id'] = $cl_client_id; - } - - if (ttUserHelper::update($user_id, $fields)) { - - // If our own login changed, set new one in cookie to remember it. - if (($user_id == $user->id) && ($user->login != $cl_login)) { - setcookie(LOGIN_COOKIE_NAME, $cl_login, time() + COOKIE_EXPIRE, '/'); - } - - // In case the name of the "on behalf" user has changed - set it in session. - if (($user->behalf_id == $user_id) && ($user->behalf_name != $cl_name)) { - $_SESSION['behalf_name'] = $cl_name; - } - - // If we deactivated our own account, do housekeeping and logout. - if ($user->id == $user_id && !is_null($cl_status) && $cl_status == INACTIVE) { - // Remove LOGIN_COOKIE_NAME cookie that stores login name. - unset($_COOKIE[LOGIN_COOKIE_NAME]); - setcookie(LOGIN_COOKIE_NAME, NULL, -1); - - $auth->doLogout(); - header('Location: login.php'); - exit(); - } - - header('Location: users.php'); - exit(); - - } else - $err->add($i18n->get('error.db')); - } else - $err->add($i18n->get('error.user_exists')); - } - } - - if ($request->getParameter('btn_delete')) { - header("Location: user_delete.php?id=$user_id"); - exit(); - } -} // isPost - -$rates = ttProjectHelper::getRates($user_id); -$smarty->assign('rates', $rates); - -$smarty->assign('auth_external', $auth->isPasswordExternal()); -$smarty->assign('active_roles', $active_roles); -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('onload', 'onLoad="document.userForm.name.focus();handleClientControl();"'); -$smarty->assign('show_quota', $show_quota); -$smarty->assign('show_projects', $show_projects); -$smarty->assign('user_id', $user_id); -$smarty->assign('title', $i18n->get('title.edit_user')); -$smarty->assign('content_page_name', 'mobile/user_edit.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/users.php b/mobile/users.php index d51cafcab..0e52072fb 100644 --- a/mobile/users.php +++ b/mobile/users.php @@ -32,6 +32,11 @@ import('ttGroupHelper'); import('ttTimeHelper'); +// Mobile pages are no longer separate. Redirect to main page. +header('Location: ../users.php'); +exit(); +// Below is no longer used code. + // Access checks. if (!(ttAccessAllowed('view_users') || ttAccessAllowed('manage_users'))) { header('Location: access_denied.php'); From 5ba5e875dcf313422b5ab1ad90fc112218deea40 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 7 Dec 2020 18:13:07 +0000 Subject: [PATCH 154/587] Cosmetic style improvement. --- default.css | 2 ++ initialize.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/default.css b/default.css index 595967e64..95f56094b 100644 --- a/default.css +++ b/default.css @@ -424,6 +424,8 @@ div.section-header { text-align: center; margin-left: auto; margin-right: auto; + margin-top: .5rem; + margin-bottom: .5rem; } /* div for a group of items in site map */ diff --git a/initialize.php b/initialize.php index 265d13aea..47f069ba8 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5407"); +define("APP_VERSION", "1.19.23.5408"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 1a4d9c3418ce261883057554887f2b36f0c5425b Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 8 Dec 2020 13:00:38 +0000 Subject: [PATCH 155/587] Improved mobile presentation of vertically stacked checkboxes. --- WEB-INF/templates/client_add2.tpl | 2 +- WEB-INF/templates/client_edit2.tpl | 2 +- WEB-INF/templates/project_add2.tpl | 4 ++-- WEB-INF/templates/project_edit2.tpl | 4 ++-- WEB-INF/templates/task_add2.tpl | 2 +- WEB-INF/templates/task_edit2.tpl | 2 +- default.css | 6 ++++++ initialize.php | 2 +- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/WEB-INF/templates/client_add2.tpl b/WEB-INF/templates/client_add2.tpl index 2704a133c..ac7a63efc 100644 --- a/WEB-INF/templates/client_add2.tpl +++ b/WEB-INF/templates/client_add2.tpl @@ -28,7 +28,7 @@ License: See license.txt *} {$i18n.label.projects}: {$i18n.label.projects}: - {$forms.clientForm.projects.control} + {$forms.clientForm.projects.control}
    {/if} diff --git a/WEB-INF/templates/client_edit2.tpl b/WEB-INF/templates/client_edit2.tpl index 67b79ecdf..39c965ae0 100644 --- a/WEB-INF/templates/client_edit2.tpl +++ b/WEB-INF/templates/client_edit2.tpl @@ -34,7 +34,7 @@ License: See license.txt *} {$i18n.label.projects}: {$i18n.label.projects}: - {$forms.clientForm.projects.control} + {$forms.clientForm.projects.control}
    {/if} diff --git a/WEB-INF/templates/project_add2.tpl b/WEB-INF/templates/project_add2.tpl index cd900cf36..8cc43fcaa 100644 --- a/WEB-INF/templates/project_add2.tpl +++ b/WEB-INF/templates/project_add2.tpl @@ -28,7 +28,7 @@ License: See license.txt *} {$i18n.label.users}: {$i18n.label.users}: - {$forms.projectForm.users.control} + {$forms.projectForm.users.control}
    {/if} @@ -37,7 +37,7 @@ License: See license.txt *} {$i18n.label.tasks}: {$i18n.label.tasks}: - {$forms.projectForm.tasks.control} + {$forms.projectForm.tasks.control}
    {/if} diff --git a/WEB-INF/templates/project_edit2.tpl b/WEB-INF/templates/project_edit2.tpl index f7b23a9ac..3ecc85a84 100644 --- a/WEB-INF/templates/project_edit2.tpl +++ b/WEB-INF/templates/project_edit2.tpl @@ -26,7 +26,7 @@ License: See license.txt *} {$i18n.label.users}: {$i18n.label.users}: - {$forms.projectForm.users.control} + {$forms.projectForm.users.control}
    {/if} @@ -35,7 +35,7 @@ License: See license.txt *} {$i18n.label.tasks}: {$i18n.label.tasks}: - {$forms.projectForm.tasks.control} + {$forms.projectForm.tasks.control}
    {/if} diff --git a/WEB-INF/templates/task_add2.tpl b/WEB-INF/templates/task_add2.tpl index 1b1c4e42e..d933160af 100644 --- a/WEB-INF/templates/task_add2.tpl +++ b/WEB-INF/templates/task_add2.tpl @@ -20,7 +20,7 @@ License: See license.txt *} {$i18n.label.projects}: {$i18n.label.projects}: - {$forms.taskForm.projects.control} + {$forms.taskForm.projects.control}
    {/if} diff --git a/WEB-INF/templates/task_edit2.tpl b/WEB-INF/templates/task_edit2.tpl index 9292ad151..c6e433b73 100644 --- a/WEB-INF/templates/task_edit2.tpl +++ b/WEB-INF/templates/task_edit2.tpl @@ -26,7 +26,7 @@ License: See license.txt *} {$i18n.label.projects}: {$i18n.label.projects}: - {$forms.taskForm.projects.control} + {$forms.taskForm.projects.control}
    {/if} diff --git a/default.css b/default.css index 95f56094b..377197f28 100644 --- a/default.css +++ b/default.css @@ -233,6 +233,12 @@ div.record-list { text-align: left; } +/* a table cell containing a set ov vertically stacked checkboxes */ +.td-with-checkboxes { + text-align: left; + width: 300px; +} + /* div containing how to contribute message */ div.contribute-msg { text-align: center; diff --git a/initialize.php b/initialize.php index 47f069ba8..6ccd4533e 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5408"); +define("APP_VERSION", "1.19.23.5409"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 7e9111012d54e0feae92598b508f99cb035167d0 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Wed, 20 Jan 2021 17:26:27 +0000 Subject: [PATCH 156/587] Dutch translation improved. --- WEB-INF/resources/nl.lang.php | 12 +++--------- initialize.php | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/WEB-INF/resources/nl.lang.php b/WEB-INF/resources/nl.lang.php index 6d51082c7..70750349d 100644 --- a/WEB-INF/resources/nl.lang.php +++ b/WEB-INF/resources/nl.lang.php @@ -390,16 +390,12 @@ // Login form. See example at https://timetracker.anuko.com/login.php. 'form.login.forgot_password' => 'Wachtwoord vergeten?', - // TODO: re-translate form.login.about as it has changed. - // 'form.login.about' => 'Anuko Time Tracker is an open source time tracking system.', -'form.login.about' => 'Anuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem.', +'form.login.about' => 'Anuko Time Tracker is een open source tijdregistratiesysteem.', // Resetting Password form. See example at https://timetracker.anuko.com/password_reset.php. 'form.reset_password.message' => 'Het verzoek om het wachtwoord te herstellen is verzonden per email.', 'form.reset_password.email_subject' => 'Anuko Time Tracker wachtwoord herstel verzoek', -// TODO: retranslate form.reset_password.email_body as the string has changed. -// 'form.reset_password.email_body' => "Dear User,\n\nSomeone from IP %s requested your Anuko Time Tracker password reset. Please visit this link if you want to reset your password.\n\n%s\n\nAnuko Time Tracker is an open source time tracking system. Visit https://www.anuko.com for more information.\n\n", -'form.reset_password.email_body' => "Geachte medewerker,\n\nIemand, met IP adres %s, heeft verzocht uw wachtwoord in Anuko Time Tracker te herstellen. Klik op deze link als u uw wachtwoord wil wijzigen.\n\n%s\n\nAnuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem. Bezoek https://www.anuko.com voor meer informatie.\n\n", +'form.reset_password.email_body' => "Beste gebruiker,\n\nIemand, met IP adres %s, heeft verzocht uw wachtwoord in Anuko Time Tracker te herstellen. Klik op deze link als u uw wachtwoord wil wijzigen.\n\n%s\n\nAnuko Time Tracker is een open source tijdregistratiesysteem. Bezoek https://www.anuko.com voor meer informatie.\n\n", // Changing Password form. See example at https://timetracker.anuko.com/password_change.php?ref=1. 'form.change_password.tip' => 'Voer het nieuwe wachtwoord in en klik op Bewaren.', @@ -546,9 +542,7 @@ // Mail form. See example at https://timetracker.anuko.com/report_send.php when emailing a report. 'form.mail.to' => 'Aan', 'form.mail.report_subject' => 'Time Tracker rapport', -// TODO: retranslate form.mail.footer as the English string has changed. -// 'form.mail.footer' => 'Anuko Time Tracker is an open source
    time tracking system. Visit www.anuko.com for more information.', -'form.mail.footer' => 'Anuko Time Tracker is een eenvoudig en gemakkelijk te gebruiken open source tijdregistratiesysteem. Bezoek www.anuko.com voor meer informatie.', +'form.mail.footer' => 'Anuko Time Tracker is een open source tijdregistratiesysteem. Bezoek www.anuko.com voor meer informatie.', 'form.mail.report_sent' => 'Rapport is verzonden.', 'form.mail.invoice_sent' => 'Factuur is verzonden.', diff --git a/initialize.php b/initialize.php index 6ccd4533e..f955479f7 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5409"); +define("APP_VERSION", "1.19.23.5410"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 13ad968d9729dbff50acdeb652bba5e298633c0e Mon Sep 17 00:00:00 2001 From: Josh Bowers Date: Wed, 27 Jan 2021 07:06:47 -0800 Subject: [PATCH 157/587] extra '+' character and end of line causing error (#105) PHP Fatal error: Uncaught TypeError: Unsupported operand types: Smarty * int in ./time_edit.php:453 --- time_edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/time_edit.php b/time_edit.php index 89988409b..4065bf08f 100644 --- a/time_edit.php +++ b/time_edit.php @@ -449,7 +449,7 @@ $smarty->assign('entry_date', $cl_date); } $smarty->assign('show_client', $showClient); -$smarty->assign('show_billable', $showBillable);+ +$smarty->assign('show_billable', $showBillable); $smarty->assign('show_paid_status', $showPaidStatus); $smarty->assign('show_project', $showProject); $smarty->assign('show_task', $showTask); From 87b5c171f0ddb7ba24e5cf86a5238f1564e12459 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 20 Feb 2021 21:03:38 +0000 Subject: [PATCH 158/587] A couple of minor fixes to remove some php8 warnings. --- WEB-INF/lib/DateAndTime.class.php | 3 ++- WEB-INF/lib/ttUser.class.php | 1 + initialize.php | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/WEB-INF/lib/DateAndTime.class.php b/WEB-INF/lib/DateAndTime.class.php index 20f274265..1184bd853 100644 --- a/WEB-INF/lib/DateAndTime.class.php +++ b/WEB-INF/lib/DateAndTime.class.php @@ -325,6 +325,7 @@ function preprocessFormatString($format) { // replace locale-dependent strings $format = str_replace('%a', mb_substr($i18n->getWeekDayName($this->mDay), 0, 3, 'utf-8'), $format); $format = str_replace('%A', $i18n->getWeekDayName($this->mDay), $format); + /* This block is commented out because we currently do not use these formatters. $abbrev_month = mb_substr($i18n->monthNames[$this->mMonth], 0, 3, 'utf-8'); $format = str_replace('%b', $abbrev_month, $format); $format = str_replace('%h', $abbrev_month, $format); @@ -332,7 +333,7 @@ function preprocessFormatString($format) { $format = str_replace('%Z', date('O'), $format); // format as 'O' for consistency with JS strftime if (strpos($format, '%c') !== false) { $format = str_replace('%c', $this->preprocessFormatString('%a %d %b %Y %T %Z'), $format); - } + }*/ return $format; } diff --git a/WEB-INF/lib/ttUser.class.php b/WEB-INF/lib/ttUser.class.php index 72b829d31..c006350fd 100644 --- a/WEB-INF/lib/ttUser.class.php +++ b/WEB-INF/lib/ttUser.class.php @@ -488,6 +488,7 @@ function getUsers($options) { $includeSelf = isset($options['include_self']); $select_part = 'select u.id, u.group_id, u.name'; + $include_quota = false; if (isset($options['include_login'])) { $select_part .= ', u.login'; // Piggy-back on include_login to see if we must also include quota_percent. diff --git a/initialize.php b/initialize.php index f955479f7..55b1a1034 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5410"); +define("APP_VERSION", "1.19.23.5411"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From f3f9921ce9d15b84658b40bf1cefe4870490e0ab Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 20 Feb 2021 21:56:04 +0000 Subject: [PATCH 159/587] A couple more fixes for php8. --- WEB-INF/lib/form/Calendar.class.php | 2 +- WEB-INF/lib/ttUser.class.php | 4 +++- initialize.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/WEB-INF/lib/form/Calendar.class.php b/WEB-INF/lib/form/Calendar.class.php index d335e1503..337737f1c 100644 --- a/WEB-INF/lib/form/Calendar.class.php +++ b/WEB-INF/lib/form/Calendar.class.php @@ -80,7 +80,7 @@ function getHtml() { $firstOfPreviousMonth = strftime(DB_DATEFORMAT, $firstOfPreviousMonth2AM); // Print calendar header. - $html .= "\n\n\n"; + $html = "\n\n\n"; $html .= ''."\n"; $html .= '
    '; $html .= '
    '; diff --git a/WEB-INF/lib/ttUser.class.php b/WEB-INF/lib/ttUser.class.php index c006350fd..b01ffe687 100644 --- a/WEB-INF/lib/ttUser.class.php +++ b/WEB-INF/lib/ttUser.class.php @@ -347,7 +347,9 @@ function getAssignedProjects($options = null) $group_id = $this->getGroup(); $org_id = $this->org_id; - if ($options['include_files']) { + $filePart = ''; + $fileJoin = ''; + if (isset($options['include_files'])) { $filePart = ', if(Sub1.entity_id is null, 0, 1) as has_files'; $fileJoin = " left join (select distinct entity_id from tt_files". " where entity_type = 'project' and group_id = $group_id and org_id = $org_id and status = 1) Sub1". diff --git a/initialize.php b/initialize.php index 55b1a1034..1aa264cca 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5411"); +define("APP_VERSION", "1.19.23.5412"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 6a5b24018a7c9d5744c84e8135d588b81b9ae6cf Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 20 Feb 2021 23:11:47 +0000 Subject: [PATCH 160/587] Updated smarty to version 3.1.39 for better php8 support. --- WEB-INF/lib/smarty/Smarty.class.php | 7 +++---- WEB-INF/lib/smarty/SmartyBC.class.php | 2 +- .../smarty_internal_compile_function.php | 5 +++++ ...internal_compile_private_special_variable.php | 8 ++++++-- .../smarty_internal_config_file_compiler.php | 4 ++-- .../sysplugins/smarty_internal_errorhandler.php | 2 +- .../smarty_internal_parsetree_template.php | 16 ++++++++-------- WEB-INF/templates/time2.tpl | 2 ++ initialize.php | 2 +- 9 files changed, 29 insertions(+), 19 deletions(-) diff --git a/WEB-INF/lib/smarty/Smarty.class.php b/WEB-INF/lib/smarty/Smarty.class.php index 9e0ca7670..375bab133 100644 --- a/WEB-INF/lib/smarty/Smarty.class.php +++ b/WEB-INF/lib/smarty/Smarty.class.php @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,7 +27,6 @@ * @author Uwe Tews * @author Rodney Rehm * @package Smarty - * @version 3.1.34-dev */ /** * set SMARTY_DIR to absolute path to Smarty library files. @@ -112,7 +111,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.36'; + const SMARTY_VERSION = '3.1.39'; /** * define variable scopes */ @@ -800,7 +799,7 @@ public function addTemplateDir($template_dir, $key = null, $isConfig = false) * @param mixed $index index of directory to get, null to get all * @param bool $isConfig true for config_dir * - * @return array list of template directories, or directory of $index + * @return array|string list of template directories, or directory of $index */ public function getTemplateDir($index = null, $isConfig = false) { diff --git a/WEB-INF/lib/smarty/SmartyBC.class.php b/WEB-INF/lib/smarty/SmartyBC.class.php index 836f98153..0550e46dc 100644 --- a/WEB-INF/lib/smarty/SmartyBC.class.php +++ b/WEB-INF/lib/smarty/SmartyBC.class.php @@ -6,7 +6,7 @@ * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * version 3.0 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_function.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_function.php index 6e408ca72..d0f2b0f4a 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_function.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_function.php @@ -58,6 +58,11 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) } unset($_attr[ 'nocache' ]); $_name = trim($_attr[ 'name' ], '\'"'); + + if (!preg_match('/^[a-zA-Z0-9_\x80-\xff]+$/', $_name)) { + $compiler->trigger_template_error("Function name contains invalid characters: {$_name}", null, true); + } + $compiler->parent_compiler->tpl_function[ $_name ] = array(); $save = array( $_attr, $compiler->parser->current_buffer, $compiler->template->compiled->has_nocache_code, diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php index b317c9f33..d53ef51ff 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_compile_private_special_variable.php @@ -81,6 +81,10 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $ case 'template': return 'basename($_smarty_tpl->source->filepath)'; case 'template_object': + if (isset($compiler->smarty->security_policy)) { + $compiler->trigger_template_error("(secure mode) template_object not permitted"); + break; + } return '$_smarty_tpl'; case 'current_dir': return 'dirname($_smarty_tpl->source->filepath)'; @@ -94,9 +98,9 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $ break; } if (strpos($_index[ 1 ], '$') === false && strpos($_index[ 1 ], '\'') === false) { - return "@constant('{$_index[1]}')"; + return "(defined('{$_index[1]}') ? constant('{$_index[1]}') : null)"; } else { - return "@constant({$_index[1]})"; + return "(defined({$_index[1]}) ? constant({$_index[1]}) : null)"; } // no break case 'config': diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php index a842fa8f3..90c5dcefa 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_config_file_compiler.php @@ -115,7 +115,7 @@ public function compileTemplate(Smarty_Internal_Template $template) $this->smarty->_debug->start_compile($this->template); } // init the lexer/parser to compile the config file - /* @var Smarty_Internal_ConfigFileLexer $this ->lex */ + /* @var Smarty_Internal_ConfigFileLexer $this->lex */ $this->lex = new $this->lexer_class( str_replace( array( @@ -127,7 +127,7 @@ public function compileTemplate(Smarty_Internal_Template $template) ) . "\n", $this ); - /* @var Smarty_Internal_ConfigFileParser $this ->parser */ + /* @var Smarty_Internal_ConfigFileParser $this->parser */ $this->parser = new $this->parser_class($this->lex, $this); if (function_exists('mb_internal_encoding') && function_exists('ini_get') diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php index 0ba00659d..56dca18fa 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_errorhandler.php @@ -65,7 +65,7 @@ public static function muteExpectedErrors() * * @return bool */ - public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) + public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext = array()) { $_is_muted_directory = false; // add the SMARTY_DIR to the list of muted directories diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php index 477232ef8..ab4c3ec3b 100644 --- a/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_parsetree_template.php @@ -127,12 +127,12 @@ public function to_smarty_php(Smarty_Internal_Templateparser $parser) } private function getChunkedSubtrees() { - $chunks = []; + $chunks = array(); $currentMode = null; - $currentChunk = []; + $currentChunk = array(); for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) { - if ($this->subtrees[ $key ]->data === '' && in_array($currentMode, ['textstripped', 'text', 'tag'])) { + if ($this->subtrees[ $key ]->data === '' && in_array($currentMode, array('textstripped', 'text', 'tag'))) { continue; } @@ -150,19 +150,19 @@ private function getChunkedSubtrees() { if ($newMode == $currentMode) { $currentChunk[] = $this->subtrees[ $key ]; } else { - $chunks[] = [ + $chunks[] = array( 'mode' => $currentMode, 'subtrees' => $currentChunk - ]; + ); $currentMode = $newMode; - $currentChunk = [$this->subtrees[ $key ]]; + $currentChunk = array($this->subtrees[ $key ]); } } if ($currentMode && $currentChunk) { - $chunks[] = [ + $chunks[] = array( 'mode' => $currentMode, 'subtrees' => $currentChunk - ]; + ); } return $chunks; } diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 487bff7cf..65216efb8 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -234,3 +234,5 @@ License: See license.txt *} {/if}
    + +{$smarty.version} diff --git a/initialize.php b/initialize.php index 1aa264cca..771995d88 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5412"); +define("APP_VERSION", "1.19.23.5413"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 85823f48d86f438909af947b57038a1090283030 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 26 Feb 2021 16:24:51 +0000 Subject: [PATCH 161/587] A minor fix to dbinstall.php to address a migration issue with custom fields. --- dbinstall.php | 4 ++-- initialize.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dbinstall.php b/dbinstall.php index 59d3923f8..9960e1ade 100644 --- a/dbinstall.php +++ b/dbinstall.php @@ -691,10 +691,10 @@ function ttGenerateKeys() { print "Updated $clients_updated clients...
    \n"; } - // The update_custom_fields function updates option_id field field in tt_custom_field_log table. + // The update_custom_fields function updates option_id field in tt_custom_field_log table. if ($_POST['update_custom_fields']) { $mdb2 = getConnection(); - $sql = "update tt_custom_field_log set option_id = value where field_id in (select id from tt_custom_fields where type = 2)"; + $sql = "update tt_custom_field_log set option_id = value where option_id is null and value is not null and field_id in (select id from tt_custom_fields where type = 2)"; $affected = $mdb2->exec($sql); if (is_a($affected, 'PEAR_Error')) die($affected->getMessage()); diff --git a/initialize.php b/initialize.php index 771995d88..5323d00b8 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5413"); +define("APP_VERSION", "1.19.23.5414"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 40f3d9345adc20e6f28eb9f59e2489aff87fecf5 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 16:00:53 +0000 Subject: [PATCH 162/587] Fixed a critical security vulnerability with password resets. --- WEB-INF/templates/report.tpl | 4 ++++ initialize.php | 2 +- password_reset.php | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/WEB-INF/templates/report.tpl b/WEB-INF/templates/report.tpl index f7ef4ff2e..0a13ea83a 100644 --- a/WEB-INF/templates/report.tpl +++ b/WEB-INF/templates/report.tpl @@ -117,6 +117,7 @@ {if $bean->getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')}{/if} {if $use_checkboxes}{/if} + {* {* column for edit icons *}   {/if} @@ -171,6 +172,7 @@ {if 1 == $item.type}{/if} {if 2 == $item.type}{/if} {/if} + {* {$i18n.label.edit}{* column for edit icons *} {if $note_on_separate_row && $bean->getAttribute('chnote') && $item.note} @@ -220,6 +222,7 @@ {if $bean->getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')}{/if} {if $use_checkboxes}{/if} + {* {* column for edit icons *} {/if} @@ -261,6 +264,7 @@ {if $bean->getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')}{/if} {if $use_checkboxes}{/if} + {* {* column for edit icons *} {/if} diff --git a/initialize.php b/initialize.php index 5323d00b8..e2aeb6c85 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.23.5414"); +define("APP_VERSION", "1.19.24.5415"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/password_reset.php b/password_reset.php index 5beafb7fc..53099b9af 100644 --- a/password_reset.php +++ b/password_reset.php @@ -46,7 +46,10 @@ if ($err->no()) { // Prepare and save a temporary reference for user. - $temp_ref = md5(uniqid()); + $cryptographically_strong = true; + $random_bytes = openssl_random_pseudo_bytes(16, $cryptographically_strong); + if ($random_bytes === false) die ("openssl_random_pseudo_bytes function call failed..."); + $temp_ref = bin2hex($random_bytes); ttUserHelper::saveTmpRef($temp_ref, $user->id); $user_i18n = null; From 1339c3a043a916cd7f5142c3aec4a956b598f69c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 16:19:09 +0000 Subject: [PATCH 163/587] Added protection against brute force guessing of random codes used in password resets. --- WEB-INF/lib/ttUserHelper.class.php | 5 +++++ initialize.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/WEB-INF/lib/ttUserHelper.class.php b/WEB-INF/lib/ttUserHelper.class.php index eac057304..accabe1fe 100644 --- a/WEB-INF/lib/ttUserHelper.class.php +++ b/WEB-INF/lib/ttUserHelper.class.php @@ -82,6 +82,11 @@ static function getUserByEmail($email) { static function getUserIdByTmpRef($ref) { $mdb2 = getConnection(); + // Some protection for brute force attacks to guess a reference for user. + // This limits an available window for brute force guessing to 1 hour. + $sql = "delete from tt_tmp_refs where created < now() - interval 1 hour"; + $affected = $mdb2->exec($sql); + $sql = "select user_id from tt_tmp_refs where ref = ".$mdb2->quote($ref); $res = $mdb2->query($sql); diff --git a/initialize.php b/initialize.php index e2aeb6c85..63215b71e 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.24.5415"); +define("APP_VERSION", "1.19.24.5416"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 9a8ee13a037931d29130379c9ad193613b45998c Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 17:35:22 +0000 Subject: [PATCH 164/587] Fixed SQL injection vulnerability in group_edit.php. --- group_edit.php | 6 ++++-- initialize.php | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/group_edit.php b/group_edit.php index c8ad2e142..f60a11331 100644 --- a/group_edit.php +++ b/group_edit.php @@ -32,15 +32,17 @@ import('ttRoleHelper'); import('ttConfigHelper'); +$id = (int)$request->getParameter('id'); + // Access checks. // There are 4 distinct situations: // 1) Editing home group in get or post. // 2) Editing a subgroup in get or post. // We'll check access separately as it is about different right checks. if ($request->isGet()) { - $group_id = $request->getParameter('id') ? $request->getParameter('id') : $user->getGroup(); + $group_id = $request->getParameter('id') ? (int)$request->getParameter('id') : $user->getGroup(); } else { - $group_id = $request->getParameter('group') ? $request->getParameter('group') : $user->getGroup(); + $group_id = $request->getParameter('group') ? (int)$request->getParameter('group') : $user->getGroup(); } $home_group = $user->group_id == $group_id; if ($home_group) { diff --git a/initialize.php b/initialize.php index 63215b71e..f069495f9 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.24.5416"); +define("APP_VERSION", "1.19.25.5417"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 2b34dc2006121e466513b50015262c6936c876bf Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 17:37:58 +0000 Subject: [PATCH 165/587] Removed garbage introduced in previous commit. --- group_edit.php | 2 -- initialize.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/group_edit.php b/group_edit.php index f60a11331..49bd1e613 100644 --- a/group_edit.php +++ b/group_edit.php @@ -32,8 +32,6 @@ import('ttRoleHelper'); import('ttConfigHelper'); -$id = (int)$request->getParameter('id'); - // Access checks. // There are 4 distinct situations: // 1) Editing home group in get or post. diff --git a/initialize.php b/initialize.php index f069495f9..7863d0aba 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.25.5417"); +define("APP_VERSION", "1.19.25.5418"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From fdf67755ae8396162b19332e3b10763c9ea274b2 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 17:49:19 +0000 Subject: [PATCH 166/587] More protection against sql injections. --- group_edit.php | 28 ++-------------------------- groups.php | 30 +++--------------------------- initialize.php | 2 +- 3 files changed, 6 insertions(+), 54 deletions(-) diff --git a/group_edit.php b/group_edit.php index 49bd1e613..d972ba387 100644 --- a/group_edit.php +++ b/group_edit.php @@ -1,30 +1,6 @@ isPost()) { - $group_id = $request->getParameter('group'); + $group_id = (int)$request->getParameter('group'); $user->setOnBehalfGroup($group_id); } else { $group_id = $user->getGroup(); diff --git a/initialize.php b/initialize.php index 7863d0aba..40ccda78d 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.25.5418"); +define("APP_VERSION", "1.19.25.5419"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 00885b9872c31eb3298b047ee2a27b278248d4c5 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 18:22:24 +0000 Subject: [PATCH 167/587] Added casts to int to sanitize some post parameters. --- admin_group_add.php | 28 ++-------------------------- admin_group_delete.php | 28 ++-------------------------- admin_group_edit.php | 28 ++-------------------------- admin_groups.php | 28 ++-------------------------- admin_options.php | 28 ++-------------------------- cf_custom_field_add.php | 36 +++++------------------------------- initialize.php | 2 +- 7 files changed, 16 insertions(+), 162 deletions(-) diff --git a/admin_group_add.php b/admin_group_add.php index c42644f09..45aa32261 100644 --- a/admin_group_add.php +++ b/admin_group_add.php @@ -1,30 +1,6 @@ isPost()) { $cl_field_name = trim($request->getParameter('name')); - $cl_entity_type = $request->getParameter('entity'); - $cl_field_type = $request->getParameter('type'); - $cl_required = $request->getParameter('required'); - if (!$cl_required) - $cl_required = 0; + $cl_entity_type = (int)$request->getParameter('entity'); + $cl_field_type = (int)$request->getParameter('type'); + $cl_required = (int)$request->getParameter('required'); } $form = new Form('fieldForm'); diff --git a/initialize.php b/initialize.php index 40ccda78d..c5edb812a 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.25.5419"); +define("APP_VERSION", "1.19.25.5420"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From bc006920353e50e27d815a8f5d529269080db40e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 27 Feb 2021 18:50:14 +0000 Subject: [PATCH 168/587] More sanitizing of user input. --- cf_custom_field_delete.php | 28 ++-------------------------- cf_custom_field_edit.php | 28 ++-------------------------- cf_custom_fields.php | 28 ++-------------------------- cf_dropdown_option_add.php | 28 ++-------------------------- cf_dropdown_option_delete.php | 30 +++--------------------------- cf_dropdown_option_edit.php | 30 +++--------------------------- cf_dropdown_options.php | 28 ++-------------------------- 7 files changed, 16 insertions(+), 184 deletions(-) diff --git a/cf_custom_field_delete.php b/cf_custom_field_delete.php index c8a133692..ba222c657 100644 --- a/cf_custom_field_delete.php +++ b/cf_custom_field_delete.php @@ -1,30 +1,6 @@ getParameter('id'); +$cl_id = (int)$request->getParameter('id'); $option = CustomFields::getOptionName($cl_id); if (!$option) { header('Location: access_denied.php'); diff --git a/cf_dropdown_option_edit.php b/cf_dropdown_option_edit.php index 4f1103d7b..4cea7358f 100644 --- a/cf_dropdown_option_edit.php +++ b/cf_dropdown_option_edit.php @@ -1,30 +1,6 @@ getParameter('id'); +$cl_id = (int)$request->getParameter('id'); $cl_name = CustomFields::getOptionName($cl_id); if (!$cl_name) { header('Location: access_denied.php'); diff --git a/cf_dropdown_options.php b/cf_dropdown_options.php index 3b4663f8c..06f53a7d8 100644 --- a/cf_dropdown_options.php +++ b/cf_dropdown_options.php @@ -1,30 +1,6 @@ Date: Sat, 27 Feb 2021 23:13:24 +0000 Subject: [PATCH 169/587] Added edit icons on reports to allow for quick edits. --- WEB-INF/lib/ttExpenseHelper.class.php | 66 ++++++++++++++++----------- WEB-INF/lib/ttReportHelper.class.php | 14 +++--- WEB-INF/lib/ttTimeHelper.class.php | 66 ++++++++++++++++----------- WEB-INF/lib/ttUserHelper.class.php | 28 +----------- WEB-INF/templates/report.tpl | 13 ++++-- expense_edit.php | 1 + initialize.php | 2 +- time_edit.php | 1 + 8 files changed, 102 insertions(+), 89 deletions(-) diff --git a/WEB-INF/lib/ttExpenseHelper.class.php b/WEB-INF/lib/ttExpenseHelper.class.php index 303ca5767..0de7eca11 100644 --- a/WEB-INF/lib/ttExpenseHelper.class.php +++ b/WEB-INF/lib/ttExpenseHelper.class.php @@ -1,30 +1,6 @@ isUserValid($user_id); + + if (!$user_valid) return false; + + // Set on behalf user. + $user->setOnBehalfUser($user_id); + // Get on behalf record. + return ttExpenseHelper::getItem($id); + } + + // getUserForItem - retrieves user id for an expense item. + static function getUserForItem($id) { + global $user; + + $group_id = $user->getGroup(); + $org_id = $user->org_id; + + $mdb2 = getConnection(); + + // Obtain user_id for the expense item. + $sql = "select ei.user_id from tt_expense_items ei ". + " where ei.id = $id and ei.group_id = $group_id and ei.org_id = $org_id and ei.status = 1"; + $res = $mdb2->query($sql); + if (is_a($res, 'PEAR_Error')) return false; + if (!$res->numRows()) return false; + + $val = $res->fetchRow(); + $user_id = $val['user_id']; + return $user_id; + } + // getItemForFileView - retrieves an expense item identified by its id for // attachment view operation. // diff --git a/WEB-INF/lib/ttReportHelper.class.php b/WEB-INF/lib/ttReportHelper.class.php index 294225e0c..b24890e7d 100644 --- a/WEB-INF/lib/ttReportHelper.class.php +++ b/WEB-INF/lib/ttReportHelper.class.php @@ -350,9 +350,10 @@ static function getItems($options) { array_push($fields, "cast(l.billable * coalesce(upb.rate, 0) * time_to_sec(l.duration)/3600 as decimal(10,2)) as cost"); // Use project rate for user. array_push($fields, "null as expense"); } - // Add approved. - if ($options['show_approved']) - array_push($fields, 'l.approved'); + // Add the fields used to determine if we show an edit icon for record. + array_push($fields, 'l.approved'); + array_push($fields, 'l.timesheet_id'); + array_push($fields, 'l.invoice_id'); // Add paid status. if ($canViewReports && $options['show_paid']) array_push($fields, 'l.paid'); @@ -513,9 +514,10 @@ static function getItems($options) { array_push($fields, 'ei.name as note'); array_push($fields, 'ei.cost as cost'); array_push($fields, 'ei.cost as expense'); - // Add approved. - if ($options['show_approved']) - array_push($fields, 'ei.approved'); + // Add the fields used to determine if we show an edit icon for record. + array_push($fields, 'ei.approved'); + array_push($fields, 'null as timesheet_id'); + array_push($fields, 'ei.invoice_id'); // Add paid status. if ($canViewReports && $options['show_paid']) array_push($fields, 'ei.paid'); diff --git a/WEB-INF/lib/ttTimeHelper.class.php b/WEB-INF/lib/ttTimeHelper.class.php index faa1197cd..f0b1ea100 100644 --- a/WEB-INF/lib/ttTimeHelper.class.php +++ b/WEB-INF/lib/ttTimeHelper.class.php @@ -1,30 +1,6 @@ isUserValid($user_id); + + if (!$user_valid) return false; + + // Set on behalf user. + $user->setOnBehalfUser($user_id); + // Get on behalf record. + return ttTimeHelper::getRecord($id); + } + + // getUserForRecord - retrieves user id for a time record. + static function getUserForRecord($id) { + global $user; + + $group_id = $user->getGroup(); + $org_id = $user->org_id; + + $mdb2 = getConnection(); + + // Obtain user_id for the time record. + $sql = "select l.user_id from tt_log l ". + " where l.id = $id and l.group_id = $group_id and l.org_id = $org_id and l.status = 1"; + $res = $mdb2->query($sql); + if (is_a($res, 'PEAR_Error')) return false; + if (!$res->numRows()) return false; + + $val = $res->fetchRow(); + $user_id = $val['user_id']; + return $user_id; + } + // getRecordForFileView - retrieves a time record identified by its id for // attachment view operation. // diff --git a/WEB-INF/lib/ttUserHelper.class.php b/WEB-INF/lib/ttUserHelper.class.php index accabe1fe..d4fc8d804 100644 --- a/WEB-INF/lib/ttUserHelper.class.php +++ b/WEB-INF/lib/ttUserHelper.class.php @@ -1,30 +1,6 @@ getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')}{/if} {if $use_checkboxes}{/if} - {* {* column for edit icons *} + {* column for edit icons *}   {/if} @@ -172,7 +172,12 @@ {if 1 == $item.type}{/if} {if 2 == $item.type}{/if} {/if} - {* {$i18n.label.edit}{* column for edit icons *} + {if $item.approved || $item.timesheet_id || $item.invoice_id} +   + {else} + {if 1 == $item.type}{$i18n.label.edit}{/if} + {if 2 == $item.type}{$i18n.label.edit}{/if} + {/if} {if $note_on_separate_row && $bean->getAttribute('chnote') && $item.note} @@ -222,7 +227,7 @@ {if $bean->getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')}{/if} {if $use_checkboxes}{/if} - {* {* column for edit icons *} + {* column for edit icons *} {/if} @@ -264,7 +269,7 @@ {if $bean->getAttribute('chtimesheet')}{/if} {if $bean->getAttribute('chfiles')}{/if} {if $use_checkboxes}{/if} - {* {* column for edit icons *} + {* column for edit icons *} {/if} diff --git a/expense_edit.php b/expense_edit.php index 092f33c11..5d1e75044 100644 --- a/expense_edit.php +++ b/expense_edit.php @@ -21,6 +21,7 @@ $cl_id = (int)$request->getParameter('id'); // Get the expense item we are editing. $expense_item = ttExpenseHelper::getItem($cl_id); +if (!$expense_item) $expense_item = ttExpenseHelper::getOnBehalfItem($cl_id); if (!$expense_item || $expense_item['approved'] || $expense_item['invoice_id']) { // Prohibit editing not ours, approved, or invoiced items. header('Location: access_denied.php'); diff --git a/initialize.php b/initialize.php index c5edb812a..3a08a9e78 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.25.5420"); +define("APP_VERSION", "1.19.26.5421"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time_edit.php b/time_edit.php index 4065bf08f..774add2c6 100644 --- a/time_edit.php +++ b/time_edit.php @@ -18,6 +18,7 @@ } $cl_id = (int)$request->getParameter('id'); $time_rec = ttTimeHelper::getRecord($cl_id); +if (!$time_rec) $time_rec = ttTimeHelper::getOnBehalfRecord($cl_id); if (!$time_rec || $time_rec['approved'] || $time_rec['timesheet_id'] || $time_rec['invoice_id']) { // Prohibit editing not ours, approved, assigned to timesheet, or invoiced records. header('Location: access_denied.php'); From 9c9e7d7976fed5b80c0d9dd74b7424f890584fc8 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 5 Mar 2021 21:06:24 +0000 Subject: [PATCH 170/587] Sanitizing of user input on charts.php. --- WEB-INF/templates/time2.tpl | 2 -- charts.php | 4 ++-- initialize.php | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 65216efb8..487bff7cf 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -234,5 +234,3 @@ License: See license.txt *} {/if} - -{$smarty.version} diff --git a/charts.php b/charts.php index d4fb52b3b..026f97463 100644 --- a/charts.php +++ b/charts.php @@ -35,7 +35,7 @@ exit(); } if ($request->isPost() && $request->getParameter('user')) { - if (!$user->isUserValid($request->getParameter('user'))) { + if (!$user->isUserValid((int)$request->getParameter('user'))) { header('Location: access_denied.php'); // Wrong user id on post. exit(); } @@ -45,7 +45,7 @@ // Determine user for which we display this page. $userChanged = $request->getParameter('user_changed'); if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); + $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); } else { $user_id = $user->getUser(); diff --git a/initialize.php b/initialize.php index 3a08a9e78..faa912032 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5421"); +define("APP_VERSION", "1.19.26.5422"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From d0af0f472a64e19dfb48473cca1c374363fb6471 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Fri, 5 Mar 2021 21:24:18 +0000 Subject: [PATCH 171/587] Some more sanitizing of post parameters. --- charts.php | 6 +++--- initialize.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/charts.php b/charts.php index 026f97463..9dc29f588 100644 --- a/charts.php +++ b/charts.php @@ -43,7 +43,7 @@ // End of access checks. // Determine user for which we display this page. -$userChanged = $request->getParameter('user_changed'); +$userChanged = (int)$request->getParameter('user_changed'); if ($request->isPost() && $userChanged) { $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); @@ -63,12 +63,12 @@ $_SESSION['date'] = $cl_date; if ($request->isPost()) { - $cl_interval = $request->getParameter('interval'); + $cl_interval = (int)$request->getParameter('interval'); if (!$cl_interval) $cl_interval = INTERVAL_THIS_MONTH; $_SESSION['chart_interval'] = $cl_interval; $uc->setValue(SYSC_CHART_INTERVAL, $cl_interval); - $cl_type = $request->getParameter('type'); + $cl_type = (int)$request->getParameter('type'); if (!$cl_type) $cl_type = ttChartHelper::adjustType($cl_type); $_SESSION['chart_type'] = $cl_type; $uc->setValue(SYSC_CHART_TYPE, $cl_type); diff --git a/initialize.php b/initialize.php index faa912032..f54941375 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5422"); +define("APP_VERSION", "1.19.26.5423"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 2eaab13803846b91c90d49680099968731d4718e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 6 Mar 2021 15:12:37 +0000 Subject: [PATCH 172/587] A bit more of sanitizing work for posts. --- WEB-INF/lib/ttUser.class.php | 14 ++++++++------ cron.php | 28 ++-------------------------- custom_css.php | 28 ++-------------------------- dbinstall.php | 28 ++-------------------------- display_options.php | 36 ++++++------------------------------ initialize.php | 2 +- 6 files changed, 21 insertions(+), 115 deletions(-) diff --git a/WEB-INF/lib/ttUser.class.php b/WEB-INF/lib/ttUser.class.php index b01ffe687..fcfc1b9d5 100644 --- a/WEB-INF/lib/ttUser.class.php +++ b/WEB-INF/lib/ttUser.class.php @@ -617,6 +617,7 @@ function getUserDetails($user_id) { $mdb2 = getConnection(); $group_id = $this->getGroup(); $org_id = $this->org_id; + $uid = (int)$user_id; // Determine max rank. If we are searching in on behalf group // then rank restriction does not apply. @@ -624,7 +625,7 @@ function getUserDetails($user_id) { $sql = "select u.id, u.name, u.login, u.role_id, u.client_id, u.status, u.rate, u.quota_percent, u.email from tt_users u". " left join tt_roles r on (u.role_id = r.id)". - " where u.id = $user_id and u.group_id = $group_id and u.org_id = $org_id and u.status is not null". + " where u.id = $uid and u.group_id = $group_id and u.org_id = $org_id and u.status is not null". " and (r.rank < $max_rank or (r.rank = $max_rank and u.id = $this->id))"; // Users with lesser roles or self. $res = $mdb2->query($sql); if (!is_a($res, 'PEAR_Error')) { @@ -897,6 +898,7 @@ function setOnBehalfGroup($group_id) { // setOnBehalfUser sets on behalf user both the object and the session. function setOnBehalfUser($user_id) { + $uid = (int)$user_id; // In case we forgot to sanitize $user_id before getting here. // Unset things first. $this->behalf_id = null; @@ -906,16 +908,16 @@ function setOnBehalfUser($user_id) { unset($_SESSION['behalf_name']); // No need to set if user is us. - if ($user_id == $this->id) return; + if ($uid == $this->id) return; // No need to set if user id is not valid. - if (!$this->isUserValid($user_id)) return; + if (!$this->isUserValid($uid)) return; // We are good to set on behalf user. - $onBehalfUserName = ttUserHelper::getUserName($user_id); - $_SESSION['behalf_id'] = $user_id; + $onBehalfUserName = ttUserHelper::getUserName($uid); + $_SESSION['behalf_id'] = $uid; $_SESSION['behalf_name'] = $onBehalfUserName; - $this->behalf_id = $user_id; + $this->behalf_id = $uid; $this->behalf_name = $onBehalfUserName; $this->behalfUser = new ttBehalfUser($this->behalf_id, $this->org_id); diff --git a/cron.php b/cron.php index 331b4f36e..5adced71e 100644 --- a/cron.php +++ b/cron.php @@ -1,30 +1,6 @@ getConfigHelper(); if ($request->isPost()) { - $cl_time_note_on_separate_row = $request->getParameter('time_note_on_separate_row'); - $cl_time_not_complete_days = $request->getParameter('time_not_complete_days'); - $cl_record_custom_fields = $request->getParameter('record_custom_fields'); - $cl_report_note_on_separate_row = $request->getParameter('report_note_on_separate_row'); + $cl_time_note_on_separate_row = (bool)$request->getParameter('time_note_on_separate_row'); + $cl_time_not_complete_days = (bool)$request->getParameter('time_not_complete_days'); + $cl_record_custom_fields = (bool)$request->getParameter('record_custom_fields'); + $cl_report_note_on_separate_row = (bool)$request->getParameter('report_note_on_separate_row'); $cl_custom_css = trim($request->getParameter('custom_css')); } else { $cl_time_note_on_separate_row = $config->getDefinedValue('time_note_on_separate_row'); diff --git a/initialize.php b/initialize.php index f54941375..eb9fd4b94 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5423"); +define("APP_VERSION", "1.19.26.5424"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 477f47a63e8e476f6c84edff830bba03c7610667 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 6 Mar 2021 15:55:04 +0000 Subject: [PATCH 173/587] Some more sanitizing. --- expense_edit.php | 4 ++-- expenses.php | 6 +++--- initialize.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/expense_edit.php b/expense_edit.php index 5d1e75044..9c85bdb79 100644 --- a/expense_edit.php +++ b/expense_edit.php @@ -43,14 +43,14 @@ $cl_item_name = trim($request->getParameter('item_name')); $cl_cost = trim($request->getParameter('cost')); if ($user->isPluginEnabled('ps')) - $cl_paid = $request->getParameter('paid'); + $cl_paid = (bool)$request->getParameter('paid'); } else { $cl_date = $item_date->toString($user->getDateFormat()); $cl_client = $expense_item['client_id']; $cl_project = $expense_item['project_id']; $cl_item_name = $expense_item['name']; $cl_cost = $expense_item['cost']; - $cl_paid = $expense_item['paid']; + $cl_paid = (bool)$expense_item['paid']; } // Initialize elements of 'expenseItemForm'. diff --git a/expenses.php b/expenses.php index 170f0cd3b..e82d9d379 100644 --- a/expenses.php +++ b/expenses.php @@ -33,7 +33,7 @@ exit(); } if ($request->isPost() && $request->getParameter('user')) { - if (!$user->isUserValid($request->getParameter('user'))) { + if (!$user->isUserValid((int)$request->getParameter('user'))) { header('Location: access_denied.php'); // Wrong user id on post. exit(); } @@ -41,9 +41,9 @@ // End of access checks. // Determine user for which we display this page. -$userChanged = $request->getParameter('user_changed'); +$userChanged = (int)$request->getParameter('user_changed'); if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); + $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); } else { $user_id = $user->getUser(); diff --git a/initialize.php b/initialize.php index eb9fd4b94..344ec8229 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5424"); +define("APP_VERSION", "1.19.26.5425"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 3a3c14ffd3a4266aeac52e7da19d7c0fa684792d Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 6 Mar 2021 17:57:57 +0000 Subject: [PATCH 174/587] A bit more sanitizing of post parameters. --- export.php | 28 ++-------------------------- file_download.php | 28 ++-------------------------- group_add.php | 28 ++-------------------------- group_advanced_edit.php | 28 ++-------------------------- group_delete.php | 28 ++-------------------------- group_edit.php | 12 ++++++------ import.php | 28 ++-------------------------- initialize.php | 2 +- invoice_add.php | 30 +++--------------------------- invoice_delete.php | 28 ++-------------------------- invoice_send.php | 28 ++-------------------------- invoice_view.php | 28 ++-------------------------- invoices.php | 28 ++-------------------------- 13 files changed, 30 insertions(+), 294 deletions(-) diff --git a/export.php b/export.php index 2206def2d..2bcba2dce 100644 --- a/export.php +++ b/export.php @@ -1,30 +1,6 @@ getParameter('group_changed'); +$groupChanged = (bool)$request->getParameter('group_changed'); if ($request->isPost() && $groupChanged) { $user->setOnBehalfGroup($group_id); } @@ -62,11 +62,11 @@ $cl_tracking_mode = $request->getParameter('tracking_mode'); $cl_project_required = $request->getParameter('project_required'); $cl_record_type = $request->getParameter('record_type'); - $cl_punch_mode = $request->getParameter('punch_mode'); - $cl_allow_overlap = $request->getParameter('allow_overlap'); - $cl_future_entries = $request->getParameter('future_entries'); - $cl_uncompleted_indicators = $request->getParameter('uncompleted_indicators'); - $cl_confirm_save = $request->getParameter('confirm_save'); + $cl_punch_mode = (bool)$request->getParameter('punch_mode'); + $cl_allow_overlap = (bool)$request->getParameter('allow_overlap'); + $cl_future_entries = (bool)$request->getParameter('future_entries'); + $cl_uncompleted_indicators = (bool)$request->getParameter('uncompleted_indicators'); + $cl_confirm_save = (bool)$request->getParameter('confirm_save'); } else { $cl_currency = ($group['currency'] == '' ? CURRENCY_DEFAULT : $group['currency']); $cl_lang = $group['lang']; diff --git a/import.php b/import.php index 938fdb3dd..b743b3f5a 100644 --- a/import.php +++ b/import.php @@ -1,30 +1,6 @@ isPost()) { $cl_date = $request->getParameter('date'); - $cl_client = $request->getParameter('client'); + $cl_client = (int)$request->getParameter('client'); $cl_project = $request->getParameter('project'); $cl_number = trim($request->getParameter('number')); $cl_start = $request->getParameter('start'); diff --git a/invoice_delete.php b/invoice_delete.php index 89ea372a3..5b473dfa0 100644 --- a/invoice_delete.php +++ b/invoice_delete.php @@ -1,30 +1,6 @@ Date: Sat, 6 Mar 2021 21:19:21 +0000 Subject: [PATCH 175/587] Some more sanitizing work. --- locking.php | 28 ++---------------- login.php | 28 ++---------------- logout.php | 28 ++---------------- notification_add.php | 28 ++---------------- notification_delete.php | 28 ++---------------- notification_edit.php | 28 ++---------------- notifications.php | 28 ++---------------- password_change.php | 28 ++---------------- plugins.php | 64 +++++++++++++---------------------------- 9 files changed, 36 insertions(+), 252 deletions(-) diff --git a/locking.php b/locking.php index 9b23c876a..04c8d9419 100644 --- a/locking.php +++ b/locking.php @@ -1,30 +1,6 @@ doLogout(); diff --git a/notification_add.php b/notification_add.php index b7f743256..83cd7a538 100644 --- a/notification_add.php +++ b/notification_add.php @@ -1,30 +1,6 @@ isPost()) { // Plugins that user wants to save for the current group. - $cl_charts = $request->getParameter('charts'); - $cl_clients = $request->getParameter('clients'); - $cl_client_required = $request->getParameter('client_required'); - $cl_invoices = $request->getParameter('invoices'); - $cl_paid_status = $request->getParameter('paid_status'); - $cl_custom_fields = $request->getParameter('custom_fields'); - $cl_expenses = $request->getParameter('expenses'); - $cl_tax_expenses = $request->getParameter('tax_expenses'); - $cl_notifications = $request->getParameter('notifications'); - $cl_locking = $request->getParameter('locking'); - $cl_quotas = $request->getParameter('quotas'); - $cl_week_view = $request->getParameter('week_view'); - $cl_work_units = $request->getParameter('work_units'); - $cl_approval = $request->getParameter('approval'); - $cl_timesheets = $request->getParameter('timesheets'); - $cl_templates = $request->getParameter('templates'); - $cl_attachments = $request->getParameter('attachments'); - $cl_work = $request->getParameter('work'); + $cl_charts = (bool)$request->getParameter('charts'); + $cl_clients = (bool)$request->getParameter('clients'); + $cl_client_required = (bool)$request->getParameter('client_required'); + $cl_invoices = (bool)$request->getParameter('invoices'); + $cl_paid_status = (bool)$request->getParameter('paid_status'); + $cl_custom_fields = (bool)$request->getParameter('custom_fields'); + $cl_expenses = (bool)$request->getParameter('expenses'); + $cl_tax_expenses = (bool)$request->getParameter('tax_expenses'); + $cl_notifications = (bool)$request->getParameter('notifications'); + $cl_locking = (bool)$request->getParameter('locking'); + $cl_quotas = (bool)$request->getParameter('quotas'); + $cl_week_view = (bool)$request->getParameter('week_view'); + $cl_work_units = (bool)$request->getParameter('work_units'); + $cl_approval = (bool)$request->getParameter('approval'); + $cl_timesheets = (bool)$request->getParameter('timesheets'); + $cl_templates = (bool)$request->getParameter('templates'); + $cl_attachments = (bool)$request->getParameter('attachments'); + $cl_work = (bool)$request->getParameter('work'); } else { // Note: we get here in get, and also in post when group changes. // Which plugins do we have enabled in currently selected group? From 5a9248484ea3248963da71b955449ce6f354580b Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sat, 6 Mar 2021 21:27:05 +0000 Subject: [PATCH 176/587] Some cosmetic refactoring. --- initialize.php | 2 +- predefined_expense_add.php | 28 ++------------------------- predefined_expense_delete.php | 36 ++++++----------------------------- predefined_expense_edit.php | 30 +++-------------------------- predefined_expenses.php | 28 ++------------------------- 5 files changed, 14 insertions(+), 110 deletions(-) diff --git a/initialize.php b/initialize.php index 22d73352c..c454c8337 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5426"); +define("APP_VERSION", "1.19.26.5427"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/predefined_expense_add.php b/predefined_expense_add.php index 2a0ab6be9..e300fa43e 100644 --- a/predefined_expense_add.php +++ b/predefined_expense_add.php @@ -1,30 +1,6 @@ getParameter('id'); -$predefined_expense = ttPredefinedExpenseHelper::get($cl_predefined_expense_id); +$predefined_expense_id = (int)$request->getParameter('id'); +$predefined_expense = ttPredefinedExpenseHelper::get($predefined_expense_id); if (!$predefined_expense) { header('Location: access_denied.php'); exit(); @@ -51,13 +27,13 @@ $predefined_expense_to_delete = $predefined_expense['name']; $form = new Form('predefinedExpenseDeleteForm'); -$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$cl_predefined_expense_id)); +$form->addInput(array('type'=>'hidden','name'=>'id','value'=>$predefined_expense_id)); $form->addInput(array('type'=>'submit','name'=>'btn_delete','value'=>$i18n->get('label.delete'))); $form->addInput(array('type'=>'submit','name'=>'btn_cancel','value'=>$i18n->get('button.cancel'))); if ($request->isPost()) { if ($request->getParameter('btn_delete')) { - if (ttPredefinedExpenseHelper::delete($cl_predefined_expense_id)) { + if (ttPredefinedExpenseHelper::delete($predefined_expense_id)) { header('Location: predefined_expenses.php'); exit(); } else diff --git a/predefined_expense_edit.php b/predefined_expense_edit.php index 3f0cb0c8c..1eca3a2c7 100644 --- a/predefined_expense_edit.php +++ b/predefined_expense_edit.php @@ -1,30 +1,6 @@ getParameter('id'); +$predefined_expense_id = (int)$request->getParameter('id'); $predefined_expense = ttPredefinedExpenseHelper::get($predefined_expense_id); if (!$predefined_expense) { header('Location: access_denied.php'); diff --git a/predefined_expenses.php b/predefined_expenses.php index e1c14d802..9f94bd1cc 100644 --- a/predefined_expenses.php +++ b/predefined_expenses.php @@ -1,30 +1,6 @@ Date: Sat, 6 Mar 2021 22:24:50 +0000 Subject: [PATCH 177/587] Cosmetic. --- WEB-INF/lib/ttRoleHelper.class.php | 2 +- initialize.php | 2 +- profile_edit.php | 28 ++------------------------ quotas.php | 28 ++------------------------ report.php | 32 ++++-------------------------- report_send.php | 28 ++------------------------ reports.php | 28 ++------------------------ role_add.php | 28 ++------------------------ role_delete.php | 28 ++------------------------ role_edit.php | 28 ++------------------------ 10 files changed, 20 insertions(+), 212 deletions(-) diff --git a/WEB-INF/lib/ttRoleHelper.class.php b/WEB-INF/lib/ttRoleHelper.class.php index 7fa9f8fb2..a3753d238 100644 --- a/WEB-INF/lib/ttRoleHelper.class.php +++ b/WEB-INF/lib/ttRoleHelper.class.php @@ -149,7 +149,7 @@ static function delete($role_id) { $group_id = $user->getGroup(); $org_id = $user->org_id; - // Mark the task as deleted. + // Mark the role as deleted. $sql = "update tt_roles set status = NULL where id = $role_id and group_id = $group_id and org_id = $org_id"; $affected = $mdb2->exec($sql); return (!is_a($affected, 'PEAR_Error')); diff --git a/initialize.php b/initialize.php index c454c8337..fc27cbaaa 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5427"); +define("APP_VERSION", "1.19.26.5428"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/profile_edit.php b/profile_edit.php index d0d3de5fe..26091823f 100644 --- a/profile_edit.php +++ b/profile_edit.php @@ -1,30 +1,6 @@ getAttribute('chapproved') && ($user->can('approve_reports') || $user->can('approve_all_reports'))) @@ -199,7 +175,7 @@ $item_ids = ttReportHelper::getFromSession(); $time_log_ids = $item_ids['report_item_ids']; $expense_item_ids = $item_ids['report_item_expense_ids']; - // The above code is here beacues the arrays are used in both "Mark paid" and "Assign to invoice" handlers below. + // The above code is here because the arrays are used in both "Mark paid" and "Assign to invoice" handlers below. } if ($err->no()) { diff --git a/report_send.php b/report_send.php index e837f3e50..a2747b957 100644 --- a/report_send.php +++ b/report_send.php @@ -1,30 +1,6 @@ Date: Sun, 7 Mar 2021 17:35:27 +0000 Subject: [PATCH 178/587] Finished work on sanitizing post parameters to reduce risk of SQL injections. --- initialize.php | 2 +- mobile/expenses.php | 30 +++--------------------------- mobile/index.php | 28 ++-------------------------- mobile/login.php | 28 ++-------------------------- mobile/projects.php | 28 ++-------------------------- mobile/tasks.php | 28 ++-------------------------- mobile/time.php | 34 +++++----------------------------- mobile/timer.php | 28 ++-------------------------- mobile/users.php | 28 ++-------------------------- roles.php | 28 ++-------------------------- site_map.php | 28 ++-------------------------- success.php | 28 ++-------------------------- template_add.php | 28 ++-------------------------- template_delete.php | 30 +++--------------------------- template_edit.php | 30 +++--------------------------- templates.php | 28 ++-------------------------- time.php | 6 +++--- timesheet_add.php | 28 ++-------------------------- timesheet_edit.php | 28 ++-------------------------- timesheet_view.php | 28 ++-------------------------- timesheets.php | 34 +++++----------------------------- tofile.php | 28 ++-------------------------- topdf.php | 28 ++-------------------------- week.php | 34 +++++----------------------------- week_view.php | 36 ++++++------------------------------ work_units.php | 34 +++++----------------------------- 26 files changed, 71 insertions(+), 647 deletions(-) diff --git a/initialize.php b/initialize.php index fc27cbaaa..fca2f15a5 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5428"); +define("APP_VERSION", "1.19.26.5429"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/expenses.php b/mobile/expenses.php index 463671f4a..4f3b097fd 100644 --- a/mobile/expenses.php +++ b/mobile/expenses.php @@ -1,30 +1,6 @@ isPost() && $request->getParameter('user')) { - if (!$user->isUserValid($request->getParameter('user'))) { + if (!$user->isUserValid((int)$request->getParameter('user'))) { header('Location: access_denied.php'); // Wrong user id on post. exit(); } diff --git a/mobile/index.php b/mobile/index.php index 88408af23..4da5fab10 100644 --- a/mobile/index.php +++ b/mobile/index.php @@ -1,30 +1,6 @@ isPost()) { - $userChanged = $request->getParameter('user_changed'); // Reused in multiple places below. - if ($userChanged && !($user->can('track_time') && $user->isUserValid($request->getParameter('user')))) { + $userChanged = (bool)$request->getParameter('user_changed'); // Reused in multiple places below. + if ($userChanged && !($user->can('track_time') && $user->isUserValid((int)$request->getParameter('user')))) { header('Location: access_denied.php'); // User changed, but no right or wrong user id. exit(); } @@ -64,7 +40,7 @@ // Determine user for whom we display this page. if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); + $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); } else { $user_id = $user->getUser(); diff --git a/mobile/timer.php b/mobile/timer.php index e301716a4..1d870b1ca 100644 --- a/mobile/timer.php +++ b/mobile/timer.php @@ -1,30 +1,6 @@ getParameter('id'); +$cl_template_id = (int)$request->getParameter('id'); $template = ttTemplateHelper::get($cl_template_id); if (!$template) { header('Location: access_denied.php'); diff --git a/template_edit.php b/template_edit.php index 117b8166b..e3fa38947 100644 --- a/template_edit.php +++ b/template_edit.php @@ -1,30 +1,6 @@ getParameter('id'); +$cl_template_id = (int)$request->getParameter('id'); $template = ttTemplateHelper::get($cl_template_id); if (!$template) { header('Location: access_denied.php'); diff --git a/templates.php b/templates.php index 45ea2e477..636d4bc10 100644 --- a/templates.php +++ b/templates.php @@ -1,30 +1,6 @@ isPost()) { - $userChanged = $request->getParameter('user_changed'); // Reused in multiple places below. - if ($userChanged && !($user->can('track_time') && $user->isUserValid($request->getParameter('user')))) { + $userChanged = (bool)$request->getParameter('user_changed'); // Reused in multiple places below. + if ($userChanged && !($user->can('track_time') && $user->isUserValid((int)$request->getParameter('user')))) { header('Location: access_denied.php'); // User changed, but no right or wrong user id. exit(); } @@ -36,7 +36,7 @@ // Determine user for whom we display this page. if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); + $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); } else { $user_id = $user->getUser(); diff --git a/timesheet_add.php b/timesheet_add.php index 7c7633c6c..536241d62 100644 --- a/timesheet_add.php +++ b/timesheet_add.php @@ -1,30 +1,6 @@ isPost()) { - $userChanged = $request->getParameter('user_changed'); // Reused in multiple places below. - if ($userChanged && !($user->can('track_time') && $user->isUserValid($request->getParameter('user')))) { + $userChanged = (bool)$request->getParameter('user_changed'); // Reused in multiple places below. + if ($userChanged && !($user->can('track_time') && $user->isUserValid((int)$request->getParameter('user')))) { header('Location: access_denied.php'); // Group changed, but no rght or wrong user id. exit(); } @@ -59,7 +35,7 @@ // Determine user for whom we display this page. if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); + $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); } else { $user_id = $user->getUser(); diff --git a/tofile.php b/tofile.php index 996ffe9fd..b10bdee02 100644 --- a/tofile.php +++ b/tofile.php @@ -1,30 +1,6 @@ isPost()) { - $userChanged = $request->getParameter('user_changed'); // Reused in multiple places below. - if ($userChanged && !($user->can('track_time') && $user->isUserValid($request->getParameter('user')))) { + $userChanged = (bool)$request->getParameter('user_changed'); // Reused in multiple places below. + if ($userChanged && !($user->can('track_time') && $user->isUserValid((int)$request->getParameter('user')))) { header('Location: access_denied.php'); // User changed, but no right or wrong user id. exit(); } @@ -66,7 +42,7 @@ // Determine user for whom we display this page. if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); + $user_id = (int)$request->getParameter('user'); $user->setOnBehalfUser($user_id); } else { $user_id = $user->getUser(); diff --git a/week_view.php b/week_view.php index 149842e87..1718afd4b 100644 --- a/week_view.php +++ b/week_view.php @@ -1,30 +1,6 @@ getConfigHelper(); if ($request->isPost()) { - $cl_week_menu = $request->getParameter('week_menu'); - $cl_week_note = $request->getParameter('week_note'); - $cl_week_list = $request->getParameter('week_list'); - $cl_notes = $request->getParameter('notes'); + $cl_week_menu = (bool)$request->getParameter('week_menu'); + $cl_week_note = (bool)$request->getParameter('week_note'); + $cl_week_list = (bool)$request->getParameter('week_list'); + $cl_notes = (bool)$request->getParameter('notes'); } else { $cl_week_menu = $config->getDefinedValue('week_menu'); $cl_week_note = $config->getDefinedValue('week_note'); diff --git a/work_units.php b/work_units.php index e4d198d5c..826f899ab 100644 --- a/work_units.php +++ b/work_units.php @@ -1,30 +1,6 @@ getConfig()); if ($request->isPost()) { - $cl_minutes_in_unit = $request->getParameter('minutes_in_unit'); - $cl_1st_unit_threshold = $request->getParameter('1st_unit_threshold'); - $cl_totals_only = $request->getParameter('totals_only'); + $cl_minutes_in_unit = (int)$request->getParameter('minutes_in_unit'); + $cl_1st_unit_threshold = (int)$request->getParameter('1st_unit_threshold'); + $cl_totals_only = (bool)$request->getParameter('totals_only'); } else { $cl_minutes_in_unit = $user->getConfigInt('minutes_in_unit', 15); $cl_1st_unit_threshold = $user->getConfigInt('1st_unit_threshold', 0); From 464291697900e30ae782477930ef45a9cb8e4cc0 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 7 Mar 2021 18:15:58 +0000 Subject: [PATCH 179/587] Removed some more no longer used mobile pages. --- WEB-INF/templates/mobile/expenses.tpl | 226 ------------------------- WEB-INF/templates/mobile/projects.tpl | 76 --------- WEB-INF/templates/mobile/tasks.tpl | 76 --------- WEB-INF/templates/mobile/users.tpl | 95 ----------- initialize.php | 2 +- mobile/expenses.php | 235 -------------------------- mobile/projects.php | 36 ---- mobile/tasks.php | 35 ---- mobile/users.php | 51 ------ 9 files changed, 1 insertion(+), 831 deletions(-) delete mode 100644 WEB-INF/templates/mobile/expenses.tpl delete mode 100644 WEB-INF/templates/mobile/projects.tpl delete mode 100644 WEB-INF/templates/mobile/tasks.tpl delete mode 100644 WEB-INF/templates/mobile/users.tpl delete mode 100644 mobile/expenses.php delete mode 100644 mobile/projects.php delete mode 100644 mobile/tasks.php delete mode 100644 mobile/users.php diff --git a/WEB-INF/templates/mobile/expenses.tpl b/WEB-INF/templates/mobile/expenses.tpl deleted file mode 100644 index 81d7a214a..000000000 --- a/WEB-INF/templates/mobile/expenses.tpl +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - -
    <<{$timestring}>>
    - -{$forms.expensesForm.open} - - - - - -
    - -{if $user_dropdown} - - - - -{/if} -{if $user->isPluginEnabled('cl')} - - - - -{/if} -{if $show_project} - - - - -{/if} -{if $predefined_expenses} - - - - - - - - -{/if} - - - - - - - - -
    {$i18n.label.user}:{$forms.expensesForm.user.control}
    {$i18n.label.client}{if $user->isOptionEnabled('client_required')} (*){/if}:{$forms.expensesForm.client.control}
    {$i18n.label.project} (*):{$forms.expensesForm.project.control}
    {$i18n.label.expense}:{$forms.expensesForm.predefined_expense.control}
    {$i18n.label.quantity}:{$forms.expensesForm.quantity.control}
    {$i18n.label.item} (*):{$forms.expensesForm.item_name.control}
    {$i18n.label.cost} (*):{$forms.expensesForm.cost.control} {$user->getCurrency()|escape}
    -
    - - - - - -
    {$forms.expensesForm.btn_submit.control}
    - - - - - -
    -{if $expense_items} - - - {if $user->isPluginEnabled('cl')} - - {/if} - {if $show_project} - - {/if} - - - - {foreach $expense_items as $item} - - {if $user->isPluginEnabled('cl')} - - {/if} - {if $show_project} - - {/if} - - - - {/foreach} -
    {$i18n.label.client}{$i18n.label.project}{$i18n.label.item}{$i18n.label.cost}
    {$item.client|escape}{$item.project|escape} - {if $item.approved || $item.invoice_id} - {$item.item|escape} - {else} - {$item.item|escape} - {/if} - {$item.cost}
    - - - - -
    {$i18n.label.day_total}: {$user->getCurrency()|escape} {$day_total}
    -{/if} -
    -{$forms.expensesForm.close} diff --git a/WEB-INF/templates/mobile/projects.tpl b/WEB-INF/templates/mobile/projects.tpl deleted file mode 100644 index 96d27054f..000000000 --- a/WEB-INF/templates/mobile/projects.tpl +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - -
    -{if $user->can('manage_projects')} - - {if $inactive_projects} - - {/if} - {if $active_projects} - - - - - {foreach $active_projects as $project} - - - - - {/foreach} - {/if} -
    {$i18n.form.projects.active_projects}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}
    - - - - - -

    -
    -
    - - {if $inactive_projects} - - - - - - - {foreach $inactive_projects as $project} - - - - - {/foreach} -
    {$i18n.form.projects.inactive_projects}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}
    - - - - - -

    -
    -
    - {/if} -{else} - - - - - - {if $active_projects} - {foreach $active_projects as $project} - - - - - {/foreach} - {/if} -
    {$i18n.label.thing_name}{$i18n.label.description}
    {$project.name|escape}{$project.description|escape}
    -{/if} -
    diff --git a/WEB-INF/templates/mobile/tasks.tpl b/WEB-INF/templates/mobile/tasks.tpl deleted file mode 100644 index 3fbee1f7d..000000000 --- a/WEB-INF/templates/mobile/tasks.tpl +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - -
    -{if $user->can('manage_tasks')} - - {if $inactive_tasks} - - {/if} - - - - - {if $active_tasks} - {foreach $active_tasks as $task} - - - - - {/foreach} - {/if} -
    {$i18n.form.tasks.active_tasks}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}
    - - - - - -

    -
    -
    - - {if $inactive_tasks} - - - - - - - {foreach $inactive_tasks as $task} - - - - - {/foreach} -
    {$i18n.form.tasks.inactive_tasks}
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}
    - - - - - -

    -
    -
    - {/if} -{else} - - - - - - {if $active_tasks} - {foreach $active_tasks as $task} - - - - - {/foreach} - {/if} -
    {$i18n.label.thing_name}{$i18n.label.description}
    {$task.name|escape}{$task.description|escape}
    - {/if} -
    diff --git a/WEB-INF/templates/mobile/users.tpl b/WEB-INF/templates/mobile/users.tpl deleted file mode 100644 index eaeb4770f..000000000 --- a/WEB-INF/templates/mobile/users.tpl +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - -
    -{if $user->can('manage_users')} - - {if $inactive_users} - - {/if} - {if $active_users} - - - - - - {foreach $active_users as $u} - - - - - - {/foreach} - {/if} -
    {$i18n.label.active_users}
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}
    - {if $uncompleted_indicators} - - {/if} - {if $u.group_id != $user->group_id || $u.rank < $user->rank || ($u.rank == $user->rank && $u.id == $user->id)} - {$u.name|escape} - {else} - {$u.name|escape} - {/if} - {$u.login|escape}{$u.role_name|escape}
    - - - - - -

    -
    -
    - - {if $inactive_users} - - - - - - - - {foreach $inactive_users as $u} - - - - - - {/foreach} -
    {$i18n.label.inactive_users}
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}
    - {if $u.group_id != $user->group_id || $u.rank < $user->rank} - {$u.name|escape} - {else} - {$u.name|escape} - {/if} - {$u.login|escape}{$u.role_name|escape}
    - - - - - -
    -
    -
    - {/if} -{else} - - - - - - - {foreach $active_users as $u} - - - - - - {/foreach} -
    {$i18n.label.person_name}{$i18n.label.login}{$i18n.form.users.role}
    {$u.name|escape}{$u.login|escape}{$u.role_name|escape}
    -{/if} -
    diff --git a/initialize.php b/initialize.php index fca2f15a5..cbdfb3cc1 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5429"); +define("APP_VERSION", "1.19.26.5430"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/mobile/expenses.php b/mobile/expenses.php deleted file mode 100644 index 4f3b097fd..000000000 --- a/mobile/expenses.php +++ /dev/null @@ -1,235 +0,0 @@ -isPluginEnabled('ex')) { - header('Location: feature_disabled.php'); - exit(); -} -if (!$user->exists()) { - header('Location: access_denied.php'); // Nobody to enter expenses for. - exit(); -} -if ($user->behalf_id && (!$user->can('track_expenses') || !$user->checkBehalfId())) { - header('Location: access_denied.php'); // Trying on behalf, but no right or wrong user. - exit(); -} -if (!$user->behalf_id && !$user->can('track_own_expenses') && !$user->adjustBehalfId()) { - header('Location: access_denied.php'); // Trying as self, but no right for self, and noone to work on behalf. - exit(); -} -if ($request->isPost() && $request->getParameter('user')) { - if (!$user->isUserValid((int)$request->getParameter('user'))) { - header('Location: access_denied.php'); // Wrong user id on post. - exit(); - } -} -// End of access checks. - -// Determine user for which we display this page. -$userChanged = $request->getParameter('user_changed'); -if ($request->isPost() && $userChanged) { - $user_id = $request->getParameter('user'); - $user->setOnBehalfUser($user_id); -} else { - $user_id = $user->getUser(); -} - -// Initialize and store date in session. -$cl_date = $request->getParameter('date', @$_SESSION['date']); -$selected_date = new DateAndTime(DB_DATEFORMAT, $cl_date); -if($selected_date->isError()) - $selected_date = new DateAndTime(DB_DATEFORMAT); -if(!$cl_date) - $cl_date = $selected_date->toString(DB_DATEFORMAT); -$_SESSION['date'] = $cl_date; - -// Determine previous and next dates for simple navigation. -$prev_date = date('Y-m-d', strtotime('-1 day', strtotime($cl_date))); -$next_date = date('Y-m-d', strtotime('+1 day', strtotime($cl_date))); - -$tracking_mode = $user->getTrackingMode(); -$show_project = MODE_PROJECTS == $tracking_mode || MODE_PROJECTS_AND_TASKS == $tracking_mode; - -// Initialize variables. -$cl_client = $request->getParameter('client', ($request->isPost() ? null : @$_SESSION['client'])); -$_SESSION['client'] = $cl_client; -$cl_project = $request->getParameter('project', ($request->isPost() ? null : @$_SESSION['project'])); -$_SESSION['project'] = $cl_project; -$cl_item_name = $request->getParameter('item_name'); -$cl_cost = $request->getParameter('cost'); - -// Elements of expensesForm. -$form = new Form('expensesForm'); - -if ($user->can('track_expenses')) { - $rank = $user->getMaxRankForGroup($user->getGroup()); - if ($user->can('track_own_expenses')) - $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_self'=>true,'self_first'=>true); - else - $options = array('status'=>ACTIVE,'max_rank'=>$rank); - $user_list = $user->getUsers($options); - if (count($user_list) >= 1) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'this.form.user_changed.value=1;this.form.submit();', - 'name'=>'user', - 'style'=>'width: 250px;', - 'value'=>$user_id, - 'data'=>$user_list, - 'datakeys'=>array('id','name'))); - $form->addInput(array('type'=>'hidden','name'=>'user_changed')); - $smarty->assign('user_dropdown', 1); - } -} - -// Dropdown for clients in MODE_TIME. Use all active clients. -if (MODE_TIME == $tracking_mode && $user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$active_clients, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - // Note: in other modes the client list is filtered to relevant clients only. See below. -} - -if ($show_project) { - // Dropdown for projects assigned to user. - $project_list = $user->getAssignedProjects(); - $form->addInput(array('type'=>'combobox', - // 'onchange'=>'fillTaskDropdown(this.value);', - 'name'=>'project', - 'style'=>'width: 250px;', - 'value'=>$cl_project, - 'data'=>$project_list, - 'datakeys'=>array('id','name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - - // Dropdown for clients if the clients plugin is enabled. - if ($user->isPluginEnabled('cl')) { - $active_clients = ttGroupHelper::getActiveClients(true); - // We need an array of assigned project ids to do some trimming. - foreach($project_list as $project) - $projects_assigned_to_user[] = $project['id']; - - // Build a client list out of active clients. Use only clients that are relevant to user. - // Also trim their associated project list to only assigned projects (to user). - foreach($active_clients as $client) { - $projects_assigned_to_client = explode(',', $client['projects']); - $intersection = array_intersect($projects_assigned_to_client, $projects_assigned_to_user); - if ($intersection) { - $client['projects'] = implode(',', $intersection); - $client_list[] = $client; - } - } - $form->addInput(array('type'=>'combobox', - 'onchange'=>'fillProjectDropdown(this.value);', - 'name'=>'client', - 'style'=>'width: 250px;', - 'value'=>$cl_client, - 'data'=>$client_list, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - } -} -// If predefined expenses are configured, add controls to select an expense and quantity. -$predefined_expenses = ttGroupHelper::getPredefinedExpenses(); -if ($predefined_expenses) { - $form->addInput(array('type'=>'combobox', - 'onchange'=>'recalculateCost();', - 'name'=>'predefined_expense', - 'style'=>'width: 250px;', - 'value'=>$cl_predefined_expense, - 'data'=>$predefined_expenses, - 'datakeys'=>array('id', 'name'), - 'empty'=>array(''=>$i18n->get('dropdown.select')))); - $form->addInput(array('type'=>'text','onchange'=>'recalculateCost();','maxlength'=>'40','name'=>'quantity','style'=>'width: 100px;','value'=>$cl_quantity)); -} -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'item_name','style'=>'width: 250px;','value'=>$cl_item_name)); -$form->addInput(array('type'=>'text','maxlength'=>'40','name'=>'cost','style'=>'width: 100px;','value'=>$cl_cost)); -$form->addInput(array('type'=>'calendar','name'=>'date','highlight'=>'expenses','value'=>$cl_date)); // calendar -$form->addInput(array('type'=>'hidden','name'=>'browser_today','value'=>'')); // User current date, which gets filled in on btn_submit click. -$form->addInput(array('type'=>'submit','name'=>'btn_submit','onclick'=>'browser_today.value=get_date()','value'=>$i18n->get('button.submit'))); - -// Submit. -if ($request->isPost()) { - if ($request->getParameter('btn_submit')) { - // Validate user input. - if ($user->isPluginEnabled('cl') && $user->isOptionEnabled('client_required') && !$cl_client) - $err->add($i18n->get('error.client')); - if ($show_project && !$cl_project) - $err->add($i18n->get('error.project')); - if (!ttValidString($cl_item_name)) $err->add($i18n->get('error.field'), $i18n->get('label.item')); - if (!ttValidFloat($cl_cost)) $err->add($i18n->get('error.field'), $i18n->get('label.cost')); - - // Prohibit creating entries in future. - if (!$user->isOptionEnabled('future_entries')) { - $browser_today = new DateAndTime(DB_DATEFORMAT, $request->getParameter('browser_today', null)); - if ($selected_date->after($browser_today)) - $err->add($i18n->get('error.future_date')); - } - if (!ttTimeHelper::canAdd()) $err->add($i18n->get('error.expired')); - // Finished validating input data. - - // Prohibit creating entries in locked range. - if ($user->isDateLocked($selected_date)) - $err->add($i18n->get('error.range_locked')); - - // Insert record. - if ($err->no()) { - if (ttExpenseHelper::insert(array('date'=>$cl_date,'client_id'=>$cl_client, - 'project_id'=>$cl_project,'name'=>$cl_item_name,'cost'=>$cl_cost,'status'=>1))) { - header('Location: expenses.php'); - exit(); - } else - $err->add($i18n->get('error.db')); - } - } elseif ($request->getParameter('onBehalfUser')) { - if($user->can('track_expenses')) { - unset($_SESSION['behalf_id']); - unset($_SESSION['behalf_name']); - - if($on_behalf_id != $user->id) { - $_SESSION['behalf_id'] = $on_behalf_id; - $_SESSION['behalf_name'] = ttUserHelper::getUserName($on_behalf_id); - } - header('Location: expenses.php'); - exit(); - } - } -} - -$smarty->assign('forms', array($form->getName()=>$form->toArray())); -$smarty->assign('show_project', $show_project); -$smarty->assign('next_date', $next_date); -$smarty->assign('prev_date', $prev_date); -$smarty->assign('day_total', ttExpenseHelper::getTotalForDay($cl_date)); -$smarty->assign('expense_items', ttExpenseHelper::getItems($cl_date)); -$smarty->assign('predefined_expenses', $predefined_expenses); -$smarty->assign('client_list', $client_list); -$smarty->assign('project_list', $project_list); -$smarty->assign('timestring', $selected_date->toString($user->getDateFormat())); -$smarty->assign('title', $i18n->get('title.expenses')); -$smarty->assign('content_page_name', 'mobile/expenses.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/projects.php b/mobile/projects.php deleted file mode 100644 index c234d984d..000000000 --- a/mobile/projects.php +++ /dev/null @@ -1,36 +0,0 @@ -getTrackingMode() && MODE_PROJECTS_AND_TASKS != $user->getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -if($user->can('manage_projects')) { - $active_projects = ttGroupHelper::getActiveProjects(); - $inactive_projects = ttGroupHelper::getInactiveProjects(); -} else - $active_projects = $user->getAssignedProjects(); - -$smarty->assign('active_projects', $active_projects); -$smarty->assign('inactive_projects', $inactive_projects); -$smarty->assign('title', $i18n->get('title.projects')); -$smarty->assign('content_page_name', 'mobile/projects.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/tasks.php b/mobile/tasks.php deleted file mode 100644 index 98530477d..000000000 --- a/mobile/tasks.php +++ /dev/null @@ -1,35 +0,0 @@ -getTrackingMode()) { - header('Location: feature_disabled.php'); - exit(); -} -// End of access checks. - -if($user->can('manage_tasks')) { - $active_tasks = ttGroupHelper::getActiveTasks(); - $inactive_tasks = ttGroupHelper::getInactiveTasks(); -} else - $active_tasks = $user->getAssignedTasks(); - -$smarty->assign('active_tasks', $active_tasks); -$smarty->assign('inactive_tasks', $inactive_tasks); -$smarty->assign('title', $i18n->get('title.tasks')); -$smarty->assign('content_page_name', 'mobile/tasks.tpl'); -$smarty->display('mobile/index.tpl'); diff --git a/mobile/users.php b/mobile/users.php deleted file mode 100644 index 45be3fcdc..000000000 --- a/mobile/users.php +++ /dev/null @@ -1,51 +0,0 @@ -getMaxRankForGroup($user->getGroup()); -if ($user->can('view_users')) - $options = array('status'=>ACTIVE,'include_clients'=>true,'include_login'=>true,'include_role'=>true); -else /* if ($user->can('manage_users')) */ - $options = array('status'=>ACTIVE,'max_rank'=>$rank,'include_clients'=>true,'include_self'=>true,'include_login'=>true,'include_role'=>true); -$active_users = $user->getUsers($options); - -// Prepare a list of inactive users. -if($user->can('manage_users')) { - $options = array('status'=>INACTIVE,'max_rank'=>$rank,'include_clients'=>true,'include_login'=>true,'include_role'=>true); - $inactive_users = $user->getUsers($options); -} - -$uncompleted_indicators = $user->getConfigOption('uncompleted_indicators'); -if ($uncompleted_indicators) { - // Check each active user if they have an uncompleted time entry. - foreach ($active_users as $key => $active_user) { - $active_users[$key]['has_uncompleted_entry'] = (bool) ttTimeHelper::getUncompleted($active_user['id']); - } - $smarty->assign('uncompleted_indicators', true); -} - -$smarty->assign('active_users', $active_users); -$smarty->assign('inactive_users', $inactive_users); -$smarty->assign('can_delete_manager', $can_delete_manager); -$smarty->assign('title', $i18n->get('title.users')); -$smarty->assign('content_page_name', 'mobile/users.tpl'); -$smarty->display('mobile/index.tpl'); From e77be7eea69df5d52e19f9f25b5b89a0e66a5b8e Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Sun, 11 Apr 2021 21:57:58 +0000 Subject: [PATCH 180/587] An attempt to mitigate cross site request forgery vulnerability. --- WEB-INF/config.php.dist | 5 +++++ WEB-INF/lib/common.lib.php | 39 ++++++++++++++++++++++++++++++++++++++ initialize.php | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 7b6eabbd2..1b7b32b0a 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -163,6 +163,11 @@ define('AUTH_MODULE', 'db'); // define('DEBUG', false); // Note: enabling DEBUG breaks redirects as debug output is printed before setting redirect header. Do not enable on production systems. +// HTTP_TARGET - defines http target for cross site request forgery protection. +// It can be used when you access the application via a proxy. +// define('HTTP_TARGET', 'localhost'); + + // Group managers can set monthly work hour quota for years between the following values. // define('MONTHLY_QUOTA_YEAR_START', 2010); // If nothing is specified, it falls back to 2015. // define('MONTHLY_QUOTA_YEAR_END', 2025); // If nothing is specified, it falls back to 2030. diff --git a/WEB-INF/lib/common.lib.php b/WEB-INF/lib/common.lib.php index 389b29c94..52589c6e0 100644 --- a/WEB-INF/lib/common.lib.php +++ b/WEB-INF/lib/common.lib.php @@ -363,6 +363,10 @@ function ttAccessAllowed($required_right) exit(); } + // Protection against cross site request forgery. + if (!ttMitigateCSRF()) + return false; + // Check IP restriction, if set. if ($user->allow_ip && !$user->can('override_allow_ip')) { $access_allowed = false; @@ -388,6 +392,41 @@ function ttAccessAllowed($required_right) return false; } +// ttMitigateCSRF verifies request headers in an attempt to block cross site request forgery. +function ttMitigateCSRF() { + // No need to do anything for get requests. + global $request; + if ($request->isGet()) + return true; + + $origin = $_SERVER['HTTP_ORIGIN']; + if ($origin) { + $pos = strpos($origin, '//'); + $origin = substr($origin, $pos+2); // Strip protocol. + } + if (!$origin) { + // Try using referer. + $origin = $_SERVER['HTTP_REFERER']; + if ($origin) { + $pos = strpos($origin, '//'); + $origin = substr($origin, $pos+2); // Strip protocol. + $pos = strpos($origin, '/'); + $origin = substr($origin, 0, $pos); // Leave host only. + } + } + error_log("origin: ".$origin); + $target = defined('HTTP_TARGET') ? HTTP_TARGET : $_SERVER['HTTP_HOST']; + error_log("target: ".$target); + if (strcmp($origin, $target)) { + error_log("Potential cross site request forgery. Origin: '$origin' does not match target: '$target'."); + return false; // Origin and target do not match, + } + + // TODO: review and improve this function for custom ports. + return true; +} + + // ttStartsWith functions checks if a string starts with a given substring. function ttStartsWith($string, $startString) { diff --git a/initialize.php b/initialize.php index cbdfb3cc1..aadc0bb07 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.26.5430"); +define("APP_VERSION", "1.19.27.5431"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From e3f8222ee308322942bcebcd86b78ecf19382563 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 12 Apr 2021 17:14:30 +0000 Subject: [PATCH 181/587] Tested CSRF fix for custom ports - it's working, also removed unnecessary logging. --- WEB-INF/config.php.dist | 2 +- WEB-INF/lib/common.lib.php | 5 +---- initialize.php | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 1b7b32b0a..3787cbc94 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -165,7 +165,7 @@ define('AUTH_MODULE', 'db'); // HTTP_TARGET - defines http target for cross site request forgery protection. // It can be used when you access the application via a proxy. -// define('HTTP_TARGET', 'localhost'); +// define('HTTP_TARGET', 'localhost:8080'); // Group managers can set monthly work hour quota for years between the following values. diff --git a/WEB-INF/lib/common.lib.php b/WEB-INF/lib/common.lib.php index 52589c6e0..d5b43f57f 100644 --- a/WEB-INF/lib/common.lib.php +++ b/WEB-INF/lib/common.lib.php @@ -414,15 +414,12 @@ function ttMitigateCSRF() { $origin = substr($origin, 0, $pos); // Leave host only. } } - error_log("origin: ".$origin); $target = defined('HTTP_TARGET') ? HTTP_TARGET : $_SERVER['HTTP_HOST']; - error_log("target: ".$target); if (strcmp($origin, $target)) { error_log("Potential cross site request forgery. Origin: '$origin' does not match target: '$target'."); - return false; // Origin and target do not match, + return false; // Origin and target do not match. } - // TODO: review and improve this function for custom ports. return true; } diff --git a/initialize.php b/initialize.php index aadc0bb07..e8588857f 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.27.5431"); +define("APP_VERSION", "1.19.27.5432"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From ee6312e1a278cfbb240ae1419d6c63eeff0913f6 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Tue, 13 Apr 2021 22:12:35 +0000 Subject: [PATCH 182/587] Added options for secure ldap authentication. --- WEB-INF/config.php.dist | 4 ++++ WEB-INF/lib/auth/Auth_ldap.class.php | 10 ++++++++++ initialize.php | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 3787cbc94..bbf647cec 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -144,6 +144,8 @@ define('AUTH_MODULE', 'db'); // 'base_dn' => 'ou=People,dc=example,dc=com', // Path of user's base distinguished name in LDAP catalog. // 'user_login_attribute' => 'uid', // LDAP attribute used for login. // 'default_domain' => 'example.com', // Default domain. +// 'tls_cacertdir' => null, // Path to a directory containing CA certificates for secure ldap. +// 'tls_cacertfile' => null, // CA certificate file name for secure ldap. // 'member_of' => array()); // List of groups, membership in which is required for user to be authenticated. @@ -154,6 +156,8 @@ define('AUTH_MODULE', 'db'); // 'type' => 'ad', // Type of server. // 'base_dn' => 'DC=example,DC=com', // Base distinguished name in LDAP catalog. // 'default_domain' => 'example.com', // Default domain. +// 'tls_cacertdir' => null, // Path to a directory containing CA certificates for secure ldap. +// 'tls_cacertfile' => null, // CA certificate file name for secure ldap. // 'member_of' => array()); // List of groups, membership in which is required for user to be authenticated. // Leave it empty if membership is not necessary. Otherwise list CN parts only. // For example: diff --git a/WEB-INF/lib/auth/Auth_ldap.class.php b/WEB-INF/lib/auth/Auth_ldap.class.php index 7f3495737..1ccbb0371 100644 --- a/WEB-INF/lib/auth/Auth_ldap.class.php +++ b/WEB-INF/lib/auth/Auth_ldap.class.php @@ -105,6 +105,16 @@ function authenticate($login, $password) if (isTrue('DEBUG')) { ldap_set_option($lc, LDAP_OPT_DEBUG_LEVEL, 7); } + // Additional options for secure ldap. + // This insert is based on https://www.anuko.com/forum/viewtopic.php?f=4&t=2091 + // I can't test it at the moment. If things break please let us know! + if (isset($this->params['tls_cacertdir'])) { + ldap_set_option(null, LDAP_OPT_X_TLS_CACERTDIR, $this->params['tls_cacertdir']); + } + if (isset($this->params['tls_cacertfile'])) { + ldap_set_option(null, LDAP_OPT_X_TLS_CACERTFILE, $this->params['tls_cacertfile']); + } + // End of addiitional options for secure ldap. // We need to handle Windows AD and OpenLDAP differently. if ($this->params['type'] == 'ad') { diff --git a/initialize.php b/initialize.php index e8588857f..a739b939e 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.27.5432"); +define("APP_VERSION", "1.19.28.5433"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); From 4fdaa18d343d0459391e62b40971843fbd0e5924 Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 19 Apr 2021 21:26:18 +0000 Subject: [PATCH 183/587] Resuming work on php8 warnings. --- WEB-INF/lib/ttTimeHelper.class.php | 2 ++ WEB-INF/templates/header2.tpl | 2 +- WEB-INF/templates/time2.tpl | 2 +- WEB-INF/templates/time_script.tpl | 16 +++++++++------- initialize.php | 2 +- time.php | 1 + 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/WEB-INF/lib/ttTimeHelper.class.php b/WEB-INF/lib/ttTimeHelper.class.php index f0b1ea100..af2a436a5 100644 --- a/WEB-INF/lib/ttTimeHelper.class.php +++ b/WEB-INF/lib/ttTimeHelper.class.php @@ -895,6 +895,8 @@ static function getRecords($date, $includeFiles = false) { $time_fields = ", ".join(', ', $time_fields_array); } + $filePart = ''; + $fileJoin = ''; if ($includeFiles) { $filePart = ', if(Sub1.entity_id is null, 0, 1) as has_files'; $fileJoin = " left join (select distinct entity_id from tt_files". diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl index 6bc5f65fe..74ccb1adc 100644 --- a/WEB-INF/templates/header2.tpl +++ b/WEB-INF/templates/header2.tpl @@ -6,7 +6,7 @@ -{if $i18n.language.rtl} +{if (isset($i18n.language.rtl) && $i18n.language.rtl)} {/if} {if $user->getCustomCss()} diff --git a/WEB-INF/templates/time2.tpl b/WEB-INF/templates/time2.tpl index 487bff7cf..4a26f9bef 100644 --- a/WEB-INF/templates/time2.tpl +++ b/WEB-INF/templates/time2.tpl @@ -93,7 +93,7 @@ License: See license.txt *}
    {/if} -{if $template_dropdown} +{if (isset($template_dropdown) && $template_dropdown)} diff --git a/WEB-INF/templates/time_script.tpl b/WEB-INF/templates/time_script.tpl index 5834ba3cc..67c5062cc 100644 --- a/WEB-INF/templates/time_script.tpl +++ b/WEB-INF/templates/time_script.tpl @@ -46,23 +46,25 @@ var task_names = new Array(); // Prepare an array of template ids for projects. var template_ids = new Array(); -{if $bind_templates_with_projects} +{if (isset($bind_templates_with_projects) && $bind_templates_with_projects)} {foreach $project_list as $project} template_ids[{$project.id}] = "{$project.templates}"; {/foreach} {/if} // Prepare an array of template names. var template_names = new Array(); -{if $bind_templates_with_projects} +{if (isset($bind_templates_with_projects) && $bind_templates_with_projects) && isset($template_list)} {foreach $template_list as $template} template_names[{$template.id}] = "{$template.name|escape:'javascript'}"; {/foreach} {/if} // Prepare an array of template bodies. var template_bodies = new Array(); -{foreach $template_list as $template} - template_bodies[{$template.id}] = "{$template.content|escape:'javascript'}"; -{/foreach} +{if isset($template_list)} + {foreach $template_list as $template} + template_bodies[{$template.id}] = "{$template.content|escape:'javascript'}"; + {/foreach} +{/if} // The fillNote function populates the Note field with a selected template body. function fillNote(id) { @@ -189,7 +191,7 @@ function fillTaskDropdown(id) { // The fillTemplateDropdown function populates the template combo box with // templates associated with a selected project (project id is passed here as id). function fillTemplateDropdown(id) { -{if !$bind_templates_with_projects} +{if (!isset($bind_templates_with_projects) || !$bind_templates_with_projects)} return; // Do nothing if we are not binding templates with projects, {/if} @@ -234,7 +236,7 @@ function fillTemplateDropdown(id) { // The prepopulateNote function populates the note field with first found template body in Template dropdown. function prepopulateNote() { - {if !$prepopulate_note} + {if (!isset($prepopulate_note) || !$prepopulate_note)} return; {/if} var dropdown = document.getElementById("template"); diff --git a/initialize.php b/initialize.php index a739b939e..d34aa56d5 100644 --- a/initialize.php +++ b/initialize.php @@ -13,7 +13,7 @@ ini_set('display_errors', 'Off'); // require_once('init_auth.php'); -define("APP_VERSION", "1.19.28.5433"); +define("APP_VERSION", "1.19.28.5434"); define("APP_DIR", dirname(__FILE__)); define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib"); define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates"); diff --git a/time.php b/time.php index 66cf4da4b..90d54c0cf 100644 --- a/time.php +++ b/time.php @@ -225,6 +225,7 @@ $largeScreenCalendarRowSpan += 2; // Client dropdown. + $client_list = array(); if ($showClient) { $active_clients = ttGroupHelper::getActiveClients(true); // We need an array of assigned project ids to do some trimming. From 1ce02deaaa3f2c66162a55fe0b62acb1dd94739a Mon Sep 17 00:00:00 2001 From: Nik Okuntseff Date: Mon, 19 Apr 2021 22:11:54 +0000 Subject: [PATCH 184/587] Addressed a few more php8 warnings. --- WEB-INF/lib/ttTimeHelper.class.php | 4 ++-- WEB-INF/templates/header2.tpl | 8 ++++---- WEB-INF/templates/time_edit2.tpl | 2 +- initialize.php | 2 +- time_edit.php | 2 ++ 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/WEB-INF/lib/ttTimeHelper.class.php b/WEB-INF/lib/ttTimeHelper.class.php index af2a436a5..78e7a2cf5 100644 --- a/WEB-INF/lib/ttTimeHelper.class.php +++ b/WEB-INF/lib/ttTimeHelper.class.php @@ -424,10 +424,10 @@ static function insert($fields) $client = $fields['client']; $project = $fields['project']; $task = $fields['task']; - $invoice = $fields['invoice']; + $invoice = isset($fields['invoice']) ? $fields['invoice'] : null; $note = $fields['note']; $billable = $fields['billable']; - $paid = $fields['paid']; + $paid = isset($fields['paid']) ? $fields['paid'] : null; $start = ttTimeHelper::to24HourFormat($start); if ($finish) { diff --git a/WEB-INF/templates/header2.tpl b/WEB-INF/templates/header2.tpl index 74ccb1adc..65af554ee 100644 --- a/WEB-INF/templates/header2.tpl +++ b/WEB-INF/templates/header2.tpl @@ -21,7 +21,7 @@ - +