Commit graph

416 commits

Author SHA1 Message Date
Benjamin Renard
d27a59f807 Add LSobject import/export API methods 2021-02-08 12:42:00 +01:00
Benjamin Renard
82a236a67c LSattr_ldap_password: fix verify method for Salted SHA2 passwords 2021-02-08 11:11:23 +01:00
Benjamin Renard
f47e40a5ac LSio: fix isSubmit() method to handle GET or POST forms 2021-02-05 18:39:24 +01:00
Benjamin Renard
1e284f098a Regroup LSimport & LSexport classes in one common LSio class 2021-02-05 18:37:07 +01:00
Benjamin Renard
f36c989136 Add import & export CLI commands 2021-02-05 18:12:44 +01:00
Benjamin Renard
b8040e3d8b LSformElement::select: fix typo in last commit 2021-02-05 16:41:10 +01:00
Benjamin Renard
19dd343106 LSformElement::getApiValue(): add $details parameter
This parameter permit to control if the returned value contain or not 
details. By default (no details), the value used the format as accept by 
create/modify method. The details mode is more efficient to display the 
value.
2021-02-05 12:22:44 +01:00
Benjamin Renard
5f4798a5a1 Add export feature using existing LSioFormats 2021-02-05 12:18:26 +01:00
Benjamin Renard
7ecfa33afc import: fix some PHP warnings and update comments 2021-02-04 12:35:14 +01:00
Benjamin Renard
7af066f4c2 LSimport: code cleaning and reload form options after submiting 2021-02-04 11:52:26 +01:00
Benjamin Renard
a25b1e8c10 LSldapObject: clean updata/validate form data code to fix handling just check mode 2021-02-04 11:49:35 +01:00
Benjamin Renard
e05f0df20d Fix PHP warning 2021-02-04 10:33:13 +01:00
Benjamin Renard
16373e6904 Fix content-type on Ajax return 2021-02-04 10:22:10 +01:00
Benjamin Renard
724e9acedd Fix PHP5 error compatibility in last commit 2021-02-03 14:46:06 +01:00
Benjamin Renard
0ec390e1fe Add API feature
Some major changes have been made to handle this new feature :
- LSsession now have a flag about API mode. The displayTemplate() and
  displayAjaxReturn() methods have been adjust to correctly handle this
  mode.
- LSauth system have been adjust to handle a custom API mode :
  - LSauthMethod can support or not this mode : the $api_mode_supported
    permit to defined if supported (default, false). Currently, only
    HTTP (default in API mode) and annonymous mode support it.
  - An api_access parameter permit to configure witch type of user
    LSobject types could use the API. This flag must be set to True to
    allow a type of LSobject (default: False). In a same way, a
    web_access parameter now permit to disable Web access for some
    types of users (but this parameter is optional and its default value
    is True).
  - The HTTP method is the privileged first method for API mode. In this
    mode, if auth data aren't present in environment, it will request it
    by triggered a 403 HTTP error. Realm can be configured with new
    LSAUTHMETHOD_HTTP_API_REALM constant.
- The LStemplate system handle API mode to correctly react on errors: it
  return a JSON answer instead of HTML page. Error pages also now return
  adjusted HTTP code (404 or 500).
- The LSurl system have been adjust to handle API mode :
  - On declaring handlers, we could now specify if it's an API view with
    new $api_mode paremeter of add_handler() method
  - The LSurlRequest object have a new attribute to check if it's an API
    request
  - The error_404() method handle the API mode to return JSON answer.
    Furthermore, if no handlers matched with the requested URL, API mode
    is automatically enabled if the requested URL starts with 'api/'.
- LSform implement it own API mode flag and a new submited flag that
  be toggle via the new setSubmited() method. Some major changes also
  occured on LSformElement classes to specifically handle API
  input/output for each types of attributes:
  - a new getApiValue() method permit to retrieve the API value of the
    attribute (on show API view)
  - the getPostData() method now have to correctly handle API input for
    the attribute (on create/modify API views). A programmatic way have
    been adopted for each types of attributes.
- The LSimport and LScli create/modify commands also evolved to enable
  API mode of the LSform. This permit to take advantage of the new
  capability of LSform/LSformElement to handle input values with a
  programmatic way.
