Compare commits

...

210 Commits
3.0.1 ... 2.7.8

Author SHA1 Message Date
Eric Espie
cf433f2f80 N°5725 - Twig update 'filter', 'map' and 'reduce' filters 2022-12-08 08:25:11 +01:00
Eric Espie
ae94e58a43 N°5725 - Twig update 'filter', 'map' and 'reduce' filters 2022-12-07 13:53:15 +01:00
Eric Espie
cda017fa4f N°5725 - Twig update 'filter', 'map' and 'reduce' filters 2022-12-07 13:37:52 +01:00
Pierre Goiffon
dad22f6f83 📄 Update Licenses 2022-12-07 11:04:33 +01:00
Eric Espie
9077f7ba37 N°5430 - OAuth authentication : customize redirect landing URL - remove unnecessary parameter to JS function OAuthConnect 2022-12-02 11:17:01 +01:00
Eric Espie
957ff40f30 N°5155 - Email by SMTP with self-signed certificate (changed default values to the previous behaviour) 2022-12-02 09:25:53 +01:00
Eric Espie
aff9c7748b N°5155 - Email by SMTP with self-signed certificate 2022-11-30 14:18:11 +01:00
Eric Espie
e518d34bc9 N°5553 - OAuth 2 : Hide Client Secret
* client_id is now 255 chars (AttributeString)
 * client_secret is now 64 chars (AttributePassword) and cannot be anymore in the uniqueness rules
 * The modification of redirect_url, client_id or client_secret change the status to inactive and generate a session message to ask for token regeneration
2022-11-30 14:15:37 +01:00
Eric Espie
f0141530b9 N°5725 - Twig update 'filter', 'map' and 'reduce' filters (+1 squashed commits)
Squashed commits:

[00148dec5] N°5725 - Twig update 'filter', 'map' and 'reduce' filters
2022-11-30 13:28:33 +01:00
xtophe38
ce5096a896 N°5758 Change setup test for GDPR consent (#336)
We were using SetupUtils::IsProductVersion, but this was blocking for certain packages like TeemIP standalone.
After this change we are now relying on a new method : \SetupUtils::IsConnectableToITopHub. It will check the iTop Hub Connector module presence instead.
2022-11-29 19:00:17 +01:00
Pierre Goiffon
23e0ed5e56 N°4449 Test for FPD detection in RuntimeDashboard 2022-11-29 18:10:17 +01:00
Pierre Goiffon
d412a52fcc N°4449 Fix FPD in dashboard export/import 2022-11-29 18:10:17 +01:00
Molkobain
3e18ad590f Fix image attributes not being visible in PDF exports 2022-11-25 19:30:35 +01:00
Eric Espie
22111bf667 N°5611 - Fix missing composer files in itop-oauth-client 2022-11-24 14:32:51 +01:00
Eric Espie
6d0c46595d N°5611 - Fix missing composer files in itop-oauth-client 2022-11-24 14:27:42 +01:00
Eric Espie
d292a6b0c3 N°5333 - OAuth and iTop url change 2022-11-24 13:55:36 +01:00
Eric Espie
74702c8d06 N°5430 - OAuth authentication : customize redirect landing URL 2022-11-24 13:55:36 +01:00
Pierre Goiffon
e9c91d986d 📝 CONTRIBUTING : fix typo (stash in stead of squash)
Thanks Molkobain ! (https://github.com/Combodo/iTop/pull/371#discussion_r1030759606)
2022-11-24 09:00:32 +01:00
Eric Espie
70a6b276ca Merge branch 'issue/5685-UpgradeApereoPHPCas' into support/2.7 2022-11-23 15:58:36 +01:00
Eric Espie
f77361ceb2 N°5685 - Upgrade apereo/phpcas 2022-11-23 15:53:43 +01:00
Eric Espie
75f4751b82 N°5741 - remove use of get_config_parameter in Twig 2022-11-23 15:09:20 +01:00
Romain Quetiez
b56f2f56f1 N°5704 - Fix compatibility with PHP <7.3 (HEREDOC syntax) 2022-11-16 17:12:53 +01:00
Eric Espie
68d44fa981 N°5724 - code hardening 2022-11-16 09:32:47 +01:00
Eric Espie
7e5307bd96 N°4867 - "Twig content not allowed" error 2022-11-16 09:31:42 +01:00
Romain Quetiez
cd010afb48 N°5704 - Unit tests on XML assembly (#329)
* Add a complete test suite for XML assembly

* Add a complete test suite for XML assembly

* Dispatched the test of GetDelta into real unit tests

* Add test for GetDelta on a rename operation

* Add comments on a weird case and a case on rename

* Update XML version after rebase from develop to support/2.7

* Fix phpdoc about coverage

* Remove ModelFactory::GetRootDirs and ItopTestCase::RecurseRmDir+CreateTmpDir+RecurseMkDir+RecurseCopy, that were meant to be introduced in iTop 3.0 and have been copied here by mistake, when rebasing the branch from develop to 2.7.0

* Update test/ItopTestCase.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update test/setup/ModelFactoryTest.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update test/ItopTestCase.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

Co-authored-by: Pierre Goiffon <pierre.goiffon@combodo.com>
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2022-11-08 19:43:07 +01:00
Pierre Goiffon
0cf8d731bb Rename iTopDesignFormat test class 2022-11-08 15:59:14 +01:00
Pierre Goiffon
189ca3c555 🚚 Move visual test file to the dedicated directory 2022-10-11 14:28:44 +02:00
Pierre Goiffon
1e1f1f78bf 📝 Backup : more details on check-backup parameters 2022-10-03 14:41:44 +02:00
Pierre Goiffon
1494604740 📝 Backup : move info from wiki to distrib file 2022-10-03 14:35:14 +02:00
Molkobain
583ab98210 Fix typo 2022-09-21 16:11:24 +02:00
Pierre Goiffon
88d743b1cc N°5538 Make PHPUnit test fail if transaction opened but not closed 2022-09-21 14:05:27 +02:00
Pierre Goiffon
7ac4bc95bb ItopDataTestCase : improve log message 2022-09-21 11:51:07 +02:00
Pierre Goiffon
d431811725 N°4947 Fix Email always picking "production" env config file (#331)
Note that the code was duplicated in both Email* impl, this is refactored : LoadConfig and m_oConfig are pulled up in Email, and SetRecipientFrom() calls are also refactored in Email
2022-09-14 15:33:48 +02:00
xtophe38
7512f721e9 Setup wizard : use the ITOP_APPLICATION constant instead of hardcoded "iTop" string (#335)
* Update wizardsteps.class.inc.php

* Done as requested

* Fix typo for better readability/genericity

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2022-09-13 20:11:38 +02:00
Pierre Goiffon
bdfe3a3b35 N°5235 Tmp dir setup check is now non blocking (woops previous commit was incomplete) (#301) 2022-09-13 18:22:29 +02:00
Pierre Goiffon
5cf391c3bb N°5235 - Add non blocking setup check : is tmp dir is writable (#301) 2022-09-13 18:20:35 +02:00
Eric Espie
4c1df9927d N°5394 - use session for the FSM 2022-09-12 09:45:30 +02:00
Pierre Goiffon
74003f12c1 N°5513 Remove test name debug info 2022-09-08 18:20:52 +02:00
Pierre Goiffon
3bc12b0434 N°5513 Improve PHPUnit output to stdout
Will allow to see progress when looking at the Jenkins output
2022-09-08 15:11:02 +02:00
Pierre Goiffon
02a0969b53 N°5414 Fix undefined constant error in notification with wrong placeholder
Fix regression introduced in 33c2168 (#282)
2022-08-29 12:31:45 +02:00
Stephen Abello
d78a25ee4e N°5462 Add a setup check to verify if directory-level configuration files (.htaccess and web.config) are used by the server 2022-08-24 16:33:54 +02:00
Pierre Goiffon
7a6a3d1ac0 Integration tests : move and comment itop-community group 2022-08-24 14:41:32 +02:00
Pierre Goiffon
6b32be0899 N°5216 Fix invalid message-id when sending notification using cron on system with a specific locale set (#297)
The timestamp used was indeed locale dependent.
This commit fixes this behavior by removing the locale dependency using a better printf format (see https://www.php.net/manual/fr/function.sprintf.php)
2022-08-17 14:11:32 +02:00
Pierre Goiffon
33c2168af2 🔊 Adds a debug log for invalid placeholders (#282)
This adds a debug log when a placeholder cannot be replaced.
Before the placeholder was just not replaced.
Now we can enable a debug log on the LogChannels::NOTIFICATION channel.
2022-08-17 14:09:59 +02:00
Lars Kaltefleiter
ae021064a4 🌐 Update German translations for oauth-client (#319) 2022-08-16 17:02:37 +02:00
Benjamin Dalsass
0a61169326 Update version to next release 2.7.8 2022-08-16 09:47:46 +02:00
Anne-Catherine
d7e5705520 N°5318 - Fix DBObject::CheckValue() messages being HTML encoded when not necessary (#326)
* Rollback N°4898 - Security fix

* N°5318 - security fix
2022-08-12 17:50:14 +02:00
Stephen Abello
35a8b501c9 N°5393 Security hardening 2022-08-12 11:33:55 +02:00
Eric Espie
8fa616f440 N°5395 - Errors from OAuth servers for email are not well handled 2022-08-10 14:57:26 +02:00
Molkobain
5829e698da Fix typo 2022-08-09 17:19:21 +02:00
Molkobain
df347b90e5 N°5383 - Declare DBObject::EnumTransitions() as "overwritable hook" 2022-08-08 11:53:46 +02:00
acognet
bb861aa262 N°3024 - Archiving Service Families (or any class with no child) with combodo-archive-manual 2022-08-04 16:26:21 +02:00
acognet
f9ac07830e Fix translation 2022-08-04 16:26:01 +02:00
Pierre Goiffon
0f4c7ac90f N°5129 Prevent "fieldForm is null" JS error when updating dependant field
For example when changing Server.location, 3 JS errors are thrown in the console :/
2022-07-29 10:12:37 +02:00
Molkobain
0687f9a0a9 Convert line endings to LF on misaligned text files 2022-07-28 09:58:04 +02:00
Molkobain
6e75ab2889 Add .gitattributes to enforce line endings
More info: https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
2022-07-28 09:44:42 +02:00
Molkobain
b90d29d448 🔧 Add IntelliLang.xml file to provide PHP synthax highlighting in DM XML files 2022-07-20 17:48:01 +02:00
Molkobain
1f78bf4119 N°5287 - Fix license in composer.json 2022-07-18 13:52:40 +02:00
Molkobain
5d25e77189 Code format 2022-07-13 17:03:01 +02:00
Molkobain
d9dabf25da PHPDoc 2022-07-13 17:03:01 +02:00
Molkobain
73af605892 Fix typo in dictionaries 2022-07-13 17:03:00 +02:00
Benjamin Dalsass
f70f95c119 Update community licence 2.7.7 (script from git bash, not php execution) 2022-07-11 15:20:36 +02:00
Benjamin Dalsass
53c50cf6fc Update community licence 2.7.7 2022-07-11 08:24:20 +02:00
Vincent Dumas
f19d1472c5 N°5102 - OAuth - replace double quote char EN
Use a special double quote characters so it is correctly handled in HTML
2022-07-08 13:44:00 +02:00
Vincent Dumas
eef00502cd N°5102 - OAuth - remove unsupported quote FR 2022-07-08 13:38:37 +02:00
Molkobain
0b1caac195 N°4867 - Restore datamodel node to avoid minor version migration crash
Will be properly removed in 3.1.0
2022-07-08 13:22:27 +02:00
Vincent Dumas
e900a44d47 N°5102 - OAuth client - FR tooltips 2022-07-08 12:22:52 +02:00
Vincent Dumas
a3de9fa898 N°5102 - OAuth client - Add EN tooltips 2022-07-08 12:06:47 +02:00
bdalsass
8b0154cc62 N°5168 - Access to unauthorized contact information on Portal (#305)
GlobalRequestMgmt issue
2022-07-08 09:51:20 +02:00
Eric Espie
1a225bf55b N°5102 - Allow to send emails using GSuite SMTP and OAuth - Access rights 2022-07-07 17:57:24 +02:00
Eric Espie
24d19cd8d6 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Add a flag to select OAuth client for SMTP usage 2022-07-07 16:34:19 +02:00
Eric Espie
c25a4a7346 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Access rights 2022-07-07 14:17:09 +02:00
Eric Espie
20fb7b241f N°5102 - Allow to send emails using GSuite SMTP and OAuth - Highlight classes 2022-07-06 17:23:44 +02:00
Eric Espie
a0553e1195 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Highlight classes 2022-07-06 17:10:59 +02:00
Eric Espie
f40141072a N°5102 - Allow to send emails using GSuite SMTP and OAuth - Fix errors on vendor name 2022-07-06 14:10:01 +02:00
Eric Espie
c759856a61 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Highlight classes 2022-07-06 10:10:42 +02:00
Pierre Goiffon
237b181eec 💡 Fix \SetupUtils::GetTmpDir PHPDoc 2022-07-05 18:09:59 +02:00
Eric Espie
48957fd2f0 N°5102 - Allow to send emails using GSuite SMTP and OAuth - refactor scopes 2022-07-05 17:54:43 +02:00
Pierre Goiffon
8a99c37200 N°5287 Fix composer.json errors
See https://getcomposer.org/doc/03-cli.md#validate
2022-07-05 15:08:29 +02:00
Eric Espie
d388c3fd3d N°5102 - Allow to send emails using GSuite SMTP and OAuth - Limit error size 2022-07-04 16:48:56 +02:00
Eric Espie
1b8e48539d N°5102 - Allow to send emails using GSuite SMTP and OAuth - Add comment in configuration 2022-07-01 14:32:44 +02:00
Eric Espie
104beff158 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Fix log 2022-06-29 15:09:17 +02:00
Pierre Goiffon
4712569a36 📝 CONTRIBUTING : fix GitMoji link 2022-06-29 10:56:21 +02:00
Pierre Goiffon
2392f4a902 🔒 Update guzzlehttp/guzzle 2022-06-28 15:13:04 +02:00
Eric Espie
a0f28a9098 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-28 10:47:20 +02:00
Eric Espie
6df622e8ed N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-23 14:05:17 +02:00
Eric Espie
54eb9d081b N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-23 12:20:53 +02:00
Eric Espie
9f60f27636 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-22 16:41:45 +02:00
Eric Espie
ba59643f52 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:47:46 +02:00
Eric Espie
01c02a75a8 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:40:43 +02:00
Eric Espie
f5b3e5f341 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:10:34 +02:00
Eric Espie
9b825cb529 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:05:58 +02:00
Eric Espie
3f326f0913 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 16:05:58 +02:00
acognet
ec86bd246a N°5129 - Unwanted popup during a transition with an AttributeExternalField 2022-06-21 15:24:25 +02:00
Eric Espie
aa90d5b6ab N°5102 - Allow to send emails using GSuite SMTP and OAuth - Rework 2022-06-21 13:51:08 +02:00
acognet
53d2129bd1 N°5129 - Unwanted popup during a transition with an AttributeExternalField 2022-06-16 17:58:19 +02:00
Benjamin Dalsass
00e8c11ec2 N°5037 - Setup: Add disclaimer about collected data
change ui organization
2022-06-14 17:18:34 +02:00
Benjamin Dalsass
617b6b991f N°5037 - Setup: Add disclaimer about collected data
flip modules array
2022-06-14 14:33:35 +02:00
Benjamin Dalsass
b3ea1050eb N°5037 - Setup: Add disclaimer about collected data 2022-06-14 12:40:36 +02:00
Benjamin Dalsass
ca98066d68 N°5037 - Setup: Add disclaimer about collected data 2022-06-14 10:54:25 +02:00
Pierre Goiffon
352f7c8675 Update guzzlehttp/guzzle 2022-06-14 09:47:13 +02:00
Eric Espie
df5d514c28 N°4642 - Core Update : limit the usage of this function to minor version - fix error message (revert) 2022-06-13 15:59:25 +02:00
Eric Espie
16663797b2 N°4642 - Core Update : limit the usage of this function to minor version - fix error message 2022-06-13 15:51:36 +02:00
Eric Espie
4099376472 N°5102 - Allow to send emails using GSuite SMTP and OAuth - Defer the deletion (expunge) to the end of connection 2022-06-09 11:40:13 +02:00
Eric Espie
6d3118d9e9 N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth (fix config error message) 2022-06-08 13:24:29 +02:00
odain
4c585614cd ease testing: CreateTestOrganization returns org object 2022-06-08 11:07:31 +02:00
Eric Espie
9674378c56 N°5211 - Core update not working with auto-selected modules (comments) 2022-06-08 10:36:55 +02:00
Eric Espie
9e314ba77b N°5211 - Core update not working with auto-selected modules 2022-06-08 10:24:03 +02:00
Eric Espie
cdd7dcdc5c N°5211 - Core update not working with auto-selected modules 2022-06-08 10:12:19 +02:00
Benjamin Dalsass
34bed5ec4f N°5215 - Portal insufficient access control for ajax search form 2022-06-07 11:14:43 +02:00
Pierre Goiffon
3ea82e37d5 N°4635 Report \LogChannels::NOTIFICATIONS 2022-06-03 18:00:29 +02:00
Pierre Goiffon
596c62aec8 💡 N°4867 Add bug reference in phpdoc 2022-06-03 09:54:29 +02:00
acognet
265415030e N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal - Add comment 2022-06-02 12:35:42 +02:00
Eric Espie
3d26f28f9b N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
* Add icons to wizard
2022-06-01 11:44:02 +02:00
Eric Espie
0abec767e3 Dictionaries 2022-06-01 10:45:53 +02:00
Benjamin Dalsass
9fd10bd73e N°5168 - Security hardening 2022-05-31 16:28:02 +02:00
acognet
95dafc87c0 N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal - Add tests 2022-05-30 15:10:50 +02:00
acognet
fe1790793e N°4898 - security hardening 2022-05-30 15:10:49 +02:00
Eric Espie
ddb95dc64e Removed laminas service manager test folder 2022-05-27 09:32:16 +02:00
Eric Espie
f6f9ee26e1 Removed laminas service manager test folder 2022-05-27 09:29:00 +02:00
Eric Espie
21faa92904 Merge branch 'support/2.7' into feature/OAuthMail 2022-05-27 09:06:28 +02:00
Eric Espie
622f40c06c N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
 * Fix legacy mailboxes compatibility
2022-05-25 08:21:16 +02:00
acognet
964134cb60 N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal - Remove useless code 2022-05-24 18:20:18 +02:00
acognet
72f498a63b N°5168 - Fix error message "Call to a member function GetKey() on null" 2022-05-24 10:50:56 +02:00
Pierre Goiffon
f9a1f68295 N°4655 Remove OQL tests
Were only here to check legacy OQL engine, but since 2.7.0 we fixed couple of bugs in the current OQL engine : we can't keep same functionalities in both engines :/.

Plus now we are working on 2.7.7 and we're not aware of any use of this legacy engine...

Note that it will be deprecated (N°3141) and removed (N°4715) very soon.
2022-05-24 10:38:59 +02:00
Pierre Goiffon
9b67b0b9d5 Same options in phpunit config files 2022-05-23 14:53:13 +02:00
acognet
f798ef1d76 N°4538 - Dashlet Groupby on ExternalKey with special character, bad display - remove useless test 2022-05-23 14:21:03 +02:00
Eric Espie
754946bf62 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
 * Fix legacy mailboxes compatibility
2022-05-23 12:09:40 +02:00
Eric Espie
a6580e3cd8 Merge branch 'support/2.7' into feature/OAuthMail 2022-05-23 10:56:32 +02:00
Pierre Goiffon
da6621f2ff Fix include warning in unittestautoload.php on Windows 2022-05-23 09:53:30 +02:00
Molkobain
f2d42a7e56 N°5002 - Simplify code 2022-05-20 18:41:39 +02:00
Benjamin Dalsass
d01e4b4a85 N°5168 - Security hardening 2022-05-20 16:08:25 +02:00
Pierre Goiffon
f57d1f1de3 Fix PHPunit errors with InlineImageMock.php and UtilsTest
HTMLDOMSanitizerTest : fix "Fatal error: Cannot declare class InlineImage, because the name is already in use in /var/www/html/iTop/test/core/sanitizer/InlineImageMock.php"
We are now injecting the class to mock, instead of declaring another class with the same name (was working before but why ?!???)

\UtilsTest::testSanitizer : no more testing the "class" filter, because it is a simple indirection, and we need to load datamodel which is causing multiple problems (see the comment in the test method dataprovider)
2022-05-20 10:48:05 +02:00
Eric Espie
a3f122184c N°4642 - Core Update : limit the usage of this function - revert due to N°4666 fix 2022-05-20 10:20:47 +02:00
acognet
16fcddc249 N°4867 - "Twig content not allowed" error when use the extkey widget search icon in the user portal (regression of N°4384 ) 2022-05-20 09:52:25 +02:00
Eric Espie
2a9c9be36a N°4666 - Core Update : handle modules 2022-05-20 09:42:14 +02:00
Eric Espie
ca3aae23a1 N°4666 - Core Update : handle modules 2022-05-20 09:33:41 +02:00
bdalsass
4dd384e418 N°4872 - Create a ticket in resolved statut Inlineimage disappear (#294) 2022-05-20 09:26:06 +02:00
Molkobain
80e7313b24 PHPDoc 2022-05-19 17:40:14 +02:00
Eric Espie
183c3c1baf N°4666 - Core Update : handle modules 2022-05-19 16:30:06 +02:00
Eric Espie
160c52fe81 Merge branch 'support/2.7' into feature/OAuthMail 2022-05-19 14:49:48 +02:00
Benjamin Dalsass
5f0a820b4a N°4899 - add sanitizer url since annotation and tests for sanitizer function 2022-05-19 08:36:42 +02:00
Benjamin Dalsass
03ef4246bf N°4899 - add sanitizer url since annotation and tests for sanitizer function 2022-05-18 12:03:07 +02:00
Pierre Goiffon
534e7cf59d N°4655 New nightly PHPUnit file containing OQL tests
Those tests were removed in 72af2b7c as they took too much time to run.
We are re-enabling them but only for nightly builds !
2022-05-18 09:35:13 +02:00
Eric Espie
e1645f6903 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * Config messages
 * Fix unit tests
2022-05-18 08:41:58 +02:00
Benjamin Dalsass
61a2d200b4 N°4900 - Stored XSS in dashlets failed OQL query 2022-05-18 08:10:01 +02:00
Benjamin Dalsass
3d6bbe4029 Revert "N°4900 - Stored XSS in dashlets failed OQL query"
This reverts commit 562dd8fc21.
2022-05-18 08:05:19 +02:00
Eric Espie
44eda676a3 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-17 16:56:43 +02:00
Molkobain
eac6f07823 N°4985 - PHP 8.0: Fix optional parameter before mandatory parameter
* Method is always (once) called with the value defined in iTop
  * No Combodo extension call the method
  * No customization in the ITSM Designer (snippets / extensions) call the method
  * Calling method with only the first parameter would crash anyway
2022-05-17 16:51:50 +02:00
Pierre Goiffon
424e2a5745 💡 Fix PHPDoc for \DBObject::CheckConsistency 2022-05-17 15:52:43 +02:00
Molkobain
0ef4fee0b4 N°4985 - PHP 8.0: Fix usort callback return type 2022-05-17 15:28:04 +02:00
Eric Espie
1d45eff9b0 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-17 10:11:15 +02:00
Benjamin Dalsass
8e97279401 N°4899 - Reflected XSS on revert_dashboard operation 2022-05-17 09:27:06 +02:00
Eric Espie
932ef780fd N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-17 09:06:49 +02:00
Benjamin Dalsass
59424c3126 N°4976 - CSRF in import page 2022-05-17 09:02:06 +02:00
Benjamin Dalsass
562dd8fc21 N°4900 - Stored XSS in dashlets failed OQL query 2022-05-17 08:20:26 +02:00
Molkobain
cf745554fb N°4985 - PHP 8.0: Fix strlen() test condition that needs to be more strict 2022-05-16 18:04:29 +02:00
Molkobain
e909eac98e N°4985 - PHP 8.0: Fix is_callable() first param syntax in ObjectFormManager 2022-05-16 17:44:34 +02:00
Molkobain
5e42efc3ec N°4985 - PHP 8.0: Fix usort callback return type in portal's lists initialization 2022-05-16 17:44:33 +02:00
Eric Espie
eb1d56f439 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration
2022-05-16 14:51:12 +02:00
Eric Espie
644e1ac4f6 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 16:27:56 +02:00
Stephen Abello
4c88dbd9ac N°2504 N°3169 N°5102 Add libraries 2022-05-13 14:39:19 +02:00
Stephen Abello
11d2e62e67 N°2504 N°3169 N°5102 Correctly disable authentication button for 2.7 2022-05-13 14:38:55 +02:00
Stephen Abello
58b27a9daa N°2504 N°3169 N°5102 Handle result display 2022-05-13 14:28:38 +02:00
Stephen Abello
caf939bf58 N°2504 N°3169 N°5102 Add dictionaries 2022-05-13 14:06:11 +02:00
Eric Espie
8c217fdac9 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 12:07:27 +02:00
Eric Espie
6b80bbeaa2 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 11:45:42 +02:00
Eric Espie
134736dce5 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
 * 2.7 migration (wip)
2022-05-13 11:37:09 +02:00
Stephen Abello
4b870bcf1e N°2504 N°3169 N°5102 Add js template 2022-05-12 17:38:38 +02:00
Eric Espie
dd8a4a0082 N°3169 - Add feature to connect Gsuite mail box with OAuth
N°2504 - Add feature to connect Office mail box with OAuth2 for Microsoft Graph
N°5102 - Allow to send emails (eg. notifications) using GSuite SMTP and OAuth
2022-05-12 14:40:55 +02:00
Molkobain
c2607c4223 N°5035 - Setup: Remove tracking image at the end of the setup 2022-05-09 13:55:06 +02:00
Pierre Goiffon
1fb0911710 🔧 N°3091 postbuild PHPunit XML : change html_errors PHP setting 2022-05-03 10:53:32 +02:00
Pierre Goiffon
b348e0ff27 🔧 N°3091 PHPunit XML : change html_errors PHP setting
We are outputting to console, and will get results in Jenkins or terminal, so no HTML please :o)
2022-05-03 10:51:48 +02:00
Pierre Goiffon
4646a05c7a N°4824 Update consumers after swiftmailer/swiftmailer
Multiple things to do as there were some changes in 6.0
Reference : https://github.com/swiftmailer/swiftmailer/blob/master/CHANGES#L107

* Fix "Call to undefined method Swift_Message::newInstance()" exception in notifications
* Fix removed Swift_MailTransport
2022-05-03 09:35:48 +02:00
Pierre Goiffon
c5527c106c 🔧 N°3091 PHPunit XML : set columns 2022-05-02 15:33:39 +02:00
Pierre Goiffon
5eac1b8730 🔧 N°3091 PHPunit XML : fix correct PHP INI settings
see https://phpunit.readthedocs.io/en/8.5/configuration.html#the-php-element
2022-05-02 15:25:59 +02:00
Pierre Goiffon
0de15d040f ⬇️ N°4824 rollback scssphp/scssphp update (won't be done in this branch !) 2022-05-02 09:15:48 +02:00
Pierre Goiffon
c4ae94fd4c Update denied test dirs 2022-04-29 17:15:50 +02:00
Pierre Goiffon
1e8818984e 📄 N°4284 Update licenses 2022-04-29 15:53:03 +02:00
Pierre Goiffon
a023f73509 N°4284 Update jquery UI SCSS to remove SCSSPHP warnings
Replace "Alpha(..." with "alpha(..."

Example of warning at compilation with SCSSPHP :

DEPRECATION WARNING: Calling built-in functions with a non-standard name is deprecated since Scssphp 1.8.0 and will not work anymore in 2.0 (they will be treated as CSS function calls instead).
Use "alpha" instead of "Alpha".
         on line 55 of /var/www/html/iTop/css/../css/ui-lightness/jqueryui.scss
2022-04-29 15:39:26 +02:00
Pierre Goiffon
6f0e1a7f47 N°4824 Update consumers after swiftmailer/swiftmailer update
Also remove new Doctrine test dir (iTopComposerTest feedback)
2022-04-29 15:24:56 +02:00
Pierre Goiffon
0ef9bb1a47 ⬆️ N°4824 Composer libs : update swiftmailer/swiftmailer 2022-04-29 15:24:56 +02:00
Pierre Goiffon
71ceedc4bb 🔨 N°4284 Detect new test dirs on composer update 2022-04-29 15:24:56 +02:00
Pierre Goiffon
73c3c1249f ⬆️ N°4824 Composer libs : update scssphp/scssphp 2022-04-29 15:24:56 +02:00
Pierre Goiffon
88a10dba28 N°4824 Update consumers after pelago/emogrifier update 2022-04-29 15:24:56 +02:00
Pierre Goiffon
001e222f67 ⬆️ N°4824 Composer libs : update pelago/emogrifier 2022-04-29 15:24:56 +02:00
Pierre Goiffon
af8bcdc242 ⬆️ N°4824 Composer libs : update pear/archive_tar 2022-04-29 15:24:56 +02:00
Pierre Goiffon
f4c7afc148 N°4824 Update consumers & tests after nikic/php-parser update
Was done in 3.0.0 with N°3867
(cherry picked from commit cd1ba097cb)
(cherry picked from commit 5b42f67a99)
(cherry picked from commit 2d98ca2318)
(cherry picked from commit ddc5bbd1bb)
2022-04-29 15:24:56 +02:00
Pierre Goiffon
b19c73a36e ⬆️ N°4284 Composer libs : update nikic/php-parser
Was done in 3.0.0 with N°3867
2022-04-29 15:24:55 +02:00
Pierre Goiffon
5fe0d0b94f ⬆️ N°4284 Composer libs : update combodo/tcpdf 2022-04-29 15:18:41 +02:00
Pierre Goiffon
f8d435d5f3 N°4284 Composer libs : refresh symfony 2022-04-29 15:18:41 +02:00
Pierre Goiffon
f15ef36fd1 N°4284 Composer libs : remove symfony/polyfill-php70
Though it is still downloaded because asked by symfony framework, but as we don't need it in our code no need to specify it here !
2022-04-29 15:18:41 +02:00
Pierre Goiffon
64b25c4daa 📌 N°4284 Composer libs : fix twig/twig to ~1.42.5
Without specifying explicitly the Twig version, since the update of require php from 5.6 to 7.0 we are getting Twig 2.12.5 !
We don't want Twig 2 as this version changes the macro scope and causes massive changes in our code... This update will be done later in other branches.
2022-04-29 15:15:32 +02:00
Pierre Goiffon
d0ba0d193b N°3091 iTopComposerTest : change deprecated PHPUnit method call 2022-04-22 14:42:12 +02:00
Pierre Goiffon
8e6e2432d3 Extensibility : iPortalUIExtension and AbstractPortalUIExtension aren't experimental anymore 2022-04-21 17:29:40 +02:00
Molkobain
83ec19dfca Remove duplicated lines in .gitignore 2022-04-21 14:26:56 +02:00
Pierre Goiffon
6e619f2c35 Fix \iTopConfigParserTest::testConfigWriteToFile_FromScratchInstallation throwing error 2022-04-21 12:02:35 +02:00
Pierre Goiffon
163ba41e8d N°3091 Update PHPUnit to 8.5 : remove doesNotPerformAssertions annotation
Modified tests :
- iTopConfigParsertest
- DBSearchIntersectTest::testIntersectOptimization

As expected this isn't working with PHPUnit 8.5
Why does it worked with previous PHPUnit 6 version ? Maybe this annotation wasn't handled yet ? The corresponding PHPUnit doc isn't available anymore...

Annotations doc for PHP 8.5 : https://phpunit.readthedocs.io/en/8.5/annotations.html#doesnotperformassertions
2022-04-21 12:02:35 +02:00
Pierre Goiffon
ec143c43db N°3091 Update PHPUnit to 8.5 : fix setUp and teardDown methods signatures
"Return type declaration must be compatible with parent"
See https://phpunit.de/announcements/phpunit-8.html "Return Type of Template Methods"
2022-04-21 12:02:35 +02:00
Pierre Goiffon
cacf0004a5 🙈 N°3091 Update PHPUnit to 8.5 : add PHPunit cache file to ignore
We don't want to disable the feature, nor we want this file to be versionned
https://phpunit.readthedocs.io/en/8.5/configuration.html#the-cacheresult-attribute
2022-04-21 12:02:35 +02:00
Pierre Goiffon
cb39541e2a N°3091 Update PHPUnit to 8.5 : composer and base files
Autoload wasn't working anymore, easy to see : just launch `php unittestautoload.php` (or see fatal errors when launching tests with your IDE)
2022-04-21 10:47:30 +02:00
Pierre Goiffon
b9ddadeb44 N°5109 update PHP requirements from 5.6 to 7.0
No embedded libs supports all versions from PHP 5.6 to 8.0 included :/
7.0.8 is required for our Symfony version (updated with N°4770)
2022-04-20 17:29:20 +02:00
Pierre Goiffon
11e811cc4b N°3717 Improve iTop object history API (#192)
This fixes a major flaw in the history API that was causing "phantom" CMDBChange records (without any CMDBChangeOp attached). That was happening especially in iProcess impl.
For example this lead to the creation of the combodo-cmdbchange-cleaner module in the Mail To Ticket extension.

The modifications in detail : 
- We can now pass a non persisted CMDBChange instance to \CMDBObject::SetCurrentChange
- No persistence done in \CMDBObject::CreateChange anymore
- Persistence of the attached CMDChange will be done if necessary in CMDBChangeOp::OnInsert
- New CMDBObject::SetCurrentChangeFromParams helper method to ease resetting the current change
2022-04-19 17:13:18 +02:00
Pierre Goiffon
e422adb0d0 N°4998 Fix CSS for AttributeDuration in transition form (#281) 2022-04-19 12:25:15 +02:00
Pierre Goiffon
e02d9f3f0e 💡 N°5090 Improve phpdoc using list array shape 2022-04-15 17:43:20 +02:00
Pierre Goiffon
e831d66b76 N°5090 Setup : improve missing dependencies message (#280)
The setup now relies on the new method MissingDependencyException::getHtmlDesc to get the message to display
MissingDependencyException is also now a CoreException child.

Note that previous behavior (MissingDependencyException instantiator setting message) is kept, as some consumer still do $e->getMessage() (like unattended install)
2022-04-15 17:30:05 +02:00
acognet
6fa2d47780 N°4538 - Dashlet Groupby on ExternalKey with special character, bad display 2022-04-15 10:03:04 +02:00
acognet
e691454339 N°5002 - memory leak after object creation in popup 2022-04-15 10:00:08 +02:00
Pierre Goiffon
92997e3e57 💡 N°2498 add @since 2022-04-08 08:54:07 +02:00
Pierre Goiffon
631b38a160 N°5003 Change cron_max_execution_time config param help text 2022-03-25 15:56:11 +01:00
1612 changed files with 166074 additions and 27110 deletions

48
.gitattributes vendored Normal file
View File

@@ -0,0 +1,48 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.bash text eol=lf
*.bat text eol=lf
*.cmd text eol=lf
*.css text eol=lf
*.scss text eol=lf
*.dist text eol=lf
.editorconfig text eol=lf
.env* text eol=lf
.gitignore text eol=lf
.htaccess text eol=lf
*.htm text eol=lf
*.html text eol=lf
*.ini text eol=lf
*.js text eol=lf
*.json text eol=lf
*.lock text eol=lf
*.md text eol=lf
*.php text eol=lf
*.php_cs text eol=lf
*.php8 text eol=lf
*.plex text eol=lf
*.sh text eol=lf
*.svg text eol=lf
*.ts text eol=lf
*.twig text eol=lf
*.txt text eol=lf
*.xml text eol=lf
*.xsd text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpeg binary
*.jpg binary
*.gif binary
*.ico binary
*.pdf binary
*.swf binary
*.zip binary
*.ttf binary
*.woff binary
*.woff2 binary

11
.gitignore vendored
View File

@@ -6,12 +6,6 @@
# maintenance mode (N°2240)
/.maintenance
# listing prevention in conf directory
/conf/**
!/conf/.htaccess
!/conf/index.php
!/conf/web.config
# composer reserver directory, from sources, populate/update using "composer install"
vendor/*
test/vendor/*
@@ -19,6 +13,7 @@ test/vendor/*
# all conf but listing prevention
/conf/**
!/conf/.htaccess
!/conf/index.php
!/conf/web.config
# all datas but listing prevention
@@ -37,9 +32,13 @@ test/vendor/*
!/log/index.php
!/log/web.config
# PHPUnit cache file
/test/.phpunit.result.cache
# Jetbrains
/.idea/**
!/.idea/IntelliLang.xml
# doc. generation
/.doc/vendor

15
.idea/IntelliLang.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="LanguageInjectionConfiguration">
<injection language="InjectablePHP" injector-id="xml">
<display-name>iTop - Class method code</display-name>
<place><![CDATA[xmlTag().withLocalName(string().equalTo("code"))]]></place>
<xpath-condition>name(..) = 'method' and count(/itop_design) = 1</xpath-condition>
</injection>
<injection language="InjectablePHP" injector-id="xml">
<display-name>iTop - Snippet code</display-name>
<place><![CDATA[xmlTag().withLocalName(string().equalTo("snippet"))]]></place>
<xpath-condition>name(..) = 'snippets' and count(/itop_design) = 1</xpath-condition>
</injection>
</component>
</project>

View File

@@ -50,14 +50,24 @@ foreach ($aDeniedButStillPresent as $sDir)
continue;
}
try
{
try {
SetupUtils::rrmdir($sDir);
echo "OK Remove denied test dir: '$sDir'\n";
}
catch (\Exception $e)
{
catch (\Exception $e) {
echo "\nFAILED to remove denied test dir: '$sDir'\n";
}
}
$aAllowedAndDeniedDirs = array_merge(
$oiTopComposer->ListAllowedTestDir(),
$oiTopComposer->ListDeniedTestDir()
);
$aExistingDirs = $oiTopComposer->ListAllTestDir();
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
if (false === empty($aMissing)) {
echo "Some new tests dirs exists !\n"
.' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n"
.' List of dirs:'."\n".var_export($aMissing, true);
}

View File

@@ -111,9 +111,9 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
* Use the present tense ("Add feature" not "Added feature")
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Limit the first line to 72 characters or less
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.carloscuesta.me/)).
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
Emoji examples :
* Please start the commit message with an applicable emoji code (following the [Gitmoji guide](https://gitmoji.dev/)).
Beware to use the code (for example `:bug:`) and not the character (🐛) as Unicode support in git clients is very poor for now...
Emoji examples :
* 🌐 `:globe_with_meridians:` for translations
* 🎨 `:art:` when improving the format/structure of the code
* ⚡️ `:zap:` when improving performance
@@ -132,7 +132,7 @@ Our tests are located in the `test/` directory, containing a PHPUnit config file
When your code is working, please:
* stash as much as possible your commits,
* squash as much as possible your commits,
* rebase your branch on our repo last commit,
* create a pull request.

View File

@@ -1083,11 +1083,11 @@ abstract class AbstractPageUIExtension implements iPageUIExtension
/**
* Implement this interface to add content to any enhanced portal page
*
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
*
* @api
* @package Extensibility
* @since 2.4.0
*
* @since 2.4.0 interface creation
* @since 2.7.0 change method signatures due to Silex to Symfony migration
*/
interface iPortalUIExtension
{
@@ -1160,7 +1160,11 @@ interface iPortalUIExtension
}
/**
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
*
* @api
* @package Extensibility
* @since 2.4.0
*/
abstract class AbstractPortalUIExtension implements iPortalUIExtension
{

View File

@@ -4735,11 +4735,15 @@ EOF
$sCSSClass = $bResult ? HILIGHT_CLASS_NONE : HILIGHT_CLASS_CRITICAL;
$sChecked = $bResult ? 'checked' : '';
$sDisabled = $bResult ? '' : 'disabled';
$aErrorsToDisplay = array_map(function($sError) {
return utils::HtmlEntities($sError);
}, $aErrors);
$aRows[] = array(
'form::select' => "<input type=\"checkbox\" class=\"selectList\" $sChecked $sDisabled\"></input>",
'object' => $oObj->GetHyperlink(),
'status' => $sStatus,
'errors' => '<p>'.($bResult ? '' : implode('</p><p>', $aErrors)).'</p>',
'errors' => '<p>'.($bResult ? '' : implode('</p><p>', $aErrorsToDisplay)).'</p>',
'@class' => $sCSSClass,
);
if ($bResult && (!$bPreview))

View File

@@ -1478,6 +1478,29 @@ JS
return $this->sDefinitionFile;
}
/**
* @param string $sDashboardFileRelative can also be an absolute path (compatibility with old URL)
*
* @return string full path to the Dashboard file
* @throws \SecurityException if path isn't under approot
* @uses utils::RealPath()
* @since 2.7.8 3.0.3 3.1.0 N°4449 remove FPD
*/
public static function GetDashboardFileFromRelativePath($sDashboardFileRelative)
{
if (utils::RealPath($sDashboardFileRelative, APPROOT)) {
// compatibility with old URL containing absolute path !
return $sDashboardFileRelative;
}
$sDashboardFile = APPROOT.$sDashboardFileRelative;
if (false === utils::RealPath($sDashboardFile, APPROOT)) {
throw new SecurityException('Invalid dashboard file !');
}
return $sDashboardFile;
}
/**
* @param string $sDefinitionFile
*/

View File

@@ -255,7 +255,7 @@ abstract class Dashlet
catch(OqlException $e)
{
$oPage->add('<div class="dashlet-content">');
$oPage->p($e->GetUserFriendlyDescription());
$oPage->p(utils::HtmlEntities($e->GetUserFriendlyDescription()));
$oPage->add('</div>');
}
catch(Exception $e)

View File

@@ -1223,7 +1223,7 @@ class DesignerComboField extends DesignerFormField
$sChecked = $this->defaultValue ? 'checked' : '';
$sMandatory = $this->bMandatory ? 'true' : 'false';
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
if ($this->IsSorted())
if ($this->IsSorted() )
{
asort($this->aAllowedValues);
}
@@ -1271,18 +1271,14 @@ class DesignerComboField extends DesignerFormField
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
}
}
foreach($this->aAllowedValues as $sKey => $sDisplayValue)
{
if ($this->bMultipleSelection)
{
foreach ($this->aAllowedValues as $sKey => $sDisplayValue) {
if ($this->bMultipleSelection) {
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
}
else
{
} else {
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
}
// Quick and dirty: display the menu parents as a tree
$sHtmlValue = str_replace(' ', '&nbsp;', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8'));
$sHtmlValue = str_replace(' ', '&nbsp;', $sDisplayValue);
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
}
$sHtml .= "</select>";

View File

@@ -59,6 +59,8 @@ class LoginBasic extends AbstractLoginFSMExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
// Save the checked user
$_SESSION['auth_user'] = $sAuthUser;
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -67,7 +69,7 @@ class LoginBasic extends AbstractLoginFSMExtension
{
if ($_SESSION['login_mode'] == 'basic')
{
list($sAuthUser) = $this->GetAuthUserAndPassword();
$sAuthUser = $_SESSION['auth_user'];
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;

View File

@@ -43,6 +43,8 @@ class LoginExternal extends AbstractLoginFSMExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
// Save the checked user
$_SESSION['auth_user'] = $sAuthUser;
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -51,7 +53,7 @@ class LoginExternal extends AbstractLoginFSMExtension
{
if ($_SESSION['login_mode'] == 'external')
{
$sAuthUser = $this->GetAuthUser();
$sAuthUser = $_SESSION['auth_user'];
LoginWebPage::OnLoginSuccess($sAuthUser, 'external', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;

View File

@@ -71,6 +71,8 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
// Save the checked user
$_SESSION['auth_user'] = $sAuthUser;
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -82,15 +84,7 @@ class LoginForm extends AbstractLoginFSMExtension implements iLoginUIExtension
{
if ($_SESSION['login_mode'] == 'form')
{
if (isset($_SESSION['auth_user']))
{
// If FSM reenter this state (example 2FA) then the auth_user is not resubmitted
$sAuthUser = $_SESSION['auth_user'];
}
else
{
$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
}
$sAuthUser = $_SESSION['auth_user'];
// Store 'auth_user' in session for further use
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}

View File

@@ -58,6 +58,8 @@ class LoginURL extends AbstractLoginFSMExtension
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS;
return LoginWebPage::LOGIN_FSM_ERROR;
}
// Save the checked user
$_SESSION['auth_user'] = $sAuthUser;
}
return LoginWebPage::LOGIN_FSM_CONTINUE;
}
@@ -66,7 +68,7 @@ class LoginURL extends AbstractLoginFSMExtension
{
if ($_SESSION['login_mode'] == 'url')
{
$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
$sAuthUser = $_SESSION['auth_user'];
LoginWebPage::OnLoginSuccess($sAuthUser, 'internal', $_SESSION['login_mode']);
}
return LoginWebPage::LOGIN_FSM_CONTINUE;

View File

@@ -208,7 +208,7 @@ class LoginWebPage extends NiceWebPage
}
// This token allows the user to change the password without knowing the previous one
$sToken = substr(md5(APPROOT.uniqid()), 0, 16);
$sToken = bin2hex(random_bytes(32));
$oUser->Set('reset_pwd_token', $sToken);
CMDBObject::SetTrackInfo('Reset password');
$oUser->AllowWrite(true);

View File

@@ -5,7 +5,6 @@ namespace Combodo\iTop;
use AttributeDateTime;
use Dict;
use Exception;
use MetaModel;
use Twig_Environment;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
@@ -115,14 +114,6 @@ class TwigExtension
return utils::IsDevelopmentEnvironment();
}));
// Function to get configuration parameter
// Usage in twig: {{ get_config_parameter('foo') }}
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_config_parameter', function($sParamName)
{
$oConfig = MetaModel::GetConfig();
return $oConfig->Get($sParamName);
}));
// Function to get the URL of a static page in a module
// Usage in twig: {{ get_static_page_module_url('itop-my-module', 'path-to-my-page') }}
$oTwigEnv->addFunction(new Twig_SimpleFunction('get_static_page_module_url', function($sModuleName, $sPage)

View File

@@ -283,6 +283,7 @@ class utils
*
* @since 2.5.2 2.6.0 new 'transaction_id' filter
* @since 2.7.0 new 'element_identifier' filter
* @since 2.7.7, 3.0.2, 3.1.0 N°4899 - new 'url' filter
*/
protected static function Sanitize_Internal($value, $sSanitizationFilter)
{
@@ -358,6 +359,11 @@ class utils
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
break;
// For URL
case 'url':
$retValue = filter_var($value, FILTER_SANITIZE_URL);
break;
default:
case 'raw_data':
$retValue = $value;
@@ -1323,19 +1329,19 @@ class utils
$oDashboard = $param;
$sDashboardId = $oDashboard->GetId();
$sDashboardFile = $oDashboard->GetDefinitionFile();
$sDashboardFileRelative = utils::LocalPath($sDashboardFile);
$sDlgTitle = addslashes(Dict::S('UI:ImportDashboardTitle'));
$sDlgText = addslashes(Dict::S('UI:ImportDashboardText'));
$sCloseBtn = addslashes(Dict::S('UI:Button:Cancel'));
$sDashboardFileJS = addslashes($sDashboardFile);
$sDashboardFileURL = urlencode($sDashboardFile);
$sDashboardFileJS = addslashes($sDashboardFileRelative);
$sDashboardFileURL = urlencode($sDashboardFileRelative);
$sUploadDashboardTransactId = utils::GetNewTransactionId();
$aResult = array(
new SeparatorPopupMenuItem(),
new URLPopupMenuItem('UI:ExportDashboard', Dict::S('UI:ExportDashBoard'), utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=export_dashboard&id='.$sDashboardId.'&file='.$sDashboardFileURL),
new JSPopupMenuItem('UI:ImportDashboard', Dict::S('UI:ImportDashBoard'), "UploadDashboard({dashboard_id: '$sDashboardId', file: '$sDashboardFileJS', title: '$sDlgTitle', text: '$sDlgText', close_btn: '$sCloseBtn', transaction: '$sUploadDashboardTransactId' })"),
);
if ($oDashboard->GetReloadURL())
{
if ($oDashboard->GetReloadURL()) {
$aResult[] = new SeparatorPopupMenuItem();
$aResult[] = new URLPopupMenuItem('UI:Menu:PrintableVersion', Dict::S('UI:Menu:PrintableVersion'), $oDashboard->GetReloadURL().'&printable=1', '_blank');
}

View File

@@ -14,7 +14,7 @@ define('APPCONF', APPROOT.'conf/');
* @used-by utils::GetItopVersionWikiSyntax()
* @used-by iTopModulesPhpVersionIntegrationTest
*/
define('ITOP_CORE_VERSION', '2.7.7');
define('ITOP_CORE_VERSION', '2.7.8');
require_once APPROOT.'bootstrap.inc.php';

View File

@@ -1,8 +1,10 @@
{
"name": "combodo/itop",
"description": "IT Operations Portal",
"type": "project",
"license": "AGPLv3",
"license": "AGPL-3.0-only",
"require": {
"php": ">=5.6.0",
"php": ">=7.0.8",
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
@@ -10,18 +12,23 @@
"ext-json": "*",
"ext-mysqli": "*",
"ext-soap": "*",
"combodo/tcpdf": "6.3.5",
"nikic/php-parser": "^3.1",
"pear/archive_tar": "1.4.14",
"pelago/emogrifier": "2.1.0",
"combodo/tcpdf": "~6.4.4",
"guzzlehttp/guzzle": "^6.5.8",
"laminas/laminas-mail": "^2.11",
"laminas/laminas-servicemanager": "^3.5",
"league/oauth2-google": "^3.0",
"nikic/php-parser": "~4.13.2",
"pear/archive_tar": "~1.4.14",
"pelago/emogrifier": "~3.1.0",
"scssphp/scssphp": "1.0.6",
"swiftmailer/swiftmailer": "5.4.12",
"swiftmailer/swiftmailer": "~6.3.0",
"symfony/console": "~3.4.47",
"symfony/dotenv": "~3.4.47",
"symfony/framework-bundle": "~3.4.47",
"symfony/polyfill-php70": "1.*",
"symfony/twig-bundle": "~3.4.47",
"symfony/yaml": "~3.4.47"
"symfony/yaml": "~3.4.47",
"thenetworg/oauth2-azure": "^2.0",
"twig/twig": "~1.42.5"
},
"require-dev": {
"symfony/stopwatch": "~3.4.47",
@@ -37,7 +44,7 @@
},
"config": {
"platform": {
"php": "5.6.0"
"php": "7.0.8"
},
"vendor-dir": "lib",
"preferred-install": {
@@ -52,7 +59,8 @@
"application",
"sources/application",
"sources/Composer",
"sources/Controller"
"sources/Controller",
"sources/Core"
],
"exclude-from-classmap": [
"core/dbobjectsearch.class.php",

1915
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -179,7 +179,7 @@ class ActionEmail extends ActionNotification
protected function FindRecipients($sRecipAttCode, $aArgs)
{
$sOQL = $this->Get($sRecipAttCode);
if (strlen($sOQL) == '') return '';
if (strlen($sOQL) === 0) return '';
try
{
@@ -328,8 +328,12 @@ class ActionEmail extends ActionNotification
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
$oObj = $aContextArgs['this->object()'];
$sMessageId = sprintf('iTop_%s_%d_%f@%s.openitop.org', get_class($oObj), $oObj->GetKey(), microtime(true /* get as float*/),
MetaModel::GetEnvironmentId());
$sMessageId = sprintf('iTop_%s_%d_%F@%s.openitop.org',
get_class($oObj),
$oObj->GetKey(),
microtime(true /* get as float*/),
MetaModel::GetEnvironmentId()
);
$sReference = '<'.$sMessageId.'>';
}
catch (Exception $e) {

View File

@@ -230,7 +230,7 @@ abstract class AsyncTask extends DBObject
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
}
$this->Set('last_error', $sErrorMessage);
$this->SetTrim('last_error', $sErrorMessage);
$this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!!
$this->Set('last_attempt', time());

View File

@@ -63,22 +63,30 @@ class CMDBChangeOp extends DBObject
/**
* Describe (as a text string) the modifications corresponding to this change
*/
*/
public function GetDescription()
{
return '';
}
/**
* Safety net: in case the change is not given, let's guarantee that it will
* be set to the current ongoing change (or create a new one)
*/
* Safety net:
* * if change isn't persisted yet, use the current change and persist it if needed
* * in case the change is not given, let's guarantee that it will be set to the current ongoing change (or create a new one)
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 do persist the current change if needed
*/
protected function OnInsert()
{
if ($this->Get('change') <= 0)
{
$this->Set('change', CMDBObject::GetCurrentChange());
$iChange = $this->Get('change');
if (($iChange <= 0) || (is_null($iChange))) {
$oChange = CMDBObject::GetCurrentChange();
if ($oChange->IsNew()) {
$oChange->DBWrite();
}
$this->Set('change', $oChange);
}
parent::OnInsert();
}
}

View File

@@ -114,6 +114,26 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange = $oChange;
}
/**
* @param string $sUserInfo
* @param string $sOrigin
* @param \DateTime $oDate
*
* @throws \CoreException
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 new method to reset current change
*/
public static function SetCurrentChangeFromParams($sUserInfo, $sOrigin = null, $oDate = null)
{
static::SetTrackInfo($sUserInfo);
static::SetTrackOrigin($sOrigin);
static::CreateChange();
if (!is_null($oDate)) {
static::$m_oCurrChange->Set("date", $oDate);
}
}
//
// Todo: simplify the APIs and do not pass the current change as an argument anymore
// SetTrackInfo to be invoked in very few cases (UI.php, CSV import, Data synchro)
@@ -145,6 +165,8 @@ abstract class CMDBObject extends DBObject
* $oMyChange->Set("userinfo", 'this is done by ... for ...');
* $iChangeId = $oMyChange->DBInsert();
*
* **warning** : this will do nothing if current change already exists !
*
* @see SetCurrentChange to specify a CMDBObject instance instead
*
* @param string $sInfo
@@ -157,6 +179,8 @@ abstract class CMDBObject extends DBObject
/**
* Provides information about the origin of the change
*
* **warning** : this will do nothing if current change already exists !
*
* @see SetTrackInfo
* @see SetCurrentChange to specify a CMDBObject instance instead
*
@@ -167,18 +191,15 @@ abstract class CMDBObject extends DBObject
{
self::$m_sOrigin = $sOrigin;
}
/**
* Get the additional information (defaulting to user name)
*/
protected static function GetTrackInfo()
*/
public static function GetTrackInfo()
{
if (is_null(self::$m_sInfo))
{
if (is_null(self::$m_sInfo)) {
return CMDBChange::GetCurrentUserName();
}
else
{
} else {
return self::$m_sInfo;
}
}
@@ -201,7 +222,8 @@ abstract class CMDBObject extends DBObject
/**
* Set to {@link $m_oCurrChange} a standard change record (done here 99% of the time, and nearly once per page)
*
* The CMDBChange is persisted so that it has a key > 0, and any new CMDBChangeOp can link to it
* @since 2.7.7 3.0.2 3.1.0 N°3717 {@see CMDBChange} **will be persisted later** in {@see \CMDBChangeOp::OnInsert} (was done previously directly here)
* This will avoid creating in DB CMDBChange lines without any corresponding CMDBChangeOp
*/
protected static function CreateChange()
{
@@ -209,7 +231,6 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange->Set("date", time());
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
self::$m_oCurrChange->Set("origin", self::GetTrackOrigin());
self::$m_oCurrChange->DBInsert();
}
/**

View File

@@ -113,10 +113,18 @@ class MySQLNoTransactionException extends MySQLException
}
/**
* @since 2.7.8 3.0.3 3.1.0 N°5538
*/
class MySQLTransactionNotClosedException extends MySQLException
{
}
/**
* CMDBSource
* database access wrapper
* database access wrapper
*
* @package iTopORM
*/

View File

@@ -476,11 +476,11 @@ class Config
'show_in_conf_sample' => true,
),
'cron_max_execution_time' => array(
'type' => 'integer',
'description' => 'Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout',
'default' => 600,
'value' => 600,
'source_of_value' => '',
'type' => 'integer',
'description' => 'Duration (seconds) of the cron.php script : if exceeded the script will exit even if there are remaining tasks to process. Must be shorter than php max_execution_time setting (note than when using CLI, this is set to 0 by default which means unlimited). If cron.php is ran via web, it must be shorter than the web server response timeout.',
'default' => 600,
'value' => 600,
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'cron_sleep' => array(
@@ -509,7 +509,7 @@ class Config
),
'email_transport' => array(
'type' => 'string',
'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)',
'description' => 'Mean to send emails: PHPMail (uses the function mail()), SMTP (implements the client protocol) or SMTP_OAuth (connect to the server using OAuth 2.0)',
'default' => "PHPMail",
'value' => "PHPMail",
'source_of_value' => '',
@@ -555,6 +555,22 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'email_transport_smtp.allow_self_signed' => array(
'type' => 'bool',
'description' => 'Allow self signed peer certificates',
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'email_transport_smtp.verify_peer' => array(
'type' => 'bool',
'description' => 'Verify peer certificate',
'default' => true,
'value' => true,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
'email_css' => array(
'type' => 'string',
'description' => 'CSS that will override the standard stylesheet used for the notifications',

View File

@@ -165,19 +165,15 @@ class CoreCannotSaveObjectException extends CoreException
public function getHtmlMessage()
{
$sTitle = Dict::S('UI:Error:SaveFailed');
$sContent = "<span><strong>{$sTitle}</strong></span>";
$sContent = "<span><strong>".utils::HtmlEntities($sTitle)."</strong></span>";
if (count($this->aIssues) == 1)
{
if (count($this->aIssues) == 1) {
$sIssue = reset($this->aIssues);
$sContent .= " <span>{$sIssue}</span>";
}
else
{
$sContent .= " <span>".utils::HtmlEntities($sIssue)."</span>";
} else {
$sContent .= '<ul>';
foreach ($this->aIssues as $sError)
{
$sContent .= "<li>$sError</li>";
foreach ($this->aIssues as $sError) {
$sContent .= "<li>".utils::HtmlEntities($sError)."</li>";
}
$sContent .= '</ul>';
}

View File

@@ -1977,9 +1977,9 @@ abstract class DBObject implements iDisplay
/**
* check attributes together
*
* @overwritable-hook You can extend this method in order to provide your own logic.
*
* @return bool
* @overwritable-hook You can extend this method in order to provide your own logic.
*
* @return true|string true if successful, the error description otherwise
*/
public function CheckConsistency()
{
@@ -3690,7 +3690,7 @@ abstract class DBObject implements iDisplay
}
/**
* @internal
* @overwritable-hook You can extend this method in order to provide your own logic.
*
* @return array
*

View File

@@ -1623,7 +1623,7 @@ abstract class DBSearch
$oSet = new DBObjectSet($this);
if (MetaModel::IsStandaloneClass($sClass))
{
$oSet->OptimizeColumnLoad(array($this->GetClassAlias() => array('')));
$oSet->OptimizeColumnLoad(array($this->GetClassAlias() => array()));
$aIds = array($sClass => $oSet->GetColumnAsArray('id'));
}
else

View File

@@ -1203,8 +1203,10 @@ class DisplayableGraph extends SimpleGraph
* @param float $xMax Right coordinate of the bounding box to display the graph
* @param float $yMin Top coordinate of the bounding box to display the graph
* @param float $yMax Bottom coordinate of the bounding box to display the graph
*
* @since 2.7.7 3.0.2 3.1.0 N°4985 $sComments param is no longer optional
*/
function RenderAsPDF(PDFPage $oPage, $sComments = '', $sContextKey, $xMin = -1, $xMax = -1, $yMin = -1, $yMax = -1)
function RenderAsPDF(PDFPage $oPage, $sComments, $sContextKey, $xMin = -1, $xMax = -1, $yMin = -1, $yMax = -1)
{
$aContextDefs = static::GetContextDefinitions($sContextKey, false); // No need to develop the parameters
$oPdf = $oPage->get_tcpdf();

View File

@@ -24,38 +24,69 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
Swift_Preferences::getInstance()->setCharset('UTF-8');
use Combodo\iTop\Core\Email\EmailFactory;
use Combodo\iTop\Core\Email\iEMail;
define ('EMAIL_SEND_OK', 0);
define ('EMAIL_SEND_PENDING', 1);
define ('EMAIL_SEND_ERROR', 2);
class EMail
class EMail implements iEMail
{
/**
* @see self::LoadConfig()
* @var Config
* @since 2.7.7 3.0.2 3.1.0 N°3169 N°5102 Move attribute to children classes
* @since 2.7.8 3.0.3 3.1.0 N°4947 pull up the attribute back to the Email class as config init is done here
*/
protected static $m_oConfig = null;
protected $oMailer;
// Serialization formats
const ORIGINAL_FORMAT = 1; // Original format, consisting in serializing the whole object, inculding the Swift Mailer's object.
// Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string
// Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string
const FORMAT_V2 = 2; // New format, only the raw data are serialized (base64 encoded if needed)
protected static $m_oConfig = null;
protected $m_aData; // For storing data to serialize
public function LoadConfig($sConfigFile = ITOP_DEFAULT_CONFIG_FILE)
{
if (is_null(self::$m_oConfig))
{
self::$m_oConfig = new Config($sConfigFile);
}
}
protected $m_oMessage;
public function __construct()
{
$this->m_aData = array();
$this->m_oMessage = Swift_Message::newInstance();
$this->SetRecipientFrom(MetaModel::GetConfig()->Get('email_default_sender_address'), MetaModel::GetConfig()->Get('email_default_sender_label'));
$this->oMailer = EmailFactory::GetMailer();
}
/**
* Sets {@see m_oConfig} if current attribute is null
*
* @returns \Config the current {@see m_oConfig} value
* @throws \ConfigException
* @throws \CoreException
*
* @uses utils::GetConfig()
*
* @since 2.7.7 3.0.2 3.1.0 N°3169 N°5102 Move method to children classes
* @since 2.7.8 3.0.3 3.1.0 N°4947 Pull up to the parent class, and remove `$sConfigFile` param
*/
public function LoadConfig()
{
if (is_null(static::$m_oConfig)) {
static::$m_oConfig = utils::GetConfig();
}
return static::$m_oConfig;
}
/**
* @return void
* @throws \ConfigException
* @throws \CoreException
* @since 2.7.8 3.0.3 3.1.0 N°4947 Method creation, to factorize same code in children classes
*/
protected function InitRecipientFrom()
{
$oConfig = $this->LoadConfig();
$this->SetRecipientFrom(
$oConfig->Get('email_default_sender_address'),
$oConfig->Get('email_default_sender_label')
);
}
/**
@@ -66,485 +97,96 @@ class EMail
*/
public function SerializeV2()
{
return serialize($this->m_aData);
return $this->oMailer->SerializeV2();
}
/**
* Custom de-serialization method
*
* @param string $sSerializedMessage The serialized representation of the message
*
* @return \Email
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
*/
static public function UnSerializeV2($sSerializedMessage)
{
$aData = unserialize($sSerializedMessage);
$oMessage = new Email();
if (array_key_exists('body', $aData))
{
$oMessage->SetBody($aData['body']['body'], $aData['body']['mimeType']);
}
if (array_key_exists('message_id', $aData))
{
$oMessage->SetMessageId($aData['message_id']);
}
if (array_key_exists('bcc', $aData))
{
$oMessage->SetRecipientBCC($aData['bcc']);
}
if (array_key_exists('cc', $aData))
{
$oMessage->SetRecipientCC($aData['cc']);
}
if (array_key_exists('from', $aData))
{
$oMessage->SetRecipientFrom($aData['from']['address'], $aData['from']['label']);
}
if (array_key_exists('reply_to', $aData))
{
$oMessage->SetRecipientReplyTo($aData['reply_to']);
}
if (array_key_exists('to', $aData))
{
$oMessage->SetRecipientTO($aData['to']);
}
if (array_key_exists('subject', $aData))
{
$oMessage->SetSubject($aData['subject']);
}
if (array_key_exists('headers', $aData))
{
foreach($aData['headers'] as $sKey => $sValue)
{
$oMessage->AddToHeader($sKey, $sValue);
}
}
if (array_key_exists('parts', $aData))
{
foreach($aData['parts'] as $aPart)
{
$oMessage->AddPart($aPart['text'], $aPart['mimeType']);
}
}
if (array_key_exists('attachments', $aData))
{
foreach($aData['attachments'] as $aAttachment)
{
$oMessage->AddAttachment(base64_decode($aAttachment['data']), $aAttachment['filename'], $aAttachment['mimeType']);
}
}
return $oMessage;
}
protected function SendAsynchronous(&$aIssues, $oLog = null)
{
try
{
AsyncSendEmail::AddToQueue($this, $oLog);
}
catch(Exception $e)
{
$aIssues = array($e->GetMessage());
return EMAIL_SEND_ERROR;
}
$aIssues = array();
return EMAIL_SEND_PENDING;
}
protected function SendSynchronous(&$aIssues, $oLog = null)
{
// If the body of the message is in HTML, embed all images based on attachments
$this->EmbedInlineImages();
$this->LoadConfig();
$sTransport = self::$m_oConfig->Get('email_transport');
switch ($sTransport)
{
case 'SMTP':
$sHost = self::$m_oConfig->Get('email_transport_smtp.host');
$sPort = self::$m_oConfig->Get('email_transport_smtp.port');
$sEncryption = self::$m_oConfig->Get('email_transport_smtp.encryption');
$sUserName = self::$m_oConfig->Get('email_transport_smtp.username');
$sPassword = self::$m_oConfig->Get('email_transport_smtp.password');
$oTransport = Swift_SmtpTransport::newInstance($sHost, $sPort, $sEncryption);
if (strlen($sUserName) > 0)
{
$oTransport->setUsername($sUserName);
$oTransport->setPassword($sPassword);
}
break;
case 'Null':
$oTransport = Swift_NullTransport::newInstance();
break;
case 'LogFile':
$oTransport = Swift_LogFileTransport::newInstance();
$oTransport->setLogFile(APPROOT.'log/mail.log');
break;
case 'PHPMail':
default:
$oTransport = Swift_MailTransport::newInstance();
}
$oMailer = Swift_Mailer::newInstance($oTransport);
$aFailedRecipients = array();
$this->m_oMessage->setMaxLineLength(0);
$oKPI = new ExecutionKPI();
try
{
$iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients);
if ($iSent === 0)
{
// Beware: it seems that $aFailedRecipients sometimes contains the recipients that actually received the message !!!
IssueLog::Warning('Email sending failed: Some recipients were invalid, aFailedRecipients contains: '.implode(', ', $aFailedRecipients));
$aIssues = array('Some recipients were invalid.');
$oKPI->ComputeStats('Email Sent', 'Error received');
return EMAIL_SEND_ERROR;
}
else
{
$aIssues = array();
$oKPI->ComputeStats('Email Sent', 'Succeded');
return EMAIL_SEND_OK;
}
}
catch (Exception $e)
{
$oKPI->ComputeStats('Email Sent', 'Error received');
throw $e;
}
}
/**
* Reprocess the body of the message (if it is an HTML message)
* to replace the URL of images based on attachments by a link
* to an embedded image (i.e. cid:....)
*/
protected function EmbedInlineImages()
{
if ($this->m_aData['body']['mimeType'] == 'text/html')
{
$oDOMDoc = new DOMDocument();
$oDOMDoc->preserveWhitespace = true;
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$this->m_aData['body']['body']); // For loading HTML chunks where the character set is not specified
$oXPath = new DOMXPath($oDOMDoc);
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
$oImagesList = $oXPath->query($sXPath);
if ($oImagesList->length != 0)
{
foreach($oImagesList as $oImg)
{
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
if ($oAttachment)
{
$sImageSecret = $oImg->getAttribute('data-img-secret');
$sAttachmentSecret = $oAttachment->Get('secret');
if ($sImageSecret !== $sAttachmentSecret)
{
// @see N°1921
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
continue;
}
$oDoc = $oAttachment->Get('contents');
$oSwiftImage = new Swift_Image($oDoc->GetData(), $oDoc->GetFileName(), $oDoc->GetMimeType());
$sCid = $this->m_oMessage->embed($oSwiftImage);
$oImg->setAttribute('src', $sCid);
}
}
}
$sHtmlBody = $oDOMDoc->saveHTML();
$this->m_oMessage->setBody($sHtmlBody, 'text/html', 'UTF-8');
}
return EmailFactory::GetMailer()::UnSerializeV2($sSerializedMessage);
}
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
{
//select a default sender if none is provided.
if(empty($this->m_aData['from']['address']) && !empty($this->m_aData['to'])){
$this->SetRecipientFrom($this->m_aData['to']);
}
if ($bForceSynchronous)
{
return $this->SendSynchronous($aIssues, $oLog);
}
else
{
$bConfigASYNC = MetaModel::GetConfig()->Get('email_asynchronous');
if ($bConfigASYNC)
{
return $this->SendAsynchronous($aIssues, $oLog);
}
else
{
return $this->SendSynchronous($aIssues, $oLog);
}
}
return $this->oMailer->Send($aIssues, $bForceSynchronous, $oLog);
}
public function AddToHeader($sKey, $sValue)
{
if (!array_key_exists('headers', $this->m_aData))
{
$this->m_aData['headers'] = array();
}
$this->m_aData['headers'][$sKey] = $sValue;
if (strlen($sValue) > 0)
{
$oHeaders = $this->m_oMessage->getHeaders();
switch(strtolower($sKey))
{
case 'return-path':
$this->m_oMessage->setReturnPath($sValue);
break;
default:
$oHeaders->addTextHeader($sKey, $sValue);
}
}
$this->oMailer->AddToHeader($sKey, $sValue);
}
public function SetMessageId($sId)
{
$this->m_aData['message_id'] = $sId;
// Note: Swift will add the angle brackets for you
// so let's remove the angle brackets if present, for historical reasons
$sId = str_replace(array('<', '>'), '', $sId);
$oMsgId = $this->m_oMessage->getHeaders()->get('Message-ID');
$oMsgId->SetId($sId);
$this->oMailer->SetMessageId($sId);
}
public function SetReferences($sReferences)
{
$this->AddToHeader('References', $sReferences);
$this->oMailer->SetReferences($sReferences);
}
public function SetBody($sBody, $sMimeType = 'text/html', $sCustomStyles = null)
{
if (($sMimeType === 'text/html') && ($sCustomStyles !== null))
{
$emogrifier = new \Pelago\Emogrifier($sBody, $sCustomStyles);
$sBody = $emogrifier->emogrify(); // Adds html/body tags if not already present
}
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
$this->m_oMessage->setBody($sBody, $sMimeType);
$this->oMailer->SetBody($sBody, $sMimeType, $sCustomStyles);
}
public function AddPart($sText, $sMimeType = 'text/html')
{
if (!array_key_exists('parts', $this->m_aData))
{
$this->m_aData['parts'] = array();
}
$this->m_aData['parts'][] = array('text' => $sText, 'mimeType' => $sMimeType);
$this->m_oMessage->addPart($sText, $sMimeType);
$this->oMailer->AddPart($sText, $sMimeType);
}
public function AddAttachment($data, $sFileName, $sMimeType)
{
if (!array_key_exists('attachments', $this->m_aData))
{
$this->m_aData['attachments'] = array();
}
$this->m_aData['attachments'][] = array('data' => base64_encode($data), 'filename' => $sFileName, 'mimeType' => $sMimeType);
$this->m_oMessage->attach(Swift_Attachment::newInstance($data, $sFileName, $sMimeType));
$this->oMailer->AddAttachment($data, $sFileName, $sMimeType);
}
public function SetSubject($sSubject)
{
$this->m_aData['subject'] = $sSubject;
$this->m_oMessage->setSubject($sSubject);
$this->oMailer->SetSubject($sSubject);
}
public function GetSubject()
{
return $this->m_oMessage->getSubject();
return $this->oMailer->GetSubject();
}
/**
* Helper to transform and sanitize addresses
* - get rid of empty addresses
*/
protected function AddressStringToArray($sAddressCSVList)
{
$aAddresses = array();
foreach(explode(',', $sAddressCSVList) as $sAddress)
{
$sAddress = trim($sAddress);
if (strlen($sAddress) > 0)
{
$aAddresses[] = $sAddress;
}
}
return $aAddresses;
}
public function SetRecipientTO($sAddress)
{
$this->m_aData['to'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setTo($aAddresses);
}
$this->oMailer->SetRecipientTO($sAddress);
}
public function GetRecipientTO($bAsString = false)
{
$aRes = $this->m_oMessage->getTo();
if ($aRes === null)
{
// There is no "To" header field
$aRes = array();
}
if ($bAsString)
{
$aStrings = array();
foreach ($aRes as $sEmail => $sName)
{
if (is_null($sName))
{
$aStrings[] = $sEmail;
}
else
{
$sName = str_replace(array('<', '>'), '', $sName);
$aStrings[] = "$sName <$sEmail>";
}
}
return implode(', ', $aStrings);
}
else
{
return $aRes;
}
return $this->oMailer->GetRecipientTO($bAsString);
}
public function SetRecipientCC($sAddress)
{
$this->m_aData['cc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setCc($aAddresses);
}
$this->oMailer->SetRecipientCC($sAddress);
}
public function SetRecipientBCC($sAddress)
{
$this->m_aData['bcc'] = $sAddress;
if (!empty($sAddress))
{
$aAddresses = $this->AddressStringToArray($sAddress);
$this->m_oMessage->setBcc($aAddresses);
}
$this->oMailer->SetRecipientBCC($sAddress);
}
public function SetRecipientFrom($sAddress, $sLabel = '')
{
$this->m_aData['from'] = array('address' => $sAddress, 'label' => $sLabel);
if ($sLabel != '')
{
$this->m_oMessage->setFrom(array($sAddress => $sLabel));
}
else if (!empty($sAddress))
{
$this->m_oMessage->setFrom($sAddress);
}
$this->oMailer->SetRecipientFrom($sAddress, $sLabel);
}
public function SetRecipientReplyTo($sAddress)
{
$this->m_aData['reply_to'] = $sAddress;
if (!empty($sAddress))
{
$this->m_oMessage->setReplyTo($sAddress);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
/**
* Extension to SwiftMailer: "debug" transport that pretends messages have been sent,
* but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport
{
protected $sLogFile;
/**
* Sends the given message.
*
* @param Swift_Mime_Message $message
* @param string[] $failedRecipients An array of failures by-reference
*
* @return int The number of sent emails
*/
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
{
$hFile = @fopen($this->sLogFile, 'a');
if ($hFile)
{
$sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n";
$sTxt .= $message->toString()."\n";
@fwrite($hFile, $sTxt);
@fclose($hFile);
}
return parent::send($message, $failedRecipients);
}
public function setLogFile($sFilename)
{
$this->sLogFile = $sFilename;
}
}
/**
* Pretends messages have been sent, but just log them to a file.
*
* @package Swift
* @author Denis Flaven
*/
class Swift_LogFileTransport extends Swift_Transport_LogFileTransport
{
/**
* Create a new LogFileTransport.
*/
public function __construct()
{
call_user_func_array(
array($this, 'Swift_Transport_LogFileTransport::__construct'),
Swift_DependencyContainer::getInstance()
->createDependenciesFor('transport.null')
);
}
/**
* Create a new LogFileTransport instance.
*
* @return Swift_LogFileTransport
*/
public static function newInstance()
{
return new self();
$this->oMailer->SetRecipientReplyTo($sAddress);
}
}

View File

@@ -116,6 +116,18 @@ abstract class DOMSanitizer extends HTMLSanitizer
{
/** @var DOMDocument */
protected $oDoc;
/**
* @var string Class to use for InlineImage static method calls
* @used-by \Combodo\iTop\Test\UnitTest\Core\Sanitizer\HTMLDOMSanitizerTest::testDoSanitizeCallInlineImageProcessImageTag
*/
protected $sInlineImageClassName;
public function __construct($sInlineImageClassName = InlineImage::class)
{
parent::__construct();
$this->sInlineImageClassName = $sInlineImageClassName;
}
abstract public function GetTagsWhiteList();
@@ -211,7 +223,7 @@ abstract class DOMSanitizer extends HTMLSanitizer
// Recurse
$this->CleanNode($oNode);
if (($oNode instanceof DOMElement) && (strtolower($oNode->tagName) == 'img')) {
InlineImage::ProcessImageTag($oNode);
$this->sInlineImageClassName::ProcessImageTag($oNode);
}
}
}
@@ -347,6 +359,30 @@ class HTMLDOMSanitizer extends DOMSanitizer
'white-space',
);
public function __construct($sInlineImageClassName = InlineImage::class)
{
parent::__construct($sInlineImageClassName);
// Building href validation pattern from url and email validation patterns as the patterns are not used the same way in HTML content than in standard attributes value.
// eg. "foo@bar.com" vs "mailto:foo@bar.com?subject=Title&body=Hello%20world"
if (!array_key_exists('href', self::$aAttrsWhiteList)) {
// Regular urls
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
// Mailto urls
$sMailtoPattern = '(mailto:('.utils::GetConfig()->Get('email_validation_pattern').')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
// Notification placeholders
// eg. $this->caller_id$, $this->hyperlink()$, $this->hyperlink(portal)$, $APP_URL$, $MODULES_URL$, ...
// Note: Authorize both $xxx$ and %24xxx%24 as the latter one is encoded when used in HTML attributes (eg. a[href])
$sPlaceholderPattern = '(\$|%24)[\w-]*(->[\w]*(\([\w-]*?\))?)?(\$|%24)';
$sPattern = $sUrlPattern.'|'.$sMailtoPattern.'|'.$sPlaceholderPattern;
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
self::$aAttrsWhiteList['href'] = $sPattern;
}
}
public function GetTagsWhiteList()
{
return static::$aTagsWhiteList;
@@ -372,30 +408,6 @@ class HTMLDOMSanitizer extends DOMSanitizer
return static::$aStylesWhiteList;
}
public function __construct()
{
parent::__construct();
// Building href validation pattern from url and email validation patterns as the patterns are not used the same way in HTML content than in standard attributes value.
// eg. "foo@bar.com" vs "mailto:foo@bar.com?subject=Title&body=Hello%20world"
if (!array_key_exists('href', self::$aAttrsWhiteList)) {
// Regular urls
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
// Mailto urls
$sMailtoPattern = '(mailto:('.utils::GetConfig()->Get('email_validation_pattern').')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
// Notification placeholders
// eg. $this->caller_id$, $this->hyperlink()$, $this->hyperlink(portal)$, $APP_URL$, $MODULES_URL$, ...
// Note: Authorize both $xxx$ and %24xxx%24 as the latter one is encoded when used in HTML attributes (eg. a[href])
$sPlaceholderPattern = '(\$|%24)[\w-]*(->[\w]*(\([\w-]*?\))?)?(\$|%24)';
$sPattern = $sUrlPattern.'|'.$sMailtoPattern.'|'.$sPlaceholderPattern;
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
self::$aAttrsWhiteList['href'] = $sPattern;
}
}
public function LoadDoc($sHTML)
{
@$this->oDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sHTML); // For loading HTML chunks where the character set is not specified

View File

@@ -6,6 +6,8 @@
*/
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter\Standard;
@@ -80,38 +82,49 @@ class iTopConfigParser
* @param \PhpParser\Parser $oParser
* @param $sConfig
*
* @return \Combodo\iTop\Config\Validator\ConfigNodesVisitor
* @return void
*/
private function BrowseFile(\PhpParser\Parser $oParser, $sConfig)
private function BrowseFile(Parser $oParser, $sConfig)
{
$prettyPrinter = new Standard();
try
{
try {
$aNodes = $oParser->parse($sConfig);
}
catch (\Error $e)
{
catch (\Error $e) {
$sMessage = Dict::Format('config-parse-error', $e->getMessage(), $e->getLine());
$this->oException = new \Exception($sMessage, 0, $e);
}
foreach ($aNodes as $oAssignation)
{
if (! $oAssignation instanceof Assign)
{
foreach ($aNodes as $sKey => $oNode) {
// With PhpParser 3 we had an Assign node at root
// In PhpParser 4 the root node is now an Expression
if (false === ($oNode instanceof \PhpParser\Node\Stmt\Expression)) {
continue;
}
/** @var \PhpParser\Node\Stmt\Expression $oNode */
if (false === ($oNode->expr instanceof Assign)) {
continue;
}
/** @var Assign $oAssignation */
$oAssignation = $oNode->expr;
if (false === ($oAssignation->var instanceof Variable)) {
continue;
}
if (false === ($oAssignation->expr instanceof PhpParser\Node\Expr\Array_)) {
continue;
}
$sCurrentRootVar = $oAssignation->var->name;
if (!array_key_exists($sCurrentRootVar, $this->aVarsMap))
{
if (!array_key_exists($sCurrentRootVar, $this->aVarsMap)) {
continue;
}
$aCurrentRootVarMap =& $this->aVarsMap[$sCurrentRootVar];
foreach ($oAssignation->expr->items as $oItem)
{
foreach ($oAssignation->expr->items as $oItem) {
$sValue = $prettyPrinter->prettyPrintExpr($oItem->value);
$aCurrentRootVarMap[$oItem->key->value] = $sValue;
}

View File

@@ -551,6 +551,13 @@ class LogChannels
const INLINE_IMAGE = 'InlineImage';
/**
* @var string
* @since 3.0.1 N°4849
* @since 2.7.7 N°4635
*/
const NOTIFICATIONS = 'notifications';
const PORTAL = 'portal';
}
@@ -691,7 +698,7 @@ abstract class LogAPI
if (isset($sLogLevelMin[static::CHANNEL_DEFAULT]))
{
return $sLogLevelMin[$sChannel];
return $sLogLevelMin[static::CHANNEL_DEFAULT];
}
return static::LEVEL_DEFAULT;

View File

@@ -7344,14 +7344,11 @@ abstract class MetaModel
$aSearches = array();
$aReplacements = array();
foreach ($aParams as $sSearch => $replace)
{
foreach ($aParams as $sSearch => $replace) {
// Some environment parameters are objects, we just need scalars
if (is_object($replace))
{
if (is_object($replace)) {
$iPos = strpos($sSearch, '->object()');
if ($iPos !== false)
{
if ($iPos !== false) {
// Expand the parameters for the object
$sName = substr($sSearch, 0, $iPos);
// Note: Capturing
@@ -7359,63 +7356,67 @@ abstract class MetaModel
// 2 - The arrow
// 3 - The attribute code
$aRegExps = array(
'/(\\$)'.$sName.'-(>|&gt;)([^\\$]+)\\$/', // Support both syntaxes: $this->xxx$ or $this-&gt;xxx$ for HTML compatibility
'/(%24)'.$sName.'-(>|&gt;)([^%24]+)%24/', // Support for urlencoded in HTML attributes (%20this-&gt;xxx%20)
);
foreach($aRegExps as $sRegExp)
{
if(preg_match_all($sRegExp, $sInput, $aMatches))
{
foreach($aMatches[3] as $idx => $sPlaceholderAttCode)
{
try
{
$sReplacement = $replace->GetForTemplate($sPlaceholderAttCode);
if($sReplacement !== null)
{
$aReplacements[] = $sReplacement;
$aSearches[] = $aMatches[1][$idx] . $sName . '-' . $aMatches[2][$idx] . $sPlaceholderAttCode . $aMatches[1][$idx];
}
}
catch(Exception $e)
{
// No replacement will occur
}
}
}
}
}
else
{
'/(\\$)'.$sName.'-(>|&gt;)([^\\$]+)\\$/', // Support both syntaxes: $this->xxx$ or $this-&gt;xxx$ for HTML compatibility
'/(%24)'.$sName.'-(>|&gt;)([^%24]+)%24/', // Support for urlencoded in HTML attributes (%20this-&gt;xxx%20)
);
foreach ($aRegExps as $sRegExp) {
if (preg_match_all($sRegExp, $sInput, $aMatches)) {
foreach ($aMatches[3] as $idx => $sPlaceholderAttCode) {
try {
$sReplacement = $replace->GetForTemplate($sPlaceholderAttCode);
if ($sReplacement !== null) {
$aReplacements[] = $sReplacement;
$aSearches[] = $aMatches[1][$idx].$sName.'-'.$aMatches[2][$idx].$sPlaceholderAttCode.$aMatches[1][$idx];
}
}
catch (Exception $e) {
$aContext = [
'placeholder' => $sPlaceholderAttCode,
'replace class' => get_class($replace),
];
if ($replace instanceof DBObject) {
$aContext['replace id'] = $replace->GetKey();
}
IssueLog::Debug(
'Invalid placeholder in notification, no replacement will occur!',
LogChannels::NOTIFICATIONS,
$aContext
);
}
}
}
}
} else {
continue; // Ignore this non-scalar value
}
}
else
{
} else {
$aRegExps = array(
'/(\$)'.$sSearch.'\$/', // Support for regular placeholders (eg. $APP_URL$)
'/(%24)'.$sSearch.'%24/', // Support for urlencoded in HTML attributes (eg. %24APP_URL%24)
);
foreach($aRegExps as $sRegExp)
{
if(preg_match_all($sRegExp, $sInput, $aMatches))
{
foreach($aMatches[1] as $idx => $sDelimiter)
{
try
{
$aReplacements[] = (string) $replace;
$aSearches[] = $aMatches[1][$idx] . $sSearch . $aMatches[1][$idx];
foreach ($aRegExps as $sRegExp) {
if (preg_match_all($sRegExp, $sInput, $aMatches)) {
foreach ($aMatches[1] as $idx => $sDelimiter) {
try {
$aReplacements[] = (string)$replace;
$aSearches[] = $aMatches[1][$idx].$sSearch.$aMatches[1][$idx];
}
catch(Exception $e)
{
// No replacement will occur
catch (Exception $e) {
IssueLog::Debug(
'Invalid placeholder in notification, no replacement will occur !',
LogChannels::NOTIFICATIONS,
[
'placeholder' => $sPlaceholderAttCode,
'replace' => $replace,
]
);
}
}
}
}
}
}
return str_replace($aSearches, $aReplacements, $sInput);
}

View File

@@ -25,6 +25,19 @@
class PDFBulkExport extends HTMLBulkExport
{
/**
* @var string For sample purposes
* @internal
* @since 2.7.8
*/
const ENUM_OUTPUT_TYPE_SAMPLE = 'sample';
/**
* @var string For the real export
* @internal
* @since 2.7.8
*/
const ENUM_OUTPUT_TYPE_REAL = 'real';
public function DisplayUsage(Page $oP)
{
$oP->p(" * pdf format options:");
@@ -190,6 +203,25 @@ EOF
return $sPDF;
}
/**
* @inheritDoc
* @since 2.7.8
*/
protected function GetSampleData($oObj, $sAttCode)
{
if ($sAttCode !== 'id')
{
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
// As sample data will be displayed in the web browser, AttributeImage needs to be rendered with a regular HTML format, meaning its "src" looking like "data:image/png;base64,iVBORw0KGgoAAAANSUh..."
// Whereas for the PDF generation it needs to be rendered with a TCPPDF-compatible format, meaning its "src" looking like "@iVBORw0KGgoAAAANSUh..."
if ($oAttDef instanceof AttributeImage) {
return $this->GetAttributeImageValue($oAttDef, $oObj->Get($sAttCode), static::ENUM_OUTPUT_TYPE_SAMPLE);
}
}
return parent::GetSampleData($oObj, $sAttCode);
}
protected function GetValue($oObj, $sAttCode)
{
switch($sAttCode)
@@ -205,31 +237,7 @@ EOF
$oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
if ($oAttDef instanceof AttributeImage)
{
// To limit the image size in the PDF output, we have to enforce the size as height/width because max-width/max-height have no effect
//
$iDefaultMaxWidthPx = 48;
$iDefaultMaxHeightPx = 48;
if ($value->IsEmpty())
{
$iNewWidth = $iDefaultMaxWidthPx;
$iNewHeight = $iDefaultMaxHeightPx;
$sUrl = $oAttDef->Get('default_image');
}
else
{
list($iWidth, $iHeight) = utils::GetImageSize($value->GetData());
$iMaxWidthPx = min($iDefaultMaxWidthPx, $oAttDef->Get('display_max_width'));
$iMaxHeightPx = min($iDefaultMaxHeightPx, $oAttDef->Get('display_max_height'));
$fScale = min($iMaxWidthPx / $iWidth, $iMaxHeightPx / $iHeight);
$iNewWidth = $iWidth * $fScale;
$iNewHeight = $iHeight * $fScale;
$sUrl = 'data:'.$value->GetMimeType().';base64,'.base64_encode($value->GetData());
}
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px">' : '';
$sRet = '<div class="view-image">'.$sRet.'</div>';
$sRet = $this->GetAttributeImageValue($oAttDef, $value, static::ENUM_OUTPUT_TYPE_REAL);
}
else
{
@@ -258,4 +266,53 @@ EOF
{
return 'pdf';
}
/**
* @param \AttributeImage $oAttDef Instance of image attribute
* @param \ormDocument $oValue Value of image attribute
* @param string $sOutputType {@see \PDFBulkExport::ENUM_OUTPUT_TYPE_SAMPLE}, {@see \PDFBulkExport::ENUM_OUTPUT_TYPE_REAL}
*
* @return string Rendered value of $oAttDef / $oValue according to the desired $sOutputType
* @since 2.7.8
*/
protected function GetAttributeImageValue(AttributeImage $oAttDef, ormDocument $oValue, string $sOutputType)
{
// To limit the image size in the PDF output, we have to enforce the size as height/width because max-width/max-height have no effect
//
$iDefaultMaxWidthPx = 48;
$iDefaultMaxHeightPx = 48;
if ($oValue->IsEmpty()) {
$iNewWidth = $iDefaultMaxWidthPx;
$iNewHeight = $iDefaultMaxHeightPx;
$sUrl = $oAttDef->Get('default_image');
} else {
list($iWidth, $iHeight) = utils::GetImageSize($oValue->GetData());
$iMaxWidthPx = min($iDefaultMaxWidthPx, $oAttDef->Get('display_max_width'));
$iMaxHeightPx = min($iDefaultMaxHeightPx, $oAttDef->Get('display_max_height'));
$fScale = min($iMaxWidthPx / $iWidth, $iMaxHeightPx / $iHeight);
$iNewWidth = $iWidth * $fScale;
$iNewHeight = $iHeight * $fScale;
$sValueAsBase64 = base64_encode($oValue->GetData());
switch ($sOutputType) {
case static::ENUM_OUTPUT_TYPE_SAMPLE:
$sUrl = 'data:'.$oValue->GetMimeType().';base64,'.$sValueAsBase64;
break;
case static::ENUM_OUTPUT_TYPE_REAL:
default:
// TCPDF requires base64-encoded images to be rendered without the usual "data:<MIMETYPE>;base64" header but with an "@"
// @link https://tcpdf.org/examples/example_009/
$sUrl = '@'.$sValueAsBase64;
break;
}
}
$sRet = ($sUrl !== null) ? '<img src="'.$sUrl.'" style="width: '.$iNewWidth.'px; height: '.$iNewHeight.'px; vertical-align: middle; text-align:center;">' : '';
$sRet = '<div class="view-image">'.$sRet.'</div>';
return $sRet;
}
}

View File

@@ -17,7 +17,7 @@
*/
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.7.7";
$version: "v2.7.8";
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
// Base colors

View File

@@ -2424,26 +2424,33 @@ fieldset .details>.field_container {
.selectize-dropdown,
.selectize-input,
.selectize-input input{
font-size: 12px;
}
.selectize-input{
padding: 2px 2px 0px 2px; /* padding-bottom = padding-top - item margin-bottom */
border: 1px solid #ABABAB;
border-radius: 0;
.selectize-input input {
font-size: 12px;
}
.attribute-set-item.partial-code{
color: transparentize($gray-darker, 0.4);
background-color: lighten($gray-lighter, 5%);
}
}
}
}
}
}
}
}
}
.selectize-input {
padding: 2px 2px 0px 2px; /* padding-bottom = padding-top - item margin-bottom */
border: 1px solid #ABABAB;
border-radius: 0;
.attribute-set-item.partial-code {
color: transparentize($gray-darker, 0.4);
background-color: lighten($gray-lighter, 5%);
}
}
}
}
}
}
}
}
}
&[data-attribute-type="AttributeDuration"] {
.field_value_container {
white-space: nowrap;
}
}
}
.one-col-details .details .field_container.field_small {
div.field_label {

View File

@@ -4,6 +4,8 @@
* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=custom-theme&bgImgOpacityError=18&bgImgOpacityHighlight=75&bgImgOpacityActive=65&bgImgOpacityHover=100&bgImgOpacityDefault=100&bgImgOpacityContent=100&bgImgOpacityHeader=35&cornerRadiusShadow=5px&offsetLeftShadow=-5px&offsetTopShadow=-5px&thicknessShadow=5px&opacityShadow=20&bgImgOpacityShadow=10&bgTextureShadow=flat&bgColorShadow=%23000000&opacityOverlay=50&bgImgOpacityOverlay=20&bgTextureOverlay=diagonals_thick&bgColorOverlay=%23666666&iconColorError=%23ffd27a&fcError=%23ffffff&borderColorError=%23cd0a0a&bgTextureError=diagonals_thick&bgColorError=%23b81900&iconColorHighlight=%231c94c4&fcHighlight=%23363636&borderColorHighlight=%23fed22f&bgTextureHighlight=flat&bgColorHighlight=%23ffe45c&iconColorActive=%23E87C1E&fcActive=%23E87C1E&borderColorActive=%23E87C1E&bgTextureActive=flat&bgColorActive=%23ffffff&iconColorHover=%23E87C1E&fcHover=%23E87C1E&borderColorHover=%23E87C1E&bgTextureHover=flat&bgColorHover=%23fde17c&iconColorDefault=%23F26522&fcDefault=%23555555&borderColorDefault=%23cccccc&bgTextureDefault=flat&bgColorDefault=%23f1f1f1&iconColorContent=%23222222&fcContent=%23333333&borderColorContent=%23dddddd&bgTextureContent=flat&bgColorContent=%23eeeeee&iconColorHeader=%23ffffff&fcHeader=%23ffffff&borderColorHeader=%23F26522&bgTextureHeader=flat&bgColorHeader=%23E87C1E&cornerRadius=0&fwDefault=bold&fsDefault=1.1em&ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif
* Copyright jQuery Foundation and other contributors; Licensed MIT
* The original css file has been scssized (through www.css2scss.com)
*
* Other modification done : replaced the `Alpha(` by `alpha(` to avoid warnings generated by SCSSPHP
*/
.ui-draggable-handle {
-ms-touch-action: none;
@@ -46,26 +48,27 @@
}
}
.ui-helper-zfix {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
filter: Alpha(Opacity=0);
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
filter: alpha(Opacity=0);
}
.ui-front {
z-index: 100;
}
.ui-state-disabled {
cursor: default !important;
pointer-events: none;
opacity: .35;
filter: Alpha(Opacity=35);
background-image: none;
.ui-icon {
filter: Alpha(Opacity=35);
}
cursor: default !important;
pointer-events: none;
opacity: .35;
filter: alpha(Opacity=35);
background-image: none;
.ui-icon {
filter: alpha(Opacity=35);
}
}
.ui-icon {
display: inline-block;
@@ -86,14 +89,14 @@
display: block;
}
.ui-widget-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #666666 url($approot-relative + "css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=" + $version) 50% 50% repeat;
opacity: .5;
filter: Alpha(Opacity=50);
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #666666 url($approot-relative + "css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png?v=" + $version) 50% 50% repeat;
opacity: .5;
filter: alpha(Opacity=50);
}
.ui-resizable {
position: relative;
@@ -1069,14 +1072,14 @@ body {
font-weight: bold;
}
.ui-priority-secondary {
opacity: .7;
filter: Alpha(Opacity=70);
font-weight: normal;
opacity: .7;
filter: alpha(Opacity=70);
font-weight: normal;
}
.ui-state-disabled {
opacity: .35;
filter: Alpha(Opacity=35);
background-image: none;
opacity: .35;
filter: alpha(Opacity=35);
background-image: none;
}
.ui-icon {
background-image: url($approot-relative + "css/ui-lightness/images/ui-icons_222222_256x240.png?v=" + $version);
@@ -1137,14 +1140,14 @@ body {
font-weight: bold;
}
.ui-priority-secondary {
opacity: .7;
filter: Alpha(Opacity=70);
font-weight: normal;
opacity: .7;
filter: alpha(Opacity=70);
font-weight: normal;
}
.ui-state-disabled {
opacity: .35;
filter: Alpha(Opacity=35);
background-image: none;
opacity: .35;
filter: alpha(Opacity=35);
background-image: none;
}
.ui-icon {
background-image: url($approot-relative + "css/ui-lightness/images/ui-icons_ffffff_256x240.png?v=" + $version);
@@ -1341,9 +1344,9 @@ a {
font-weight: bold;
}
.ui-priority-secondary {
opacity: .7;
filter: Alpha(Opacity=70);
font-weight: normal;
opacity: .7;
filter: alpha(Opacity=70);
font-weight: normal;
}
.ui-icon-blank {
background-position: 16px 16px;

View File

@@ -1,5 +1,13 @@
{
"require" : {
"apereo/phpcas" : "~1.3"
}
"config" : {
"classmap-authoritative" : true
},
"autoload" : {
"psr-4" : {
"Combodo\\iTop\\Cas\\" : "src"
}
},
"require" : {
"apereo/phpcas" : "~1.6.0"
}
}

View File

@@ -4,28 +4,32 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4db4df78154f0de344ba35a27fe766b7",
"content-hash": "46afbbe7e92c2ccfe403f366ef1877e5",
"packages": [
{
"name": "apereo/phpcas",
"version": "1.3.7",
"version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/apereo/phpCAS.git",
"reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082"
"reference": "f817c72a961484afef95ac64a9257c8e31f063b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/apereo/phpCAS/zipball/b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
"reference": "b5b29102c3a42f570c4a3e852f3cf67cae6d6082",
"url": "https://api.github.com/repos/apereo/phpCAS/zipball/f817c72a961484afef95ac64a9257c8e31f063b9",
"reference": "f817c72a961484afef95ac64a9257c8e31f063b9",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.4.0"
"ext-dom": "*",
"php": ">=7.1.0",
"psr/log": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"phpunit/phpunit": "~3.7.10"
"monolog/monolog": "^1.0.0 || ^2.0.0",
"phpstan/phpstan": "^1.5",
"phpunit/phpunit": ">=7.5"
},
"type": "library",
"extra": {
@@ -45,11 +49,16 @@
"authors": [
{
"name": "Joachim Fritschi",
"homepage": "https://wiki.jasig.org/display/~fritschi"
"email": "jfritschi@freenet.de",
"homepage": "https://github.com/jfritschi"
},
{
"name": "Adam Franco",
"homepage": "https://wiki.jasig.org/display/~adamfranco"
"homepage": "https://github.com/adamfranco"
},
{
"name": "Henry Pan",
"homepage": "https://github.com/phy25"
}
],
"description": "Provides a simple API for authenticating users against a CAS server",
@@ -59,7 +68,61 @@
"cas",
"jasig"
],
"time": "2019-04-22T19:48:16+00:00"
"support": {
"issues": "https://github.com/apereo/phpCAS/issues",
"source": "https://github.com/apereo/phpCAS/tree/1.6.0"
},
"time": "2022-10-31T20:39:27+00:00"
},
{
"name": "psr/log",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.4"
},
"time": "2021-05-03T11:20:27+00:00"
}
],
"packages-dev": [],
@@ -69,5 +132,6 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
"platform-dev": [],
"plugin-api-version": "2.1.0"
}

View File

@@ -1,4 +0,0 @@
<?php
require_once __DIR__.'/vendor/autoload.php';
require_once __DIR__.'/src/Config.php';
require_once __DIR__.'/src/CASLoginExtension.php';

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-cas/2.7.7',
'authent-cas/2.7.8',
array(
// Identification
//
@@ -24,7 +24,8 @@ SetupWebPage::AddModule(
//
'datamodel' => array(
'model.authent-cas.php',
'main.php'
'vendor/autoload.php',
'src/CASLoginExtension.php',
),
'webservice' => array(
@@ -50,6 +51,7 @@ SetupWebPage::AddModule(
'cas_port' => '',
'cas_context' => '',
'cas_version' => '',
'service_base_url' => '',
),
)
);

View File

@@ -0,0 +1,17 @@
<?php
/**
* @copyright Copyright (C) 2010-2022 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Cas;
use LogAPI;
class CASLog extends LogAPI
{
const CHANNEL_DEFAULT = 'CASLog';
protected static $m_oFileLog = null;
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* @copyright Copyright (C) 2010-2022 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Cas;
use IssueLog;
use LogAPI;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
class CASLogger implements LoggerInterface
{
public function __construct($sDebugFile)
{
CASLog::Enable($sDebugFile);
}
const LEVEL_COMPAT = [
LogLevel::EMERGENCY => LogAPI::LEVEL_ERROR,
LogLevel::ALERT => LogAPI::LEVEL_ERROR,
LogLevel::CRITICAL => LogAPI::LEVEL_ERROR,
LogLevel::ERROR => LogAPI::LEVEL_ERROR,
LogLevel::WARNING => LogAPI::LEVEL_WARNING,
LogLevel::NOTICE => LogAPI::LEVEL_INFO,
LogLevel::INFO => LogAPI::LEVEL_INFO,
LogLevel::DEBUG => LogAPI::LEVEL_DEBUG,
];
public function emergency($message, array $context = array())
{
CASLog::Error('EMERGENCY: '.$message, CASLog::CHANNEL_DEFAULT, $context);
IssueLog::Error('EMERGENCY: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function alert($message, array $context = array())
{
CASLog::Error('ALERT: '.$message, CASLog::CHANNEL_DEFAULT, $context);
IssueLog::Error('ALERT: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function critical($message, array $context = array())
{
CASLog::Error('CRITICAL: '.$message, CASLog::CHANNEL_DEFAULT, $context);
IssueLog::Error('CRITICAL: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function error($message, array $context = array())
{
CASLog::Error('ERROR: '.$message, CASLog::CHANNEL_DEFAULT, $context);
IssueLog::Error('ERROR: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function warning($message, array $context = array())
{
CASLog::Warning('WARNING: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function notice($message, array $context = array())
{
CASLog::Info('NOTICE: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function info($message, array $context = array())
{
CASLog::Info('INFO: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function debug($message, array $context = array())
{
CASLog::Debug('DEBUG: '.$message, CASLog::CHANNEL_DEFAULT, $context);
}
public function log($level, $message, array $context = array())
{
$sLevel = self::LEVEL_COMPAT[$level] ?? LogAPI::LEVEL_ERROR;
CASLog::Log($sLevel, strtoupper($level).": $message", CASLog::CHANNEL_DEFAULT, $context);
}
}

View File

@@ -154,7 +154,7 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
$bCASDebug = Config::Get('cas_debug');
if ($bCASDebug)
{
phpCAS::setDebug(APPROOT.'log/cas.log');
phpCAS::setLogger(new CASLogger(APPROOT.'log/cas.log'));
}
// Initialize phpCAS
@@ -162,7 +162,8 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
$sCASHost = Config::Get('cas_host');
$iCASPort = Config::Get('cas_port');
$sCASContext = Config::Get('cas_context');
phpCAS::client($sCASVersion, $sCASHost, $iCASPort, $sCASContext, false /* session already started */);
$sServiceBaseURL = Config::Get('service_base_url', self::GetServiceBaseURL());
phpCAS::client($sCASVersion, $sCASHost, $iCASPort, $sCASContext, $sServiceBaseURL, false /* session already started */);
$sCASCACertPath = Config::Get('cas_server_ca_cert_path');
if (empty($sCASCACertPath))
{
@@ -178,6 +179,38 @@ class CASLoginExtension extends AbstractLoginFSMExtension implements iLogoutExte
}
}
private static function GetServiceBaseURL()
{
$protocol = $_SERVER['REQUEST_SCHEME'];
$protocol .= '://';
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
// explode the host list separated by comma and use the first host
$hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
// see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default
return $protocol . $hosts[0];
} else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
$server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
} else {
if (empty($_SERVER['SERVER_NAME'])) {
$server_url = $_SERVER['HTTP_HOST'];
} else {
$server_url = $_SERVER['SERVER_NAME'];
}
}
if (!strpos($server_url, ':')) {
if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
$server_port = $_SERVER['SERVER_PORT'];
} else {
$ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
$server_port = $ports[0];
}
$server_url .= ':';
$server_url .= $server_port;
}
return $protocol . $server_url;
}
private function DoUserProvisioning($sLogin)
{
$bCASUserSynchro = Config::Get('cas_user_synchro');

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS.php
* @category Authentication
@@ -27,4 +27,6 @@
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
require_once dirname(__FILE__).'/source/CAS.php';
require_once __DIR__.'/source/CAS.php';
trigger_error('Including CAS.php is deprecated. Install phpCAS using composer instead.', E_USER_DEPRECATED);

View File

@@ -6,22 +6,21 @@ users via a Central Authentication Service (CAS) server.
Please see the wiki website for more information:
https://wiki.jasig.org/display/CASC/phpCAS
https://apereo.github.io/phpCAS/
Api documentation can be found here:
https://apereo.github.io/phpCAS/
https://apereo.github.io/phpCAS/api/
[![Build Status](https://travis-ci.org/apereo/phpCAS.png)](https://travis-ci.org/apereo/phpCAS)
[![Test](https://github.com/apereo/phpCAS/actions/workflows/test.yml/badge.svg)](https://github.com/apereo/phpCAS/actions/workflows/test.yml)
LICENSE
-------
Copyright 2007-2015, JA-SIG, Inc.
This project includes software developed by Jasig.
http://www.jasig.org/
Copyright 2007-2020, Apereo Foundation.
This project includes software developed by Apereo Foundation.
http://www.apereo.org/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this software except in compliance with the License.

View File

@@ -1,29 +1,55 @@
{
"name": "apereo/phpcas",
"description": "Provides a simple API for authenticating users against a CAS server",
"keywords": ["cas", "jasig", "apereo"],
"homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
"type": "library",
"license": "Apache-2.0",
"authors": [
{"name": "Joachim Fritschi", "homepage": "https://wiki.jasig.org/display/~fritschi"},
{"name": "Adam Franco", "homepage": "https://wiki.jasig.org/display/~adamfranco"}
],
"require": {
"php": ">=5.4.0",
"ext-curl": "*"
"name" : "apereo/phpcas",
"description" : "Provides a simple API for authenticating users against a CAS server",
"keywords" : [
"cas",
"jasig",
"apereo"
],
"homepage" : "https://wiki.jasig.org/display/CASC/phpCAS",
"type" : "library",
"license" : "Apache-2.0",
"authors" : [{
"name" : "Joachim Fritschi",
"homepage" : "https://github.com/jfritschi",
"email" : "jfritschi@freenet.de"
}, {
"name" : "Adam Franco",
"homepage" : "https://github.com/adamfranco"
}, {
"name" : "Henry Pan",
"homepage" : "https://github.com/phy25"
}
],
"require" : {
"php" : ">=7.1.0",
"ext-curl" : "*",
"ext-dom" : "*",
"psr/log" : "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"phpunit/phpunit": "~3.7.10"
},
"autoload": {
"classmap": [
"source/"
]
},
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
}
"require-dev" : {
"monolog/monolog" : "^1.0.0 || ^2.0.0",
"phpunit/phpunit" : ">=7.5",
"phpstan/phpstan" : "^1.5"
},
"autoload" : {
"classmap" : [
"source/"
]
},
"autoload-dev" : {
"files": ["source/CAS.php"],
"psr-4" : {
"PhpCas\\" : "test/CAS/"
}
},
"scripts" : {
"test" : "phpunit",
"phpstan" : "phpstan"
},
"extra" : {
"branch-alias" : {
"dev-master" : "1.3.x-dev"
}
}
}

View File

@@ -20,7 +20,7 @@
*
*
* Interface class of the phpCAS library
* PHP Version 5
* PHP Version 7
*
* @file CAS/CAS.php
* @category Authentication
@@ -35,6 +35,7 @@
* @ingroup public
*/
use Psr\Log\LoggerInterface;
//
// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI']
@@ -44,11 +45,6 @@ if (!isset($_SERVER['REQUEST_URI']) && isset($_SERVER['SCRIPT_NAME']) && isset($
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
}
// Add a E_USER_DEPRECATED for php versions <= 5.2
if (!defined('E_USER_DEPRECATED')) {
define('E_USER_DEPRECATED', E_USER_NOTICE);
}
// ########################################################################
// CONSTANTS
@@ -61,7 +57,7 @@ if (!defined('E_USER_DEPRECATED')) {
/**
* phpCAS version. accessible for the user by phpCAS::getVersion().
*/
define('PHPCAS_VERSION', '1.3.7');
define('PHPCAS_VERSION', '1.6.0');
/**
* @addtogroup public
@@ -140,11 +136,6 @@ define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');
*/
define("SAML_ATTRIBUTES", 'SAMLATTRIBS');
/**
* SAML Attributes
*/
define("DEFAULT_ERROR", 'Internal script failure');
/** @} */
/**
* @addtogroup publicPGTStorage
@@ -224,6 +215,8 @@ define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese');
define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish');
define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan');
define("PHPCAS_LANG_CHINESE_SIMPLIFIED", 'CAS_Languages_ChineseSimplified');
define("PHPCAS_LANG_GALEGO", 'CAS_Languages_Galego');
define("PHPCAS_LANG_PORTUGUESE", 'CAS_Languages_Portuguese');
/** @} */
@@ -261,7 +254,7 @@ define('DEFAULT_DEBUG_DIR', gettmpdir()."/");
/** @} */
// include the class autoloader
require_once dirname(__FILE__) . '/CAS/Autoload.php';
require_once __DIR__ . '/CAS/Autoload.php';
/**
* The phpCAS class is a simple container for the phpCAS library. It provides CAS
@@ -330,12 +323,22 @@ class phpCAS
/**
* phpCAS client initializer.
*
* @param string $server_version the version of the CAS server
* @param string $server_hostname the hostname of the CAS server
* @param int $server_port the port the CAS server is running on
* @param string $server_uri the URI the CAS server is responding on
* @param bool $changeSessionID Allow phpCAS to change the session_id (Single
* Sign Out/handleLogoutRequests is based on that change)
* @param string $server_version the version of the CAS server
* @param string $server_hostname the hostname of the CAS server
* @param int $server_port the port the CAS server is running on
* @param string $server_uri the URI the CAS server is responding on
* @param string|string[]|CAS_ServiceBaseUrl_Interface
* $service_base_url the base URL (protocol, host and the
* optional port) of the CAS client; pass
* in an array to use auto discovery with
* an allowlist; pass in
* CAS_ServiceBaseUrl_Interface for custom
* behavior. Added in 1.6.0. Similar to
* serverName config in other CAS clients.
* @param bool $changeSessionID Allow phpCAS to change the session_id
* (Single Sign Out/handleLogoutRequests
* is based on that change)
* @param \SessionHandlerInterface $sessionHandler the session handler
*
* @return void a newly created CAS_Client object
* @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
@@ -343,7 +346,8 @@ class phpCAS
* and phpCAS::setDebug()).
*/
public static function client($server_version, $server_hostname,
$server_port, $server_uri, $changeSessionID = true
$server_port, $server_uri, $service_base_url,
$changeSessionID = true, \SessionHandlerInterface $sessionHandler = null
) {
phpCAS :: traceBegin();
if (is_object(self::$_PHPCAS_CLIENT)) {
@@ -362,8 +366,8 @@ class phpCAS
// initialize the object $_PHPCAS_CLIENT
try {
self::$_PHPCAS_CLIENT = new CAS_Client(
$server_version, false, $server_hostname, $server_port, $server_uri,
$changeSessionID
$server_version, false, $server_hostname, $server_port, $server_uri, $service_base_url,
$changeSessionID, $sessionHandler
);
} catch (Exception $e) {
phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
@@ -374,12 +378,22 @@ class phpCAS
/**
* phpCAS proxy initializer.
*
* @param string $server_version the version of the CAS server
* @param string $server_hostname the hostname of the CAS server
* @param int $server_port the port the CAS server is running on
* @param string $server_uri the URI the CAS server is responding on
* @param bool $changeSessionID Allow phpCAS to change the session_id (Single
* Sign Out/handleLogoutRequests is based on that change)
* @param string $server_version the version of the CAS server
* @param string $server_hostname the hostname of the CAS server
* @param string $server_port the port the CAS server is running on
* @param string $server_uri the URI the CAS server is responding on
* @param string|string[]|CAS_ServiceBaseUrl_Interface
* $service_base_url the base URL (protocol, host and the
* optional port) of the CAS client; pass
* in an array to use auto discovery with
* an allowlist; pass in
* CAS_ServiceBaseUrl_Interface for custom
* behavior. Added in 1.6.0. Similar to
* serverName config in other CAS clients.
* @param bool $changeSessionID Allow phpCAS to change the session_id
* (Single Sign Out/handleLogoutRequests
* is based on that change)
* @param \SessionHandlerInterface $sessionHandler the session handler
*
* @return void a newly created CAS_Client object
* @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
@@ -387,7 +401,8 @@ class phpCAS
* and phpCAS::setDebug()).
*/
public static function proxy($server_version, $server_hostname,
$server_port, $server_uri, $changeSessionID = true
$server_port, $server_uri, $service_base_url,
$changeSessionID = true, \SessionHandlerInterface $sessionHandler = null
) {
phpCAS :: traceBegin();
if (is_object(self::$_PHPCAS_CLIENT)) {
@@ -406,8 +421,8 @@ class phpCAS
// initialize the object $_PHPCAS_CLIENT
try {
self::$_PHPCAS_CLIENT = new CAS_Client(
$server_version, true, $server_hostname, $server_port, $server_uri,
$changeSessionID
$server_version, true, $server_hostname, $server_port, $server_uri, $service_base_url,
$changeSessionID, $sessionHandler
);
} catch (Exception $e) {
phpCAS :: error(get_class($e) . ': ' . $e->getMessage());
@@ -435,6 +450,24 @@ class phpCAS
* @{
*/
/**
* Set/unset PSR-3 logger
*
* @param LoggerInterface $logger the PSR-3 logger used for logging, or
* null to stop logging.
*
* @return void
*/
public static function setLogger($logger = null)
{
if (empty(self::$_PHPCAS_DEBUG['unique_id'])) {
self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);
}
self::$_PHPCAS_DEBUG['logger'] = $logger;
self::$_PHPCAS_DEBUG['indent'] = 0;
phpCAS :: trace('START ('.date("Y-m-d H:i:s").') phpCAS-' . PHPCAS_VERSION . ' ******************');
}
/**
* Set/unset debug mode
*
@@ -442,9 +475,13 @@ class phpCAS
* to stop debugging.
*
* @return void
*
* @deprecated
*/
public static function setDebug($filename = '')
{
trigger_error('phpCAS::setDebug() is deprecated in favor of phpCAS::setLogger().', E_USER_DEPRECATED);
if ($filename != false && gettype($filename) != 'string') {
phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)');
}
@@ -518,14 +555,7 @@ class phpCAS
$indent_str = ".";
if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
// Check if file exists and modifiy file permissions to be only
// readable by the webserver
if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
touch(self::$_PHPCAS_DEBUG['filename']);
// Chmod will fail on windows
@chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
}
if (isset(self::$_PHPCAS_DEBUG['logger']) || !empty(self::$_PHPCAS_DEBUG['filename'])) {
for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) {
$indent_str .= '| ';
@@ -533,7 +563,20 @@ class phpCAS
// allow for multiline output with proper identing. Usefull for
// dumping cas answers etc.
$str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str);
error_log(self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
$str3 = self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2;
if (isset(self::$_PHPCAS_DEBUG['logger'])) {
self::$_PHPCAS_DEBUG['logger']->info($str3);
}
if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
// Check if file exists and modifiy file permissions to be only
// readable by the webserver
if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
touch(self::$_PHPCAS_DEBUG['filename']);
// Chmod will fail on windows
@chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
}
error_log($str3 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
}
}
}
@@ -567,8 +610,6 @@ class phpCAS
}
if (self::$_PHPCAS_VERBOSE) {
echo "<br />\n<b>phpCAS error</b>: <font color=\"FF0000\"><b>" . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . "</b></font> in <b>" . $file . "</b> on line <b>" . $line . "</b><br />\n";
} else {
echo "<br />\n<b>Error</b>: <font color=\"FF0000\"><b>". DEFAULT_ERROR ."</b><br />\n";
}
phpCAS :: trace($msg . ' in ' . $file . 'on line ' . $line );
phpCAS :: traceEnd();
@@ -1869,6 +1910,14 @@ class phpCAS
}
}
/**
* @return CAS_Client
*/
public static function getCasClient()
{
return self::$_PHPCAS_CLIENT;
}
/**
* For testing purposes, use this method to set the client to a test double
*

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/AuthenticationException.php
* @category Authentication
@@ -72,11 +72,15 @@ implements CAS_Exception
phpCAS::traceBegin();
$lang = $client->getLangObj();
$client->printHTMLHeader($lang->getAuthenticationFailed());
printf(
$lang->getYouWereNotAuthenticated(),
htmlentities($client->getURL()),
isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN']:''
);
if (phpCAS::getVerbose()) {
printf(
$lang->getYouWereNotAuthenticated(),
htmlentities($client->getURL()),
$_SERVER['SERVER_ADMIN'] ?? ''
);
}
phpCAS::trace($messages[] = 'CAS URL: '.$cas_url);
phpCAS::trace($messages[] = 'Authentication failure: '.$failure);
if ( $no_response ) {

View File

@@ -3,7 +3,7 @@
/**
* Autoloader Class
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Autoload.php
* @category Authentication
@@ -26,18 +26,24 @@ function CAS_autoload($class)
// Static to hold the Include Path to CAS
static $include_path;
// Check only for CAS classes
if (substr($class, 0, 4) !== 'CAS_') {
if (substr($class, 0, 4) !== 'CAS_' && substr($class, 0, 7) !== 'PhpCas\\') {
return false;
}
// Setup the include path if it's not already set from a previous call
if (empty($include_path)) {
$include_path = array(dirname(dirname(__FILE__)), dirname(dirname(__FILE__)) . '/../test/' );
$include_path = array(dirname(__DIR__));
}
// Declare local variable to store the expected full path to the file
foreach ($include_path as $path) {
$file_path = $path . '/' . str_replace('_', '/', $class) . '.php';
$class_path = str_replace('_', DIRECTORY_SEPARATOR, $class);
// PhpCas namespace mapping
if (substr($class_path, 0, 7) === 'PhpCas\\') {
$class_path = 'CAS' . DIRECTORY_SEPARATOR . substr($class_path, 7);
}
$file_path = $path . DIRECTORY_SEPARATOR . $class_path . '.php';
$fp = @fopen($file_path, 'r', true);
if ($fp) {
fclose($fp);
@@ -54,6 +60,7 @@ function CAS_autoload($class)
return true;
}
}
$e = new Exception(
'Class ' . $class . ' could not be loaded from ' .
$file_path . ', file does not exist (Path="'
@@ -61,22 +68,22 @@ function CAS_autoload($class)
);
$trace = $e->getTrace();
if (isset($trace[2]) && isset($trace[2]['function'])
&& in_array($trace[2]['function'], array('class_exists', 'interface_exists'))
&& in_array($trace[2]['function'], array('class_exists', 'interface_exists', 'trait_exists'))
) {
return false;
}
if (isset($trace[1]) && isset($trace[1]['function'])
&& in_array($trace[1]['function'], array('class_exists', 'interface_exists'))
&& in_array($trace[1]['function'], array('class_exists', 'interface_exists', 'trait_exists'))
) {
return false;
}
die ((string) $e);
}
// set up __autoload
if (!(spl_autoload_functions())
|| !in_array('CAS_autoload', spl_autoload_functions())
) {
// Set up autoload if not already configured by composer.
if (!class_exists('CAS_Client'))
{
trigger_error('phpCAS autoloader is deprecated. Install phpCAS using composer instead.', E_USER_DEPRECATED);
spl_autoload_register('CAS_autoload');
if (function_exists('__autoload')
&& !in_array('__autoload', spl_autoload_functions())
@@ -86,5 +93,3 @@ if (!(spl_autoload_functions())
spl_autoload_register('__autoload');
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/CookieJar.php
* @category Authentication
@@ -231,6 +231,7 @@ class CAS_CookieJar
case 'commenturl':
case 'discard':
case 'httponly':
case 'samesite':
$cookie[$attributeNameLC] = $attributeValue;
break;
default:

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Exception.php
* @category Authentication
@@ -56,4 +56,4 @@ interface CAS_Exception
{
}
?>
?>

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/GracefullTerminationException.php
* @category Authentication
@@ -83,4 +83,4 @@ implements CAS_Exception
}
}
?>
?>

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/InvalidArgumentException.php
* @category Authentication
@@ -43,4 +43,4 @@ implements CAS_Exception
{
}
?>
?>

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/Catalan.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/ChineseSimplified.php
* @category Authentication
@@ -111,4 +111,4 @@ class CAS_Languages_ChineseSimplified implements CAS_Languages_LanguageInterface
{
return '服务器 <b>%s</b> 不可用(<b>%s</b>)。';
}
}
}

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/English.php
* @category Authentication
@@ -111,4 +111,4 @@ class CAS_Languages_English implements CAS_Languages_LanguageInterface
{
return 'The service `<b>%s</b>\' is not available (<b>%s</b>).';
}
}
}

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/French.php
* @category Authentication
@@ -113,4 +113,4 @@ class CAS_Languages_French implements CAS_Languages_LanguageInterface
}
}
?>
?>

View File

@@ -0,0 +1,117 @@
<?php
/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 7
*
* @file CAS/Language/Galego.php
* @category Authentication
* @package PhpCAS
* @author Enrique Huelva Rivero enrique.huelvarivero@plexus.es
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
/**
* Galego language class
*
* @class CAS_Languages_Galego
* @category Authentication
* @package PhpCAS
* @author Enrique Huelva Rivero enrique.huelvarivero@plexus.es
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*
* @sa @link internalLang Internationalization @endlink
* @ingroup internalLang
*/
class CAS_Languages_Galego implements CAS_Languages_LanguageInterface
{
/**
* Get the using server string
*
* @return string using server
*/
public function getUsingServer()
{
return 'usando servidor';
}
/**
* Get authentication wanted string
*
* @return string authentication wanted
*/
public function getAuthenticationWanted()
{
return 'Autenticación CAS necesaria!';
}
/**
* Get logout string
*
* @return string logout
*/
public function getLogout()
{
return 'Saída CAS necesaria!';
}
/**
* Get the should have been redirected string
*
* @return string should habe been redirected
*/
public function getShouldHaveBeenRedirected()
{
return 'Xa debería ser redireccionado ao servidor CAS. Faga click <a href="%s">aquí</a> para continuar';
}
/**
* Get authentication failed string
*
* @return string authentication failed
*/
public function getAuthenticationFailed()
{
return 'Autenticación CAS errada!';
}
/**
* Get the your were not authenticated string
*
* @return string not authenticated
*/
public function getYouWereNotAuthenticated()
{
return '
<p>Non estás autenticado</p><p>Podes volver tentalo facendo click <a href="%s">aquí</a>.</p><p>Se o problema persiste debería contactar con el <a href="mailto:%s">administrador deste sitio</a>.</p>';
}
/**
* Get the service unavailable string
*
* @return string service unavailable
*/
public function getServiceUnavailable()
{
return 'O servizo `<b>%s</b>\' non está dispoñible (<b>%s</b>).';
}
}
?>

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/German.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/Greek.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/Japanese.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/LanguageInterface.php
* @category Authentication
@@ -93,4 +93,4 @@ interface CAS_Languages_LanguageInterface
public function getServiceUnavailable();
}
?>
?>

View File

@@ -0,0 +1,114 @@
<?php
/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 7
*
* @file CAS/Language/Portuguese.php
* @category Authentication
* @package PhpCAS
* @author Sherwin Harris <sherwin.harris@gmail.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://apereo.atlassian.net/wiki/spaces/CASC/pages/103252517/phpCAS
*/
/**
* Portuguese language class
*
* @class CAS_Languages_Portuguese
* @category Authentication
* @package PhpCAS
* @author Sherwin Harris <sherwin.harris@gmail.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://apereo.atlassian.net/wiki/spaces/CASC/pages/103252517/phpCAS
*
* @sa @link internalLang Internationalization @endlink
* @ingroup internalLang
*/
class CAS_Languages_Portuguese implements CAS_Languages_LanguageInterface
{
/**
* Get the using server string
*
* @return string using server
*/
public function getUsingServer()
{
return 'Usando o servidor';
}
/**
* Get authentication wanted string
*
* @return string authentication wanted
*/
public function getAuthenticationWanted()
{
return 'A autenticação do servidor CAS desejado!';
}
/**
* Get logout string
*
* @return string logout
*/
public function getLogout()
{
return 'Saida do servidor CAS desejado!';
}
/**
* Get the should have been redirected string
*
* @return string should have been redirected
*/
public function getShouldHaveBeenRedirected()
{
return 'Você já deve ter sido redirecionado para o servidor CAS. Clique <a href="%s">aqui</a> para continuar';
}
/**
* Get authentication failed string
*
* @return string authentication failed
*/
public function getAuthenticationFailed()
{
return 'A autenticação do servidor CAS falheu!';
}
/**
* Get the your were not authenticated string
*
* @return string not authenticated
*/
public function getYouWereNotAuthenticated()
{
return '<p>Você não foi autenticado.</p><p>Você pode enviar sua solicitação novamente clicando <a href="%s">aqui</a>. </p><p>Se o problema persistir, você pode entrar em contato com <a href="mailto:%s">o administrador deste site</a>.</p>';
}
/**
* Get the service unavailable string
*
* @return string service unavailable
*/
public function getServiceUnavailable()
{
return 'O serviço `<b>%s</b>\' não está disponível (<b>%s</b>).';
}
}

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Language/Spanish.php
* @category Authentication

View File

@@ -18,7 +18,7 @@
* limitations under the License.
*
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/OutOfSequenceBeforeAuthenticationCallException.php
* @category Authentication

View File

@@ -18,7 +18,7 @@
* limitations under the License.
*
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/OutOfSequenceBeforeClientException.php
* @category Authentication

View File

@@ -18,7 +18,7 @@
* limitations under the License.
*
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/OutOfSequenceBeforeProxyException.php
* @category Authentication

View File

@@ -18,7 +18,7 @@
* limitations under the License.
*
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/OutOfSequenceException.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/PGTStorage/AbstractStorage.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/PGTStorage/Db.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/PGTStorage/AbstractStorage.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Abstract.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Exception.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Http.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Http/Abstract.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Http/Get.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Http/Post.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Imap.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxiedService/Testabel.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxyChain.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxyChain/AllowedList.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxyChain/Any.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxyChain/Interface.php
* @category Authentication
@@ -50,4 +50,4 @@ interface CAS_ProxyChain_Interface
*/
public function matches(array $list);
}
}

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/ProxyChain/Trusted.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @class CAS/ProxyTicketException.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Request/AbstractRequest.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Request/AbstractRequest.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Request/CurlRequest.php
* @category Authentication
@@ -106,14 +106,7 @@ implements CAS_Request_RequestInterface
*********************************************************/
$ch = curl_init($this->url);
if (version_compare(PHP_VERSION, '5.1.3', '>=')) {
//only avaible in php5
curl_setopt_array($ch, $this->_curlOptions);
} else {
foreach ($this->_curlOptions as $key => $value) {
curl_setopt($ch, $key, $value);
}
}
curl_setopt_array($ch, $this->_curlOptions);
/*********************************************************
* Set SSL configuration
@@ -167,6 +160,11 @@ implements CAS_Request_RequestInterface
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postBody);
}
/*********************************************************
* Set User Agent
*********************************************************/
curl_setopt($ch, CURLOPT_USERAGENT, 'phpCAS/' . phpCAS::getVersion());
return $ch;
}
@@ -179,7 +177,7 @@ implements CAS_Request_RequestInterface
*
* @return void
*/
private function _storeResponseBody ($body)
public function _storeResponseBody ($body)
{
$this->storeResponseBody($body);
}
@@ -192,7 +190,7 @@ implements CAS_Request_RequestInterface
*
* @return int
*/
private function _curlReadHeaders ($ch, $header)
public function _curlReadHeaders ($ch, $header)
{
$this->storeResponseHeader($header);
return strlen($header);

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Request/Exception.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Request/MultiRequestInterface.php
* @category Authentication

View File

@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 5
* PHP Version 7
*
* @file CAS/Request/RequestInterface.php
* @category Authentication

View File

@@ -0,0 +1,152 @@
<?php
/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 7
*
* @file CAS/ServiceBaseUrl/AllowedListDiscovery.php
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
/**
* Class that gets the service base URL of the PHP server by HTTP header
* discovery and allowlist check. This is used to generate service URL
* and PGT callback URL.
*
* @class CAS_ServiceBaseUrl_AllowedListDiscovery
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
class CAS_ServiceBaseUrl_AllowedListDiscovery
extends CAS_ServiceBaseUrl_Base
{
private $_list = array();
public function __construct($list) {
if (is_array($list)) {
if (count($list) === 0) {
throw new CAS_InvalidArgumentException('$list should not be empty');
}
foreach ($list as $value) {
$this->allow($value);
}
} else {
throw new CAS_TypeMismatchException($list, '$list', 'array');
}
}
/**
* Add a base URL to the allowed list.
*
* @param $url protocol, host name and port to add to the allowed list
*
* @return void
*/
public function allow($url)
{
$this->_list[] = $this->removeStandardPort($url);
}
/**
* Check if the server name is allowed by configuration.
*
* @param $name server name to check
*
* @return bool whether the allowed list contains the server name
*/
protected function isAllowed($name)
{
return in_array($name, $this->_list);
}
/**
* Discover the server name through HTTP headers.
*
* We read:
* - HTTP header X-Forwarded-Host
* - HTTP header X-Forwarded-Server and X-Forwarded-Port
* - HTTP header Host and SERVER_PORT
* - PHP SERVER_NAME (which can change based on the HTTP server used)
*
* The standard port will be omitted (80 for HTTP, 443 for HTTPS).
*
* @return string the discovered, unsanitized server protocol, hostname and port
*/
protected function discover()
{
$isHttps = $this->isHttps();
$protocol = $isHttps ? 'https' : 'http';
$protocol .= '://';
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
// explode the host list separated by comma and use the first host
$hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
// see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default
return $protocol . $hosts[0];
} else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
$server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
} else {
if (empty($_SERVER['SERVER_NAME'])) {
$server_url = $_SERVER['HTTP_HOST'];
} else {
$server_url = $_SERVER['SERVER_NAME'];
}
}
if (!strpos($server_url, ':')) {
if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
$server_port = $_SERVER['SERVER_PORT'];
} else {
$ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
$server_port = $ports[0];
}
$server_url .= ':';
$server_url .= $server_port;
}
return $protocol . $server_url;
}
/**
* Get PHP server base URL.
*
* @return string the server protocol, hostname and port
*/
public function get()
{
phpCAS::traceBegin();
$result = $this->removeStandardPort($this->discover());
phpCAS::trace("Discovered server base URL: " . $result);
if ($this->isAllowed($result)) {
phpCAS::trace("Server base URL is allowed");
phpCAS::traceEnd(true);
} else {
$result = $this->_list[0];
phpCAS::trace("Server base URL is not allowed, using default: " . $result);
phpCAS::traceEnd(false);
}
return $result;
}
}

View File

@@ -0,0 +1,98 @@
<?php
/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 7
*
* @file CAS/ServiceBaseUrl/Base.php
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
/**
* Base class of CAS/ServiceBaseUrl that implements isHTTPS method.
*
* @class CAS_ServiceBaseUrl_Base
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
abstract class CAS_ServiceBaseUrl_Base
implements CAS_ServiceBaseUrl_Interface
{
/**
* Get PHP server name.
*
* @return string the server hostname and port of the server
*/
abstract public function get();
/**
* Check whether HTTPS is used.
*
* This is used to construct the protocol in the URL.
*
* @return bool true if HTTPS is used
*/
public function isHttps() {
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
return ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) {
return ($_SERVER['HTTP_X_FORWARDED_PROTOCOL'] === 'https');
} elseif ( isset($_SERVER['HTTPS'])
&& !empty($_SERVER['HTTPS'])
&& strcasecmp($_SERVER['HTTPS'], 'off') !== 0
) {
return true;
}
return false;
}
/**
* Remove standard HTTP and HTTPS port for discovery and allowlist input.
*
* @param $url URL as https://domain:port without trailing slash
* @return standardized URL, or the original URL
* @throws CAS_InvalidArgumentException if the URL does not include the protocol
*/
protected function removeStandardPort($url) {
if (strpos($url, "://") === false) {
throw new CAS_InvalidArgumentException(
"Configured base URL should include the protocol string: " . $url);
}
$url = rtrim($url, '/');
if (strpos($url, "https://") === 0 && substr_compare($url, ':443', -4) === 0) {
return substr($url, 0, -4);
}
if (strpos($url, "http://") === 0 && substr_compare($url, ':80', -3) === 0) {
return substr($url, 0, -3);
}
return $url;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 7
*
* @file CAS/ServerHostname/Interface.php
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
/**
* An interface for classes that gets the server name of the PHP server.
* This is used to generate service URL and PGT callback URL.
*
* @class CAS_ServiceBaseUrl_Interface
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
interface CAS_ServiceBaseUrl_Interface
{
/**
* Get PHP HTTP protocol and server name.
*
* @return string protocol, server hostname, and optionally port,
* without trailing slash (https://localhost:8443)
*/
public function get();
/**
* Check whether HTTPS is used.
*
* This is used to construct the protocol in the URL.
*
* @return bool true if HTTPS is used
*/
public function isHttps();
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP Version 7
*
* @file CAS/ServiceBaseUrl/Static.php
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
/**
* Class that gets the server name of the PHP server by statically set
* hostname and port. This is used to generate service URL and PGT
* callback URL.
*
* @class CAS_ServiceBaseUrl_Static
* @category Authentication
* @package PhpCAS
* @author Henry Pan <git@phy25.com>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://wiki.jasig.org/display/CASC/phpCAS
*/
class CAS_ServiceBaseUrl_Static
extends CAS_ServiceBaseUrl_Base
{
private $_name = null;
public function __construct($name) {
if (is_string($name)) {
$this->_name = $this->removeStandardPort($name);
} else {
throw new CAS_TypeMismatchException($name, '$name', 'string');
}
}
/**
* Get the server name through static config.
*
* @return string the server hostname and port of the server configured
*/
public function get()
{
phpCAS::traceBegin();
phpCAS::trace("Returning static server name: " . $this->_name);
phpCAS::traceEnd(true);
return $this->_name;
}
}

Some files were not shown because too many files have changed in this diff Show More