Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
S
sg_routes
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
TYPO3
sg_routes
Merge requests
!19
Release 5.0.0
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Release 5.0.0
release_5.0.0
into
master
Overview
0
Commits
9
Changes
1
Merged
Georgi
requested to merge
release_5.0.0
into
master
3 years ago
Overview
0
Commits
9
Changes
1
Expand
0
0
Merge request reports
Viewing commit
77fe3d15
Prev
Next
Show latest version
1 file
+
21
−
36
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
77fe3d15
[BUGFIX] Fixed the Flash messages for the license key check
· 77fe3d15
Georgi Mateev
authored
3 years ago
Classes/Service/LicenceCheckService.php
0 → 100644
+
604
−
0
Options
<?php
namespace
SGalinski\SgRoutes\Service
;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script 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 General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use
TYPO3\CMS\Core\Http\RequestFactory
;
use
TYPO3\CMS\Core\Registry
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Core\Utility\VersionNumberUtility
;
use
TYPO3\CMS\Extbase\Utility\LocalizationUtility
;
/**
* Class LicenceCheckService
*
* @package SGalinski\SgRoutes\Service
*/
class
LicenceCheckService
{
/**
* The product key from ShopWare
*/
const
PRODUCT_KEY
=
'sg_routes'
;
/**
* Namespace for the sys registry
*/
const
REGISTRY_NAMESPACE
=
'tx_sgroutes'
;
/**
* Keys for the sys registry
*/
const
IS_KEY_VALID_KEY
=
'isKeyValid'
;
const
LAST_WARNING_TIMESTAMP_KEY
=
'lastWarningTimestamp'
;
const
HAS_VALID_LICENSE_UNTIL_TIMESTAMP_KEY
=
'hasValidLicenseUntilTimestamp'
;
const
LICENSE_CHECKED_IN_VERSION_KEY
=
'licenceCheckedInVersion'
;
const
LAST_CHECKED_TIMESTAMP_KEY
=
'lastCheckedTimestamp'
;
const
LAST_AJAX_TIMESTAMP_KEY
=
'lastAjaxTimestamp'
;
const
LAST_LICENSE_KEY_CHECKED_KEY
=
'lastLicenseKeyChecked'
;
/**
* Error codes
*/
const
ERROR_INVALID_RESPONSE_CODE
=
-
1
;
const
ERROR_INVALID_RESPONSE_DATA
=
-
2
;
const
ERROR_INVALID_LICENSE_KEY
=
-
3
;
const
ERROR_INVALID_LICENSE_STRUCTURE
=
-
4
;
const
ERROR_TIMESTAMP_INVALID
=
-
5
;
const
ERROR_LICENSE_CHECK_EXCEPTION
=
-
6
;
/**
* Earliest TYPO3 Version that we support
*/
const
EARLIEST_SUPPORTED_VERSION
=
8000000
;
/**
* Last response code from server
*
* @var int
*/
protected
static
$lastHttpResponseCode
=
0
;
/**
* The last exception from the server
*
* @var string
*/
protected
static
$lastException
=
''
;
/**
* The validUntil timestamp
*
* @var null|int
*/
protected
static
$validUntil
;
/**
* Check the license key once per how many days
*/
const
AMOUNT_OF_DAYS_UNTIL_NEXT_CHECK
=
1
;
/**
* Show a warning if the license has expired but we are still in the same version once per how many days
*/
const
AMOUNT_OF_DAYS_UNTIL_WARNING
=
30
;
/**
* License server credentials
*/
const
API_USER
=
'license_check'
;
const
API_PASSWORD
=
'lGKLiHc5We6gBqsggVlwdLNoWv9CEKnWiy7cgMUO'
;
const
API_URL
=
'https://shop.sgalinski.de/api/license'
;
/**
* The current extension version
*/
const
CURRENT_VERSION
=
'5.0'
;
/**
* @var array
*/
private
static
$versionToReleaseTimestamp
=
[
'1.0'
=>
1489067959
,
// 2017-03-09T13:59:19Z
'1.1'
=>
1498747343
,
// 2017-06-29T14:42:23Z
'2.0'
=>
1504800293
,
// 2017-09-07T16:04:53Z
'2.1'
=>
1508256404
,
// 2017-10-17T16:06:44Z
'2.2'
=>
1522765553
,
// 2018-04-03T14:25:53Z
'2.3'
=>
1524846409
,
// 2018-04-27T16:26:49Z
'3.0'
=>
1550247265
,
// 2019-02-15T16:14:25Z
'3.1'
=>
1553179645
,
// 2019-03-21T14:47:25Z
'4.0'
=>
1597422494
,
// 2020-08-14T16:28:14Z
'4.1'
=>
1613577836
,
// 2021-02-17T16:03:56Z
'4.2'
=>
1626183803
,
// 2021-02-17T16:03:56Z
'5.0'
=>
1628865891
,
// 2021-08-13T17:45:56Z
];
/**
* @param mixed $validUntil A timestamp, which says the lifetime of this key.
* @return boolean True, if the timestamp is invalid.
*/
public
static
function
isTimestampInvalid
(
$validUntil
)
{
if
(
$validUntil
<
0
)
{
return
TRUE
;
}
$releaseTimestampOfCurrentVersion
=
self
::
$versionToReleaseTimestamp
[
self
::
CURRENT_VERSION
];
if
(
$releaseTimestampOfCurrentVersion
===
NULL
||
$validUntil
<
$releaseTimestampOfCurrentVersion
)
{
return
TRUE
;
}
self
::
$validUntil
=
$validUntil
;
return
FALSE
;
}
/**
* Should we perform the license check for this key and in this version at this point of time
*
* @param string $licenseKey
* @return bool
*/
public
static
function
shouldCheckKey
(
$licenseKey
)
{
if
(
$licenseKey
!==
self
::
getLastKey
())
{
return
TRUE
;
}
if
(
self
::
getLicenseCheckedInVersion
()
!==
self
::
CURRENT_VERSION
)
{
return
TRUE
;
}
// the license was valid last time we checked, but it has expired and we haven't done another check since it expired
// let's make sure we don't have the wrong state in this case
$licenseExpirationDate
=
self
::
getValidLicenseUntilTimestamp
();
/** @noinspection NotOptimalIfConditionsInspection */
return
self
::
getValidLicense
()
&&
$licenseExpirationDate
<
$GLOBALS
[
'EXEC_TIME'
]
&&
$licenseExpirationDate
>=
self
::
getLastLicenseCheckTimestamp
();
}
/**
* Returns the license key that has been set
*
* @return string
*/
public
static
function
getLicenseKey
()
{
return
(
string
)
ExtensionSettingsService
::
getSetting
(
ExtensionSettingsService
::
SETTING_LICENSE
);
}
/**
* Checks whether the system has a valid license
*
* @return bool
*/
public
static
function
hasValidLicense
()
{
$licenseKey
=
self
::
getLicenseKey
();
if
(
!
self
::
shouldCheckKey
(
$licenseKey
))
{
return
self
::
getValidLicense
();
}
self
::
clearRegistryValues
();
if
(
!
self
::
isLicenseServerReachable
())
{
return
TRUE
;
}
if
(
!
self
::
isLicenseValid
(
$licenseKey
))
{
self
::
setLastKey
(
$licenseKey
);
self
::
setValidLicense
(
FALSE
);
self
::
setLicenseCheckedInVersion
(
self
::
CURRENT_VERSION
);
self
::
setValidLicenseUntilTimestamp
(
0
);
self
::
setLastLicenseCheckTimestamp
();
}
else
{
self
::
setValidLicenseUntilTimestamp
(
self
::
getValidUntil
());
self
::
setValidLicense
(
TRUE
);
self
::
setLastKey
(
$licenseKey
);
self
::
setLicenseCheckedInVersion
(
self
::
CURRENT_VERSION
);
self
::
setLastLicenseCheckTimestamp
();
return
TRUE
;
}
return
FALSE
;
}
/**
* Sets the last key checked for from the registry
*
* @param string $licenseKey
*/
protected
static
function
setLastKey
(
$licenseKey
)
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_LICENSE_KEY_CHECKED_KEY
,
$licenseKey
);
}
/**
* Gets the last key checked for from the registry
*
* @return mixed|null
*/
public
static
function
getLastKey
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_LICENSE_KEY_CHECKED_KEY
);
}
/**
* Sets if the license is valid in the registry
*
* @param bool $isValid
*/
protected
static
function
setValidLicense
(
$isValid
)
{
$isValid
=
(
bool
)
$isValid
;
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
IS_KEY_VALID_KEY
,
$isValid
);
}
/**
* Gets the isValid from the registry
*
* @return bool
*/
protected
static
function
getValidLicense
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
(
bool
)
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
IS_KEY_VALID_KEY
);
}
/**
* Stores the last warning timestamp
*
* @param int $timestamp
*/
protected
static
function
setLastWarningTimestamp
(
$timestamp
)
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_WARNING_TIMESTAMP_KEY
,
$timestamp
);
}
/**
* Gets the last warning timestamp
*
* @return mixed|null
*/
protected
static
function
getLastWarningTimestamp
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_WARNING_TIMESTAMP_KEY
);
}
/**
* Stores the valid until timestamp in the registry
*
* @param mixed $validUntil
*/
protected
static
function
setValidLicenseUntilTimestamp
(
$validUntil
)
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
HAS_VALID_LICENSE_UNTIL_TIMESTAMP_KEY
,
$validUntil
);
}
/**
* Gets the valid until timestamp from the registry
*
* @return mixed|null
*/
protected
static
function
getValidLicenseUntilTimestamp
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
HAS_VALID_LICENSE_UNTIL_TIMESTAMP_KEY
);
}
/**
* Sets the version that the license was last valid for
*
* @param string $version
*/
protected
static
function
setLicenseCheckedInVersion
(
$version
)
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
LICENSE_CHECKED_IN_VERSION_KEY
,
$version
);
}
/**
* Gets the version that the license was last valid for
*
* @return mixed|null
*/
protected
static
function
getLicenseCheckedInVersion
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
LICENSE_CHECKED_IN_VERSION_KEY
);
}
/**
* Sets the timestamp of the last check in the registry
*/
protected
static
function
setLastLicenseCheckTimestamp
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_CHECKED_TIMESTAMP_KEY
,
$GLOBALS
[
'EXEC_TIME'
]);
}
/**
* Gets the timestamp of the last check from the registry
*
* @return mixed|null
*/
public
static
function
getLastLicenseCheckTimestamp
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_CHECKED_TIMESTAMP_KEY
);
}
/**
* Sets the timestamp of the last AJAX Notification check in the registry
*/
public
static
function
setLastAjaxNotificationCheckTimestamp
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
set
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_AJAX_TIMESTAMP_KEY
,
$GLOBALS
[
'EXEC_TIME'
]);
}
/**
* Gets the timestamp of the last AJAX Notification check from the registry
*
* @return mixed|null
*/
protected
static
function
getLastAjaxNotificationCheckTimestamp
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
return
$registry
->
get
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_AJAX_TIMESTAMP_KEY
);
}
/**
* Clears the registry values
*/
protected
static
function
clearRegistryValues
()
{
$registry
=
GeneralUtility
::
makeInstance
(
Registry
::
class
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_CHECKED_TIMESTAMP_KEY
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
HAS_VALID_LICENSE_UNTIL_TIMESTAMP_KEY
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
LICENSE_CHECKED_IN_VERSION_KEY
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
IS_KEY_VALID_KEY
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_LICENSE_KEY_CHECKED_KEY
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_WARNING_TIMESTAMP_KEY
);
$registry
->
remove
(
self
::
REGISTRY_NAMESPACE
,
self
::
LAST_AJAX_TIMESTAMP_KEY
);
}
/**
* Gets the validUntil date from this current check
*
* @return mixed
*/
public
static
function
getValidUntil
()
{
if
(
self
::
$validUntil
===
NULL
)
{
self
::
$validUntil
=
self
::
getValidLicenseUntilTimestamp
();
}
return
self
::
$validUntil
;
}
/**
* The timestamp of the key lifetime, if the given license key is valid, or -1 if invalid.
*
* @param string $licenseKey A license key, which should be validated.
* @return
*/
public
static
function
isLicenseValid
(
$licenseKey
)
{
if
(
!
self
::
checkLicenseKeyStructure
(
$licenseKey
))
{
return
self
::
ERROR_INVALID_LICENSE_STRUCTURE
;
}
$validUntil
=
self
::
getValidUntilTimestampByLicenseKey
(
$licenseKey
);
return
!
self
::
isTimestampInvalid
(
$validUntil
);
}
/**
* Check if the given license key is valid.
*
* @param string $licenseKey A license key, which should be validated.
* @return boolean
*/
public
static
function
checkLicenseKeyStructure
(
$licenseKey
)
{
// Structure: XXXXXX-XXXXXX-XXXXXX-XXXXXX | All upper case
if
(
substr_count
(
$licenseKey
,
'-'
)
!==
3
)
{
return
FALSE
;
}
$caseControl
=
strtoupper
(
$licenseKey
);
return
$licenseKey
===
$caseControl
&&
strlen
(
$licenseKey
)
===
27
;
}
/**
* True, if the license server is reachable.
*
* @return boolean
*/
public
static
function
isLicenseServerReachable
()
{
try
{
$requestFactory
=
GeneralUtility
::
makeInstance
(
RequestFactory
::
class
);
$response
=
$requestFactory
->
request
(
self
::
API_URL
,
'GET'
,
[
'auth'
=>
[
self
::
API_USER
,
self
::
API_PASSWORD
],
'timeout'
=>
1
,
'connect_timeout'
=>
1
,
]
);
self
::
$lastHttpResponseCode
=
(
int
)
$response
->
getStatusCode
();
if
(
self
::
$lastHttpResponseCode
!==
200
&&
self
::
$lastHttpResponseCode
!==
201
)
{
return
FALSE
;
}
}
catch
(
\Exception
$exception
)
{
return
FALSE
;
}
return
TRUE
;
}
/**
* Returns The timestamp of the key lifetime, if the given license key is valid, on the server, or -1 if invalid.
*
* @param string $licenseKey
* @return int
*/
private
static
function
getValidUntilTimestampByLicenseKey
(
$licenseKey
)
{
try
{
$url
=
self
::
API_URL
.
'/'
.
urldecode
(
$licenseKey
)
.
'?product='
.
self
::
PRODUCT_KEY
;
$requestFactory
=
GeneralUtility
::
makeInstance
(
RequestFactory
::
class
);
$response
=
$requestFactory
->
request
(
$url
,
'GET'
,
[
'auth'
=>
[
self
::
API_USER
,
self
::
API_PASSWORD
],
'timeout'
=>
1
,
'connect_timeout'
=>
1
,
]
);
self
::
$lastHttpResponseCode
=
(
int
)
$response
->
getStatusCode
();
if
(
self
::
$lastHttpResponseCode
!==
200
&&
self
::
$lastHttpResponseCode
!==
201
)
{
return
self
::
ERROR_INVALID_RESPONSE_CODE
;
}
if
(
!
$response
->
getBody
())
{
return
self
::
ERROR_INVALID_RESPONSE_DATA
;
}
$jsonData
=
json_decode
(
$response
->
getBody
(),
TRUE
);
if
(
!
$jsonData
[
'serial'
][
'valid'
])
{
return
self
::
ERROR_INVALID_LICENSE_KEY
;
}
return
(
int
)
$jsonData
[
'serial'
][
'validUntil'
];
}
catch
(
\Exception
$exception
)
{
self
::
$lastException
=
$exception
->
getMessage
();
}
return
self
::
ERROR_LICENSE_CHECK_EXCEPTION
;
}
/**
* Checks whether we are in development context
*
* @return bool
*/
public
static
function
isInDevelopmentContext
()
{
$versionNumber
=
VersionNumberUtility
::
convertVersionNumberToInteger
(
TYPO3_version
);
if
(
$versionNumber
>=
9000000
)
{
// Since TYPO3 9LTS
$context
=
\TYPO3\CMS\Core\Core\Environment
::
getContext
();
}
else
{
// Prior to TYPO3 9LTS
$context
=
\TYPO3\CMS\Core\Utility\GeneralUtility
::
getApplicationContext
();
}
return
$context
->
isDevelopment
();
}
/**
* Checks if the current TYPO3 version is supported for the license check
*
* @return bool
*/
public
static
function
isTYPO3VersionSupported
()
{
$versionNumber
=
VersionNumberUtility
::
convertVersionNumberToInteger
(
TYPO3_version
);
return
$versionNumber
>=
self
::
EARLIEST_SUPPORTED_VERSION
;
}
/**
* Checks if the time for the next check has expired.
* error = 0 means no error
* error = 1 is an error
* error = 2 is a warning
*
* @return bool
*/
public
static
function
isTimeForNextCheck
()
{
return
self
::
getLastAjaxNotificationCheckTimestamp
()
+
self
::
AMOUNT_OF_DAYS_UNTIL_NEXT_CHECK
*
24
*
60
*
60
<
$GLOBALS
[
'EXEC_TIME'
];
}
/**
* Performs the license check and returns the output data to the frontend
*
* @param bool $isAjaxCheck
* @return array
*/
public
static
function
getLicenseCheckResponseData
(
$isAjaxCheck
=
false
)
{
// if the key is empty - error
if
(
!
self
::
getLicenseKey
())
{
return
[
'error'
=>
1
,
'title'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.error.title'
,
'sg_routes'
),
'message'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.noLicenseKey'
,
'sg_routes'
,
[
LocalizationUtility
::
translate
(
'backend.licenceCheck.shopLink'
,
'sg_routes'
)
]
)
];
}
// if not valid - error
if
(
!
self
::
hasValidLicense
())
{
return
[
'error'
=>
1
,
'title'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.error.title'
,
'sg_routes'
),
'message'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.expiredError.message'
,
'sg_routes'
,
[
LocalizationUtility
::
translate
(
'backend.licenceCheck.shopLink'
,
'sg_routes'
)
]
)
];
}
// if it's valid - check validUntil and throw a warning if the license has expired but you are still
// on the valid version
if
(
self
::
getValidUntil
()
<
$GLOBALS
[
'EXEC_TIME'
])
{
$date
=
date
(
'd.m.Y'
,
self
::
getValidUntil
());
if
(
$isAjaxCheck
)
{
$lastWarningTimestamp
=
(
int
)
self
::
getLastWarningTimestamp
();
// relevant only for the AJAX notifications
}
if
(
!
$isAjaxCheck
||
(
$lastWarningTimestamp
+
self
::
AMOUNT_OF_DAYS_UNTIL_WARNING
*
24
*
60
*
60
<
$GLOBALS
[
'EXEC_TIME'
]))
{
if
(
$isAjaxCheck
)
{
self
::
setLastWarningTimestamp
(
$GLOBALS
[
'EXEC_TIME'
]);
}
return
[
'error'
=>
2
,
'title'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.warning.title'
,
'sg_routes'
),
'message'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.expiringWarning.message'
,
'sg_routes'
,
[
$date
,
LocalizationUtility
::
translate
(
'backend.licenceCheck.shopLink'
,
'sg_routes'
)
]
)
];
}
}
/** @noinspection SuspiciousAssignmentsInspection */
$date
=
date
(
'd.m.Y'
,
self
::
getValidUntil
());
// 19.01.2038 == lifetime license
if
(
$date
===
'19.01.2038'
)
{
$date
=
LocalizationUtility
::
translate
(
'backend.licenceCheck.status.lifetime'
,
'sg_routes'
);
}
return
[
'error'
=>
0
,
'title'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.status.title'
,
'sg_routes'
),
'message'
=>
LocalizationUtility
::
translate
(
'backend.licenceCheck.status.okMessage'
,
'sg_routes'
,
[
$date
]
)
];
}
}
Loading