- New routes have been add to handle API views. All this new routes
  start with 'api/1.0/' and use the same URL schema as the web UI. The
  API currently permit to search/show/add/modify/remove LSobjects and
  manages their relations.
2021-02-03 14:40:28 +01:00
Benjamin Renard
e92bc10c8b LSldapObject: fix default $attrValues handling for updateObjectsInRelation/deleteOneObjectInRelation methods 2021-02-03 14:19:37 +01:00
Benjamin Renard
305d7447ff LSsession: Fix relationCanAccess() method and add debuging infos 2021-02-03 12:44:38 +01:00
Benjamin Renard
841b3d0bcf LSsearch::setParamsFromRequest(): add check on parameters load from request data 2021-02-02 20:42:02 +01:00
Benjamin Renard
eb8cfbf66a LSsearch: rename method setParamsFormPostData() to setParamsFromRequest() 2021-02-02 20:30:08 +01:00
Benjamin Renard
2544687b27 LSsession::checkAccess(): fix checking read right 2021-02-02 20:28:02 +01:00
Benjamin Renard
cb0106fda9 LSurlRequest: fix fatal error on logging 2021-01-29 17:12:29 +01:00
Benjamin Renard
ac7e042c2a LSattribute: add default LDAP & HTML type (ascii / text) 2021-01-29 15:59:13 +01:00
Benjamin Renard
40a17c3524 LSlang: improve generate_lang_file command
Improve detection in PHP files, add detection in LSaddons/LSauthMethod 
config files and includes PHP files. Add -I/--include-upstream parameter 
(and use it for generate_ldapsaisie_pot command)
2021-01-29 15:23:22 +01:00
Benjamin Renard
bc9cc77cde LSattr_ldap::shadowExpire: fix to rounding method to avoid date change 2021-01-29 12:30:59 +01:00
Benjamin Renard
29e499e1d6 LSldapObject::submitChange(): fix error renaming LSobject
Old RDN value was keep and block the update ot the other changed 
attributes.
2021-01-28 16:59:42 +01:00
Benjamin Renard
fadfe2d2ba LSldapObject::validateAttrData(): fix fatal errors on missing formated log messages 2021-01-28 16:57:51 +01:00
Benjamin Renard
9680f8a18e LSform: fix displaying error in form in case of global error 2021-01-18 15:04:14 +01:00
Benjamin Renard
957777d44f LSldapObject::validateAttrData(): fix checking LDAP validation result 2021-01-18 15:03:26 +01:00
Benjamin Renard
7ef6e57c49 LSldapObject::submitChange(): code cleaning 2020-12-22 19:46:57 +01:00
Benjamin Renard
a353ca5c37 LSldapObject::submitChange(): Add security check about isNew() return 2020-12-22 19:45:35 +01:00
Benjamin Renard
06b8fddc51 LSldapObject::validateAttrData(): check return type of LSldap::getNumberResult() 2020-12-22 19:44:51 +01:00
Benjamin Renard
89ecbb8a5c LSldap: fix search & getNumberResult methods to use basedn from configuration instead of empty one. 2020-12-22 19:43:50 +01:00
Benjamin Renard
14352da6bd LSformElement::jsonCompositeAttribute: Fix PHP warning 2020-12-22 19:32:14 +01:00
Benjamin Renard
514a2eb0fd Code cleaning 2020-12-22 18:42:56 +01:00
Benjamin Renard
7535530416 LSformRule: do not defined validate_one_by_one constant visibility
To keep compatibility with PHP < 7.1.
2020-12-22 18:05:28 +01:00
Benjamin Renard
43d2620f8e CLI search: add JSON output (with -j|--json parameters)
Futhermore, --pretty parameter also permit to prettify the JSON 
output.
2020-12-22 11:01:38 +01:00
Benjamin Renard
1c13aa7cdd CLI search: add --all parameter to permit to disable pagination 2020-12-22 11:00:49 +01:00
Benjamin Renard
f6f2e352bc CLI show: add JSON output (with -j|--json parameters)
Futhermore, -p|--pretty parameter also permit to prettify the JSON 
output.
2020-12-22 10:31:23 +01:00
Benjamin Renard
d39bba45fb CLI show: fix handling --raw-values parameter 2020-12-22 10:27:22 +01:00
Benjamin Renard
1428b5df62 LSattr_ldap::pwdHistory: fix fatal error on time encoding. 2020-12-21 14:54:37 +01:00
Benjamin Renard
114e3c48ac LSformRule: add validate_values() method and use it to value rules
Also add validate_one_by_one class constant to allow to handle 
validation on all values together instead of one-by-one.
2020-12-21 14:53:36 +01:00
Benjamin Renard
089693ea0e Fix/improve LSsession_13 errors (unconfigured/unknown custom action function) 2020-12-16 17:42:55 +01:00
Benjamin Renard
0f0bff5a77 LSldapObject::submitChange(): on new object, check if generated DN is not already affected 2020-12-14 19:42:19 +01:00
Benjamin Renard
ab922356c0 LSsession :: loadLSprofilesLSobjects(): fix a PHP warning 2020-12-14 19:37:13 +01:00
Benjamin Renard
a49cf4ba0c LSldapObject: fix/improve validateAttrData() 2020-12-14 19:36:21 +01:00
Benjamin Renard
8b292f538d LSconfig :: get(): add array casting (using ensureIsArray()) 2020-12-14 19:35:03 +01:00
Benjamin Renard
2abc369c73 LSformElement::labeledValue: fix label translation on freeze view 2020-12-10 17:21:21 +01:00
Benjamin Renard
f6a6c226f4 LSattribute: fix handling default_value in generateValue() 2020-12-02 20:17:18 +01:00
Benjamin Renard
852b375964 LSattribute: fix canBeGenerated() when default_value isn't a string 2020-12-02 19:53:29 +01:00
Benjamin Renard
1da0693138 LSaddon::samba: fix PHP warning about LS_SAMBA_UNIX_ID_POOL_DN contant 2020-12-02 19:49:37 +01:00
Benjamin Renard
a7ab192274 Add LSldap_attr::pwdHistory 2020-12-02 18:12:00 +01:00
Benjamin Renard
c6501d479b LSattr_html::jsonCompositeAttribute: Add fullWidth parameter and improve responsive display 2020-12-02 17:43:55 +01:00
Benjamin Renard
2161cc701a LSattr_ldap::compositeValueToJSON: use static instead of self keyword
Use static instead of self keyword to use static method. This permit to 
easily override this class.
2020-12-02 16:37:41 +01:00
Benjamin Renard
bc462c07b6 Add some debugging/trace messages 2020-12-01 16:48:07 +01:00
Benjamin Renard
597054acad LSattr_ldap::shadowExpire: fix getUpdateData()
Fix to return a correctly rounded value as string.
2020-12-01 16:43:31 +01:00
Benjamin Renard
42dd0aa728 LSformElement :: date: fix getPostData() method 2020-12-01 16:42:20 +01:00
Benjamin Renard
3c75ef482e Remove historic read right on all attributes of the hard-coded "admin" LSprofile 2020-12-01 16:40:21 +01:00
Benjamin Renard
4e8a6db06b LSaddon::posix: fix generate_shadowLastChange()
Just return a timestamp because its designed to be used with 
LSattr_ldap_shadowExpire that will handled the division by 86400.
2020-12-01 16:37:01 +01:00
Benjamin Renard
0addf22c2e LSldapObject :: _updateData(): make method protected instead of private
This change allow this method usage from children classes to allow 
custom relation implementations.
2020-12-01 15:04:20 +01:00
Benjamin Renard
b4a5824ee8 Code cleaning 2020-11-30 19:44:14 +01:00
Benjamin Renard
106a2d9f04 Use ensureIsArray() helper to make code more readable 2020-11-30 19:43:52 +01:00
Benjamin Renard
770533b7ec Ensure attributes values are always an array in LSattribute & LSattr_ldap 2020-11-30 19:37:44 +01:00
Benjamin Renard
f7231229f5 LSsession: fix errors in changeAuthUser() and add logging messages 2020-11-30 16:13:36 +01:00
Benjamin Renard
b93187f208 LSformElement::labeledValue: add translate_labels parameter and fix translating it 2020-11-25 15:46:25 +01:00
Benjamin Renard
8b996885d1 LSsession: improve loadLSaddons() method 2020-11-17 17:56:04 +01:00
Benjamin Renard
56ffbd7a71 Fix bug in last commit 2020-11-17 17:47:50 +01:00
Benjamin Renard
d5bfddf124 LSaddon::mail: Add test_send_mail CLI command 2020-11-17 11:26:06 +01:00
Benjamin Renard
6c35af3109 Fix PHP warning about undefined constant SELF (routes.php) 2020-10-08 18:08:35 +02:00
Benjamin Renard
3598e48c6e LSaddon::LSaccessRightsMatrixView: handle customActions & customSearchActions 2020-09-23 14:10:50 +02:00
Benjamin Renard
85b74feb86 LSaddon SUPANN: add supannCheckEntityCouldBeDeleted() function 2020-09-22 20:47:03 +02:00
Benjamin Renard
43cf5ccd7a LSaddon SUPANN: add support for some attributes
Add support of following attributes:
- supannCivilite:
  add supannGetCivilitePossibleValues()
