Commit graph

180 commits

Author SHA1 Message Date
Amir Sarabadani
4bb2886562 Reorg: Migrate WikiMap to WikiMap/ out of includes
And WikiReference

Bug: T321882
Change-Id: I60cf4b9ef02b9d58118caa39172677ddfe03d787
2023-02-27 05:19:46 +01:00
Gergő Tisza
1c53f5902e psysh: Dump selected log channels
* Extend ConsoleLogger to support filtering by log level and
  forwarding to another logger.
* Extend ConsoleSpi to support filtering by channel/level and
  forwarding to another provider.
* Allow configuring which channels shell.php should log to STDERR
  and at what levels.
* Deprecate shell.php -d, use more meaningful parameter names.
* Change logging behavior so that logging to STDERR doesn't
  prevent normal logging, which seemed like confusing behavior
  (either we should always disable normal logging for shell.php
  or never, it shouldn't depend on whether we log to console).
  Keep old behavior for -d, just in case.

Change-Id: I5d29c95995bf83784c96dd40df9c96e22b9ec73e
2023-02-09 11:35:59 +00:00
Timo Tijhof
4ef0891994 rdbms: Consolidate logger channels into one
Notable changes:

* In SqlBagOStuff::getConnectionFromServerInfo, only two loggers were
  injected. The rest implicitly got a NullLogger due to being absent.
  These are now effectively unsilenced.

* Database::__construct() required almost all parameters, even the
  loggers. I've wanted to move some of DatabaseFactory into the ctor
  here for a while. In order to make this change not a breaking
  change, the new 'logger' parameter is optional with NullLogger as
  default. This allowed some of the test cases, which were simply
  passing NullLogger, to be fixed by passing nothing instead of
  passing the new option name.

  The Database class is behind a dozen layers of indirection for
  real use, so this will still be injected just fine (DBF, LB, LBF,
  MWLBF, etc.).

* In LegacyLogger, the handling for $wgDBerrorLog was previously
  limited to DBConnection and DBQuery. This now includes errors
  from other (generally, newer) parts of Rdbms as well, which were
  previously missing.

  This only affects sites (typically CI and dev setup) where
  $wgDBerrorLog is used, as opposed to the more common
  $wgDebugLogGroups by-channel configuration.

* TransactionProfiler gets its logger injected in a rather odd way,
  via entrypoints (MediaWiki.php, ApiMain.php, and MaintenanceRunner)
  as opposed to service wiring. This is kept as-is for now.

* In LBFactoryTest, in particular testInvalidSelectDBIndependent2,
  there are cases that intentionally produce failures of which
  the result is then observed. In CI we assert that dberror.log is
  empty so instead of adding the missing logger fields to that
  LBFactory instance, the only one set (replLogger) is removed.
  The alternative is to set 'logger' now, which would naturally
  cause CI failures due to unexpected entries coming through to
  non-mocked error log.

Bug: T320873
Change-Id: I7ca996618e41b93f488cb5c4de82000bb36e0dd3
2023-01-03 22:46:38 +00:00
Umherirrender
45e6a2b0f9 Use str_starts_with/str_ends_with/str_contains
Use the new function in conditions to avoid creating substrings or to
search the whole string

Change-Id: Ibad6b1b447a4f62cceb34359231f88ebb967a90b
2022-12-12 19:54:24 +01:00
Reedy
0cb2c3c106 Fix casing of class and function name usages
Bug: T253628
Change-Id: I5c64f436d3cf757390b751ce3e34bfc7872bc176
2022-12-04 19:09:30 +00:00
Tim Starling
7b3e7c017a Respond to some messages from Phan on PHP 8.1
* ForkController, OrderedStreamingForkController: indeed pcntl_fork()
  can't return false.
* RL\Image: Specify type instead of using suppression, since the issue
  name changes.
* VueComponentParser: Accept complaint about nullable nodeValue.
* Disable PHP 8.0 polyfill stubs when running on PHP 8.0+ to avoid
  duplicate interface errors.
* Add Socket stub and use it in LegacyHandler instead of multiple
  existing suppressions.
* MemcachedPeclBagOStuff: accept complaint recommending !$result over
  $result === false when the type is boolean.
* MemcachedPeclBagOStuff: fix probable bug, ignoring errors from
  Memcached::getMulti(). Phan noticed that $res=false was unreachable,
  but it should probably be reachable.
* DatabaseMysqli: accept complaint that $this->conn->errno is already
  known to be an int. It was probably a hack for some previous version
  of Phan.
* BcryptPassword, MWOldPassword, MWSaltedPassword: accept complaint that
  the !is_string() checks are unnecessary, after code review of PHP.
* Pbkdf2PasswordUsingHashExtension: note that contrary to Phan's
  suggestion, this check is necessary.
* DefaultPreferencesFactory: remove an existing hack for
  array_diff_key(), no longer necessary on 7.4 and causes an error on
  8.1. Use coalesce instead of cast for the remaining
  array_intersect_key() hack since it better shows that we are casting
  away null.
* FullSearchResultWidget: fix likely bug involving strict comparison
  between a float and an int.
* SpecialWatchlist: accept complaint that $selectedHours is
  unconditionally a float, being the return value of round(), and thus
  the cast is unnecessary.
* Add stub for AllowDynamicProperties, resolving an error in User.php.
* Xml: accept complaint that $encMonth is already known to be an int.

Six errors remain. These need suppressions or otherwise conflict with
PHP 7.4 support.

Bug: T322278
Change-Id: Ie375bbc8ccf22330b9a169e8da98f2bbe26ec8b9
2022-11-03 16:25:43 +11:00
Zabe
f6b9381d7f Revert "Reorg: Move some of request related classes to MediaWiki/Request"
This reverts commit 2bdc0b2b72.

Reason for revert: T166010#8349431

Bug: T166010
Change-Id: Idcd3025647aec99532f5d69b9c1718c531761283
2022-10-27 13:14:16 +00:00
Amir Sarabadani
2bdc0b2b72 Reorg: Move some of request related classes to MediaWiki/Request
Moving:
 - DerivativeRequest
 - FauxRequest
 - FauxRequestUpload
 - PathRouter
 - WebRequest
 - WebRequestUpload

Bug: T166010
Change-Id: I5ea70120d745f2876ae31d039f3f8a51e49e9ad8
2022-10-26 16:49:10 +02:00
jenkins-bot
67361d6f04 Merge "Revision: Log traces as 'exception.trace' instead of 'trace'" 2022-05-13 19:49:18 +00:00
Matěj Suchánek
e47c441078 Fix many typos in comments
Found using IntelliJ's "Typo" code inspection.

Change-Id: I746220ebe6e1e39f6cb503390ec9053e6518cf16
2022-05-10 12:46:11 +00:00
Timo Tijhof
8ffee67611 Revision: Log traces as 'exception.trace' instead of 'trace'
Various in RevisionStore did this already, but we forgot a few.

Bug: T233342
Change-Id: Ib678868b239bcd4ff4ae62b2ab47022b5a70e8be
2022-04-13 22:18:50 +00:00
Timo Tijhof
1b218b2b54 debug: Fix $wgDebugRawPage to work with PSR-3 debug logging
The benefit of this setting was largely lost due to wfDebug() having
been replaced with calls to Logger->debug() for much of our code.

This is motivated by making ResourcLoader debug=2 able to make
its concurrent load.php requests more quickly during local dev.

This effectively reverts T49960. I was wrong there, thinking that
this variable has no reason for being. The vast majority of the time,
these aren't of interest on subresource requests. It's trivial
to enable when wanted, and any non-debug level messages still come
through either way, including PHP runtime errors, exceptions,
warnings, etc.

This seems to make load.php about 50% faster for local development
when using mediawiki-docker.
I used `ab` to perform a load.php request 300 times. The mean was
320-360ms before this patch (with and without DebugRawPage=false),
and around 120-140ms with patch (with DebugRawPage=false, default).

Bug: T85805
Bug: T225730
Change-Id: I061419adebf43e83cd0103bdb9b7a3296a2a1122
2022-04-13 00:29:40 +00:00
jenkins-bot
ecda9ff29d Merge "logger: Add fallback message for unknown version in LogstashFormatter" 2022-03-30 17:42:46 +00:00
Umherirrender
6803b3a012 logger: Add fallback message for unknown version in LogstashFormatter
Ensure that $message is set when used

Found by phan (T259172)

Bug: T259172
Change-Id: I381eec29d0af4ba1c32b34140f8a850b388e4302
2022-03-30 17:24:17 +00:00
James D. Forrester
24e67e03b1 phan: Upgrade mediawiki-phan-config to 0.11.1 and set minimum_target_php_version
MediaWiki still supports PHP 7.2+, but we want to mainly test in newer versions
of PHP. Setting minimum_target_php_version to 7.2 this lets us run phan without
phan trying to get us to make PHP 7.2-incompatible changes to 'appease' PHP 8.0
or whatever later changes.

Some switches of generic 'resource' type-hinting to 'resource|object' to inform
phan to ignore this (triggering PHPCS at the time, ah well), rather than trying
to hint the specific novel PHP encapsulation classes to that have replaced them
from PHP 8.0 onwards but don't yet exist, and fixes from where we were checking
the results of implode and explode.

Bug: T293924
Change-Id: I629e3fb3adfad73beb3d424a07e643c2e079d9bb
2022-03-29 16:54:36 +00:00
Timo Tijhof
2de79774e1 Remove deprecated EventRelayerKafka and KafkaHandler
Also remove the unmaintained kafka-php package from the from "suggested"
and "dev" composer dependencies, as this is now no longer used.

Change-Id: If5668974f417b627df95bce47db18d46fa03327c
2022-03-25 00:07:22 +00:00
Timo Tijhof
3dec1399ac Deprecate EventRelayerKafka and KafkaHandler
These require use of nmred/kafka-php 0.1.0, which is from 2015.
Upstream has had one major release since then, in 2017. There have
been various commits, issues, and pull requests since but nothing
released for five years.

EventRelayer was created for use with WANObjectCache, where WMF
considered use of Kafka as one of the possible transports. This never
happened, and WANObjectCache has not supported EventRelayer since 2019,
removed with change I328eb74f21c23.

The EventRelayer abstraction itself remained unused, until it became
re-purposed for CdnCacheUpdate, which WMF now relays via EventBus.

Monolog KafkaHandler is no longer used, and was similarly created for
WMF's use case. It seems unlikely to be of interest to most third
parties. And those larger installs like WMF would likely be more
interested in SyslogHandler which is more standardised across the
industry (especially for cloud native tooling around containers).

Someone using this can continue to do this by adding a similar class
to their own code instead, possibly published as an extension.

Deprecating this in MW 1.38 (with backport) means we can remove it
shortly after in master, and no longer maintain this unused/untested
integration for which no known users exist, as well as remove our
supported suggested dependency on the unmaintained kafka-php lib.

Change-Id: I475227293ca050acead357efebce12e93a971f65
2022-03-24 18:55:39 +00:00
Umherirrender
1f71eccf63 phan: Disable null_casts_as_any_type setting
Make phan stricter about null types by setting null_casts_as_any_type to
false (the default in mediawiki-phan-config)
Remaining false positive issues are suppressed.
The suppression and the setting change can only be done together

Bug: T242536
Bug: T301991
Change-Id: I0f295382b96fb3be8037a01c10487d9d591e7e01
2022-03-21 18:25:07 +00:00
Alexander Vorwerk
9b09bf3112 Use updated ObjectFactory namespace
Depends-On: I99c5e5664d2401c36a9890f148eba7c25e6e8324
Depends-On: I48ab818b2965da14af15ef370aa83ad9455badd9
Depends-On: I018371e4b77911e56152ca7b2df734afc73f58a5
Change-Id: I04ebdb52102f6191d49a9cc70b1f98308299e72f
2022-03-09 23:04:51 +00:00
Umherirrender
b126dbe3f2 Fix various documentation related to null types
The functions returning null or the class property is set explict null

Found by phan strict checks

Change-Id: I4a271093fb6526564d8083a08249c64cb21f2453
2022-02-26 10:31:24 +01:00
Reedy
86934b2fa8 Replace some more usages of Wikimedia\(suppress|restore)Warnings()
Change-Id: I2eb133a9e32116cd155f59086245bc4d15ecbfcc
2022-02-24 20:27:46 +00:00
daniel
a5277ce87f Avoid references to DefaultSettings.
This replaces references to DefaultSettings with
references to config-schema.yaml where appropriate.

NOTE: this does not yet change Setup.php. DefaultSettings.php
remains intact and is still being used.

NOTE: this does not remove usages in the installer, see I5d8843a1062fbf
for that.

Bug: T300129
Change-Id: Ie6152cf510c3be61bc22167ca6d90dfc28910a45
2022-02-22 19:43:50 +01:00
Tim Starling
54c735354f Stop using is_resource() where possible
* Enforce the ban on is_resource in phpcs
* In OrderedStreamingForkController, the comment was incorrect. I
  confirmed using a small test script that if the child closes one end
  of a socket pair, the other end will still be open, and is_resource()
  will still return true, and fclose() will not fail. The issue was
  introduced in c82d30d19c, it was not present in the
  CirrusSearch copy of the class.
* Allow is_resource() for debug logging.
* Allow is_resource() for parameter validation where a stream may be
  passed to a function, since there is no alternative.

Bug: T260735
Change-Id: I59a752f7bb4b043ddfb2434b52a02f9221bf54db
2022-01-26 10:03:23 +11:00
Siddharth VP
b4b2a62040 Fix typos in comments (L)
Change-Id: I3deb34aec51504e09b20a367a93ebe863335be26
2022-01-09 22:54:04 +05:30
Reedy
2a2bb1e9bd Remove or replace usages of "sane"
Bug: T254646
Change-Id: I096b2cf738a1395a14f1d47bcbed0c2c686c2581
2021-11-22 13:35:17 +00:00
Umherirrender
769bdbf091 docs: Fix nullable documentation for class properties
Change-Id: I6d0577124d852103f485ffdc819876a13f6641c3
2021-09-24 00:54:53 +00:00
libraryupgrader
5357695270 build: Updating dependencies
composer:
* mediawiki/mediawiki-codesniffer: 36.0.0 → 37.0.0
  The following sniffs now pass and were enabled:
  * Generic.ControlStructures.InlineControlStructure
  * MediaWiki.PHPUnit.AssertCount.NotUsed

npm:
* svgo: 2.3.0 → 2.3.1
  * https://npmjs.com/advisories/1754 (CVE-2021-33587)

Change-Id: I2a9bbee2fecbf7259876d335f565ece4b3622426
2021-07-22 03:36:05 +00:00
Fomafix
356f1b72ef Use IEC prefixes instead of SI prefixes for byte sizes (docs+backend)
This change doesn't change any UI messages.

Bug: T54687
Change-Id: Ia62899a2a6fe8910618c35cd667291e397ddb055
2021-06-28 11:59:09 +01:00
Aaron Schulz
99d5d2e8cc rdbms: cleanup getServer() and connection parameter fields in Database
Make getServer() always return a string, as documented, even with new
Database::NEW_UNCONNECTED handles that have yet to call open(). If the
'host' parameter to __construct() is ''/null, getServer() now returns
'localhost' instead of null. This avoids problems like fatal errors in
calls to TransactionProfiler::recordConnection().

Use Database constants for "connectionParams" field keys for better
static analysis.

Also:
* Add Database::getServerName() method that returns "readable" server
  names in the style of LoadBalancer::getServerName(). Note that the
  "hostName" field is already passed in from LoadBalancer.
* Migrate most getServer() callers to getServerName() for easier
  debugging and more readable logging.
* Also, normalize Database/LoadBalancer SPI logging context to use
  "db_server" and reduce logging code duplication in LoadBalancer.

Bug: T277056
Change-Id: I00ed4049ebb45edab1ea07561c47e226a423ea3b
2021-05-05 19:44:02 +00:00
Umherirrender
e69f56fc9b build: Remove unneeded phpcs:ignore on false positives
False positives are resolved with the current release

Change-Id: I21986ec808edb341bf56abae8ee4e34e1559bc49
2021-04-29 23:50:07 +02:00
Sébastien Beyou
659cd2f3ae Do not use a NullLogger when no handler is declared
This reverts the patch I124391cc7b44 because it is no more needed with
Monolog 2.x to push a NullLogger to log nothing. This patch is a
micro-optimisation for Monolog channels where nothing is logged.

Bug: T196906
Change-Id: I1f414090a37cd4d84d37a2fca8833e3623c2983f
2021-04-06 01:51:18 +02:00
James D. Forrester
b4c6a5d629 Drop Avro format option for monolog without deprecation
Bug: T265967
Change-Id: I1b46df143b71db7cc387d3239a4a4489c1f47c96
2021-03-25 08:26:17 -07:00
Reedy
e5d91fe516 Correctly forwardport LogstashFormatter from monolog/monolog 1.25.3
Brings in code from:
https://github.com/Seldaek/monolog/blob/1.25.3/src/Monolog/Formatter/LogstashFormatter.php
https://github.com/wikimedia/mediawiki/blob/1b3bc28/includes/debug/logger/monolog/LogstashFormatter.php

Bug: T269286
Change-Id: I2e8e36579a8b6a6c52c888300f6ea2dfa19cf9db
2020-12-02 21:35:18 +00:00
Reedy
1fa599c377 Updating monolog/monolog (1.25.3 => 2.0.2)
https://github.com/Seldaek/monolog/releases/tag/2.0.2
https://github.com/Seldaek/monolog/releases/tag/2.0.1
https://github.com/Seldaek/monolog/releases/tag/2.0.0
https://github.com/Seldaek/monolog/blob/2.0.0/UPGRADE.md

https://github.com/Seldaek/monolog/compare/1.25.3...2.0.2

Import LogstashFormatter::formatV1 from monolog/monolog 1.25.3,
so that we don't change the format

Bug: T242751
Change-Id: I0198a28a5c39631d6989abf842d8a5153ccee17d
Depends-On: I31ad7dc288ceb35e042b2fef7248a0319016fbfc
2020-11-17 15:37:18 -08:00
Seb35
069c81bfe5 Empty Monolog loggers are now real blackholes and add tests
Before this commit empty Monolog loggers (or at least when no handlers are
defined) were assigned (by Monolog 1.x) the stream handler php://stderr with
the level 'debug'. This whole behaviour from MediaWiki config to Monolog is
unexpected; in the outcomes, depending on the PHP execution program, stderr
is or is not saved somewhere by default, leading to very different behaviours.

The behaviour will change in Monolog 2.x and nothing will happen is such cases
(similar hence to a NullHandler). With this commit the behaviour is uniform
accross all environments and (future) Monolog version: nothing is logged if
no handler is defined.

Precisely, a NullHandler for a given logger/MediaWiki logging channel is
defined here either when there is no key 'handlers', either when this key is
an empty array or 'false'.

Bug: T196906
Change-Id: I124391cc7b4485081980c5015431404234f40073
2020-09-20 18:11:51 +00:00
Umherirrender
61b7c9e19d Do not use @var on const
Change-Id: I4aa5bda5796121647f2802195da1e6de17e57dc9
2020-07-31 21:55:28 +02:00
daniel
e6e0ad2472 Replace "@stable for implementation" with "@stable to implement"
For compliance with the new version of the table interface policy
(T255803).

This patch was created by an automated search & replace operation
on the includes/ directory.

Bug: T257789
Change-Id: I17e5e92e24c708ffc846945a136347670a3a20c7
2020-07-13 11:05:49 +02:00
daniel
442fb30ce1 Stability annotations for interfaces.
Per the Stable Interface Policy, PHP interfaces should not be
directly implemented by extensions, unless they are marked to be safe
for that purpose.

Bug: T247862
Change-Id: Idd5783b70fc00c03d57f5b1a887f0e47c4d7b146
2020-07-07 22:01:29 +00:00
Tim Starling
da5810bda8 Don't suppress debug log lines for queries when the debug toolbar is enabled
Log lines for SQL queries were not shown in either the debug toolbar's
debug log, or in the file configured by $wgDebugLogFile. I think it is
useful to have SQL queries both in a timeline context in the debug log,
and separately in table format.

This is a very similar complaint to I8edb41aa1d8236047b80830, which
affected deprecation messages.

Change-Id: Ie0ca7bf8394d3008e3f9e950c201da1a96276fea
2020-06-02 12:24:20 +10:00
Reedy
34729dedcf Fix numerous PSR12.Properties.ConstantVisibility.NotFound
Change-Id: I9b08bde11727f47e262f5f7f422eac5585ea7fca
2020-05-11 01:59:00 +00:00
Timo Tijhof
e0ed6df864 phpunit: Add setNullLogger() and make tests default to LegacySpi
== Motivation

Mute a log channel, for which the Logger object is injected by
service wiring, for a service that is overridden by default,
such as 'DBLoadBalancerFactory'. For that, calling setLogger()
mid-test would be too late.

== Changes

* Add a test-only method to LegacyLogger that makes it possible
  to change its `minimumLevel` attribute, thus making it turn
  itself into a NullLogger if raised to infinity. This is the
  same principle we use already for disabled log channels when
  using MediaWiki normally (see LegacyLogger::__construct).

* Previously, the developer's LocalSettings.php was loaded
  which includes the Spi configuration. This meant other Spi's
  could be configured which means we might not be dealing with
  a LegacyLogger object.

  Similar to what we do with ObjectCache and JobQueue already,
  make the default Spi in tests the same as the normal MW default.

* Add setNullLogger() which makes use of these two.

Bug: T248195
Change-Id: Ieade3585812de47342259afa765e230fff06f526
2020-04-07 22:00:13 +00:00
Timo Tijhof
95ec909e52 WikiMap: Add WikiMap::getCurrentWikiId() to make common use case easier
Change-Id: Ie225ebfc37c824e3167742137bbbc9f64aca5f5e
2020-03-03 16:04:21 +00:00
Timo Tijhof
8dfa162439 profiler: Remove support for $wgDebugLogGroups['profileoutput']
Profiler outputs should instead be configured via $wgProfiler.

Bug: T245835
Change-Id: Ib27ce8d066bde27596e61491750c508b259746f4
2020-02-29 18:24:55 +00:00
Timo Tijhof
f575721a06 Update all use of $wgVersion to MW_VERSION
Follows-up I04628de4152dd5.

Bug: T212738
Change-Id: I718474ec0d9fd29ac2c05477f0f2493615d8aff5
2020-02-25 02:16:12 +00:00
Ricordisamoa
1b3bc281ac Clean up redundant Exception|Throwable union type
PHP 7.0 makes many error conditions throw instances of the new Error class
which does not extend the known Exception.
The Throwable interface provides a concise and type-safe way of handling
either, e.g. for logging purposes, but HHVM did not support it, requiring
tedious fallback checks.

This commit replaces occurrences of Exception in code paths equally
covered by Throwable, like Exception|Throwable parameter and return types
(also nullable), instanceof guards, duplicated `catch` blocks, as well as
related comments and documentation blocks, with the exception of $previous
parameter descriptions consistent with the manual at
https://www.php.net/manual/en/exception.construct.php

Proper type declarations have been added or reinstated where possible.

Change-Id: I5d3920d3cc66936a350314e2f19c4f6faeffd7c0
2020-02-12 20:28:40 +00:00
James D. Forrester
0958a0bce4 Coding style: Auto-fix MediaWiki.Usage.IsNull.IsNull
Change-Id: I90cfe8366c0245c9c67e598d17800684897a4e27
2020-01-10 14:17:13 -08:00
James D. Forrester
4f2d1efdda Coding style: Auto-fix MediaWiki.Classes.UnsortedUseStatements.UnsortedUse
Change-Id: I94a0ae83c65e8ee419bbd1ae1e86ab21ed4d8210
2020-01-10 09:32:25 -08:00
Timo Tijhof
9f2d61c0d2 debug: Move global after early return in LegacyLogger::log()
Follows-up a4ae47a7b7. Untested micro-optimisation.

Change-Id: I94178ee40baf9d1d6dd2cac558ec2e205918964b
2019-12-13 03:28:04 +00:00
Daimona Eaytoy
598c4d7fcb build: Upgrade phan to 0.9.0
Scalar casts are still allowed (for now), because there's a huge amount
of false positives. Ditto for invalid array offsets.

Thoughts about the rest: luckily, many false positives with array offsets
have gone. Moreover, since *Internal issues are suppressed in the base
config, we can remove inline suppressions.

Unfortunately, there are a couple of new issues about array additions
with only false positives, because apparently they don't take
branches into account.

Change-Id: I5a3913c6e762f77bfdae55051a395fae95d1f841
2019-12-07 20:16:19 +00:00
Thiemo Kreuz
78ca9eff4a Remove duplicate variable name from class property PHPDocs
Repeating the variable name doesn't do anything. Documentation
generators don't need it. It's more stuff to read that doesn't add new
information. And it can become outdated.

Note there are two types of @var docs. When used inline (and not on a
class property) the variable name is needed.

Change-Id: If5a520405efacd8cefd90b878c999b842b91ac61
2019-12-02 12:58:29 +00:00