checkpoint.
This commit is contained in:
parent
76db457830
commit
80d11df2f9
423
notes
423
notes
|
@ -9,15 +9,7 @@ query info -->
|
||||||
|
|
||||||
---
|
---
|
||||||
use automake
|
use automake
|
||||||
|
use doxygen
|
||||||
order includes according to source directory
|
|
||||||
fix function definitions
|
|
||||||
return type on first line
|
|
||||||
function name in 1st column on 2nd line
|
|
||||||
parameters at 1st tab stop starting 3rd line, one per line
|
|
||||||
fix parameter indentation
|
|
||||||
in header file: 7th tab stop (not 8th)
|
|
||||||
in source file: 1st tab stop (not 8th)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
HTTP stuff
|
HTTP stuff
|
||||||
|
@ -30,13 +22,54 @@ HTTP stuff
|
||||||
handy for debugging at least
|
handy for debugging at least
|
||||||
|
|
||||||
---
|
---
|
||||||
CThreadRep::threadSignalHandler not shutdown on assert
|
make generic input devices?
|
||||||
thread stays around and holds our resources (like sockets)
|
replace mouse and keyboard with button and valuator devices?
|
||||||
should ensure that it terminates correctly
|
could fairly easily add new devices then
|
||||||
|
valuators would have to come in groups that change together
|
||||||
|
mouse position would be two ganged valuators
|
||||||
|
key events are not simply button presses though
|
||||||
|
they have a non-boolean character, shift state, and repeat count
|
||||||
|
maybe another device type: {data, state, repeat}
|
||||||
|
|
||||||
|
must handle on-the-fly addition/removal of devices
|
||||||
|
USB allows hotplugging and we should support, say, an added joystick
|
||||||
|
|
||||||
|
must have device negotiation
|
||||||
|
at very least it negotiates mouse/keyboard at start
|
||||||
|
|
||||||
|
---
|
||||||
|
should add clipboard data type format negotiation
|
||||||
|
server sends permitted data type formats
|
||||||
|
client responds with known formats in permitted list
|
||||||
|
client must only send permitted formats
|
||||||
|
server can discard non-permitted formats
|
||||||
|
server must only send known, permitted formats to client
|
||||||
|
formats are names of the form [a-zA-Z0-9_/]+
|
||||||
|
server must be able to translate between all permitted formats
|
||||||
|
example: text formats:
|
||||||
|
text/plain/CRLF -- windows plain text
|
||||||
|
text/plain/LF -- unix plain text
|
||||||
|
text/plain/CR -- mac plain text
|
||||||
|
text/rtf -- rich text (does that require a particular newline?)
|
||||||
|
or image formats:
|
||||||
|
image/BMP
|
||||||
|
image/RAW
|
||||||
|
image/XPM
|
||||||
|
|
||||||
|
this will allow future versions to interoperate better. it also
|
||||||
|
allows compatibility with versions that are identical except for
|
||||||
|
the support clipboard formats, obviating bumping up the protocol
|
||||||
|
version number.
|
||||||
|
|
||||||
|
---
|
||||||
|
hot keys
|
||||||
|
should have keyboard shortcuts to jump to screens
|
||||||
|
|
||||||
---
|
---
|
||||||
win32:
|
win32:
|
||||||
|
need icon
|
||||||
provide taskbar icon
|
provide taskbar icon
|
||||||
|
provide control panel?
|
||||||
|
|
||||||
win32 dll:
|
win32 dll:
|
||||||
should make this as small as possible
|
should make this as small as possible
|
||||||
|
@ -44,15 +77,15 @@ win32 dll:
|
||||||
use custom _DllMainCRTStartup(); just call DllMain() from it.
|
use custom _DllMainCRTStartup(); just call DllMain() from it.
|
||||||
use /MERGE linker switch to merge sections
|
use /MERGE linker switch to merge sections
|
||||||
|
|
||||||
|
win32 service:
|
||||||
|
need message table for proper event reporting
|
||||||
|
|
||||||
clean up c:\winnt\synergy.sgc
|
clean up c:\winnt\synergy.sgc
|
||||||
|
|
||||||
desktop switcher program failure when running synergy as service
|
desktop switcher program failure when running synergy as service
|
||||||
returns access denied from CreateDesktop()
|
returns access denied from CreateDesktop()
|
||||||
don't know why
|
don't know why
|
||||||
|
|
||||||
client will need to be able to retry connecting to server
|
|
||||||
in case server isn't ready yet, client can camp
|
|
||||||
|
|
||||||
---
|
---
|
||||||
bug with half-duplex keys
|
bug with half-duplex keys
|
||||||
win32 server sent num-lock to grace
|
win32 server sent num-lock to grace
|
||||||
|
@ -68,60 +101,6 @@ must send up key events when leaving screen for keys still down
|
||||||
ctrl and alt up not sent to grace
|
ctrl and alt up not sent to grace
|
||||||
grace thinks ctrl and alt are down 'til user physically press/releases them
|
grace thinks ctrl and alt are down 'til user physically press/releases them
|
||||||
|
|
||||||
---
|
|
||||||
CClient and CServer:
|
|
||||||
not checking in stop() that we're actually running
|
|
||||||
must mutex m_primary/m_screen
|
|
||||||
they could be NULL if in the middle of shutting down
|
|
||||||
|
|
||||||
---
|
|
||||||
win32 screen saver
|
|
||||||
win95 etc:
|
|
||||||
keybd_event can terminate screen saver but not mouse_event
|
|
||||||
keybd_event resets screen saver start timer but not mouse_event
|
|
||||||
to kill screen saver (if it's known to be running):
|
|
||||||
PostMessage (GetActiveWindow(), WM_CLOSE, 0, 0L);
|
|
||||||
to find if screen saver is running:
|
|
||||||
FindWindow ("WindowsScreenSaverClass", NULL);
|
|
||||||
win nt 4:
|
|
||||||
mouse_event resets screen saver start timer but not keybd_event
|
|
||||||
neither can stop screen saver because it runs in a separate desktop
|
|
||||||
to kill screen saver:
|
|
||||||
BOOL CALLBACK KillScreenSaverFunc(HWND hwnd, LPARAM lParam)
|
|
||||||
{
|
|
||||||
if(IsWindowVisible(hwnd))
|
|
||||||
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
HDESK hdesk;
|
|
||||||
|
|
||||||
hdesk = OpenDesktop(TEXT("Screen-saver"),
|
|
||||||
0,
|
|
||||||
FALSE,
|
|
||||||
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
|
|
||||||
if (hdesk)
|
|
||||||
{
|
|
||||||
EnumDesktopWindows(hdesk, KillScreenSaverFunc, 0);
|
|
||||||
CloseDesktop(hdesk);
|
|
||||||
}
|
|
||||||
|
|
||||||
---
|
|
||||||
unix:
|
|
||||||
restarting fails to connect until a user logs in:
|
|
||||||
Xlib: no protocol specified
|
|
||||||
this is caused by login manager
|
|
||||||
all clients are rejected, except those started by manager itself
|
|
||||||
workaround is to have synergy started by login manager
|
|
||||||
should then use --no-restart, though that's not necessary
|
|
||||||
affects client and server
|
|
||||||
cannot switch screens on login screen:
|
|
||||||
xdm,kdm grab keyboard for duration of login screen
|
|
||||||
synergy cannot switch unless it can grab keyboard
|
|
||||||
gdm doesn't appear to grab keyboard or mouse for duration
|
|
||||||
affects server, only
|
|
||||||
check if DISPLAY env var is unset. use ":0.0" as default.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
bug in updating screens
|
bug in updating screens
|
||||||
saw a goofy set of screens after update
|
saw a goofy set of screens after update
|
||||||
|
@ -130,11 +109,24 @@ bug in updating screens
|
||||||
C
|
C
|
||||||
D E
|
D E
|
||||||
|
|
||||||
|
---
|
||||||
|
should switch to user nobody (or something similar) if running as root
|
||||||
|
for security reasons
|
||||||
|
will make it impossible to overwrite /etc/synergy.conf
|
||||||
|
if that file is only root writable (as it should be)
|
||||||
|
|
||||||
|
---
|
||||||
|
Xsetup file may have to kill previous synergy
|
||||||
|
or synergy should exit if there's already a synergy running
|
||||||
|
|
||||||
---
|
---
|
||||||
not handling international characters
|
not handling international characters
|
||||||
|
|
||||||
---
|
---
|
||||||
not handling screen saver at all yet
|
screen saver won't lock screen if on secondary screen
|
||||||
|
because synergy has mouse/keyboard grabbed
|
||||||
|
synergy will immediately release grabs when screen saver activates
|
||||||
|
but looks like xscreensaver wont map window until it grabs
|
||||||
|
|
||||||
---
|
---
|
||||||
not distinguishing between caps lock and shift lock
|
not distinguishing between caps lock and shift lock
|
||||||
|
@ -152,17 +144,15 @@ currently sending all clipboards to all clients
|
||||||
add filtering mechanism
|
add filtering mechanism
|
||||||
|
|
||||||
---
|
---
|
||||||
sometimes not sending correct clipboard
|
sometimes jumping too far into secondary screen
|
||||||
some kind of race condition i think
|
probably bogus delta (adding in center pixel coords into delta?)
|
||||||
can select text then switch and get empty clipboard
|
this is with an X primary and secondary
|
||||||
switching back to owner screen then out gets correct clipboard
|
don't know which matters but probably X primary
|
||||||
dunno if this is still a problem
|
|
||||||
|
|
||||||
---
|
---
|
||||||
win32 not sending correct clipboard
|
not handling large motif selections
|
||||||
got 43 bytes sent for a 3 byte selection
|
there must be a limit because properties can only be so big
|
||||||
remaining bytes were 0
|
don't know protocol for transfer, though
|
||||||
problem persisted; also got 43 bytes for a 2 byte selection
|
|
||||||
|
|
||||||
---
|
---
|
||||||
need timeout on CXWindowsClipboard::CReply objects
|
need timeout on CXWindowsClipboard::CReply objects
|
||||||
|
@ -188,7 +178,50 @@ win32 hook DLL sometimes not unloaded when server is killed?
|
||||||
try to figure out why it's not unloading
|
try to figure out why it's not unloading
|
||||||
|
|
||||||
---
|
---
|
||||||
test:
|
avoid fullscreen transparent window on win32
|
||||||
|
using CBT hook to discard activation/focus messages
|
||||||
|
but it's not being called when we lose keyboard input
|
||||||
|
also, we sometimes don't get the keyboard input to start with
|
||||||
|
|
||||||
|
---
|
||||||
|
keyboard hook problems (win32)
|
||||||
|
now passing keyboard events through in most cases
|
||||||
|
this fixes problem on isabel where toggle lights don't toggle
|
||||||
|
and num-lock behaved incorrectly (generated wrong keys).
|
||||||
|
seems the DefWindowProc() needed to process the keys
|
||||||
|
unfortunately, keys sometimes leak into wrong app. seems related
|
||||||
|
to times when we don't get the keyboard input. key events are
|
||||||
|
not delivered to app on primary until cursor returns to primary.
|
||||||
|
no idea how that's possible.
|
||||||
|
current have some code to check active window and reset it in
|
||||||
|
keyboard hook. that code doesn't work.
|
||||||
|
seem to be having problems with windows key now, too. looks like
|
||||||
|
a down is sent but not the corresponding up so secondary system
|
||||||
|
thinks the key is always down.
|
||||||
|
|
||||||
|
---
|
||||||
|
try to determine keyboard quirks automatically
|
||||||
|
in particular, set the half-duplex flags
|
||||||
|
maybe KBD extension will help determine this
|
||||||
|
|
||||||
|
---
|
||||||
|
key events sent to console on win me (95/98?) are very slow
|
||||||
|
1/4 to 1/2 second delay before key up is processed
|
||||||
|
key up log message is also delayed
|
||||||
|
console causing a system-wide delay?
|
||||||
|
|
||||||
|
---
|
||||||
|
adjust thread priorities on win32
|
||||||
|
maybe remove changes altogether
|
||||||
|
currently isabel starts single-stepping mouse when dragging window
|
||||||
|
sometimes it goes normal speed but it's mostly very slow
|
||||||
|
even a very high priority doesn't seem to help
|
||||||
|
haven't tried real-time priority
|
||||||
|
a very high priority on client fixes delay when typeing into console
|
||||||
|
is it the output console causing the slowness?
|
||||||
|
|
||||||
|
---
|
||||||
|
results:
|
||||||
X primary
|
X primary
|
||||||
ctrl+alt+keypad_add, ctrl+alt_keypad_minus -> eaten by primary X server
|
ctrl+alt+keypad_add, ctrl+alt_keypad_minus -> eaten by primary X server
|
||||||
ctrl+alt+backspace probably eaten by primary X server if so configured
|
ctrl+alt+backspace probably eaten by primary X server if so configured
|
||||||
|
@ -254,49 +287,6 @@ test:
|
||||||
check accessibility shortcuts work on secondary
|
check accessibility shortcuts work on secondary
|
||||||
check accessibility features work on secondary
|
check accessibility features work on secondary
|
||||||
|
|
||||||
---
|
|
||||||
avoid fullscreen transparent window on win32
|
|
||||||
using CBT hook to discard activation/focus messages
|
|
||||||
but it's not being called when we lose keyboard input
|
|
||||||
also, we sometimes don't get the keyboard input to start with
|
|
||||||
|
|
||||||
---
|
|
||||||
keyboard hook problems (win32)
|
|
||||||
now passing keyboard events through in most cases
|
|
||||||
this fixes problem on isabel where toggle lights don't toggle
|
|
||||||
and num-lock behaved incorrectly (generated wrong keys).
|
|
||||||
seems the DefWindowProc() needed to process the keys
|
|
||||||
unfortunately, keys sometimes leak into wrong app. seems related
|
|
||||||
to times when we don't get the keyboard input. key events are
|
|
||||||
not delivered to app on primary until cursor returns to primary.
|
|
||||||
no idea how that's possible.
|
|
||||||
current have some code to check active window and reset it in
|
|
||||||
keyboard hook. that code doesn't work.
|
|
||||||
seem to be having problems with windows key now, too. looks like
|
|
||||||
a down is sent but not the corresponding up so secondary system
|
|
||||||
thinks the key is always down.
|
|
||||||
|
|
||||||
---
|
|
||||||
try to determine keyboard quirks automatically
|
|
||||||
in particular, set the half-duplex flags
|
|
||||||
maybe KBD extension will help determine this
|
|
||||||
|
|
||||||
---
|
|
||||||
key events sent to console on win me (95/98?) are very slow
|
|
||||||
1/4 to 1/2 second delay before key up is processed
|
|
||||||
key up log message is also delayed
|
|
||||||
console causing a system-wide delay?
|
|
||||||
|
|
||||||
---
|
|
||||||
adjust thread priorities on win32
|
|
||||||
maybe remove changes altogether
|
|
||||||
currently isabel starts single-stepping mouse when dragging window
|
|
||||||
sometimes it goes normal speed but it's mostly very slow
|
|
||||||
even a very high priority doesn't seem to help
|
|
||||||
haven't tried real-time priority
|
|
||||||
a very high priority on client fixes delay when typeing into console
|
|
||||||
is it the output console causing the slowness?
|
|
||||||
|
|
||||||
---
|
---
|
||||||
Accessibility Shortcuts
|
Accessibility Shortcuts
|
||||||
|
|
||||||
|
@ -340,12 +330,6 @@ Q179905
|
||||||
suggestion for bypassing hook code when called by debugger.
|
suggestion for bypassing hook code when called by debugger.
|
||||||
may prevent system from getting locked up when debugging.
|
may prevent system from getting locked up when debugging.
|
||||||
|
|
||||||
---
|
|
||||||
how is CTCPSocket::connect() able to cancel?
|
|
||||||
looks like it can't
|
|
||||||
make it asynchronous and use poll() to wait for connection
|
|
||||||
use testCancel() to make it cancellable
|
|
||||||
|
|
||||||
---
|
---
|
||||||
win32 rel notes:
|
win32 rel notes:
|
||||||
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\NoInteractiveServices
|
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\NoInteractiveServices
|
||||||
|
@ -359,3 +343,184 @@ win32 rel notes:
|
||||||
maybe possible to get around NoInteractiveServices
|
maybe possible to get around NoInteractiveServices
|
||||||
modify DACLs on windows station/desktops to impersonate logged on user
|
modify DACLs on windows station/desktops to impersonate logged on user
|
||||||
see "Interacting with the User by a Win32 Service"
|
see "Interacting with the User by a Win32 Service"
|
||||||
|
|
||||||
|
---
|
||||||
|
unix release notes:
|
||||||
|
restarting fails to connect until a user logs in:
|
||||||
|
Xlib: no protocol specified
|
||||||
|
this is caused by login manager
|
||||||
|
all clients are rejected, except those started by manager itself
|
||||||
|
workaround is to have synergy started by login manager
|
||||||
|
should then use --no-restart, though that's not necessary
|
||||||
|
affects client and server
|
||||||
|
cannot switch screens on login screen:
|
||||||
|
xdm,kdm grab keyboard for duration of login screen
|
||||||
|
synergy cannot switch unless it can grab keyboard
|
||||||
|
gdm doesn't appear to grab keyboard or mouse for duration
|
||||||
|
affects server, only
|
||||||
|
|
||||||
|
=== feedback ===
|
||||||
|
send all toggle states instead of (individual) toggle ups/downs (gspencer)
|
||||||
|
Actually, Teleffect already does that too, but what I meant was that
|
||||||
|
each time the state of a "toggle" key (caps lock, scroll lock, num lock)
|
||||||
|
changes on the master, I think it should force the client to take on
|
||||||
|
that state, instead of just toggling on the client. That way when Word
|
||||||
|
(on the client) helpfullly turns off the caps lock, it doesn't get
|
||||||
|
toggled back on when I turn off the caps lock on the master. Ideally,
|
||||||
|
it would just notice that Word turned off the caps lock on the client
|
||||||
|
and turn it off on the master (and all other clients) too, but I think
|
||||||
|
that's probably too complicated to implement.
|
||||||
|
|
||||||
|
dragging windows is too slow
|
||||||
|
grace (as client) exhibits this
|
||||||
|
dunno if it happens with audrey2 as the client
|
||||||
|
liz says her windows laptop does it too
|
||||||
|
|
||||||
|
double clicking NT binaries fails (liz)
|
||||||
|
add note to README or use separate binaries for services. client
|
||||||
|
would also need a dialog to query options. server would probably
|
||||||
|
need one too. use dialogs if there are no command line args.
|
||||||
|
|
||||||
|
how to exit (liz)
|
||||||
|
no good way to exit on windows
|
||||||
|
|
||||||
|
win32 console disappears too quickly (liz)
|
||||||
|
maybe show a message box if exiting to due an error
|
||||||
|
|
||||||
|
better support for reloading configuration (liz)
|
||||||
|
use SIGHUP on unix
|
||||||
|
use an app message on win32
|
||||||
|
provide access through a control panel or taskbar icon
|
||||||
|
|
||||||
|
non-functional on ctrl+alt+del screen in win2k (kurt)
|
||||||
|
i suppose it must be when win2k is the client. mouse input wasn't
|
||||||
|
working. keyboard probably didn't work either.
|
||||||
|
|
||||||
|
---
|
||||||
|
automake stuff
|
||||||
|
rebuild:
|
||||||
|
* 'autoheader' - creates config.h.in
|
||||||
|
* 'touch NEWS README AUTHORS ChangeLog'
|
||||||
|
* 'touch stamp-h'
|
||||||
|
* aclocal - adds aclocal.m4 to directory. Defines some m4 macros used by the auto tools.
|
||||||
|
* 'autoconf '- creates configure from configure.in
|
||||||
|
* 'automake' - Creates Makefile.in from Makefile.am
|
||||||
|
* './configure' - creates Makefile from Makefile.in
|
||||||
|
* 'make'
|
||||||
|
|
||||||
|
funky functions:
|
||||||
|
snprintf -- ick!
|
||||||
|
some return negative value -- no problem
|
||||||
|
some return truncated length -- uh oh
|
||||||
|
some return buffer length without truncation -- huh?
|
||||||
|
some actually overrun the buffer -- must not build on those!
|
||||||
|
|
||||||
|
use AC_LIBOBJ(function) for missing/broken functions
|
||||||
|
adds function.c to build
|
||||||
|
must add @LIBOBJS@ to *_LIBADD
|
||||||
|
or AC_REPLACE_FUNCS(function ...)
|
||||||
|
automatically calls AC_LIBOBJ for missing functions
|
||||||
|
use AC_CHECK_FUNC or AC_CHECK_FUNCS to detect missing functions
|
||||||
|
use AC_CHECK_LIB first if function not in std C lib
|
||||||
|
|
||||||
|
maybe AC_CHECK_TYPE for size_t and ssize_t
|
||||||
|
|
||||||
|
replace sys/time.h with:
|
||||||
|
#if TIME_WITH_SYS_TIME
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <time.h>
|
||||||
|
#else
|
||||||
|
# if HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h>
|
||||||
|
# else
|
||||||
|
# include <time.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
what does `make install' do?
|
||||||
|
|
||||||
|
check in derived files?
|
||||||
|
aclocal.m4
|
||||||
|
config.h.in
|
||||||
|
configure
|
||||||
|
|
||||||
|
used library functions:
|
||||||
|
accept
|
||||||
|
bind
|
||||||
|
chdir
|
||||||
|
close
|
||||||
|
connect
|
||||||
|
dup
|
||||||
|
fork
|
||||||
|
fprintf
|
||||||
|
getenv
|
||||||
|
gethostbyaddr
|
||||||
|
gethostbyname
|
||||||
|
gethostname
|
||||||
|
getpeername
|
||||||
|
getprotobyname
|
||||||
|
getprotobynumber
|
||||||
|
getservbyname
|
||||||
|
getservbyport
|
||||||
|
getsockname
|
||||||
|
getsockopt
|
||||||
|
gettimeofday
|
||||||
|
inet_addr
|
||||||
|
inet_ntoa
|
||||||
|
ioctl
|
||||||
|
listen
|
||||||
|
memcpy
|
||||||
|
memmove
|
||||||
|
memset
|
||||||
|
nanosleep
|
||||||
|
open
|
||||||
|
openlog
|
||||||
|
poll
|
||||||
|
read
|
||||||
|
recv
|
||||||
|
recvfrom
|
||||||
|
send
|
||||||
|
sendto
|
||||||
|
setsid
|
||||||
|
setsockopt
|
||||||
|
shutdown
|
||||||
|
sigaction
|
||||||
|
sigaddset
|
||||||
|
sigemptyset
|
||||||
|
socket
|
||||||
|
sprintf
|
||||||
|
strcat
|
||||||
|
strcmp
|
||||||
|
strerror
|
||||||
|
strrchr
|
||||||
|
syslog
|
||||||
|
umask
|
||||||
|
vsnprintf
|
||||||
|
write
|
||||||
|
|
||||||
|
included files
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
these put stuff in std::. replace with .h versions or use std::?
|
||||||
|
3 #include <cctype>
|
||||||
|
3 #include <cerrno>
|
||||||
|
1 #include <clocale>
|
||||||
|
3 #include <cstdio>
|
||||||
|
4 #include <cstdlib>
|
||||||
|
12 #include <cstring>
|
||||||
|
1 #include <ctime>
|
||||||
|
|
||||||
|
can we use AC_REPLACE_FUNCS and only build the missing function files
|
||||||
|
in a single directory. do we have to have a separate configure.in
|
||||||
|
script to do that?
|
||||||
|
|
Loading…
Reference in New Issue