diff --git a/Api/V8/Config/services/middlewares.php b/Api/V8/Config/services/middlewares.php index d932173f6..5af7a7f65 100644 --- a/Api/V8/Config/services/middlewares.php +++ b/Api/V8/Config/services/middlewares.php @@ -9,6 +9,7 @@ use Api\V8\OAuth2\Repository\ClientRepository; use Api\V8\OAuth2\Repository\RefreshTokenRepository; use Api\V8\OAuth2\Repository\ScopeRepository; use Api\V8\OAuth2\Repository\UserRepository; +use League\OAuth2\Server\Grant\ClientCredentialsGrant; use Psr\Container\ContainerInterface as Container; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\Grant\PasswordGrant; @@ -19,7 +20,7 @@ use Api\V8\Helper\OsHelper; use League\OAuth2\Server\CryptKey; return CustomLoader::mergeCustomArray([ - AuthorizationServer::class => function (Container $container) { + AuthorizationServer::class => static function (Container $container) { // base dir must exist in entryPoint.php $baseDir = $GLOBALS['BASE_DIR']; @@ -41,7 +42,7 @@ return CustomLoader::mergeCustomArray([ $shouldCheckPermissions ), new CryptKey( - sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PRIVATE_KEY), + sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PUBLIC_KEY), null, $shouldCheckPermissions ) @@ -60,8 +61,8 @@ return CustomLoader::mergeCustomArray([ // Client credentials grant $server->enableGrantType( - new \League\OAuth2\Server\Grant\ClientCredentialsGrant(), - new \DateInterval('PT1H') + new ClientCredentialsGrant(), + new DateInterval('PT1H') ); // Password credentials grant @@ -70,31 +71,37 @@ return CustomLoader::mergeCustomArray([ new UserRepository($container->get(BeanManager::class)), new RefreshTokenRepository($container->get(BeanManager::class)) ), - new \DateInterval('PT1H') + new DateInterval('PT1H') ); $refreshGrant = new RefreshTokenGrant( new RefreshTokenRepository($container->get(BeanManager::class)) ); - $refreshGrant->setRefreshTokenTTL(new \DateInterval('P1M')); + $refreshGrant->setRefreshTokenTTL(new DateInterval('P1M')); $server->enableGrantType( $refreshGrant, - new \DateInterval('PT1H') + new DateInterval('PT1H') ); return $server; }, - ResourceServer::class => function (Container $container) { + ResourceServer::class => static function (Container $container) { $baseDir = $GLOBALS['BASE_DIR']; + $shouldCheckPermissions = OsHelper::getOS() !== OsHelper::OS_WINDOWS; + return new ResourceServer( new AccessTokenRepository( new AccessTokenEntity(), $container->get(BeanManager::class) ), - sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PUBLIC_KEY) + new CryptKey( + sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PUBLIC_KEY), + null, + $shouldCheckPermissions + ) ); }, ], basename(__FILE__)); diff --git a/data/SugarBean.php b/data/SugarBean.php index cd3636597..4372b2814 100755 --- a/data/SugarBean.php +++ b/data/SugarBean.php @@ -415,6 +415,11 @@ class SugarBean */ public $old_modified_by_name; + /** + * @var bool $createdAuditRecords + */ + public $createdAuditRecords; + /** * @var SugarBean[][] $line_item_entries */ diff --git a/files.md5 b/files.md5 index 6c720d0ac..70d89f960 100755 --- a/files.md5 +++ b/files.md5 @@ -1,7 +1,6 @@ 'deaa6f875467f423cf0e8e193b552172', './Api/Core/Config/ApiConfig.php' => '69a1e7b3d7755a2a63499a16ddae81cf', './Api/Core/Config/slim.php' => 'b134e68765e6a1403577e2a5a06322b8', './Api/Core/Loader/ContainerLoader.php' => '6d5e0db5708f5e34bec7ba8fb8196bdc', @@ -18,7 +17,7 @@ $md5_string = array ( './Api/V8/Config/services/factories.php' => 'abedc3b0445f9076cf55fb81f922999b', './Api/V8/Config/services/globals.php' => 'd1bdcccf5150b16b84fc8192f63affdd', './Api/V8/Config/services/helpers.php' => 'd15737677999e4f7307443aa83da8afa', - './Api/V8/Config/services/middlewares.php' => '18dde9147c371f54d571ba15e2ed329c', + './Api/V8/Config/services/middlewares.php' => 'a7e3340374c5bfb6b26b4d99e61a8935', './Api/V8/Config/services/params.php' => '9fd77ca190fbcea45ad11f156d5db9b7', './Api/V8/Config/services/services.php' => '1c6d1cc19c087015430b4b965705e2fb', './Api/V8/Config/services/validators.php' => '884d713ad8ed932500039acaf285fa45', @@ -117,7 +116,7 @@ $md5_string = array ( './ModuleInstall/PackageManager/tpls/PackageManagerLicense.tpl' => 'df5e267d1df5ce08fb9406e42d5b4816', './ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl' => '98e396c0aa57329731fda19c790fffb2', './ModuleInstall/extensions.php' => '87596ad3f28a39c996a5551cad3b5cab', - './README.md' => '32252d95761ee022e09c9a54ddde4d95', + './README.md' => 'f712500fcbf7b512966c0bf3374807ce', './RoboFile.php' => '045b82c1df69553824d0e4ffcce6e03c', './SugarSecurity.php' => '47e316b2d408e8c5192c8ea4a4f921b3', './TreeData.php' => '32873e20cb5fd33f9d1cdaf18c3cac5c', @@ -505,11 +504,9 @@ $md5_string = array ( './Zend/Validate/Interface.php' => 'e313ef824309253dcfab90ff1d38ac86', './Zend/Validate/Ip.php' => 'e313ef824309253dcfab90ff1d38ac86', './Zend/Version.php' => 'e313ef824309253dcfab90ff1d38ac86', - './build/push_output.sh' => 'cde8cd38e3b0c4e988ec4be7d81faa89', - './build/travis-ci-apache' => 'e1e212c4eaf679b6ec620cd0b12f4571', './campaign_tracker.php' => '321e43ca8b664e6ca57ae5589e8c0667', - './composer.json' => 'ec30e8bd48195ff38dd62cbcde73c2a7', - './composer.lock' => '638558a83673b7e29ef0c5d4bf8189d3', + './composer.json' => 'e1f1995de0b0dd645e55494af19c8b0d', + './composer.lock' => '2319e305117e2685d966bf0fe98fd6ae', './cron.php' => '0b8b6bd839a2232a8da074b31feaa708', './crossdomain.xml' => '24b7711640c652b21aa89c9d83d6ec13', './data/BeanFactory.php' => '84b7c36b6a59ea8c5c4069659cc72950', @@ -523,7 +520,7 @@ $md5_string = array ( './data/Relationships/One2OneRelationship.php' => 'c46d3067d5651fbc928763600d5e1a51', './data/Relationships/RelationshipFactory.php' => '98a46e44186f2d2db23be9b894a4f1e2', './data/Relationships/SugarRelationship.php' => 'a71b96492ee7457826fc91a2356c4ebd', - './data/SugarBean.php' => 'd4f57253f79507904f9eacc6502dde53', + './data/SugarBean.php' => 'd90992bfdf9e5aa73d0324d414d57f3c', './deprecated.php' => 'f5f507fd6314f38d29c97e2cc2c62239', './dictionary.php' => 'b7c1370fb75a2940c04db74627c4462c', './download.php' => 'f2d366039d134ac463ff1e75634ce509', @@ -570,10 +567,10 @@ $md5_string = array ( './include/ErrorMessageException.php' => 'cbb52742f39a2b77a951889b571c6e0f', './include/Exceptions/SugarControllerException.php' => '4fde226677e926620e90e83f0ec761f2', './include/Exceptions/SuiteException.php' => '83c2319718dcdee178eda29b56e375b1', - './include/GoogleSync/GoogleSync.php' => '08230174ff7ea894ef16846c46aeb500', - './include/GoogleSync/GoogleSyncBase.php' => 'e57b11431c5e49f71b2e7d2e5dee1832', + './include/GoogleSync/GoogleSync.php' => '957fdac94e2446dc1b69f6e669a406fe', + './include/GoogleSync/GoogleSyncBase.php' => 'b8a6e57f6e7df10eb22b4460d20e7991', './include/GoogleSync/GoogleSyncExceptions.php' => '34218995be6d57d316d17e97064f994f', - './include/GoogleSync/GoogleSyncHelper.php' => '938e195cf4251ee30b31a4674a72a654', + './include/GoogleSync/GoogleSyncHelper.php' => 'd7519e89f6ecb6143db97e8bd7775e95', './include/GroupedTabs/GroupedTabStructure.php' => 'f6fdcc2242695b666e2a1b67318ddd70', './include/HTMLPurifier/CREDITS' => 'a5f9ddecea015543001404c0a9bfd181', './include/HTMLPurifier/HTMLPurifier.autoload.php' => '4b4731b18fc20cf22a3524093b122278', @@ -2727,7 +2724,7 @@ $md5_string = array ( './install/installSystemCheck.php' => 'd5f666ece13475386610cb7915ae3c93', './install/installType.php' => '7acf23c138ceafad2ce0393bd3c116f0', './install/install_defaults.php' => 'd25503407f0db14fa875b295d0f34ae5', - './install/install_utils.php' => '8fb3fc994c368eecd4c875bf0dee4479', + './install/install_utils.php' => '640b6ec4a434023fbb8422e3d4fcbd83', './install/lang.config.php' => 'cb3e68fdb0600481497dcd60f0746aca', './install/language/en_us.lang.php' => '443a21c6c24b089d6dc085a3ebb588d8', './install/license.js' => '9b5c798584a7ae54703dcfa2d1bb991f', @@ -4958,7 +4955,7 @@ $md5_string = array ( './modules/Emails/include/ComposeView/ComposeView.tpl' => '1ec29fbb9803c24e5ed8a12155668e58', './modules/Emails/include/ComposeView/ComposeViewBlank.tpl' => '22365ce6727ffb560e5ad3fc187f13f2', './modules/Emails/include/ComposeView/ComposeViewToolbar.tpl' => '656b26827857375278124e4610b9ff06', - './modules/Emails/include/ComposeView/EmailsComposeView.js' => '4a493e1cefdac676a0988051d45ca3dd', + './modules/Emails/include/ComposeView/EmailsComposeView.js' => '5c836fdc4d36bb39c6b027f13f9724db', './modules/Emails/include/DetailView/EmailsDetailView.php' => 'f95937f398f37afe3927ecc035b8b743', './modules/Emails/include/DetailView/EmailsDraftDetailView.php' => 'baafca815e89a4c0ec3df8b6192552ea', './modules/Emails/include/DetailView/EmailsNonImportedDetailView.php' => 'ef9ecbcf65fa6f03e32f94b6a9805b2f', @@ -5256,7 +5253,7 @@ $md5_string = array ( './modules/Import/Importer.php' => 'c4bf3967c463f929acff62fa541cc664', './modules/Import/Menu.php' => '776e6242c638410abd3290c9387e134e', './modules/Import/UsersLastImport.php' => 'a1c22f45aa62094045f32acbcba0ba8d', - './modules/Import/controller.php' => '84c58a01c2fcff75550e1f90d3dffe9d', + './modules/Import/controller.php' => '461f26cd01bc94f0fa0f17608183120b', './modules/Import/language/en_us.lang.php' => '41328cd1de165898134141618e777774', './modules/Import/maps/ImportMap.php' => 'f8a79c733d4ec686203476e5930c0670', './modules/Import/maps/ImportMapAct.php' => '15401c409712de8a08e3dfc7f95df8a0', @@ -5291,7 +5288,7 @@ $md5_string = array ( './modules/Import/views/view.last.php' => '7c4d08eb99783e31971a4a641d531a50', './modules/Import/views/view.step1.php' => '7f515a1fc6c2c182c24d6af3c65d73b3', './modules/Import/views/view.step2.php' => '30d49b03050d05f5605dc935ea87fd9a', - './modules/Import/views/view.step3.php' => 'a0e152da156d05178d33052f0780495a', + './modules/Import/views/view.step3.php' => 'cb5d880a6d7268fc416d431ff85983b2', './modules/Import/views/view.step4.php' => '8694e2f07e6ddc9128af648d42aa802d', './modules/Import/views/view.undo.php' => '0f11a824c733c819214ef88f666358b5', './modules/InboundEmail/AOPInboundEmail.php' => '2c74ce41273c1982b221a8862dfcc997', @@ -6013,7 +6010,7 @@ $md5_string = array ( './modules/SecurityGroups/javascript/popup_relate.js' => '7579a87bd17a42988d7cfdb1983061d3', './modules/SecurityGroups/language/en_us.lang.php' => '4b8424175457d63eaefd8d924f86920e', './modules/SecurityGroups/metadata/SearchFields.php' => '96c05b90550f5063a76b0ccf0a27f6bf', - './modules/SecurityGroups/metadata/detailviewdefs.php' => 'c2a93e716003fb32e5e2784ea7983664', + './modules/SecurityGroups/metadata/detailviewdefs.php' => '05a1c1a20a12755f8b1e4b18f0769985', './modules/SecurityGroups/metadata/editviewdefs.php' => '6739d8de7b420f85ff4396f5f7603161', './modules/SecurityGroups/metadata/listviewdefs.php' => 'f2405e3ec285440740c0b030b85a1c66', './modules/SecurityGroups/metadata/metafiles.php' => 'be0931e2262e0459e06038d775203322', @@ -6332,7 +6329,7 @@ $md5_string = array ( './modules/Users/Error.php' => '974cf5b2e9d530a56a38f54295452f12', './modules/Users/Forms.php' => '542f6a00ce7cf53d86c21b24b03c286f', './modules/Users/GeneratePassword.php' => 'c14fa3a7d189159f59c0adf91bf07268', - './modules/Users/GoogleApiKeySaverEntryPoint.php' => '4bcae8920af13ae01cc376f763d673fb', + './modules/Users/GoogleApiKeySaverEntryPoint.php' => '31a2b6771f4b67065a06bf5aa4133ecb', './modules/Users/ListRoles.php' => '470204e9dd0e9421f06f7304cf72e063', './modules/Users/LoggedOut.php' => '651bfc7c6c36f3791c2693bda075beb9', './modules/Users/LoggedOut.tpl' => '9537c8e192b86a038ba3177d9e2fdff1', @@ -6351,7 +6348,7 @@ $md5_string = array ( './modules/Users/SetTimezone.tpl' => 'f0fb5ed64fae81a5657ebc8f167967c9', './modules/Users/UpdateTourStatus.php' => 'cc111e28e6df1d96b98678661dd42490', './modules/Users/User.js' => '430d6a4d4b14300ea4c6c3592601fa6c', - './modules/Users/User.php' => '8b3e002479e07d08376dc8063538e5aa', + './modules/Users/User.php' => '6b94a6e99c975c19d2bd3fdbdec31c94', './modules/Users/UserEditView.js' => 'a5d33c708bf0e30356dfe2945df13704', './modules/Users/UserEmailOptions.tpl' => '96b848efbf7f6d4fee7b6bf13a1a1aee', './modules/Users/UserEmailSettings.tpl' => '5d9ff3379f63dcf7c5efbbcc3e88d8ed', @@ -6379,7 +6376,7 @@ $md5_string = array ( './modules/Users/authentication/SugarAuthenticate/SugarAuthenticate.php' => '4b1d9b735022ae8cf9a1d5ea3515617b', './modules/Users/authentication/SugarAuthenticate/SugarAuthenticateUser.php' => 'c59bb9e71e48bed5bb9322ec9416e7b9', './modules/Users/controller.php' => '65021ed13247766dc3353cdbf8e8dada', - './modules/Users/entryPointSaveGoogleApiKey.php' => '93594685ab60cfa9a47606f9b00f7c9a', + './modules/Users/entryPointSaveGoogleApiKey.php' => 'af2395a659fbe4c935ac555e4f3b592b', './modules/Users/field_arrays.php' => 'b2de6918c313caef59c28582475ab3a6', './modules/Users/googleApiKeySaverEntryPointError.tpl' => '5b45b5ce045c459e3e6c571d43eef873', './modules/Users/language/en_us.lang.php' => '7cf5849bd441e65eb84ae48067c4a47b', @@ -6638,7 +6635,7 @@ $md5_string = array ( './soap.php' => 'e28988c2e0b8e2c484587b537a710525', './sugar_version.json' => 'bdfbcefae2f9af559bef6a36367df7bb', './sugar_version.php' => 'db7b6c8d51f87879fce1e6172eedfbed', - './suitecrm_version.php' => '000d6549775d93be1199f3d48df797e6', + './suitecrm_version.php' => '75f00d095bff2cbfc0640daa1fab3c4c', './themes/SuiteP/css/Dawn/color-palette.scss' => 'f85621a6c8b0cd015a8c4703e83e519b', './themes/SuiteP/css/Dawn/icons.scss' => 'd59f8c5855e7a8df09542a663835a196', './themes/SuiteP/css/Dawn/style.css' => 'a6fcb84280b719f1c3dabe74385553bd', @@ -8043,7 +8040,7 @@ $md5_string = array ( './themes/SuiteP/include/DetailView/header.tpl' => 'ba7fbc5faa2a0e336373aae9b1e52a8e', './themes/SuiteP/include/DetailView/tab_panel_content.tpl' => '38b33c06fc8e5c4d55b5276b457d0330', './themes/SuiteP/include/DetailView/test.tpl' => 'fcf838f4139733066cc727fc7f3818ae', - './themes/SuiteP/include/EditView/EditView.tpl' => '875af492db7774ac8c18b11c3946f634', + './themes/SuiteP/include/EditView/EditView.tpl' => '5e279ffcc56b22f3c2d6032247fa288e', './themes/SuiteP/include/EditView/QuickCreate.tpl' => '3acca81ef6a983731de021c1943f4c0b', './themes/SuiteP/include/EditView/SugarVCR.tpl' => 'eed25c746ed4a7ffeeaaae25a36f49c4', './themes/SuiteP/include/EditView/actions_buttons.tpl' => '3ccfac667a36f3f67706deb6de2f9a77', diff --git a/include/GoogleSync/GoogleSync.php b/include/GoogleSync/GoogleSync.php index c6794e441..63f24a512 100644 --- a/include/GoogleSync/GoogleSync.php +++ b/include/GoogleSync/GoogleSync.php @@ -63,11 +63,11 @@ class GoogleSync extends GoogleSyncBase * Gets the combined titles of a Meeting/Event pair for Logging * * @param Meeting $meeting The CRM Meeting - * @param \Google_Service_Calendar_Event $event The Google Event + * @param \Google\Service\Calendar\Event $event The Google Event * * @return string The combined title */ - protected function getTitle(Meeting $meeting = null, Google_Service_Calendar_Event $event = null) + protected function getTitle(Meeting $meeting = null, Google\Service\Calendar\Event $event = null) { $meetingTitle = isset($meeting) ? $meeting->name : null; $eventTitle = isset($event) ? $event->getSummary() : null; @@ -89,13 +89,13 @@ class GoogleSync extends GoogleSyncBase * * @param string $action The action to take with the two events * @param Meeting $meeting The CRM Meeting - * @param \Google_Service_Calendar_Event $event The Google Event + * @param \Google\Service\Calendar\Event $event The Google Event * * @return bool Success/Failure * @throws GoogleSyncException if $action is invalid. * @throws GoogleSyncException if something else fails. */ - protected function doAction($action, Meeting $meeting = null, Google_Service_Calendar_Event $event = null) + protected function doAction($action, Meeting $meeting = null, Google\Service\Calendar\Event $event = null) { $title = $this->getTitle($meeting, $event); @@ -194,12 +194,12 @@ class GoogleSync extends GoogleSyncBase * Used when an event w/ a matching ID is on both ends of the sync. * At least one of the params is required. * - * @param Meeting|null $meeting (optional) Meeting Bean or Google_Service_Calendar_Event Object - * @param \Google_Service_Calendar_Event|null $event (optional) Google_Service_Calendar_Event Object + * @param Meeting|null $meeting (optional) Meeting Bean or Google\Service\Calendar\Event Object + * @param \Google\Service\Calendar\Event|null $event (optional) Google\Service\Calendar\Event Object * * @return string|bool 'push(_delete)', 'pull(_delete)', 'skip', false (on error) */ - protected function pushPullSkip(Meeting $meeting = null, Google_Service_Calendar_Event $event = null) + protected function pushPullSkip(Meeting $meeting = null, Google\Service\Calendar\Event $event = null) { if (empty($meeting) && empty($event)) { throw new GoogleSyncException('Missing Parameter, You must pass at least one event'); diff --git a/include/GoogleSync/GoogleSyncBase.php b/include/GoogleSync/GoogleSyncBase.php index 0b7900ebb..e95459cb0 100755 --- a/include/GoogleSync/GoogleSyncBase.php +++ b/include/GoogleSync/GoogleSyncBase.php @@ -61,10 +61,10 @@ class GoogleSyncBase /** @var User The SuiteCRM User Bean we're currently working with */ protected $workingUser; - /** @var \Google_Client The Google client object for the current sync job */ + /** @var \Google\Client The Google client object for the current sync job */ protected $gClient; - /** @var \Google_Service_Calendar The Google Calendar Service Object */ + /** @var \Google\Service\Calendar The Google Calendar Service Object */ protected $gService; /** @var array The Google AuthcConfig json */ @@ -158,7 +158,7 @@ class GoogleSyncBase * * @param string $id : the SuiteCRM user id * - * @return \Google_Client|false Google_Client on success. False on failure. + * @return \Google\Client|false Google\Client on success. False on failure. * @throws GoogleSyncException if user invalid, unable to retrive the user, or json error */ protected function getClient($id) @@ -201,9 +201,9 @@ class GoogleSyncBase * New Google Client and refresh the token if needed * * @param array $accessToken - * @return \Google_Client or false on Exception + * @return \Google\Client or false on Exception * @throws GoogleSyncException If the refresh token is missing - * @throws Exception rethrows if caught from Google_Client::fetchAccessTokenWithRefreshToken + * @throws Exception rethrows if caught from Google\Client::fetchAccessTokenWithRefreshToken */ protected function getGoogleClient($accessToken) { @@ -212,9 +212,9 @@ class GoogleSyncBase } // New Google Client - $client = new Google_Client(); + $client = new \Google\Client(); $client->setApplicationName('SuiteCRM'); - $client->setScopes(Google_Service_Calendar::CALENDAR); + $client->setScopes(Google\Service\Calendar::CALENDAR); $client->setAccessType('offline'); $client->setAuthConfig($this->authJson); $client->setAccessToken($accessToken); @@ -349,7 +349,7 @@ class GoogleSyncBase $this->logger->info(__FILE__ . ':' . __LINE__ . ' ' . __METHOD__ . ' - ' . 'Unable to find the SuiteCRM Google Calendar, wiping current sync data & creating it!'); $helper = new GoogleSyncHelper; $helper->wipeLocalSyncData($this->workingUser->id); - $calendar = new Google_Service_Calendar_Calendar(); + $calendar = new \Google\Service\Calendar\Calendar(); $calendar->setSummary('SuiteCRM'); $calendar->setTimeZone($this->timezone); @@ -367,11 +367,11 @@ class GoogleSyncBase /** * find the id of the 'SuiteCRM' calendar ... in the future, this will return the calendar of the users choosing. * - * @param Google_Service_Calendar_CalendarList $calendarList + * @param \Google\Service\Calendar\CalendarList $calendarList * * @return string|null Matching Google Calendar ID or null. */ - protected function getSuiteCRMCalendar(Google_Service_Calendar_CalendarList $calendarList) + protected function getSuiteCRMCalendar(Google\Service\Calendar\CalendarList $calendarList) { foreach ($calendarList->getItems() as $calendarListEntry) { if ($calendarListEntry->getSummary() == 'SuiteCRM') { @@ -386,7 +386,7 @@ class GoogleSyncBase * Get events in users google calendar * * - * @return bool|array Array of Google_Service_Calendar_Event Objects + * @return bool|array Array of Google\Service\Calendar\Event Objects */ protected function getUserGoogleEvents() { @@ -453,7 +453,7 @@ class GoogleSyncBase * * @param string $event_id Google Event ID * - * @return \Google_Service_Calendar_Event|null Google_Service_Calendar_Event if found, null if not found + * @return \Google\Service\Calendar\Event|null Google\Service\Calendar\Event if found, null if not found * @throws GoogleSyncException if $event_id is empty * @throws GoogleSyncException if Google Service not set up */ @@ -528,7 +528,7 @@ class GoogleSyncBase } // create new calendar service - $this->gService = new Google_Service_Calendar($this->gClient); + $this->gService = new \Google\Service\Calendar($this->gClient); if ($this->isServiceExists()) { return true; } @@ -543,20 +543,20 @@ class GoogleSyncBase * be updated. * * @param Meeting $event_local : SuiteCRM Meeting Bean - * @param \Google_Service_Calendar_Event $event_remote (optional) \Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event_remote (optional) \Google\Service\Calendar\Event Object * * @return string|bool Meeting Id on success, false on failure */ - protected function pushEvent(Meeting $event_local = null, Google_Service_Calendar_Event $event_remote = null) + protected function pushEvent(Meeting $event_local = null, Google\Service\Calendar\Event $event_remote = null) { if (!$event_local instanceof Meeting) { throw new InvalidArgumentException('Argument 1 passed to GoogleSyncBase::pushEvent() must be an instance of Meeting, ' . getType($event_local) . ' given.'); } - if (!$this->gService instanceof Google_Service_Calendar) { - throw new GoogleSyncException('GooleSyncBase is trying to push event but Google_Service_Calendar_Resource_Events is not set.', GoogleSyncException::NO_GSERVICE_SET); + if (!$this->gService instanceof Google\Service\Calendar) { + throw new GoogleSyncException('GooleSyncBase is trying to push event but Google\Service\Calendar\Resource\Events is not set.', GoogleSyncException::NO_GSERVICE_SET); } - if (!$this->gService->events instanceof Google_Service_Calendar_Resource_Events) { - throw new GoogleSyncException('GooleSyncBase is trying to push event but Google_Service_Calendar_Resource_Events is not set.', GoogleSyncException::NO_GRESOURCE_SET); + if (!$this->gService->events instanceof Google\Service\Calendar\Resource\Events) { + throw new GoogleSyncException('GooleSyncBase is trying to push event but Google\Service\Calendar\Resource\Events is not set.', GoogleSyncException::NO_GRESOURCE_SET); } if (!isset($event_remote) || empty($event_remote)) { @@ -568,7 +568,7 @@ class GoogleSyncBase } /* We don't get a status code back showing success. Instead, the return of the - * create or update is the Google_Service_Calendar_Event object after saving. + * create or update is the Google\Service\Calendar\Event object after saving. * So we check to make sure it has an ID to determine Success/Failure. */ if (!isset($return->id)) { @@ -580,16 +580,16 @@ class GoogleSyncBase } /** - * Helper method to get a Google_Service_Calendar_EventExtendedProperties object for the Google event + * Helper method to get a Google\Service\Calendar\EventExtendedProperties object for the Google event * - * Takes the local and remote events, and returns a Google_Service_Calendar_EventExtendedProperties + * Takes the local and remote events, and returns a Google\Service\Calendar\EventExtendedProperties * - * @param \Google_Service_Calendar_Event $event_remote \Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event_remote \Google\Service\Calendar\Event Object * @param Meeting $event_local Meeting (optional) \Meeting Bean * - * @return Google_Service_Calendar_EventExtendedProperties object + * @return Google\Service\Calendar\EventExtendedProperties object */ - protected function returnExtendedProperties(Google_Service_Calendar_Event $event_remote, Meeting $event_local) + protected function returnExtendedProperties(Google\Service\Calendar\Event $event_remote, Meeting $event_local) { // We pull the existing extendedProperties, and change our values // That way we don't mess with anything else that's using other values. @@ -598,7 +598,7 @@ class GoogleSyncBase if (!empty($extendedProperties)) { $private = $extendedProperties->getPrivate(); } elseif (empty($extendedProperties)) { - $extendedProperties = new Google_Service_Calendar_EventExtendedProperties; + $extendedProperties = new Google\Service\Calendar\EventExtendedProperties; $private = array(); } @@ -616,16 +616,16 @@ class GoogleSyncBase * If the SuiteCRM Meeting is not provided, a new one will be created * and inserted. If one is provided, the existing meeting will be updated. * - * @param \Google_Service_Calendar_Event $event_remote \Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event_remote \Google\Service\Calendar\Event Object * @param Meeting $event_local Meeting (optional) \Meeting Bean * * @return bool Success/Failure of setLastSync, since that's what saves the record * @throws GoogleSyncException if returned event invalid */ - protected function pullEvent(Google_Service_Calendar_Event $event_remote = null, Meeting $event_local = null) + protected function pullEvent(Google\Service\Calendar\Event $event_remote = null, Meeting $event_local = null) { - if (!$event_remote instanceof Google_Service_Calendar_Event) { - throw new InvalidArgumentException('Argument 1 passed to GoogleSyncBase::pullEvent() must be an instance of Google_Service_Calendar_Event, ' . getType($event_local) . ' given.'); + if (!$event_remote instanceof Google\Service\Calendar\Event) { + throw new InvalidArgumentException('Argument 1 passed to GoogleSyncBase::pullEvent() must be an instance of Google\Service\Calendar\Event, ' . getType($event_local) . ' given.'); } if (!isset($event_local) || empty($event_local)) { @@ -646,7 +646,7 @@ class GoogleSyncBase $greturn = $this->gService->events->update($this->calendarId, $event_remote->getId(), $event_remote); /* We don't get a status code back showing success. Instead, the return of the - * create or update is the Google_Service_Calendar_Event object after saving. + * create or update is the Google\Service\Calendar\Event object after saving. * So we check to make sure it has an ID to determine Success/Failure. */ if (isset($greturn->id)) { @@ -676,7 +676,7 @@ class GoogleSyncBase /** * Delete Google Event * - * @param \Google_Service_Calendar_Event $event \Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event \Google\Service\Calendar\Event Object * @param String $meeting_id SuiteCRM Meeting Id * * @return string Meeting Id on success @@ -685,10 +685,10 @@ class GoogleSyncBase * @throws GoogleSyncException If Meeting ID fails validation * @throws GoogleSyncException If delete fails */ - protected function delEvent(Google_Service_Calendar_Event $event = null, $meeting_id = null) + protected function delEvent(Google\Service\Calendar\Event $event = null, $meeting_id = null) { - if (!$event instanceof Google_Service_Calendar_Event) { - throw new InvalidArgumentException('Argument 1 passed to GoogleSyncBase::delEvent() must be an instance of Google_Service_Calendar_Event, ' . gettype($event) . ' given'); + if (!$event instanceof Google\Service\Calendar\Event) { + throw new InvalidArgumentException('Argument 1 passed to GoogleSyncBase::delEvent() must be an instance of Google\Service\Calendar\Event, ' . gettype($event) . ' given'); } // Make sure the calendar service is set up @@ -754,12 +754,12 @@ class GoogleSyncBase * Update SuiteCRM Meeting from Google Calendar Event * * @param Meeting $event_local SuiteCRM Meeting Bean - * @param \Google_Service_Calendar_Event $event_remote Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event_remote Google\Service\Calendar\Event Object * * @return Meeting|bool SuiteCRM Meeting Bean or false on failure * @throws GoogleSyncException if the Google Event is missing required data */ - protected function updateSuitecrmMeetingEvent(Meeting $event_local, Google_Service_Calendar_Event $event_remote) + protected function updateSuitecrmMeetingEvent(Meeting $event_local, Google\Service\Calendar\Event $event_remote) { $event_local->name = (string) $event_remote->getSummary(); @@ -775,13 +775,13 @@ class GoogleSyncBase $start = $event_remote->getStart(); if (!$start) { throw new GoogleSyncException( - 'GoogleSyncBase is trying to get "start" as Google_Service_Calendar_EventDateTime but it is not set', + 'GoogleSyncBase is trying to get "start" as Google\Service\Calendar\EventDateTime but it is not set', GoogleSyncException::NO_REMOVE_EVENT_START_IS_NOT_SET ); } - if (!$start instanceof Google_Service_Calendar_EventDateTime) { + if (!$start instanceof Google\Service\Calendar\EventDateTime) { throw new GoogleSyncException( - 'GoogleSyncBase is trying to get "start" as Google_Service_Calendar_EventDateTime but it is incorrect, ' . + 'GoogleSyncBase is trying to get "start" as Google\Service\Calendar\EventDateTime but it is incorrect, ' . gettype($start) . ' given.', GoogleSyncException::NO_REMOVE_EVENT_START_IS_INCORRECT ); @@ -834,12 +834,12 @@ class GoogleSyncBase /** * Create SuiteCRM Meeting event * - * @param \Google_Service_Calendar_Event $event_remote The Google_Service_Calendar_Event we're creating a SuiteCRM Meeting for + * @param \Google\Service\Calendar\Event $event_remote The Google\Service\Calendar\Event we're creating a SuiteCRM Meeting for * * @return Meeting|bool SuiteCRM Meeting Bean or false on failure * @throws GoogleSyncException if fails to retrive meeting */ - protected function createSuitecrmMeetingEvent(Google_Service_Calendar_Event $event_remote) + protected function createSuitecrmMeetingEvent(Google\Service\Calendar\Event $event_remote) { $this->logger->debug(__FILE__ . ':' . __LINE__ . ' ' . __METHOD__ . ' - ' . 'Creating New SuiteCRM Meeting'); $meeting = BeanFactory::getBean('Meetings'); @@ -856,11 +856,11 @@ class GoogleSyncBase * Update Google Calendar Event from SuiteCRM Meeting * * @param Meeting $event_local SuiteCRM Meeting Bean - * @param \Google_Service_Calendar_Event $event_remote Google Event Object + * @param \Google\Service\Calendar\Event $event_remote Google Event Object * - * @return \Google_Service_Calendar_Event + * @return \Google\Service\Calendar\Event */ - protected function updateGoogleCalendarEvent(Meeting $event_local, Google_Service_Calendar_Event $event_remote) + protected function updateGoogleCalendarEvent(Meeting $event_local, Google\Service\Calendar\Event $event_remote) { $event_remote->setSummary($event_local->name); $event_remote->setDescription($event_local->description); @@ -870,12 +870,12 @@ class GoogleSyncBase $localStart = $timedate->to_db($event_local->date_start, false); $localEnd = $timedate->to_db($event_local->date_end, false); - $startDateTime = new Google_Service_Calendar_EventDateTime; + $startDateTime = new \Google\Service\Calendar\EventDateTime; $startDateTime->setDateTime(date(DATE_ATOM, strtotime($localStart . ' UTC'))); $startDateTime->setTimeZone($this->timezone); $event_remote->setStart($startDateTime); - $endDateTime = new Google_Service_Calendar_EventDateTime; + $endDateTime = new \Google\Service\Calendar\EventDateTime; $endDateTime->setDateTime(date(DATE_ATOM, strtotime($localEnd . ' UTC'))); $endDateTime->setTimeZone($this->timezone); $event_remote->setEnd($endDateTime); @@ -893,11 +893,11 @@ class GoogleSyncBase ); if ($reminders_local) { - $reminders_remote = new Google_Service_Calendar_EventReminders; + $reminders_remote = new Google\Service\Calendar\EventReminders; $reminders_remote->setUseDefault(false); $reminders_array = array(); foreach ($reminders_local as $reminder_local) { - $reminder_remote = new Google_Service_Calendar_EventReminder; + $reminder_remote = new Google\Service\Calendar\EventReminder; $reminder_remote->setMethod('popup'); $reminder_remote->setMinutes($reminder_local->timer_popup / 60); $reminders_array[] = $reminder_remote; @@ -913,15 +913,15 @@ class GoogleSyncBase * * @param Meeting $event_local SuiteCRM Meeting Bean * - * @return \Google_Service_Calendar_Event Google_Service_Calendar_Event Object + * @return \Google\Service\Calendar\Event Google\Service\Calendar\Event Object */ protected function createGoogleCalendarEvent(Meeting $event_local) { //We're creating a new event - $event_remote_empty = new Google_Service_Calendar_Event; + $event_remote_empty = new Google\Service\Calendar\Event; - $extendedProperties = new Google_Service_Calendar_EventExtendedProperties; + $extendedProperties = new Google\Service\Calendar\EventExtendedProperties; $extendedProperties->setPrivate(array()); $event_remote_empty->setExtendedProperties($extendedProperties); diff --git a/include/GoogleSync/GoogleSyncHelper.php b/include/GoogleSync/GoogleSyncHelper.php index c124c6af0..bb2404671 100644 --- a/include/GoogleSync/GoogleSyncHelper.php +++ b/include/GoogleSync/GoogleSyncHelper.php @@ -61,11 +61,11 @@ class GoogleSyncHelper * At least one of the params is required. * * @param Meeting $meeting (optional) Meeting Bean - * @param \Google_Service_Calendar_Event $event (optional) Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event (optional) Google\Service\Calendar\Event Object * * @return string push, pull, skip, or false on error */ - public function singleEventAction(Meeting $meeting = null, Google_Service_Calendar_Event $event = null) + public function singleEventAction(Meeting $meeting = null, Google\Service\Calendar\Event $event = null) { if (empty($meeting) && empty($event)) { return false; @@ -84,11 +84,11 @@ class GoogleSyncHelper * Takes two calendar events, and extracts their last modified and sync times. * * @param Meeting $meeting Meeting Bean - * @param \Google_Service_Calendar_Event $event Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event Google\Service\Calendar\Event Object * * @return array key/value array with [sModified, $gModified, lastsync] keys */ - public function getTimeStrings(Meeting $meeting, Google_Service_Calendar_Event $event) + public function getTimeStrings(Meeting $meeting, Google\Service\Calendar\Event $event) { $timeArray = array(); @@ -114,12 +114,12 @@ class GoogleSyncHelper * Takes two calendar events and the timeArray from getTimeStrings, and returns a push/pull[_delete] string. * * @param Meeting $meeting Meeting Bean - * @param \Google_Service_Calendar_Event $event Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event Google\Service\Calendar\Event Object * @param array timeArray from getTimeStrings * * @return string 'push(_delete)', 'pull(_delete)' */ - public function getNewestMeetingResponse(Meeting $meeting, Google_Service_Calendar_Event $event, array $timeArray) + public function getNewestMeetingResponse(Meeting $meeting, Google\Service\Calendar\Event $event, array $timeArray) { if ($timeArray['gModified'] > $timeArray['sModified']) { if ($event->status == 'cancelled') { @@ -140,13 +140,13 @@ class GoogleSyncHelper * Takes two calendar events and the timeArray from getTimeStrings, and returns bool (should we skip this record). * * @param Meeting $meeting Meeting Bean - * @param \Google_Service_Calendar_Event $event Google_Service_Calendar_Event Object + * @param \Google\Service\Calendar\Event $event Google\Service\Calendar\Event Object * @param array $timeArray from getTimeStrings * @param array $syncedList from GoogleSyncBase Class * * @return bool should we skip this record */ - public function isSkippable(Meeting $meeting, Google_Service_Calendar_Event $event, array $timeArray, array $syncedList) + public function isSkippable(Meeting $meeting, Google\Service\Calendar\Event $event, array $timeArray, array $syncedList) { $ret = false; @@ -173,7 +173,7 @@ class GoogleSyncHelper * * Creates reminders for event from google event reminders * - * @param array $overrides Google Calendar Event Reminders (See Class Google_Service_Calendar_EventReminders) + * @param array $overrides Google Calendar Event Reminders (See Class Google\Service\Calendar\EventReminders) * @param string $meeting Meeting Bean * * @return array|bool Nested array of unsaved reminders and reminder_invitees, false on Failure diff --git a/install/install_utils.php b/install/install_utils.php index 1ec340a03..98b38d685 100755 --- a/install/install_utils.php +++ b/install/install_utils.php @@ -1288,17 +1288,15 @@ function create_table_if_not_exist(&$focus) } - function create_default_users() { - $db = DBManagerFactory::getInstance(); global $setup_site_admin_password; global $setup_site_admin_user_name; global $create_default_user; global $sugar_config; require_once('install/UserDemoData.php'); - + //Create default admin user $user = BeanFactory::newBean('Users'); $user->id = 1; @@ -1310,11 +1308,9 @@ function create_default_users() $user->is_admin = true; $user->employee_status = 'Active'; $user->user_hash = User::getPasswordHash($setup_site_admin_password); - $user->save(); - //Bug#53793: Keep default current user in the global variable in order to store 'created_by' info as default user - // while installation is proceed. - $GLOBALS['current_user'] = $user; + $GLOBALS['current_user'] = $user; + $GLOBALS['current_user']->save(); if ($create_default_user) { $default_user = BeanFactory::newBean('Users'); diff --git a/lib/PDF/PDFConfigurator.php b/lib/PDF/PDFConfigurator.php new file mode 100644 index 000000000..b5c5ba031 --- /dev/null +++ b/lib/PDF/PDFConfigurator.php @@ -0,0 +1,109 @@ +configurator = $configurator; + } + + /** + * Factory method for nice fluent syntax. + * + * @return PDFConfigurator + */ + public static function make(): PDFConfigurator + { + return new self(); + } + + /** + * @param string $engine + * @return $this + */ + public function setEngine(string $engine): PDFConfigurator + { + if (empty($engine)) { + throw new InvalidArgumentException('PDF Engine cannot be empty'); + } + + $this->configurator->config['pdf']['defaultEngine'] = $engine; + + return $this; + } + + /** + * Saves the current configuration. + * + * @return PDFConfigurator + */ + public function save(): PDFConfigurator + { + $this->configurator->saveConfig(); + + return $this; + } +} diff --git a/lib/PDF/PDFWrapper.php b/lib/PDF/PDFWrapper.php index d0f0d96a0..ec503f952 100644 --- a/lib/PDF/PDFWrapper.php +++ b/lib/PDF/PDFWrapper.php @@ -172,4 +172,12 @@ class PDFWrapper return $sugar_config['pdf'][$key] ?? null; } + + /** + * @return string|null + */ + public static function getController(): ?string + { + return self::getPDFConfig('controller'); + } } diff --git a/lib/Search/SearchConfigurator.php b/lib/Search/SearchConfigurator.php index cb30f7ac7..4e21745e8 100644 --- a/lib/Search/SearchConfigurator.php +++ b/lib/Search/SearchConfigurator.php @@ -94,7 +94,7 @@ class SearchConfigurator public function setEngine(string $engine): SearchConfigurator { if (empty($engine)) { - throw new InvalidArgumentException('$engine cannot be empty'); + throw new InvalidArgumentException('Search Engine cannot be empty'); } $searchController = 'UnifiedSearch'; diff --git a/modules/Administration/PDF/Controller.php b/modules/Administration/PDF/Controller.php new file mode 100644 index 000000000..df58241b0 --- /dev/null +++ b/modules/Administration/PDF/Controller.php @@ -0,0 +1,81 @@ +setEngine($PDFEngine) + ->save(); + + if ($this->isAjax()) { + $this->yieldJson(['status' => 'success']); + } + + $this->redirect('index.php?module=Administration&action=index'); + } +} diff --git a/modules/Administration/PDF/MVC/Controller.php b/modules/Administration/PDF/MVC/Controller.php new file mode 100644 index 000000000..020c16c3c --- /dev/null +++ b/modules/Administration/PDF/MVC/Controller.php @@ -0,0 +1,53 @@ +smarty->assign('MOD', $mod_strings); + $this->smarty->assign('APP', $app_strings); + $this->smarty->assign('APP_LIST', $app_list_strings); + $this->smarty->assign('LANGUAGES', get_languages()); + $this->smarty->assign('JAVASCRIPT', get_set_focus_js()); + $this->smarty->assign('error', $errors); + $this->smarty->assign('BUTTONS', $this->getButtons()); + + if (empty($sugar_config['pdf'])) { + LoggerManager::getLogger()->warn('Configuration does not contains default PDF settings.'); + } + + $pdfSettings = $sugar_config['pdf'] ?? null; + $this->smarty->assign('config', $pdfSettings); + } + + /** + * Returns the cancel and save button. + * + * @return string + */ + protected function getButtons(): string + { + global $mod_strings; + global $app_strings; + + $this->smarty->assign('MOD', $mod_strings); + $this->smarty->assign('APP', $app_strings); + + return $this->smarty->fetch('modules/Administration/PDF/buttons.tpl'); + } + + /** + * Returns an associative array with their class name and translated label + * + * @return array + */ + protected function getEngines(): array + { + $engines = []; + + foreach (PDFWrapper::getEngines() as $engine) { + $engines[$engine] = StringUtils::camelToTranslation($engine); + } + + return $engines; + } +} diff --git a/modules/Administration/PDF/PDFView.php b/modules/Administration/PDF/PDFView.php new file mode 100644 index 000000000..f93794567 --- /dev/null +++ b/modules/Administration/PDF/PDFView.php @@ -0,0 +1,89 @@ +smarty->assign('selectedController', PDFWrapper::getController()); + $this->smarty->assign('selectedEngine', PDFWrapper::getDefaultEngine()); + $engines = $this->getEngines(); + + $this->smarty->assign('engines', [ + translate('LBL_PDF_WRAPPER_ENGINES') => $engines + ]); + } + + /** + * @see SugarView::display() + */ + public function display(): void + { + global $mod_strings, $app_strings; + + $this->smarty->assign('APP', $app_strings); + $this->smarty->assign('MOD', $mod_strings); + + $template = $this->templateFile; + if (file_exists('custom/' . $this->templateFile)) { + $template = 'custom/' . $this->templateFile; + } + + $this->smarty->display($template); + } +} diff --git a/modules/Administration/PDF/buttons.tpl b/modules/Administration/PDF/buttons.tpl new file mode 100644 index 000000000..d9e1fc45d --- /dev/null +++ b/modules/Administration/PDF/buttons.tpl @@ -0,0 +1,50 @@ +{* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. + * + * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. + * Copyright (C) 2011 - 2021 SalesAgility Ltd. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not + * reasonably feasible for technical reasons, the Appropriate Legal Notices must + * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". + *} +  + diff --git a/modules/Administration/PDF/view.tpl b/modules/Administration/PDF/view.tpl new file mode 100644 index 000000000..be1c3e821 --- /dev/null +++ b/modules/Administration/PDF/view.tpl @@ -0,0 +1,84 @@ +{* + * SugarCRM Community Edition is a customer relationship management program developed by + * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. + * + * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. + * Copyright (C) 2011 - 2021 SalesAgility Ltd. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY + * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License along with + * this program; if not, see http://www.gnu.org/licenses or write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, + * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not + * reasonably feasible for technical reasons, the Appropriate Legal Notices must + * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". + *} +

{sugar_translate label="LBL_PDF_HEADER"}

+ +
+ + + +
+
+
{$MOD.LBL_PDF_INTERFACE}
+
+
+
+
+
+ +
+
+ {sugar_translate label="LBL_PDF_OPTIONS_HELP"} +
+
+
+
+
+ {html_options + options=$engines + selected=$selectedEngine + id="pdf-engine" + name="pdf-engine" + class="form-control" + } +
+
+
+
+ + {$JAVASCRIPT} + +
+ {$BUTTONS} +
+
+ diff --git a/modules/Administration/PDFSettings.php b/modules/Administration/PDFSettings.php new file mode 100644 index 000000000..2050e5529 --- /dev/null +++ b/modules/Administration/PDFSettings.php @@ -0,0 +1,54 @@ +handle(); diff --git a/modules/Administration/Search/MVC/View.php b/modules/Administration/Search/MVC/View.php index 27aa7847a..84ae7b220 100644 --- a/modules/Administration/Search/MVC/View.php +++ b/modules/Administration/Search/MVC/View.php @@ -74,9 +74,10 @@ abstract class View extends BaseView $this->smarty->assign('error', $errors); $this->smarty->assign('BUTTONS', $this->getButtons()); - if (!empty($sugar_config['search'])) { + if (empty($sugar_config['search'])) { LoggerManager::getLogger()->warn('Configuration does not contains default search settings.'); } + $search = $sugar_config['search'] ?? null; $this->smarty->assign('config', $search); } diff --git a/modules/Administration/language/en_us.lang.php b/modules/Administration/language/en_us.lang.php index ada50ae6a..84f890fd3 100755 --- a/modules/Administration/language/en_us.lang.php +++ b/modules/Administration/language/en_us.lang.php @@ -967,6 +967,18 @@ $mod_strings = array( 'LBL_ELASTIC_SEARCH_ENGINE' => 'Elasticsearch Engine', 'LBL_SIMPLE_SQL_SEARCH_ENGINE' => 'Simple SQL Search Engine', + // SearchWrapper Settings + 'LBL_PDF_HEADER' => 'PDF Settings', + 'LBL_CHANGE_PDF_SETTINGS' => 'Change PDF Settings', + 'LBL_PDF_HEADER_DESC' => 'Manage your PDF preferences', + 'LBL_PDF_OPTIONS' => 'PDF Engine', + 'LBL_PDF_OPTIONS_HELP' => 'Select the PDF engine that users will be able to use.', + 'LBL_PDF_INTERFACE' => 'PDF Interface', + + // PDF Engines Translations + 'LBL_PDF_WRAPPER_ENGINES' => 'PDF Engines', + 'LBL_MPDF_ENGINE' => 'MPDF Engine', + // Ajax Submit 'LBL_AJAX_SUBMIT_FAIL' => 'An error has occurred while saving the settings.', ); diff --git a/modules/Administration/metadata/adminpaneldefs.php b/modules/Administration/metadata/adminpaneldefs.php index 12d143235..eab8d1337 100755 --- a/modules/Administration/metadata/adminpaneldefs.php +++ b/modules/Administration/metadata/adminpaneldefs.php @@ -109,6 +109,14 @@ $admin_option_defs['Administration']['oauth2_clients'] = array( 'password' ); +$admin_option_defs['Administration']['pdf'] = array( + 'PDF', + 'LBL_PDF_HEADER', + 'LBL_CHANGE_PDF_SETTINGS', + './index.php?module=Administration&action=PDFSettings', + 'system-settings' +); + $admin_group_header[]= array('LBL_ADMINISTRATION_HOME_TITLE','',false,$admin_option_defs, 'LBL_ADMINISTRATION_HOME_DESC'); @@ -224,7 +232,6 @@ $admin_option_defs['Administration']['aos'] = array( './index.php?module=Administration&action=AOSAdmin', 'aos-settings' ); - $admin_option_defs['Administration']['aop'] = array( 'AOP', 'LBL_AOP_SETTINGS', diff --git a/modules/Emails/include/ComposeView/EmailsComposeView.js b/modules/Emails/include/ComposeView/EmailsComposeView.js index bac852dce..a89051d01 100644 --- a/modules/Emails/include/ComposeView/EmailsComposeView.js +++ b/modules/Emails/include/ComposeView/EmailsComposeView.js @@ -100,30 +100,30 @@ fields[$(this).attr('data-open-popup-email-address-field')] = 'qtip_bar_email_address'; } - $.fn.EmailsComposeView.setEmailAddressFieldFromPopup = function(resultData) { - var contact_name = resultData.name_to_value_array.qtip_bar_name; - var contact_email_address = resultData.name_to_value_array.qtip_bar_email_address; + $.fn.EmailsComposeView.setEmailAddressFieldFromPopup = function(resultData) { + var contact_name = resultData.name_to_value_array.qtip_bar_name; + var contact_email_address = resultData.name_to_value_array.qtip_bar_email_address; - if (trim(contact_email_address) !== '') { - var formatted_email_address = ''; - if (trim(contact_name) !== '') { - // use name format - formatted_email_address = contact_name + ' <' + contact_email_address + '>'; - } else { - // use email address - formatted_email_address = contact_email_address; - } + if (trim(contact_email_address) !== '') { + var formatted_email_address = ''; + if (trim(contact_name) !== '') { + // use name format + formatted_email_address = contact_name + ' <' + contact_email_address + '>'; + } else { + // use email address + formatted_email_address = contact_email_address; + } - if (trim($(self.active_elementQTipBar).val()) === '') { - $(self.active_elementQTipBar).val(formatted_email_address); - } else { - $(self.active_elementQTipBar).val( - $(self.active_elementQTipBar).val() + ', ' + - formatted_email_address - ); - } - } - }; + if (trim($(self.active_elementQTipBar).val()) === '') { + $(self.active_elementQTipBar).val(formatted_email_address); + } else { + $(self.active_elementQTipBar).val( + $(self.active_elementQTipBar).val() + ', ' + + formatted_email_address + ); + } + } + }; var popupWindow = open_popup( $(this).attr('data-open-popup-module'), diff --git a/modules/Import/controller.php b/modules/Import/controller.php index eb454ff90..c705a3bfc 100755 --- a/modules/Import/controller.php +++ b/modules/Import/controller.php @@ -1,15 +1,11 @@ bean; } } - + public function action_index() { $this->action_Step1(); @@ -128,24 +128,33 @@ class ImportController extends SugarController } } } - + echo json_encode($results); sugar_cleanup(true); } + public function action_RefreshMapping() { global $mod_strings; - require_once('modules/Import/sources/ImportFile.php'); - require_once('modules/Import/views/view.confirm.php'); + require_once __DIR__ . '/../../modules/Import/sources/ImportFile.php'; + require_once __DIR__ . '/../../modules/Import/views/view.confirm.php'; $v = new ImportViewConfirm(); $fileName = $_REQUEST['importFile']; + + if (isset($fileName) && strpos($fileName, '..') !== false) { + LoggerManager::getLogger()->security('Directory navigation attack denied'); + return; + } + $delim = $_REQUEST['delim']; - if ($delim == '\t') { + + if ($delim === '\t') { $delim = "\t"; } + $enclosure = $_REQUEST['qualif']; $enclosure = html_entity_decode($enclosure, ENT_QUOTES); - $hasHeader = isset($_REQUEST['header']) && !empty($_REQUEST['header']) ? true : false; + $hasHeader = !empty($_REQUEST['header']); $importFile = new ImportFile($fileName, $delim, $enclosure, false); $importFile->setHeaderRow($hasHeader); @@ -175,10 +184,10 @@ class ImportController extends SugarController $if->setHeaderRow($has_header); $lv = new ImportListView($if, array('offset'=> $offset), $tableID); $lv->display(false); - + sugar_cleanup(true); } - + public function action_Step1() { $fromAdminView = isset($_REQUEST['from_admin_wizard']) ? $_REQUEST['from_admin_wizard'] : false; @@ -189,7 +198,7 @@ class ImportController extends SugarController $this->view = 'step2'; } } - + public function action_Step2() { $this->view = 'step2'; @@ -214,17 +223,17 @@ class ImportController extends SugarController { $this->view = 'step4'; } - + public function action_Last() { $this->view = 'last'; } - + public function action_Undo() { $this->view = 'undo'; } - + public function action_Error() { $this->view = 'error'; @@ -244,7 +253,7 @@ class ImportController extends SugarController { $this->view = 'extimport'; } - + public function action_GetControl() { echo getControl($_REQUEST['import_module'], $_REQUEST['field_name']); diff --git a/modules/Import/views/view.step3.php b/modules/Import/views/view.step3.php index 9365975ec..c857e1bc5 100755 --- a/modules/Import/views/view.step3.php +++ b/modules/Import/views/view.step3.php @@ -1,14 +1,11 @@ getRequestDelimiter(); - + $this->ss->assign("CUSTOM_DELIMITER", $delimiter); $this->ss->assign("CUSTOM_ENCLOSURE", (!empty($_REQUEST['custom_enclosure']) ? $_REQUEST['custom_enclosure'] : "")); @@ -122,6 +123,11 @@ class ImportViewStep3 extends ImportView $uploadFileName = $_REQUEST['file_name']; + if (isset($uploadFileName) && strpos($uploadFileName, '..') !== false) { + LoggerManager::getLogger()->security('Directory navigation attack denied'); + return; + } + if (strpos($uploadFileName, 'phar://') !== false) { return; } diff --git a/modules/SecurityGroups/metadata/detailviewdefs.php b/modules/SecurityGroups/metadata/detailviewdefs.php index aa537e1f6..7b2ef4cba 100755 --- a/modules/SecurityGroups/metadata/detailviewdefs.php +++ b/modules/SecurityGroups/metadata/detailviewdefs.php @@ -1,46 +1,60 @@ array('form' => array('buttons'=>array('EDIT', 'DUPLICATE', 'DELETE', - )), - 'maxColumns' => '2', - 'widths' => array( - array('label' => '10', 'field' => '30'), - array('label' => '10', 'field' => '30') - ), +$viewdefs[$module_name]['DetailView'] = + array( + 'templateMeta' => + array( + 'form' => + array( + 'buttons' => + array( + 'EDIT', 'DUPLICATE', 'DELETE', + )), + 'maxColumns' => '2', + 'widths' => array( + 0 => + array( + 'label' => '10', + 'field' => '30' ), - -'panels' =>array( - - array( - 'name', - 'assigned_user_name', - ), + 1 => + array( + 'label' => '10', + 'field' => '30' + ) + ), + ), + + 'panels' => + array( + 'LBL_PANEL_OVERVIEW' => + array( + 0 => + array( + 'name', + 'assigned_user_name', + ), - - - - - - array( - array( - 'name' => 'date_entered', - 'customCode' => '{$fields.date_entered.value} {$APP.LBL_BY} {$fields.created_by_name.value}', - 'label' => 'LBL_DATE_ENTERED', - ), - array( - 'name' => 'date_modified', - 'customCode' => '{$fields.date_modified.value} {$APP.LBL_BY} {$fields.modified_by_name.value}', - 'label' => 'LBL_DATE_MODIFIED', - ), - ), - array( - 'noninheritable', - ), - array( - 'description', - ), -) -); + array( + array( + 'name' => 'date_entered', + 'customCode' => '{$fields.date_entered.value} {$APP.LBL_BY} {$fields.created_by_name.value}', + 'label' => 'LBL_DATE_ENTERED', + ), + array( + 'name' => 'date_modified', + 'customCode' => '{$fields.date_modified.value} {$APP.LBL_BY} {$fields.modified_by_name.value}', + 'label' => 'LBL_DATE_MODIFIED', + ), + ), + array( + 'noninheritable', + ), + array( + 'description', + ), + ), + ) + ); diff --git a/modules/Users/GoogleApiKeySaverEntryPoint.php b/modules/Users/GoogleApiKeySaverEntryPoint.php index 4bedb30f6..7e5e7abef 100644 --- a/modules/Users/GoogleApiKeySaverEntryPoint.php +++ b/modules/Users/GoogleApiKeySaverEntryPoint.php @@ -71,7 +71,7 @@ class GoogleApiKeySaverEntryPoint /** * - * @var Google_Client + * @var Google\Client */ protected $client; @@ -85,10 +85,10 @@ class GoogleApiKeySaverEntryPoint * * @param User $current_user * @param array $sugar_config - * @param Google_Client $client + * @param Google\Client $client * @param array $request */ - public function __construct(User $current_user, $sugar_config, Google_Client $client, $request) + public function __construct(User $current_user, $sugar_config, Google\Client $client, $request) { $this->currentUser = $current_user; $this->sugarConfig = $sugar_config; @@ -105,7 +105,7 @@ class GoogleApiKeySaverEntryPoint protected function handleEntryPoint() { $this->client->setApplicationName('SuiteCRM'); - $this->client->setScopes(Google_Service_Calendar::CALENDAR); + $this->client->setScopes(Google\Service\Calendar::CALENDAR); if (!isset($this->sugarConfig['google_auth_json'])) { throw new Exception('google_auth_json requested variable is missing', 1); } diff --git a/modules/Users/User.php b/modules/Users/User.php index 345521c2a..7ad10d332 100755 --- a/modules/Users/User.php +++ b/modules/Users/User.php @@ -666,6 +666,10 @@ class User extends Person implements EmailInterface $this->portal_only = 0; } + // If the current user is not an admin, do not allow them to set the admin flag to true. + if (!is_admin($current_user)) { + $this->is_admin = 0; + } // set some default preferences when creating a new user $setNewUserPreferences = empty($this->id) || !empty($this->new_with_id); diff --git a/modules/Users/entryPointSaveGoogleApiKey.php b/modules/Users/entryPointSaveGoogleApiKey.php index e1abd8d61..bcd10ec80 100644 --- a/modules/Users/entryPointSaveGoogleApiKey.php +++ b/modules/Users/entryPointSaveGoogleApiKey.php @@ -53,5 +53,5 @@ if (!defined('sugarEntry') || !sugarEntry) { include_once __DIR__ . '/GoogleApiKeySaverEntryPoint.php'; global $current_user, $sugar_config; -$client = new Google_Client(); +$client = new \Google\Client(); new GoogleApiKeySaverEntryPoint($current_user, $sugar_config, $client, $_REQUEST); diff --git a/suitecrm_version.php b/suitecrm_version.php index 8690bd4a2..9ac7d4406 100755 --- a/suitecrm_version.php +++ b/suitecrm_version.php @@ -4,5 +4,5 @@ if (!defined('sugarEntry') || !sugarEntry) { } $suitecrm_version = '8.0.0-beta.3'; -$suitecrm_legacy = '7.11.21'; -$suitecrm_timestamp = '2021-08-16 17:00:00'; +$suitecrm_legacy = '7.11.22'; +$suitecrm_timestamp = '2021-09-24 17:00:00'; diff --git a/tests/unit/phpunit/modules/Users/GoogleApiKeySaverEntryPointTest.php b/tests/unit/phpunit/modules/Users/GoogleApiKeySaverEntryPointTest.php index bc62ebead..9a415c76b 100644 --- a/tests/unit/phpunit/modules/Users/GoogleApiKeySaverEntryPointTest.php +++ b/tests/unit/phpunit/modules/Users/GoogleApiKeySaverEntryPointTest.php @@ -56,7 +56,7 @@ class GoogleApiKeySaverEntryPointTest extends SuitePHPUnitFrameworkTestCase $user = BeanFactory::getBean('Users'); $cfg['site_url'] = 'http://foo/bar.org'; $cfg['google_auth_json'] = base64_encode('{"web":{"client_id":"UNIT_TEST_client_id","project_id":"UNIT_TEST_project_id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"UNIT_TEST_client_secret","redirect_uris":["http://www.example.com/index.php?entryPoint=saveGoogleApiKey"]}}'); - $client = new Google_Client(); + $client = new Google\Client(); $request['error'] = 'ERR_NOT_ADMIN'; $epMock = new GoogleApiKeySaverEntryPointMock($user, $cfg, $client, $request); $dieOk = $epMock->getDieOk(); @@ -80,7 +80,7 @@ class GoogleApiKeySaverEntryPointTest extends SuitePHPUnitFrameworkTestCase $user = BeanFactory::getBean('Users'); $cfg['site_url'] = 'http://foo/bar.org'; $cfg['google_auth_json'] = base64_encode('{"web":{"client_id":"UNIT_TEST_client_id","project_id":"UNIT_TEST_project_id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"UNIT_TEST_client_secret","redirect_uris":["http://www.example.com/index.php?entryPoint=saveGoogleApiKey"]}}'); - $client = new Google_Client(); + $client = new Google\Client(); $request['getnew'] = 'ERR_NOT_ADMIN'; $epMock = new GoogleApiKeySaverEntryPointMock($user, $cfg, $client, $request); $expected = "https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline&client_id=UNIT_TEST_client_id&redirect_uri=http%3A%2F%2Fwww.example.com%2Findex.php%3FentryPoint%3DsaveGoogleApiKey&state&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar&approval_prompt=force"; @@ -97,7 +97,7 @@ class GoogleApiKeySaverEntryPointTest extends SuitePHPUnitFrameworkTestCase $cfg['site_url'] = 'http://foo/bar.org'; $cfg['google_auth_json'] = base64_encode('{"web":{"client_id":"UNIT_TEST_client_id","project_id":"UNIT_TEST_project_id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"UNIT_TEST_client_secret","redirect_uris":["http://www.example.com/index.php?entryPoint=saveGoogleApiKey"]}}'); - $client = new Google_Client(); + $client = new Google\Client(); $request['code'] = '1234567890'; try { $epMock = new GoogleApiKeySaverEntryPointMock($user, $cfg, $client, $request); @@ -116,7 +116,7 @@ class GoogleApiKeySaverEntryPointTest extends SuitePHPUnitFrameworkTestCase $cfg['site_url'] = 'http://foo/bar.org'; $cfg['google_auth_json'] = base64_encode('{"web":{"client_id":"UNIT_TEST_client_id","project_id":"UNIT_TEST_project_id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"UNIT_TEST_client_secret","redirect_uris":["http://www.example.com/index.php?entryPoint=saveGoogleApiKey"]}}'); - $client = new Google_Client(); + $client = new Google\Client(); $request['setinvalid'] = ''; $epMock = new GoogleApiKeySaverEntryPointMock($user, $cfg, $client, $request); $expected = "http://foo/bar.org/index.php?module=Users&action=EditView&record=" . $user->id; @@ -133,7 +133,7 @@ class GoogleApiKeySaverEntryPointTest extends SuitePHPUnitFrameworkTestCase $user->save(); $cfg['site_url'] = 'http://foo/bar.org'; $cfg['google_auth_json'] = base64_encode('{"web":{"client_id":"UNIT_TEST_client_id","project_id":"UNIT_TEST_project_id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://www.googleapis.com/oauth2/v3/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"UNIT_TEST_client_secret","redirect_uris":["http://www.example.com/index.php?entryPoint=saveGoogleApiKey"]}}'); - $client = new Google_Client(); + $client = new Google\Client(); $request['INVALID'] = 'INVALID'; $epMock = new GoogleApiKeySaverEntryPointMock($user, $cfg, $client, $request); $expected = "http://foo/bar.org/index.php?module=Users&action=EditView&record=" . $user->id; diff --git a/themes/suite8/include/EditView/EditView.tpl b/themes/suite8/include/EditView/EditView.tpl index f5ef59055..1c7109195 100644 --- a/themes/suite8/include/EditView/EditView.tpl +++ b/themes/suite8/include/EditView/EditView.tpl @@ -241,7 +241,7 @@ $(document).ready(function() {ldelim} }; var selectTabOnErrorInputHandle = function(inputHandle) { - var tab = $(inputHandle).closest('.tab-pane-NOBOOTSTRAPTOGGLER').attr('id').match(/^detailpanel_(.*)$/)[1]; + var tab = $(inputHandle).closest('.tab-pane-NOBOOTSTRAPTOGGLER').attr('id').match(/^tab-content-(.*)$/)[1]; selectTabOnError(tab); };