2020-04-07 21:30:36 -04:00
|
|
|
import base64
|
|
|
|
import json
|
|
|
|
import logging
|
2020-03-27 09:03:35 -04:00
|
|
|
import os
|
2020-04-07 21:30:36 -04:00
|
|
|
import pwd
|
|
|
|
import re
|
|
|
|
# We COULD use pyperclip or pygtk or whatever for this, but we have enough external deps already.
|
2020-03-27 09:03:35 -04:00
|
|
|
import subprocess
|
2020-04-07 21:30:36 -04:00
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
import warnings
|
|
|
|
_logger = logging.getLogger()
|
|
|
|
##
|
|
|
|
import psutil
|
|
|
|
##
|
|
|
|
from . import constants
|
|
|
|
|
|
|
|
|
|
|
|
def getProc(display, clipboard):
|
|
|
|
real_uid = pwd.getpwnam(os.getlogin()).pw_uid
|
|
|
|
procs = [] # Normally I'd do this in a list comprehension but switching to a loop for readability.
|
|
|
|
for p in psutil.process_iter(attrs = ['name', 'cmdline', 'environ', 'uids']):
|
|
|
|
if p.name() != 'xclip':
|
|
|
|
continue
|
|
|
|
if p.uids().effective == real_uid:
|
|
|
|
p_display = p.environ().get('DISPLAY')
|
|
|
|
cbrd = None
|
|
|
|
for idx, arg in enumerate(p.cmdline()):
|
|
|
|
if arg.startswith('-se'):
|
|
|
|
cbrd = p.cmdline()[(idx + 1)]
|
|
|
|
break
|
|
|
|
if p_display == display and cbrd == clipboard:
|
|
|
|
return(p)
|
|
|
|
return(None)
|
|
|
|
|
|
|
|
|
|
|
|
def pasteClipboard(data,
|
|
|
|
seconds = constants.CLIP_TIMEOUT,
|
|
|
|
clipboard = constants.CLIPBOARD,
|
|
|
|
printme = False,
|
|
|
|
*args, **kwargs):
|
|
|
|
if clipboard not in constants.ALLOWED_CLIPBOARDS:
|
|
|
|
_logger.error('Invalid clipboard name')
|
|
|
|
_logger.debug(('The clipboard "{0}" is invalid. '
|
|
|
|
'Must be one of: {1}.').format(', '.join((clipboard, constants.ALLOWED_CLIPBOARDS))))
|
|
|
|
raise ValueError('Invalid clipboard')
|
|
|
|
if isinstance(data, dict):
|
|
|
|
data = json.dumps(dict, indent = 4)
|
|
|
|
if not isinstance(data, str):
|
|
|
|
data = str(data)
|
|
|
|
_logger.debug('Copying to clipboard {0} for {1} seconds'.format(clipboard, seconds))
|
|
|
|
termname = os.environ.get('TERM', 'linux')
|
|
|
|
if termname == 'linux':
|
|
|
|
# We don't have X, so we have no usable xclip.
|
|
|
|
_logger.warning('Disabling clipboard copying because we don\'t have X')
|
|
|
|
return(None)
|
|
|
|
display = os.environ.get('DISPLAY')
|
|
|
|
if not display:
|
|
|
|
# We don't have X, so we have no usable xclip.
|
|
|
|
_logger.warning('Disabling clipboard copying because we don\'t have X')
|
|
|
|
return(None)
|
|
|
|
exists = getProc(display)
|
|
|
|
current = None
|
|
|
|
if exists:
|
|
|
|
cmd = subprocess.run(['xclip',
|
|
|
|
'-out',
|
|
|
|
'-display', display,
|
|
|
|
'-selection', clipboard])
|
|
|
|
current = cmd.stdout
|
|
|
|
exists.kill()
|
|
|
|
cmd = subprocess.run(['xclip',
|
|
|
|
'-display', display,
|
|
|
|
'-selection', clipboard],
|
|
|
|
input = data.encode('utf-8'),
|
|
|
|
stdout = subprocess.PIPE,
|
|
|
|
stderr = subprocess.PIPE)
|
|
|
|
if cmd.returncode != 0:
|
|
|
|
_logger.error('Could not write to clipboard')
|
|
|
|
_logger.debug('Could not write to clipboard "{0}" on display {1}.'.format(clipboard, display))
|
|
|
|
for x in ('stdout', 'stderr'):
|
|
|
|
i = getattr(cmd, x)
|
|
|
|
if i:
|
|
|
|
i = i.decode('utf-8').strip()
|
|
|
|
if i != '':
|
|
|
|
_logger.debug('{0}: {1}'.format(x.upper(), i))
|
|
|
|
raise RuntimeError('Could not write to clipboard')
|
|
|
|
if printme:
|
|
|
|
print('Copied to clipboard "{0}".'.format(clipboard))
|
|
|
|
if seconds is not None:
|
|
|
|
if printme:
|
|
|
|
print('Active for {0} seconds...'.format(seconds))
|
|
|
|
for s in range(seconds, 0, -1):
|
|
|
|
sys.stdout.write('{0} seconds remaining...'.format(s))
|
|
|
|
sys.stdout.flush()
|
|
|
|
time.sleep(1)
|
|
|
|
sys.stdout.write('\r')
|
|
|
|
print('\033[2KClipboard cleared.')
|
|
|
|
else:
|
|
|
|
for s in range(seconds, 0, -1):
|
|
|
|
time.sleep(1)
|
|
|
|
if current:
|
|
|
|
cmd = subprocess.run(['xclip',
|
|
|
|
'-display', display,
|
|
|
|
'-selection', clipboard],
|
|
|
|
input = current,
|
|
|
|
stdout = subprocess.PIPE,
|
|
|
|
stderr = subprocess.PIPE)
|
|
|
|
if cmd.returncode != 0:
|
|
|
|
_logger.warning('Could not restore clipboard')
|
|
|
|
_logger.debug('Could not restore clipboard "{0}" on display {1}.'.format(clipboard, display))
|
|
|
|
for x in ('stdout', 'stderr'):
|
|
|
|
i = getattr(cmd, x)
|
|
|
|
if i:
|
|
|
|
i = i.decode('utf-8').strip()
|
|
|
|
if i != '':
|
|
|
|
_logger.debug('{0}: {1}'.format(x.upper(), i))
|
|
|
|
# We absolutely should warn about this.
|
|
|
|
warnings.warn('Could not restore clipboard; secret remains in clipboard!')
|
|
|
|
else:
|
|
|
|
proc = getProc(display, clipboard)
|
|
|
|
if not proc:
|
|
|
|
_logger.warning('Could not restore clipboard')
|
|
|
|
_logger.debug('Could not restore clipboard "{0}" on display {1}.'.format(clipboard, display))
|
|
|
|
# We absolutely should warn about this.
|
|
|
|
warnings.warn('Could not restore clipboard; secret remains in clipboard!')
|
|
|
|
else:
|
|
|
|
proc.kill()
|
|
|
|
return(None)
|