Commit Graph

236 Commits

Author SHA1 Message Date
Enrico Weigelt, metux IT consult
e4e99bff2d compext: Xi: use return value of X_SEND_REPLY_SIMPLE()
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-22 12:13:43 +02:00
stefan11111
a4d08427cf Xext: composite: xfixes: Fix warnings when building with -Dxinerama=false
Signed-off-by: stefan11111 <stefan11111@shitposting.expert>
2025-09-22 12:12:48 +02:00
Enrico Weigelt, metux IT consult
b0ffa7b286 treewide: rename dixGetFirstScreenPtr() to dixGetMasterScreen() for correct semantics
In Xinerama/Panoramix configuration there's one screen that's having special
meaning - it's used for simulating as the frontend for all client operations:
the clients (should) only talk to that screen, while panoramix subsystem is
proxying those operations to all the other screens (with certain changed
applied, eg. coordinate transformations).

Historically, this screen happens to be the first one in the system (some of
it's proc's are hooked up in order to achieve desired behaviour). That's why it
used to be accessed via screenInfo.screens[0] - that already had been encapsulated
into a tiny helper `dixGetFirstScreen()`.

a) the correct terminus technicus for a situation where one device (or SW entity)
   entirely controlling others is a master-slave-relationship: the controlling
   device/entity is `master`, the controlled ones are `slave` (to that specific
   master).

b) the term "first screen" is inacurate and misleading here: what the caller's are
   actually interest in isn't the first entry in the screen array, but the screen
   that's controlling the others. With upcoming refactoring of the Xinerama/Panoramix
   subsystem, this might well be a different array index than 0.

c) the term `default` also wouldn't match: `default` implies there's a real practical
   choice, and such value applies when no explicit choice has been made. But in this
   case, it practically doesn't make sense (except perhaps for debugging purpose)
   for a client to use any different screen.

Therefore fixing the function name to the correct technical terminology.
(for sake of patch readability, renaming corresponding variables is left to
subsequent patches).

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-12 11:44:05 +02:00
Enrico Weigelt, metux IT consult
a6854775b5 composite: ProcCompositeGetOverlayWindow(): declare cs when needed
it's cleaner to declare variables where they're assigned first.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-12 09:51:34 +02:00
Enrico Weigelt, metux IT consult
e474b81a45 damage: move the extension under the Xext directory
Tidying up the source tree structure a bit.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-10 17:06:13 +02:00
Enrico Weigelt, metux IT consult
6bc438ab5a treewide: use inline helper for accessing first screen
Instead of everybody directly accessing the (internal) screenInfo struct,
let those consumers only interested in first screen use a little helper.

Also caching the value if it's needed several times.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-10 13:45:05 +02:00
Enrico Weigelt, metux IT consult
eb17b34362 Xinerama: lambda-esque macro for walking Xinerama screens
Move the walking loops on Xinerama screens into lambda-esque macros:
the callers look quite like we've been using lambda functions and
closures, but actually are just fancy macro trickery.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-09 14:12:40 +02:00
Enrico Weigelt, metux IT consult
dcb5bb08ca composite: canonical walkScreenIdx variable on screen list iterations
When iterating screen lists, consistently use the same variable name
`walkScreenIdx` for holding current screen index everywhere.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-03 09:26:47 +02:00
Enrico Weigelt, metux IT consult
2e0024a2b7 compext: simplify ProcCompositeQueryVersion() a little bit
Since we're already statically initializing the reply header anyways,
use the default case values here and overwrite them only when requested
version is lower than server's one.

That code path is so cold (at max only called once per client), we really
don't need to care whether there's any chance for saving a few cycles.
So not trying to be clever, but instead focus on readability.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-24 12:11:09 +02:00
Enrico Weigelt, metux IT consult
7e7716c6b2 compext: xtest: use X_SEND_REPLY_SIMPLE()
Use X_SEND_REPLY_SIMPLE() for sending out simple replies.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-22 15:39:27 +02:00
Enrico Weigelt, metux IT consult
a49f0fd9b2 composite: canonical walkScreen variable on screen list iterations
When iterating screen lists, consistently use the same variable name
`walkScreen` for holding current screen pointer everywhere.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-18 10:52:49 +02:00
Enrico Weigelt, metux IT consult
79cda3dce3 treewide: replace PICT_r8g8b8 by PIXMAN_r8g8b8
Try not to use old compat macros anymore, use the real ones instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-11 20:23:43 +02:00
Enrico Weigelt, metux IT consult
35a43252ca treewide: replace PICT_a8r8g8b8 by PIXMAN_a8r8g8b8
Try not to use old compat macros anymore, use the real ones instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-11 20:23:43 +02:00
Enrico Weigelt, metux IT consult
d8a06a2f9f treewide: replace PICT_TYPE_COLOR by PIXMAN_TYPE_COLOR
Try not to use old compat macros anymore, use the real ones instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-07 15:35:38 +02:00
Enrico Weigelt, metux IT consult
803355e874 treewide: replace PICT_FORMAT_TYPE by PIXMAN_FORMAT_TYPE
Try not to use old compat macros anymore, use the real ones instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-07 12:45:37 +02:00
Enrico Weigelt, metux IT consult
7783ae7723 treewide: replace PICT_FORMAT_BPP by PIXMAN_FORMAT_BPP
Try not to use old compat macros anymore, use the real ones instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-08-07 12:45:37 +02:00
Enrico Weigelt, metux IT consult
181e63f46e composite: use NULL instead of NullClient
No need to have another name for NULL, we can use NULL directly.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-07-18 22:24:55 +02:00
Enrico Weigelt, metux IT consult
43e8b77d2b compext: declare variables when needed
The code is easier to understand if variables are declared when
they're needed first.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-07-18 05:25:41 +02:00
dasha_uwu
7c64a06ba4 treewide: remove "lib" prefix in static_library names (meson)
this was producing static libraries named "liblibsomething.a"

Signed-off-by: dasha_uwu <dasha@linuxping.win>
2025-07-03 12:01:52 +02:00
Enrico Weigelt, metux IT consult
e6467895f9 dix: add dixAllocServerXID()
Adding a separate function for allocating server-client's XIDs.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:48 +02:00
Enrico Weigelt, metux IT consult
3c028a8cc0 miext: move over extinit_priv.h from include
Since most of the extension init logic (and on/off switches for them)
is driven from miext, this seems the appropriate place for the header.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:46 +02:00
Enrico Weigelt, metux IT consult
7e120f0f03 composite: simplify dispatcher
The dispatcher functions are much more complex than they're usually are
(just switch/case statement). Bring them in line with the standard scheme
used in the Xserver, so further steps become easier.

It's also much cleaner to use the defines from proto headers instead of
raw numbers.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:44 +02:00
Enrico Weigelt, metux IT consult
0bf08776c8 composite: untwist Xinerama handling
The current way of switching between Xinerama and single-screen handlers
is quite complicated and needs call vector tables that are changed on
the fly, which in turn makes dispatching more complicated.

Reworking this into a simple and straight code flow, where individual request
procs just look at a flag to decide whether to call the Xinerama or single
screen version.

This isn't just much easier to understand (and debug), but also removes the need
or the call vectors, thus allowing further simplification of the dispatcher.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:44 +02:00
Enrico Weigelt, metux IT consult
fb38ed0917 composite: clean up including panoramix headers
* use their actual path instead of relying this to be in compiler's
  include path list.
* no need to do it only conditionally, no #ifdef needed

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:43 +02:00
Enrico Weigelt, metux IT consult
adc27c5220 dix: move ColormapRec declaration out of public header
Not used by any external module/driver, so no need to keep it in
public header.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:43 +02:00
Enrico Weigelt, metux IT consult
a527589819 composite: drop obsolete including of colormapst.h
All relevant things are now in dix/colormap_priv.h, so no need
to include colormapst.h anymore.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:43 +02:00
Enrico Weigelt, metux IT consult
62b86f2b13 dix: make LEGAL_NEW_RESOURCE() macro private
Not used by any external driver, so no need to keep it in public header.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:43 +02:00
Enrico Weigelt, metux IT consult
4ac10378e1 dix: unexport and rename CreateWindow()
a) an internal function that's not used by any drivers
b) conflicting with function/define of same name on win32

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 17:21:43 +02:00
Enrico Weigelt, metux IT consult
a09805f675 dix: add dixClientForXID()
Retrieves the ClientPtr for the owner of given resource.
This way reducing the sites directly accessing clients[] array.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:53:34 +02:00
Enrico Weigelt, metux IT consult
0a315e45dd dix: replace CLIENT_ID() macro by dixClientIdForXID() inline function
Make it type-safe and a bit more obvious what it really does,
also adding some inline documentation. Since it's just some
bit shifting magic, it's qualified for inlining.

The CLIENT_ID() macro isn't used by any external modules, so the
new function doesn't need to be in a public header.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:53:27 +02:00
Enrico Weigelt, metux IT consult
d697618c16 dix: replace wClient() macro by dixClientForWindow() inline function
Hide internals (drop the need to include windowstr.h), make it typesafe
as well as the naming easier to understand.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:53:13 +02:00
Enrico Weigelt, metux IT consult
abfa0b888c compext: drop unused function CompositeRegisterImplicitRedirectionException()
Not used anywhere, neither internal nor drivers, so no need to keep it around.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:50:55 +02:00
Enrico Weigelt, metux IT consult
c6b8b78a29 composite: use calloc() instead of malloc()
Using calloc() instead of malloc() as preventive measure, so there
never can be any hidden bugs or leaks due uninitialized memory.

The extra cost of using this compiler intrinsic should be practically
impossible to measure - in many cases a good compiler can even deduce
if certain areas really don't need to be zero'd (because they're written
to right after allocation) and create more efficient machine code.

The code pathes in question are pretty cold anyways, so it's probably
not worth even thinking about potential extra runtime costs.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:49:13 +02:00
Enrico Weigelt, metux IT consult
074fa9b0ba compext: use CloseScreen hook
Wrapping ScreenRec's function pointers is problematic for many reasons,
so use the new screen close notify hook instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:45:21 +02:00
Enrico Weigelt, metux IT consult
669391f477 dbe: use window position notify hook
Wrapping ScreenRec's function pointers is problematic for many reasons,
so use the new window position notify hook instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:44:36 +02:00
Enrico Weigelt, metux IT consult
9dad5500ac (!1714) composite: use window position notify hook
Wrapping ScreenRec's function pointers is problematic for many reasons,
so use the new window position notify hook instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:44:35 +02:00
Enrico Weigelt, metux IT consult
c3d780d07f composite: use window destructor hook
Wrapping ScreenRec's function pointers is problematic for many reasons,
so use the new window destructor hook instead.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:44:16 +02:00
Enrico Weigelt, metux IT consult
1e2842f3e5 composite: silence some warnings on possible NULL dereference
Unlikely to practically happen, but still safer to just check for sure.
A simple zero-value test doesn't cost us much (on modern CPUs perhaps
not even a full clock cycle).

| ../composite/compalloc.c: In function ‘compRedirectWindow’:
| ../composite/compalloc.c:167:35: warning: dereference of NULL ‘pClient’ [CWE-476] [-Wanalyzer-null-dereference]
|   167 |     ccw->id = FakeClientID(pClient->index);
|       |                            ~~~~~~~^~~~~~~

| ../composite/compalloc.c: In function ‘compUnredirectWindow’:
| ../composite/compalloc.c:331:75: warning: dereference of NULL ‘pClient’ [CWE-476] [-Wanalyzer-null-dereference]
|   331 |         if (ccw->update == update && dixClientIdForXID(ccw->id) == pClient->index) {
|       |                                                                    ~~~~~~~^~~~~~~

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:35:39 +02:00
Enrico Weigelt, metux IT consult
25f50e2cc5 panoramix: replace FOR_NSCREENS() by FOR_NSCREENS_BACKWARD(i)
FOR_NSCREENS() is just alias for FOR_NSCREENS_BACKWARD(). In many cases
it really matters that we're going backwards and the last iteration visited
the screen #0, and that one is panoramix-wrapped.

Thus directly calling FOR_NSCREENS_BACKWARD() here and dropping the alias.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:24:18 +02:00
Enrico Weigelt, metux IT consult
e9351ba7e0 include: drop obsolete dixevents.h
The include has become empty now. Not used by any external drivers,
so it can be dropped now.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-06-12 16:17:35 +02:00
Olivier Fourdan
b07192a8be composite: initialize border clip even when pixmap alloc fails
If it fails to allocate the pixmap, the function compAllocPixmap() would
return early and leave the borderClip region uninitialized, which may
lead to the use of uninitialized value as reported by valgrind:

 Conditional jump or move depends on uninitialised value(s)
    at 0x4F9B33: compClipNotify (compwindow.c:317)
    by 0x484FC9: miComputeClips (mivaltree.c:476)
    by 0x48559A: miValidateTree (mivaltree.c:679)
    by 0x4F0685: MapWindow (window.c:2693)
    by 0x4A344A: ProcMapWindow (dispatch.c:922)
    by 0x4A25B5: Dispatch (dispatch.c:560)
    by 0x4B082A: dix_main (main.c:282)
    by 0x429233: main (stubmain.c:34)
  Uninitialised value was created by a heap allocation
    at 0x4841866: malloc (vg_replace_malloc.c:446)
    by 0x4F47BC: compRedirectWindow (compalloc.c:171)
    by 0x4FA8AD: compCreateWindow (compwindow.c:592)
    by 0x4EBB89: CreateWindow (window.c:925)
    by 0x4A2E6E: ProcCreateWindow (dispatch.c:768)
    by 0x4A25B5: Dispatch (dispatch.c:560)
    by 0x4B082A: dix_main (main.c:282)
    by 0x429233: main (stubmain.c:34)

 Conditional jump or move depends on uninitialised value(s)
    at 0x48EEDBC: pixman_region_translate (pixman-region.c:2233)
    by 0x4F9255: RegionTranslate (regionstr.h:312)
    by 0x4F9B7E: compClipNotify (compwindow.c:319)
    by 0x484FC9: miComputeClips (mivaltree.c:476)
    by 0x48559A: miValidateTree (mivaltree.c:679)
    by 0x4F0685: MapWindow (window.c:2693)
    by 0x4A344A: ProcMapWindow (dispatch.c:922)
    by 0x4A25B5: Dispatch (dispatch.c:560)
    by 0x4B082A: dix_main (main.c:282)
    by 0x429233: main (stubmain.c:34)
  Uninitialised value was created by a heap allocation
    at 0x4841866: malloc (vg_replace_malloc.c:446)
    by 0x4F47BC: compRedirectWindow (compalloc.c:171)
    by 0x4FA8AD: compCreateWindow (compwindow.c:592)
    by 0x4EBB89: CreateWindow (window.c:925)
    by 0x4A2E6E: ProcCreateWindow (dispatch.c:768)
    by 0x4A25B5: Dispatch (dispatch.c:560)
    by 0x4B082A: dix_main (main.c:282)
    by 0x429233: main (stubmain.c:34)

 Conditional jump or move depends on uninitialised value(s)
    at 0x48EEE33: UnknownInlinedFun (pixman-region.c:2241)
    by 0x48EEE33: pixman_region_translate (pixman-region.c:2225)
    by 0x4F9255: RegionTranslate (regionstr.h:312)
    by 0x4F9B7E: compClipNotify (compwindow.c:319)
    by 0x484FC9: miComputeClips (mivaltree.c:476)
    by 0x48559A: miValidateTree (mivaltree.c:679)
    by 0x4F0685: MapWindow (window.c:2693)
    by 0x4A344A: ProcMapWindow (dispatch.c:922)
    by 0x4A25B5: Dispatch (dispatch.c:560)
    by 0x4B082A: dix_main (main.c:282)
    by 0x429233: main (stubmain.c:34)
  Uninitialised value was created by a heap allocation
    at 0x4841866: malloc (vg_replace_malloc.c:446)
    by 0x4F47BC: compRedirectWindow (compalloc.c:171)
    by 0x4FA8AD: compCreateWindow (compwindow.c:592)
    by 0x4EBB89: CreateWindow (window.c:925)
    by 0x4A2E6E: ProcCreateWindow (dispatch.c:768)
    by 0x4A25B5: Dispatch (dispatch.c:560)
    by 0x4B082A: dix_main (main.c:282)
    by 0x429233: main (stubmain.c:34)

Fix compAllocPixmap() to initialize the border clip even if the creation
of the backing pixmap has failed, to avoid depending later on
uninitialized border clip values.

Related to CVE-2025-26599, ZDI-CAN-25851

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1828>
2025-02-25 11:43:01 +01:00
Olivier Fourdan
c1ff84bef2 composite: Handle failure to redirect in compRedirectWindow()
The function compCheckRedirect() may fail if it cannot allocate the
backing pixmap.

In that case, compRedirectWindow() will return a BadAlloc error.

However that failure code path will shortcut the validation of the
window tree marked just before, which leaves the validate data partly
initialized.

That causes a use of uninitialized pointer later.

The fix is to not shortcut the call to compHandleMarkedWindows() even in
the case of compCheckRedirect() returning an error.

CVE-2025-26599, ZDI-CAN-25851

This vulnerability was discovered by:
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1828>
2025-02-25 11:43:01 +01:00
Enrico Weigelt, metux IT consult
eb5476381a composite: use dixDestroyPixmap() instead of direct driver call
Direct calls to ScreenRec->DestroyPixmap() blocks cleaning up the wrapping
jungle, so use the proper dix function instead.

See: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1754

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1711>
2025-02-12 17:48:30 +01:00
Enrico Weigelt, metux IT consult
356e18dcc6 os: move out extension disable flags to corresponing extensions
The OS abstraction isn't really the right place for those flags,
they are're probably better off in their corresponding extensions.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1519>
2025-02-07 12:00:53 +01:00
Enrico Weigelt, metux IT consult
96344583e4 composite: drop swapping request length fields
The request struct's length fields aren't used anymore - we have the
client->req_len field instead, which also is bigreq-compatible.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1639>
2025-02-06 22:28:49 +00:00
Enrico Weigelt, metux IT consult
fb696a7d7b rename old symbol PANORAMIX to XINERAMA
PANORAMIX was the original working title of the extension, before it became
official standard. Just nobody cared about fixing the symbols to the official
naming.

For backwards compatibility with drivers, the old PANORAMIX symbol will
still be set.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1258>
2025-02-06 15:51:27 +00:00
Enrico Weigelt, metux IT consult
1642adec3b dix: unexport Ones()
It's not used by any module/driver, so no need to keep it exported.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1695>
2024-10-26 16:35:57 +00:00
Enrico Weigelt, metux IT consult
a917f6a8a8 drop obsolete HAVE_DIX_CONFIG_H
The symbol controls whether to include dix-config.h, and it's always set,
thus we don't need it (and dozens of ifdef's) anymore.

This commit only removes them from our own source files, where we can
guarantee that dix-config.h is present - leaving the (potentially exported)
headers untouched.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2024-10-10 13:38:31 +00:00
Enrico Weigelt, metux IT consult
c4481fc20f treewide: fix indentions got broke by recent commit
Commit f26f17c66a broke some indentions,
fixing them now.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1662>
2024-08-27 20:08:32 +02:00
Enrico Weigelt, metux IT consult
f26f17c66a treewide: mark pGC->ops->CopyArea() calls not using result as void
We alread have several of these calls, that aren't interested in result value,
explicitly casting to void. Fixing this up for the remaining ones.

This is helpful for the human reader as well as quality analysis tools.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1648>
2024-08-26 03:44:23 +00:00