- eduPersonAffiliation:
  add supannGetAffiliationPossibleValues() and
  supannCheckEduPersonAffiliation()
- supannCheckEduPersonAffiliation:
  add supannGetAffiliationPossibleValues() and
  supannCheckEduPersonPrimaryAffiliation()
- supannCheckEduPersonPrimaryAffiliation:
  add generate_eduPersonPrincipalName()
2020-09-22 18:10:05 +02:00
Benjamin Renard
de62999fea LSattr_html::select_list: add get_possible_values parameter 2020-09-22 15:04:31 +02:00
Benjamin Renard
8f407e9345 Add LSaddon::showTechInfo 2020-09-21 15:47:07 +02:00
Benjamin Renard
5315005382 LSldapObject::loadData(): explicitly list need attributes in LDAP request 2020-09-21 12:45:39 +02:00
Benjamin Renard
9edfa2b92e LSldap::getAttrs(): add $attrs and $include_internal optional parameters 2020-09-21 12:45:33 +02:00
Benjamin Renard
d6c9e358f3 LSaddon::mail: add possibility to send HTML email 2020-09-16 10:35:47 +02:00
Benjamin Renard
255817d7aa Improve POSIX support and add examples to handle this type of attributes 2020-09-11 13:54:08 +02:00
Benjamin Renard
bf482c648f LSattr_ldap::shadowExpire: fix getUpdateData() method to return string values 2020-09-11 13:40:48 +02:00
Benjamin Renard
41d816c025 LSformElement:📅 add clear btn 2020-09-11 13:38:07 +02:00
Benjamin Renard
e4ca5bbf71 LSformElement:📅 Make today btn working even if input is empty 2020-09-11 13:35:35 +02:00
Benjamin Renard
052882eb49 Fix handling "0" (zero string) value 2020-09-11 13:34:42 +02:00
Benjamin Renard
1169772c4a LSattr_html::select_list: clean code of getPossibleValues() method 2020-09-10 15:53:19 +02:00
Benjamin Renard
b8c00a8708 LSattr_html::select_box: fix double translation of labels on unfreeze field 2020-09-10 15:52:29 +02:00
Benjamin Renard
e62ddbdc19 LSformElement::image: fix error on non-AJAX form when no file is submited 2020-09-10 15:46:10 +02:00
Benjamin Renard
aeea76ab2a LSform: fix/improve handling config
Permit to fix handling ajaxSubmit form.
2020-09-10 15:45:26 +02:00
Benjamin Renard
00132e32ad LSform: fix non-AJAX form submission (or form with input[type=file]) 2020-09-10 15:43:52 +02:00
Benjamin Renard
060ebf1bff Allow conversion of LSattr_ldap to string 2020-09-10 12:26:48 +02:00
Benjamin Renard
00d92d1c37 generate_lang_file CLI command: improve logging 2020-09-10 12:26:25 +02:00
Benjamin Renard
4e87ddb898 generate_lang_file CLI command: factor handling possible_values of select list&box 2020-09-10 12:09:26 +02:00
Benjamin Renard
d344c56f45 generate_lang_file CLI command: fix PHP warning 2020-09-10 12:07:04 +02:00
Benjamin Renard
be04b6becf Add warning on unknown key requested using __get methods 2020-09-10 10:38:35 +02:00
Benjamin Renard
d0d3e944ed Extend LSlog_handler using LSlog_staticLoggerClass 2020-09-10 10:26:49 +02:00
Benjamin Renard
988054bfc5 LSlog handlers: fix log TRACE enabled error (even if disabled) 2020-09-10 10:17:19 +02:00
Benjamin Renard
fd4bf4f38a Fix some PHP5 syntax errors 2020-09-09 20:11:03 +02:00
Benjamin Renard
02ad9ded1e generate_lang_file CLI command: add Q choice in interactive mode to quit 2020-09-09 20:06:43 +02:00
Benjamin Renard
63f57cfd77 LSldap: fix/improve update() and getEntry() methods 2020-09-09 19:02:32 +02:00
Benjamin Renard
a4183a88fc Improve Samba support using LSaddon::samba 2020-09-09 19:00:55 +02:00
Benjamin Renard
15941ac678 Add LSattr LDAP & HTML sambaAcctFlags type 2020-09-09 18:45:34 +02:00
Benjamin Renard
7e74853021 LSattr_html::date & LSformRule:📅 add special_values parameter 2020-09-09 18:40:44 +02:00
Benjamin Renard
cccce6edb5 LSldapObject::submitChange(): improve logging 2020-09-09 18:36:46 +02:00
Benjamin Renard
6a3fd60d3e LSformElement::getEmptyField() / LSformElement.tpl: Provide value index as $value_idx template variable 2020-09-08 18:42:54 +02:00
Benjamin Renard
df1c46eab6 Add __toString() method to all common extendable PHP classes
This permit to make context logging easier.
2020-09-08 17:29:10 +02:00
Benjamin Renard
e89d13d002 LSsearch: fix PHP warning 2020-09-08 16:36:54 +02:00
Benjamin Renard
14bccc1e17 LSrelation: check relation is correctly configured before using it
To avoid some unreal warnings in case of misconfigured relation
2020-09-03 18:59:13 +02:00
Benjamin Renard
88d8d7f026 LSrelation: fix error codes prefix 2020-09-03 18:38:08 +02:00
Benjamin Renard
9db67eb2ba LSsession: improve error messages 2020-09-03 18:31:53 +02:00
Benjamin Renard
bbaa0a99df Auto declare simple PHP class for simple LSObject type
On LSsession::loadLSobject(), if PHP class file is not found, a simple 
one will be declare.
2020-09-03 16:00:51 +02:00
Benjamin Renard
406b017023 Add method LSldapObject::isValidTypeName() and use it in LSsession::loadLSobject() 2020-09-03 15:40:59 +02:00
Benjamin Renard
4c427b26d6 Improve logging on LSobject & LSattribute triggers executions 2020-08-26 18:08:14 +02:00
Benjamin Renard
8be45249cb LSformRule :: imagesize: use self :: log_debug() instead of LSdebug() 2020-08-26 16:11:21 +02:00
Benjamin Renard
5b9e6409f4 LSform: fix call of LSformRules validate method to provide LSformElement by ref 2020-08-26 16:10:50 +02:00
Benjamin Renard
4c1c7b2fae LSldapObject->getValue(): add $first and $default parameters 2020-08-26 12:56:58 +02:00
Benjamin Renard
699631b63c LsformRule: provide reference to LSformElement instead of copied value 2020-08-26 11:45:59 +02:00
Benjamin Renard
f0ef642cf0 LScli::add_command(): fix typo in comment 2020-08-25 20:33:08 +02:00
Benjamin Renard
a8e2ecc343 Translate LSerror message at formating/diplaying time
It's permit to be sure to translate message in the right user language, 
even if its context isn't loaded at error emission time.
2020-08-25 17:31:50 +02:00
Benjamin Renard
827cf2ca7f Handle redirections of old-style URL even if user not authenticated
It's avoid to display error only after login form success.
2020-08-25 17:14:34 +02:00
Benjamin Renard
3d49092262 LSlang: fix warning about return not True 2020-08-25 11:01:28 +02:00
Benjamin Renard
75cbea9459 modify page: fix URL encode object DN in redirection URL 2020-08-25 10:55:28 +02:00
Benjamin Renard
a7d202e5ff LScli: add --trace parameter 2020-08-24 18:03:50 +02:00
Benjamin Renard
8a1eefc5e3 LSsession::loadLSprofiles(): restructuring code and improve comments and logging 2020-08-24 17:56:42 +02:00
Benjamin Renard
c4dc2a0441 LSsearch::getHash(): fix handling onlyAccessible parameter 2020-08-24 16:55:24 +02:00
Benjamin Renard
11c2e3c9d4 LSsearch: remove buggy _hash cache parameter and replace it by an hash accessible key 2020-08-24 16:54:43 +02:00
Benjamin Renard
7c8fb87c99 LSsearchEntry: remove useless $hash private property 2020-08-24 16:14:16 +02:00
Benjamin Renard
70370f99f9 LSsearch: fix/improve logging 2020-08-24 16:04:23 +02:00
Benjamin Renard
e8768d94ce LStemplate::getImagePath(): handle SVG image type/ext as prefered format 2020-08-20 18:29:19 +02:00
Benjamin Renard
b13ff9b832 LSurl::redirect: fix handling absolute URL without protocol
For instance "//localhost/phpldapadmin/")
2020-08-20 18:11:48 +02:00
Benjamin Renard
34d7e10f9a Log referer URL in case of old-style URL redirection 2020-08-19 15:35:18 +02:00
Benjamin Renard
845fdbb4d8 LSauthMethod :: authenticate(): fix PHP warning 2020-08-19 15:11:49 +02:00
Benjamin Renard
f223827157 LSsession::includeFile(): improve logging 2020-08-17 20:04:21 +02:00
Benjamin Renard
cdd6189e91 dumpFile(): add $force_download and $filename parameters 2020-08-13 16:20:34 +02:00
Benjamin Renard
848d85589b LSauthMethod_basic::authenticate(): add debug/trace messages 2020-08-07 18:27:54 +02:00
Benjamin Renard
5fcf3bbf9c LSsession: add trace messages in whoami() and canAccess methods 2020-08-07 18:19:24 +02:00
Benjamin Renard
1f1a4e16fa LSsession: add log_exception() method 2020-08-07 18:17:02 +02:00
Benjamin Renard
f234709722 LSlog: add TRACE log level 2020-08-07 18:05:50 +02:00
Benjamin Renard
42e6437966 LSsession: fix usage of self :: $topDn instead of self :: getTopDn() 2020-08-07 17:40:40 +02:00
Benjamin Renard
3ce495c2c3 LSerror: format error message at adding time
Format error message at adding time to make sure to be able to format 
it, even if the component triggered it is not loaded.
2020-08-07 16:11:32 +02:00
Benjamin Renard
6eee099bd2 LScli: fix --sub-dn autocompletion even if LDAP server not selected 2020-08-07 11:09:20 +02:00
Benjamin Renard
3dc0d7f637 LScli :: search: remove buggy --subDn parameter 2020-08-07 10:55:18 +02:00
Benjamin Renard
5bbe076e23 LScli: fix handling LDAP servers with configured subDn
In case of LDAP server with configured subDn, always select a subDn, 
even if user didn't make it with --sub-dn parameter. Futhermore, in BASH 
autocompletion, autocomplete LSobject types with only available ones in 
current subDn.
2020-08-07 10:39:41 +02:00
Benjamin Renard
d5d88d2601 LSsession : fix handling subDn in recoverPassword feature 2020-08-06 17:01:51 +02:00
Benjamin Renard
ba85e5c2fc LSerror: fix PHP error 2020-08-06 16:44:18 +02:00
Benjamin Renard
14f28a1ec0 LScli: add global --sub-dn parameter 2020-08-06 16:43:50 +02:00
Benjamin Renard
3dbfe18afb LSsession: add setSubDn() method 2020-08-06 16:43:35 +02:00
Benjamin Renard
1420439403 LScli: fix autocomplete_LSobject_types() in case of configured subDn 2020-08-06 15:11:41 +02:00
Benjamin Renard
712d18b09f LSsession: fix/improve methods & doc about global preference parameters 2020-08-06 13:48:43 +02:00
Benjamin Renard
626e0d854c Fix subDn form style 2020-08-06 13:20:49 +02:00
Benjamin Renard
36ecea5174 Typo 2020-08-04 10:31:02 +02:00
Benjamin Renard
669d679464 LSformElement :: boolean: fix translation of default labels 2020-08-04 10:30:49 +02:00
Benjamin Renard
f9ebf06a63 LSview: Fix validated URL generation 2020-07-28 12:40:46 +02:00
Benjamin Renard
7eac609bd9 LSformElement JS : fire change event on input field cleared 2020-07-24 11:16:22 +02:00