org.sikuli.vnc.ThreadLocalSecurityClient Maven / Gradle / Ivy
/* Copyright (c) 2017, Sikuli.org, sikulix.com
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package org.sikuli.vnc;
import com.tigervnc.rfb.CConnection;
import com.tigervnc.rfb.CSecurity;
import com.tigervnc.rfb.SecurityClient;
import com.tigervnc.rfb.UserPasswdGetter;
import com.tigervnc.vncviewer.CConn;
import java.lang.reflect.Field;
/**
* Workaround for static state in TigerVNC.
*
* The UserPasswdGetter used by TigerVNC is a static field (CConn.upg).
* In SikuliX need to be able to specify a password per connection without requesting user input.
* To do that we set the global UserPasswdGetter to one that retrieves the actual UserPasswdGetter
* instance from a thread-local variable.
* This extension of SecurityClient sets the thread-local variable to the correct value just before
* it is going to be requested by the TigerVNC code.
*/
class ThreadLocalSecurityClient extends SecurityClient
{
private static final ThreadLocal UPG = new ThreadLocal<>();
static {
CConn.upg = new UserPasswdGetter()
{
@Override
public boolean getUserPasswd(StringBuffer user, StringBuffer pass)
{
UserPasswdGetter upg = UPG.get();
if (upg != null) {
return upg.getUserPasswd(user, pass);
} else {
if (user != null) {
user.setLength(0);
}
if (pass != null) {
pass.setLength(0);
}
return false;
}
}
};
}
private final UserPasswdGetter upg;
ThreadLocalSecurityClient(UserPasswdGetter userPasswdGetter)
{
upg = userPasswdGetter;
try {
// An assertion fails is the SecurityClient#msg is null
// I couldn't find any other way to set it than via reflection.
Field field = SecurityClient.class.getDeclaredField("msg");
field.setAccessible(true);
field.set(this, "");
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
public CSecurity GetCSecurity(int securityType)
{
final CSecurity security = super.GetCSecurity(securityType);
if (security != null) {
return new CSecurity()
{
@Override
public boolean processMsg(CConnection cConnection)
{
UPG.set(upg);
return security.processMsg(cConnection);
}
@Override
public int getType()
{
return security.getType();
}
@Override
public String description()
{
return security.description();
}
};
} else {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy