We mostly use classical C strings, but the memory management around them can get confusing and error prone. Let's use std::string for the cases where we need to return a newly allocated string.pull/1587/head
return new TcpSocket(fd); | return new TcpSocket(fd); | ||||
} | } | ||||
void TcpListener::getMyAddresses(std::list<char*>* result) { | |||||
std::list<std::string> TcpListener::getMyAddresses() { | |||||
struct addrinfo *ai, *current, hints; | struct addrinfo *ai, *current, hints; | ||||
std::list<std::string> result; | |||||
initSockets(); | initSockets(); | ||||
// Windows doesn't like NULL for service, so specify something | // Windows doesn't like NULL for service, so specify something | ||||
if ((getaddrinfo(NULL, "1", &hints, &ai)) != 0) | if ((getaddrinfo(NULL, "1", &hints, &ai)) != 0) | ||||
return; | |||||
return result; | |||||
for (current= ai; current != NULL; current = current->ai_next) { | for (current= ai; current != NULL; current = current->ai_next) { | ||||
char addr[INET6_ADDRSTRLEN]; | |||||
switch (current->ai_family) { | switch (current->ai_family) { | ||||
case AF_INET: | case AF_INET: | ||||
if (!UseIPv4) | if (!UseIPv4) | ||||
continue; | continue; | ||||
} | } | ||||
char *addr = new char[INET6_ADDRSTRLEN]; | |||||
getnameinfo(current->ai_addr, current->ai_addrlen, addr, INET6_ADDRSTRLEN, | getnameinfo(current->ai_addr, current->ai_addrlen, addr, INET6_ADDRSTRLEN, | ||||
NULL, 0, NI_NUMERICHOST); | NULL, 0, NI_NUMERICHOST); | ||||
result->push_back(addr); | |||||
result.push_back(addr); | |||||
} | } | ||||
freeaddrinfo(ai); | freeaddrinfo(ai); | ||||
return result; | |||||
} | } | ||||
int TcpListener::getMyPort() { | int TcpListener::getMyPort() { | ||||
return pattern; | return pattern; | ||||
} | } | ||||
char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) { | |||||
std::string TcpFilter::patternToStr(const TcpFilter::Pattern& p) { | |||||
char addr[INET6_ADDRSTRLEN + 2]; | char addr[INET6_ADDRSTRLEN + 2]; | ||||
if (p.address.u.sa.sa_family == AF_INET) { | if (p.address.u.sa.sa_family == AF_INET) { | ||||
else | else | ||||
snprintf(result, resultlen, "%c%s/%u", action, addr, p.prefixlen); | snprintf(result, resultlen, "%c%s/%u", action, addr, p.prefixlen); | ||||
return result; | |||||
std::string out = result; | |||||
delete [] result; | |||||
return out; | |||||
} | } |
#endif | #endif | ||||
#include <list> | #include <list> | ||||
#include <string> | |||||
/* Tunnelling support. */ | /* Tunnelling support. */ | ||||
#define TUNNEL_PORT_OFFSET 5500 | #define TUNNEL_PORT_OFFSET 5500 | ||||
virtual int getMyPort(); | virtual int getMyPort(); | ||||
static void getMyAddresses(std::list<char*>* result); | |||||
static std::list<std::string> getMyAddresses(); | |||||
protected: | protected: | ||||
virtual Socket* createSocket(int fd); | virtual Socket* createSocket(int fd); | ||||
vnc_sockaddr_t mask; // computed from address and prefix | vnc_sockaddr_t mask; // computed from address and prefix | ||||
}; | }; | ||||
static Pattern parsePattern(const char* s); | static Pattern parsePattern(const char* s); | ||||
static char* patternToStr(const Pattern& p); | |||||
static std::string patternToStr(const Pattern& p); | |||||
protected: | protected: | ||||
std::list<Pattern> filter; | std::list<Pattern> filter; | ||||
}; | }; |
strFree(serverClipboard); | strFree(serverClipboard); | ||||
serverClipboard = NULL; | serverClipboard = NULL; | ||||
serverClipboard = latin1ToUTF8(str); | |||||
serverClipboard = strDup(latin1ToUTF8(str).c_str()); | |||||
handleClipboardAnnounce(true); | handleClipboardAnnounce(true); | ||||
} | } | ||||
strFree(serverClipboard); | strFree(serverClipboard); | ||||
serverClipboard = NULL; | serverClipboard = NULL; | ||||
serverClipboard = convertLF((const char*)data[0], lengths[0]); | |||||
std::string filtered(convertLF((const char*)data[0], lengths[0])); | |||||
serverClipboard = strDup(filtered.c_str()); | |||||
// FIXME: Should probably verify that this data was actually requested | // FIXME: Should probably verify that this data was actually requested | ||||
handleClipboardData(serverClipboard); | handleClipboardData(serverClipboard); | ||||
void CConnection::sendClipboardData(const char* data) | void CConnection::sendClipboardData(const char* data) | ||||
{ | { | ||||
if (server.clipboardFlags() & rfb::clipboardProvide) { | if (server.clipboardFlags() & rfb::clipboardProvide) { | ||||
CharArray filtered(convertCRLF(data)); | |||||
size_t sizes[1] = { strlen(filtered.buf) + 1 }; | |||||
const uint8_t* data[1] = { (const uint8_t*)filtered.buf }; | |||||
std::string filtered(convertCRLF(data)); | |||||
size_t sizes[1] = { filtered.size() + 1 }; | |||||
const uint8_t* data[1] = { (const uint8_t*)filtered.c_str() }; | |||||
if (unsolicitedClipboardAttempt) { | if (unsolicitedClipboardAttempt) { | ||||
unsolicitedClipboardAttempt = false; | unsolicitedClipboardAttempt = false; | ||||
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); | writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); | ||||
} else { | } else { | ||||
CharArray latin1(utf8ToLatin1(data)); | |||||
std::string latin1(utf8ToLatin1(data)); | |||||
writer()->writeClientCutText(latin1.buf); | |||||
writer()->writeClientCutText(latin1.c_str()); | |||||
} | } | ||||
} | } | ||||
if (lengths[i] == 0) | if (lengths[i] == 0) | ||||
vlog.debug(" %s (only notify)", type); | vlog.debug(" %s (only notify)", type); | ||||
else { | else { | ||||
char bytes[1024]; | |||||
iecPrefix(lengths[i], "B", bytes, sizeof(bytes)); | |||||
vlog.debug(" %s (automatically send up to %s)", | vlog.debug(" %s (automatically send up to %s)", | ||||
type, bytes); | |||||
type, iecPrefix(lengths[i], "B").c_str()); | |||||
} | } | ||||
} | } | ||||
} | } |
} | } | ||||
CharArray ca(len); | CharArray ca(len); | ||||
is->readBytes(ca.buf, len); | is->readBytes(ca.buf, len); | ||||
CharArray filtered(convertLF(ca.buf, len)); | |||||
handler->serverCutText(filtered.buf); | |||||
std::string filtered(convertLF(ca.buf, len)); | |||||
handler->serverCutText(filtered.c_str()); | |||||
return true; | return true; | ||||
} | } |
void CSecurityDH::writeCredentials() | void CSecurityDH::writeCredentials() | ||||
{ | { | ||||
CharArray username; | |||||
CharArray password; | |||||
std::string username; | |||||
std::string password; | |||||
rdr::RandomStream rs; | rdr::RandomStream rs; | ||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); | |||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); | |||||
std::vector<uint8_t> bBytes(keyLength); | std::vector<uint8_t> bBytes(keyLength); | ||||
if (!rs.hasData(keyLength)) | if (!rs.hasData(keyLength)) | ||||
throw ConnFailedException("failed to generate DH private key"); | throw ConnFailedException("failed to generate DH private key"); | ||||
if (!rs.hasData(128)) | if (!rs.hasData(128)) | ||||
throw ConnFailedException("failed to generate random padding"); | throw ConnFailedException("failed to generate random padding"); | ||||
rs.readBytes(buf, 128); | rs.readBytes(buf, 128); | ||||
size_t len = strlen(username.buf); | |||||
if (len >= 64) | |||||
if (username.size() >= 64) | |||||
throw AuthFailureException("username is too long"); | throw AuthFailureException("username is too long"); | ||||
memcpy(buf, username.buf, len + 1); | |||||
len = strlen(password.buf); | |||||
if (len >= 64) | |||||
memcpy(buf, username.c_str(), username.size() + 1); | |||||
if (password.size() >= 64) | |||||
throw AuthFailureException("password is too long"); | throw AuthFailureException("password is too long"); | ||||
memcpy(buf + 64, password.buf, len + 1); | |||||
memcpy(buf + 64, password.c_str(), password.size() + 1); | |||||
aes128_encrypt(&aesCtx, 128, (uint8_t *)buf, (uint8_t *)buf); | aes128_encrypt(&aesCtx, 128, (uint8_t *)buf, (uint8_t *)buf); | ||||
rdr::OutStream* os = cc->getOutStream(); | rdr::OutStream* os = cc->getOutStream(); |
void CSecurityMSLogonII::writeCredentials() | void CSecurityMSLogonII::writeCredentials() | ||||
{ | { | ||||
CharArray username; | |||||
CharArray password; | |||||
std::string username; | |||||
std::string password; | |||||
rdr::RandomStream rs; | rdr::RandomStream rs; | ||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username.buf, &password.buf); | |||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); | |||||
std::vector<uint8_t> bBytes(8); | std::vector<uint8_t> bBytes(8); | ||||
if (!rs.hasData(8)) | if (!rs.hasData(8)) | ||||
throw ConnFailedException("failed to generate DH private key"); | throw ConnFailedException("failed to generate DH private key"); | ||||
throw ConnFailedException("failed to generate random padding"); | throw ConnFailedException("failed to generate random padding"); | ||||
rs.readBytes(user, 256); | rs.readBytes(user, 256); | ||||
rs.readBytes(pass, 64); | rs.readBytes(pass, 64); | ||||
size_t len = strlen(username.buf); | |||||
if (len >= 256) | |||||
if (username.size() >= 256) | |||||
throw AuthFailureException("username is too long"); | throw AuthFailureException("username is too long"); | ||||
memcpy(user, username.buf, len + 1); | |||||
len = strlen(password.buf); | |||||
if (len >= 64) | |||||
memcpy(user, username.c_str(), username.size() + 1); | |||||
if (password.size() >= 64) | |||||
throw AuthFailureException("password is too long"); | throw AuthFailureException("password is too long"); | ||||
memcpy(pass, password.buf, len + 1); | |||||
memcpy(pass, password.c_str(), password.size() + 1); | |||||
// DES-CBC with the original key as IV, and the reversed one as the DES key | // DES-CBC with the original key as IV, and the reversed one as the DES key | ||||
struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx; | struct CBC_CTX(struct des_ctx, DES_BLOCK_SIZE) ctx; |
#include <rfb/CConnection.h> | #include <rfb/CConnection.h> | ||||
#include <rfb/CSecurityPlain.h> | #include <rfb/CSecurityPlain.h> | ||||
#include <rfb/UserPasswdGetter.h> | #include <rfb/UserPasswdGetter.h> | ||||
#include <rfb/util.h> | |||||
#include <rdr/OutStream.h> | #include <rdr/OutStream.h> | ||||
{ | { | ||||
rdr::OutStream* os = cc->getOutStream(); | rdr::OutStream* os = cc->getOutStream(); | ||||
CharArray username; | |||||
CharArray password; | |||||
std::string username; | |||||
std::string password; | |||||
(CSecurity::upg)->getUserPasswd(cc->isSecure(), &username.buf, &password.buf); | |||||
(CSecurity::upg)->getUserPasswd(cc->isSecure(), &username, &password); | |||||
// Return the response to the server | // Return the response to the server | ||||
os->writeU32(strlen(username.buf)); | |||||
os->writeU32(strlen(password.buf)); | |||||
os->writeBytes(username.buf,strlen(username.buf)); | |||||
os->writeBytes(password.buf,strlen(password.buf)); | |||||
os->writeU32(username.size()); | |||||
os->writeU32(password.size()); | |||||
os->writeBytes(username.data(), username.size()); | |||||
os->writeBytes(password.data(), password.size()); | |||||
os->flush(); | os->flush(); | ||||
return true; | return true; | ||||
} | } |
void CSecurityRSAAES::writeCredentials() | void CSecurityRSAAES::writeCredentials() | ||||
{ | { | ||||
CharArray username; | |||||
CharArray password; | |||||
std::string username; | |||||
std::string password; | |||||
(CSecurity::upg)->getUserPasswd( | |||||
isSecure(), | |||||
subtype == secTypeRA2UserPass ? &username.buf : NULL, &password.buf | |||||
); | |||||
size_t len; | |||||
if (username.buf) { | |||||
len = strlen(username.buf); | |||||
if (len > 255) | |||||
if (subtype == secTypeRA2UserPass) | |||||
(CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); | |||||
else | |||||
(CSecurity::upg)->getUserPasswd(isSecure(), NULL, &password); | |||||
if (subtype == secTypeRA2UserPass) { | |||||
if (username.size() > 255) | |||||
throw AuthFailureException("username is too long"); | throw AuthFailureException("username is too long"); | ||||
raos->writeU8(len); | |||||
if (len) | |||||
raos->writeBytes(username.buf, len); | |||||
raos->writeU8(username.size()); | |||||
raos->writeBytes(username.data(), username.size()); | |||||
} else { | } else { | ||||
raos->writeU8(0); | raos->writeU8(0); | ||||
} | } | ||||
len = strlen(password.buf); | |||||
if (len > 255) | |||||
if (password.size() > 255) | |||||
throw AuthFailureException("password is too long"); | throw AuthFailureException("password is too long"); | ||||
raos->writeU8(len); | |||||
if (len) | |||||
raos->writeBytes(password.buf, len); | |||||
raos->writeU8(password.size()); | |||||
raos->writeBytes(password.data(), password.size()); | |||||
raos->flush(); | raos->flush(); | ||||
} | } |
#include <stdio.h> | #include <stdio.h> | ||||
#include <rfb/CConnection.h> | #include <rfb/CConnection.h> | ||||
#include <rfb/Password.h> | |||||
#include <rfb/CSecurityVncAuth.h> | #include <rfb/CSecurityVncAuth.h> | ||||
#include <rfb/util.h> | #include <rfb/util.h> | ||||
#include <rfb/Security.h> | #include <rfb/Security.h> | ||||
// Read the challenge & obtain the user's password | // Read the challenge & obtain the user's password | ||||
uint8_t challenge[vncAuthChallengeSize]; | uint8_t challenge[vncAuthChallengeSize]; | ||||
is->readBytes(challenge, vncAuthChallengeSize); | is->readBytes(challenge, vncAuthChallengeSize); | ||||
PlainPasswd passwd; | |||||
(CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd.buf); | |||||
std::string passwd; | |||||
(CSecurity::upg)->getUserPasswd(cc->isSecure(), 0, &passwd); | |||||
// Calculate the correct response | // Calculate the correct response | ||||
uint8_t key[8]; | uint8_t key[8]; | ||||
int pwdLen = strlen(passwd.buf); | |||||
for (int i=0; i<8; i++) | |||||
key[i] = i<pwdLen ? passwd.buf[i] : 0; | |||||
for (size_t i=0; i<8; i++) | |||||
key[i] = i<passwd.size() ? passwd[i] : 0; | |||||
deskey(key, EN0); | deskey(key, EN0); | ||||
for (int j = 0; j < vncAuthChallengeSize; j += 8) | for (int j = 0; j < vncAuthChallengeSize; j += 8) | ||||
des(challenge+j, challenge+j); | des(challenge+j, challenge+j); |
void ComparingUpdateTracker::logStats() | void ComparingUpdateTracker::logStats() | ||||
{ | { | ||||
double ratio; | double ratio; | ||||
char a[1024], b[1024]; | |||||
siPrefix(totalPixels, "pixels", a, sizeof(a)); | |||||
siPrefix(missedPixels, "pixels", b, sizeof(b)); | |||||
ratio = (double)totalPixels / missedPixels; | ratio = (double)totalPixels / missedPixels; | ||||
vlog.info("%s in / %s out", a, b); | |||||
vlog.info("%s in / %s out", | |||||
siPrefix(totalPixels, "pixels").c_str(), | |||||
siPrefix(missedPixels, "pixels").c_str()); | |||||
vlog.info("(1:%g ratio)", ratio); | vlog.info("(1:%g ratio)", ratio); | ||||
totalPixels = missedPixels = 0; | totalPixels = missedPixels = 0; |
fprintf(stderr, "%s Parameters:\n", name.buf); | fprintf(stderr, "%s Parameters:\n", name.buf); | ||||
while (current) { | while (current) { | ||||
char* def_str = current->getDefaultStr(); | |||||
std::string def_str = current->getDefaultStr(); | |||||
const char* desc = current->getDescription(); | const char* desc = current->getDescription(); | ||||
fprintf(stderr," %-*s -", nameWidth, current->getName()); | fprintf(stderr," %-*s -", nameWidth, current->getName()); | ||||
int column = strlen(current->getName()); | int column = strlen(current->getName()); | ||||
if (!s) break; | if (!s) break; | ||||
} | } | ||||
if (def_str) { | |||||
if (column + (int)strlen(def_str) + 11 > width) | |||||
if (!def_str.empty()) { | |||||
if (column + (int)def_str.size() + 11 > width) | |||||
fprintf(stderr,"\n%*s",nameWidth+4,""); | fprintf(stderr,"\n%*s",nameWidth+4,""); | ||||
fprintf(stderr," (default=%s)\n",def_str); | |||||
strFree(def_str); | |||||
fprintf(stderr," (default=%s)\n",def_str.c_str()); | |||||
} else { | } else { | ||||
fprintf(stderr,"\n"); | fprintf(stderr,"\n"); | ||||
} | } | ||||
return param->setParam(); | return param->setParam(); | ||||
} | } | ||||
char* | |||||
AliasParameter::getDefaultStr() const { | |||||
return 0; | |||||
std::string AliasParameter::getDefaultStr() const { | |||||
return ""; | |||||
} | } | ||||
char* AliasParameter::getValueStr() const { | |||||
std::string AliasParameter::getValueStr() const { | |||||
return param->getValueStr(); | return param->getValueStr(); | ||||
} | } | ||||
vlog.debug("set %s(Bool) to %d", getName(), value); | vlog.debug("set %s(Bool) to %d", getName(), value); | ||||
} | } | ||||
char* | |||||
BoolParameter::getDefaultStr() const { | |||||
return strDup(def_value ? "1" : "0"); | |||||
std::string BoolParameter::getDefaultStr() const { | |||||
return def_value ? "1" : "0"; | |||||
} | } | ||||
char* BoolParameter::getValueStr() const { | |||||
return strDup(value ? "1" : "0"); | |||||
std::string BoolParameter::getValueStr() const { | |||||
return value ? "1" : "0"; | |||||
} | } | ||||
bool BoolParameter::isBool() const { | bool BoolParameter::isBool() const { | ||||
return true; | return true; | ||||
} | } | ||||
char* | |||||
IntParameter::getDefaultStr() const { | |||||
char* result = new char[16]; | |||||
std::string IntParameter::getDefaultStr() const { | |||||
char result[16]; | |||||
sprintf(result, "%d", def_value); | sprintf(result, "%d", def_value); | ||||
return result; | return result; | ||||
} | } | ||||
char* IntParameter::getValueStr() const { | |||||
char* result = new char[16]; | |||||
std::string IntParameter::getValueStr() const { | |||||
char result[16]; | |||||
sprintf(result, "%d", value); | sprintf(result, "%d", value); | ||||
return result; | return result; | ||||
} | } | ||||
return value != 0; | return value != 0; | ||||
} | } | ||||
char* StringParameter::getDefaultStr() const { | |||||
return strDup(def_value); | |||||
std::string StringParameter::getDefaultStr() const { | |||||
return def_value; | |||||
} | } | ||||
char* StringParameter::getValueStr() const { | |||||
std::string StringParameter::getValueStr() const { | |||||
LOCK_CONFIG; | LOCK_CONFIG; | ||||
return strDup(value); | |||||
return std::string(value); | |||||
} | } | ||||
StringParameter::operator const char *() const { | StringParameter::operator const char *() const { | ||||
} | } | ||||
} | } | ||||
char* BinaryParameter::getDefaultStr() const { | |||||
std::string BinaryParameter::getDefaultStr() const { | |||||
return binToHex(def_value, def_length); | return binToHex(def_value, def_length); | ||||
} | } | ||||
char* BinaryParameter::getValueStr() const { | |||||
std::string BinaryParameter::getValueStr() const { | |||||
LOCK_CONFIG; | LOCK_CONFIG; | ||||
return binToHex(value, length); | return binToHex(value, length); | ||||
} | } |
virtual bool setParam(const char* value) = 0; | virtual bool setParam(const char* value) = 0; | ||||
virtual bool setParam(); | virtual bool setParam(); | ||||
virtual char* getDefaultStr() const = 0; | |||||
virtual char* getValueStr() const = 0; | |||||
virtual std::string getDefaultStr() const = 0; | |||||
virtual std::string getValueStr() const = 0; | |||||
virtual bool isBool() const; | virtual bool isBool() const; | ||||
virtual void setImmutable(); | virtual void setImmutable(); | ||||
ConfigurationObject co=ConfGlobal); | ConfigurationObject co=ConfGlobal); | ||||
virtual bool setParam(const char* value); | virtual bool setParam(const char* value); | ||||
virtual bool setParam(); | virtual bool setParam(); | ||||
virtual char* getDefaultStr() const; | |||||
virtual char* getValueStr() const; | |||||
virtual std::string getDefaultStr() const; | |||||
virtual std::string getValueStr() const; | |||||
virtual bool isBool() const; | virtual bool isBool() const; | ||||
virtual void setImmutable(); | virtual void setImmutable(); | ||||
private: | private: | ||||
virtual bool setParam(const char* value); | virtual bool setParam(const char* value); | ||||
virtual bool setParam(); | virtual bool setParam(); | ||||
virtual void setParam(bool b); | virtual void setParam(bool b); | ||||
virtual char* getDefaultStr() const; | |||||
virtual char* getValueStr() const; | |||||
virtual std::string getDefaultStr() const; | |||||
virtual std::string getValueStr() const; | |||||
virtual bool isBool() const; | virtual bool isBool() const; | ||||
operator bool() const; | operator bool() const; | ||||
protected: | protected: | ||||
using VoidParameter::setParam; | using VoidParameter::setParam; | ||||
virtual bool setParam(const char* value); | virtual bool setParam(const char* value); | ||||
virtual bool setParam(int v); | virtual bool setParam(int v); | ||||
virtual char* getDefaultStr() const; | |||||
virtual char* getValueStr() const; | |||||
virtual std::string getDefaultStr() const; | |||||
virtual std::string getValueStr() const; | |||||
operator int() const; | operator int() const; | ||||
protected: | protected: | ||||
int value; | int value; | ||||
ConfigurationObject co=ConfGlobal); | ConfigurationObject co=ConfGlobal); | ||||
virtual ~StringParameter(); | virtual ~StringParameter(); | ||||
virtual bool setParam(const char* value); | virtual bool setParam(const char* value); | ||||
virtual char* getDefaultStr() const; | |||||
virtual char* getValueStr() const; | |||||
virtual std::string getDefaultStr() const; | |||||
virtual std::string getValueStr() const; | |||||
operator const char*() const; | operator const char*() const; | ||||
// getData() returns a copy of the data - it must be delete[]d by the | |||||
// caller. | |||||
char* getData() const { return getValueStr(); } | |||||
protected: | protected: | ||||
char* value; | char* value; | ||||
char* def_value; | char* def_value; | ||||
virtual ~BinaryParameter(); | virtual ~BinaryParameter(); | ||||
virtual bool setParam(const char* value); | virtual bool setParam(const char* value); | ||||
virtual void setParam(const uint8_t* v, size_t l); | virtual void setParam(const uint8_t* v, size_t l); | ||||
virtual char* getDefaultStr() const; | |||||
virtual char* getValueStr() const; | |||||
virtual std::string getDefaultStr() const; | |||||
virtual std::string getValueStr() const; | |||||
std::vector<uint8_t> getData() const; | std::vector<uint8_t> getData() const; | ||||
double ratio; | double ratio; | ||||
char a[1024], b[1024]; | |||||
rects = 0; | rects = 0; | ||||
pixels = bytes = equivalent = 0; | pixels = bytes = equivalent = 0; | ||||
ratio = (double)stats[i].equivalent / stats[i].bytes; | ratio = (double)stats[i].equivalent / stats[i].bytes; | ||||
siPrefix(stats[i].rects, "rects", a, sizeof(a)); | |||||
siPrefix(stats[i].pixels, "pixels", b, sizeof(b)); | |||||
vlog.info(" %s: %s, %s", encodingName(i), a, b); | |||||
iecPrefix(stats[i].bytes, "B", a, sizeof(a)); | |||||
vlog.info(" %s: %s, %s", encodingName(i), | |||||
siPrefix(stats[i].rects, "rects").c_str(), | |||||
siPrefix(stats[i].pixels, "pixels").c_str()); | |||||
vlog.info(" %*s %s (1:%g ratio)", | vlog.info(" %*s %s (1:%g ratio)", | ||||
(int)strlen(encodingName(i)), "", | (int)strlen(encodingName(i)), "", | ||||
a, ratio); | |||||
iecPrefix(stats[i].bytes, "B").c_str(), ratio); | |||||
} | } | ||||
ratio = (double)equivalent / bytes; | ratio = (double)equivalent / bytes; | ||||
siPrefix(rects, "rects", a, sizeof(a)); | |||||
siPrefix(pixels, "pixels", b, sizeof(b)); | |||||
vlog.info(" Total: %s, %s", a, b); | |||||
iecPrefix(bytes, "B", a, sizeof(a)); | |||||
vlog.info(" %s (1:%g ratio)", a, ratio); | |||||
vlog.info(" Total: %s, %s", | |||||
siPrefix(rects, "rects").c_str(), | |||||
siPrefix(pixels, "pixels").c_str()); | |||||
vlog.info(" %s (1:%g ratio)", | |||||
iecPrefix(bytes, "B").c_str(), ratio); | |||||
} | } | ||||
void DecodeManager::setThreadException(const rdr::Exception& e) | void DecodeManager::setThreadException(const rdr::Exception& e) |
double ratio; | double ratio; | ||||
char a[1024], b[1024]; | |||||
rects = 0; | rects = 0; | ||||
pixels = bytes = equivalent = 0; | pixels = bytes = equivalent = 0; | ||||
ratio = (double)copyStats.equivalent / copyStats.bytes; | ratio = (double)copyStats.equivalent / copyStats.bytes; | ||||
siPrefix(copyStats.rects, "rects", a, sizeof(a)); | |||||
siPrefix(copyStats.pixels, "pixels", b, sizeof(b)); | |||||
vlog.info(" %s: %s, %s", "Copies", a, b); | |||||
iecPrefix(copyStats.bytes, "B", a, sizeof(a)); | |||||
vlog.info(" %s: %s, %s", "Copies", | |||||
siPrefix(copyStats.rects, "rects").c_str(), | |||||
siPrefix(copyStats.pixels, "pixels").c_str()); | |||||
vlog.info(" %*s %s (1:%g ratio)", | vlog.info(" %*s %s (1:%g ratio)", | ||||
(int)strlen("Copies"), "", | (int)strlen("Copies"), "", | ||||
a, ratio); | |||||
iecPrefix(copyStats.bytes, "B").c_str(), ratio); | |||||
} | } | ||||
for (i = 0;i < stats.size();i++) { | for (i = 0;i < stats.size();i++) { | ||||
ratio = (double)stats[i][j].equivalent / stats[i][j].bytes; | ratio = (double)stats[i][j].equivalent / stats[i][j].bytes; | ||||
siPrefix(stats[i][j].rects, "rects", a, sizeof(a)); | |||||
siPrefix(stats[i][j].pixels, "pixels", b, sizeof(b)); | |||||
vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j), a, b); | |||||
iecPrefix(stats[i][j].bytes, "B", a, sizeof(a)); | |||||
vlog.info(" %s: %s, %s", encoderTypeName((EncoderType)j), | |||||
siPrefix(stats[i][j].rects, "rects").c_str(), | |||||
siPrefix(stats[i][j].pixels, "pixels").c_str()); | |||||
vlog.info(" %*s %s (1:%g ratio)", | vlog.info(" %*s %s (1:%g ratio)", | ||||
(int)strlen(encoderTypeName((EncoderType)j)), "", | (int)strlen(encoderTypeName((EncoderType)j)), "", | ||||
a, ratio); | |||||
iecPrefix(stats[i][j].bytes, "B").c_str(), ratio); | |||||
} | } | ||||
} | } | ||||
ratio = (double)equivalent / bytes; | ratio = (double)equivalent / bytes; | ||||
siPrefix(rects, "rects", a, sizeof(a)); | |||||
siPrefix(pixels, "pixels", b, sizeof(b)); | |||||
vlog.info(" Total: %s, %s", a, b); | |||||
iecPrefix(bytes, "B", a, sizeof(a)); | |||||
vlog.info(" %s (1:%g ratio)", a, ratio); | |||||
vlog.info(" Total: %s, %s", | |||||
siPrefix(rects, "rects").c_str(), | |||||
siPrefix(pixels, "pixels").c_str()); | |||||
vlog.info(" %s (1:%g ratio)", | |||||
iecPrefix(bytes, "B").c_str(), ratio); | |||||
} | } | ||||
bool EncodeManager::supported(int encoding) | bool EncodeManager::supported(int encoding) |
return true; | return true; | ||||
} | } | ||||
static void getHostAndPort(const char* hi, char** host, int* port, int basePort=5900) { | |||||
static void getHostAndPort(const char* hi, std::string* host, | |||||
int* port, int basePort=5900) | |||||
{ | |||||
const char* hostStart; | const char* hostStart; | ||||
const char* hostEnd; | const char* hostEnd; | ||||
const char* portStart; | const char* portStart; | ||||
hostEnd--; | hostEnd--; | ||||
if (hostStart == hostEnd) | if (hostStart == hostEnd) | ||||
*host = strDup("localhost"); | |||||
else { | |||||
size_t len; | |||||
len = hostEnd - hostStart + 1; | |||||
*host = new char[len]; | |||||
strncpy(*host, hostStart, len-1); | |||||
(*host)[len-1] = '\0'; | |||||
} | |||||
*host = "localhost"; | |||||
else | |||||
*host = std::string(hostStart, hostEnd - hostStart); | |||||
if (portStart == NULL) | if (portStart == NULL) | ||||
*port = basePort; | *port = basePort; |
LogWriter::setLogParams("*::0"); | LogWriter::setLogParams("*::0"); | ||||
StringParameter::setParam(v); | StringParameter::setParam(v); | ||||
CharArray logParam; | CharArray logParam; | ||||
CharArray params(getData()); | |||||
CharArray params(strDup(getValueStr().c_str())); | |||||
while (params.buf) { | while (params.buf) { | ||||
strSplit(params.buf, ',', &logParam.buf, ¶ms.buf); | strSplit(params.buf, ',', &logParam.buf, ¶ms.buf); | ||||
if (strlen(logParam.buf) && !LogWriter::setLogParams(logParam.buf)) | if (strlen(logParam.buf) && !LogWriter::setLogParams(logParam.buf)) |
strFree(clientClipboard); | strFree(clientClipboard); | ||||
clientClipboard = NULL; | clientClipboard = NULL; | ||||
clientClipboard = latin1ToUTF8(str); | |||||
clientClipboard = strDup(latin1ToUTF8(str).c_str()); | |||||
handleClipboardAnnounce(true); | handleClipboardAnnounce(true); | ||||
} | } | ||||
strFree(clientClipboard); | strFree(clientClipboard); | ||||
clientClipboard = NULL; | clientClipboard = NULL; | ||||
clientClipboard = convertLF((const char*)data[0], lengths[0]); | |||||
std::string filtered(convertLF((const char*)data[0], lengths[0])); | |||||
clientClipboard = strDup(filtered.c_str()); | |||||
// FIXME: Should probably verify that this data was actually requested | // FIXME: Should probably verify that this data was actually requested | ||||
handleClipboardData(clientClipboard); | handleClipboardData(clientClipboard); | ||||
{ | { | ||||
if (client.supportsEncoding(pseudoEncodingExtendedClipboard) && | if (client.supportsEncoding(pseudoEncodingExtendedClipboard) && | ||||
(client.clipboardFlags() & rfb::clipboardProvide)) { | (client.clipboardFlags() & rfb::clipboardProvide)) { | ||||
CharArray filtered(convertCRLF(data)); | |||||
size_t sizes[1] = { strlen(filtered.buf) + 1 }; | |||||
const uint8_t* data[1] = { (const uint8_t*)filtered.buf }; | |||||
std::string filtered(convertCRLF(data)); | |||||
size_t sizes[1] = { filtered.size() + 1 }; | |||||
const uint8_t* data[1] = { (const uint8_t*)filtered.c_str() }; | |||||
if (unsolicitedClipboardAttempt) { | if (unsolicitedClipboardAttempt) { | ||||
unsolicitedClipboardAttempt = false; | unsolicitedClipboardAttempt = false; | ||||
writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); | writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); | ||||
} else { | } else { | ||||
CharArray latin1(utf8ToLatin1(data)); | |||||
std::string latin1(utf8ToLatin1(data)); | |||||
writer()->writeServerCutText(latin1.buf); | |||||
writer()->writeServerCutText(latin1.c_str()); | |||||
} | } | ||||
} | } | ||||
if (lengths[i] == 0) | if (lengths[i] == 0) | ||||
vlog.debug(" %s (only notify)", type); | vlog.debug(" %s (only notify)", type); | ||||
else { | else { | ||||
char bytes[1024]; | |||||
iecPrefix(lengths[i], "B", bytes, sizeof(bytes)); | |||||
vlog.debug(" %s (automatically send up to %s)", | vlog.debug(" %s (automatically send up to %s)", | ||||
type, bytes); | |||||
type, iecPrefix(lengths[i], "B").c_str()); | |||||
} | } | ||||
} | } | ||||
} | } |
CharArray ca(len); | CharArray ca(len); | ||||
is->readBytes(ca.buf, len); | is->readBytes(ca.buf, len); | ||||
CharArray filtered(convertLF(ca.buf, len)); | |||||
handler->clientCutText(filtered.buf); | |||||
std::string filtered(convertLF(ca.buf, len)); | |||||
handler->clientCutText(filtered.c_str()); | |||||
return true; | return true; | ||||
} | } |
bool PasswordValidator::validUser(const char* username) | bool PasswordValidator::validUser(const char* username) | ||||
{ | { | ||||
CharArray users(plainUsers.getValueStr()), user; | |||||
CharArray users(strDup(plainUsers.getValueStr().c_str())); | |||||
CharArray user; | |||||
while (users.buf) { | while (users.buf) { | ||||
strSplit(users.buf, ',', &user.buf, &users.buf); | strSplit(users.buf, ',', &user.buf, &users.buf); |
*/ | */ | ||||
#ifndef __RFB_USERPASSWDGETTER_H__ | #ifndef __RFB_USERPASSWDGETTER_H__ | ||||
#define __RFB_USERPASSWDGETTER_H__ | #define __RFB_USERPASSWDGETTER_H__ | ||||
#include <string> | |||||
namespace rfb { | namespace rfb { | ||||
class UserPasswdGetter { | class UserPasswdGetter { | ||||
public: | public: | ||||
// getUserPasswd gets the username and password. This might involve a | // getUserPasswd gets the username and password. This might involve a | ||||
// dialog, getpass(), etc. The user buffer pointer can be null, in which | // dialog, getpass(), etc. The user buffer pointer can be null, in which | ||||
// case no user name will be retrieved. The caller MUST delete [] the | |||||
// result(s). | |||||
virtual void getUserPasswd(bool secure, char** user, char** password)=0; | |||||
// case no user name will be retrieved. | |||||
virtual void getUserPasswd(bool secure, std::string* user, | |||||
std::string* password)=0; | |||||
virtual ~UserPasswdGetter() {} | virtual ~UserPasswdGetter() {} | ||||
}; | }; | ||||
} | } | ||||
#endif | #endif |
delete [] s; | delete [] s; | ||||
} | } | ||||
void strFree(wchar_t* s) { | |||||
delete [] s; | |||||
} | |||||
bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) { | bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd) { | ||||
CharArray out1old, out2old; | CharArray out1old, out2old; | ||||
} | } | ||||
} | } | ||||
char* binToHex(const uint8_t* in, size_t inlen) { | |||||
char* out = new char[inlen*2+1](); | |||||
binToHex(in, inlen, out, inlen*2); | |||||
std::string binToHex(const uint8_t* in, size_t inlen) { | |||||
char* buffer = new char[inlen*2+1](); | |||||
std::string out; | |||||
binToHex(in, inlen, buffer, inlen*2); | |||||
out = buffer; | |||||
delete [] buffer; | |||||
return out; | return out; | ||||
} | } | ||||
return out; | return out; | ||||
} | } | ||||
char* convertLF(const char* src, size_t bytes) | |||||
std::string convertLF(const char* src, size_t bytes) | |||||
{ | { | ||||
char* buffer; | |||||
size_t sz; | size_t sz; | ||||
std::string out; | |||||
char* out; | |||||
const char* in; | const char* in; | ||||
size_t in_len; | size_t in_len; | ||||
// Always include space for a NULL | |||||
sz = 1; | |||||
// Compute output size | // Compute output size | ||||
sz = 0; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
in_len--; | in_len--; | ||||
} | } | ||||
// Alloc | |||||
buffer = new char[sz]; | |||||
memset(buffer, 0, sz); | |||||
// Reserve space | |||||
out.reserve(sz); | |||||
// And convert | // And convert | ||||
out = buffer; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
if (*in != '\r') { | if (*in != '\r') { | ||||
*out++ = *in++; | |||||
out += *in++; | |||||
in_len--; | in_len--; | ||||
continue; | continue; | ||||
} | } | ||||
if ((in_len < 2) || (*(in+1) != '\n')) | if ((in_len < 2) || (*(in+1) != '\n')) | ||||
*out++ = '\n'; | |||||
out += '\n'; | |||||
in++; | in++; | ||||
in_len--; | in_len--; | ||||
} | } | ||||
return buffer; | |||||
return out; | |||||
} | } | ||||
char* convertCRLF(const char* src, size_t bytes) | |||||
std::string convertCRLF(const char* src, size_t bytes) | |||||
{ | { | ||||
char* buffer; | |||||
std::string out; | |||||
size_t sz; | size_t sz; | ||||
char* out; | |||||
const char* in; | const char* in; | ||||
size_t in_len; | size_t in_len; | ||||
// Always include space for a NULL | |||||
sz = 1; | |||||
// Compute output size | // Compute output size | ||||
sz = 0; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
in_len--; | in_len--; | ||||
} | } | ||||
// Alloc | |||||
buffer = new char[sz]; | |||||
memset(buffer, 0, sz); | |||||
// Reserve space | |||||
out.reserve(sz); | |||||
// And convert | // And convert | ||||
out = buffer; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
if (*in == '\n') { | if (*in == '\n') { | ||||
if ((in == src) || (*(in-1) != '\r')) | if ((in == src) || (*(in-1) != '\r')) | ||||
*out++ = '\r'; | |||||
out += '\r'; | |||||
} | } | ||||
*out = *in; | |||||
out += *in; | |||||
if (*in == '\r') { | if (*in == '\r') { | ||||
if ((in_len < 2) || (*(in+1) != '\n')) { | |||||
out++; | |||||
*out = '\n'; | |||||
} | |||||
if ((in_len < 2) || (*(in+1) != '\n')) | |||||
out += '\n'; | |||||
} | } | ||||
out++; | |||||
in++; | in++; | ||||
in_len--; | in_len--; | ||||
} | } | ||||
return buffer; | |||||
return out; | |||||
} | } | ||||
size_t ucs4ToUTF8(unsigned src, char dst[5]) { | size_t ucs4ToUTF8(unsigned src, char dst[5]) { | ||||
return 2; | return 2; | ||||
} | } | ||||
char* latin1ToUTF8(const char* src, size_t bytes) { | |||||
char* buffer; | |||||
std::string latin1ToUTF8(const char* src, size_t bytes) { | |||||
std::string out; | |||||
size_t sz; | size_t sz; | ||||
char* out; | |||||
const char* in; | const char* in; | ||||
size_t in_len; | size_t in_len; | ||||
// Always include space for a NULL | |||||
sz = 1; | |||||
// Compute output size | // Compute output size | ||||
sz = 0; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
in_len--; | in_len--; | ||||
} | } | ||||
// Alloc | |||||
buffer = new char[sz]; | |||||
memset(buffer, 0, sz); | |||||
// Reserve space | |||||
out.reserve(sz); | |||||
// And convert | // And convert | ||||
out = buffer; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
out += ucs4ToUTF8(*(const unsigned char*)in, out); | |||||
char buf[5]; | |||||
ucs4ToUTF8(*(const unsigned char*)in, buf); | |||||
out += buf; | |||||
in++; | in++; | ||||
in_len--; | in_len--; | ||||
} | } | ||||
return buffer; | |||||
return out; | |||||
} | } | ||||
char* utf8ToLatin1(const char* src, size_t bytes) { | |||||
char* buffer; | |||||
std::string utf8ToLatin1(const char* src, size_t bytes) { | |||||
std::string out; | |||||
size_t sz; | size_t sz; | ||||
char* out; | |||||
const char* in; | const char* in; | ||||
size_t in_len; | size_t in_len; | ||||
// Always include space for a NULL | |||||
sz = 1; | |||||
// Compute output size | // Compute output size | ||||
sz = 0; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
sz++; | sz++; | ||||
} | } | ||||
// Alloc | |||||
buffer = new char[sz]; | |||||
memset(buffer, 0, sz); | |||||
// Reserve space | |||||
out.reserve(sz); | |||||
// And convert | // And convert | ||||
out = buffer; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
in_len -= len; | in_len -= len; | ||||
if (ucs > 0xff) | if (ucs > 0xff) | ||||
*out++ = '?'; | |||||
out += '?'; | |||||
else | else | ||||
*out++ = (unsigned char)ucs; | |||||
out += (unsigned char)ucs; | |||||
} | } | ||||
return buffer; | |||||
return out; | |||||
} | } | ||||
char* utf16ToUTF8(const wchar_t* src, size_t units) | |||||
std::string utf16ToUTF8(const wchar_t* src, size_t units) | |||||
{ | { | ||||
char* buffer; | |||||
std::string out; | |||||
size_t sz; | size_t sz; | ||||
char* out; | |||||
const wchar_t* in; | const wchar_t* in; | ||||
size_t in_len; | size_t in_len; | ||||
// Always include space for a NULL | |||||
sz = 1; | |||||
// Compute output size | // Compute output size | ||||
sz = 0; | |||||
in = src; | in = src; | ||||
in_len = units; | in_len = units; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
sz += ucs4ToUTF8(ucs, buf); | sz += ucs4ToUTF8(ucs, buf); | ||||
} | } | ||||
// Alloc | |||||
buffer = new char[sz]; | |||||
memset(buffer, 0, sz); | |||||
// Reserve space | |||||
out.reserve(sz); | |||||
// And convert | // And convert | ||||
out = buffer; | |||||
in = src; | in = src; | ||||
in_len = units; | in_len = units; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
size_t len; | size_t len; | ||||
unsigned ucs; | unsigned ucs; | ||||
char buf[5]; | |||||
len = utf16ToUCS4(in, in_len, &ucs); | len = utf16ToUCS4(in, in_len, &ucs); | ||||
in += len; | in += len; | ||||
in_len -= len; | in_len -= len; | ||||
out += ucs4ToUTF8(ucs, out); | |||||
ucs4ToUTF8(ucs, buf); | |||||
out += buf; | |||||
} | } | ||||
return buffer; | |||||
return out; | |||||
} | } | ||||
wchar_t* utf8ToUTF16(const char* src, size_t bytes) | |||||
std::wstring utf8ToUTF16(const char* src, size_t bytes) | |||||
{ | { | ||||
wchar_t* buffer; | |||||
std::wstring out; | |||||
size_t sz; | size_t sz; | ||||
wchar_t* out; | |||||
const char* in; | const char* in; | ||||
size_t in_len; | size_t in_len; | ||||
// Always include space for a NULL | |||||
sz = 1; | |||||
// Compute output size | // Compute output size | ||||
sz = 0; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
sz += ucs4ToUTF16(ucs, buf); | sz += ucs4ToUTF16(ucs, buf); | ||||
} | } | ||||
// Alloc | |||||
buffer = new wchar_t[sz]; | |||||
memset(buffer, 0, sz * sizeof(wchar_t)); | |||||
// Reserve space | |||||
out.reserve(sz); | |||||
// And convert | // And convert | ||||
out = buffer; | |||||
in = src; | in = src; | ||||
in_len = bytes; | in_len = bytes; | ||||
while ((in_len > 0) && (*in != '\0')) { | while ((in_len > 0) && (*in != '\0')) { | ||||
size_t len; | size_t len; | ||||
unsigned ucs; | unsigned ucs; | ||||
wchar_t buf[3]; | |||||
len = utf8ToUCS4(in, in_len, &ucs); | len = utf8ToUCS4(in, in_len, &ucs); | ||||
in += len; | in += len; | ||||
in_len -= len; | in_len -= len; | ||||
out += ucs4ToUTF16(ucs, out); | |||||
ucs4ToUTF16(ucs, buf); | |||||
out += buf; | |||||
} | } | ||||
return buffer; | |||||
return out; | |||||
} | } | ||||
unsigned msBetween(const struct timeval *first, | unsigned msBetween(const struct timeval *first, | ||||
return false; | return false; | ||||
} | } | ||||
static size_t doPrefix(long long value, const char *unit, | |||||
char *buffer, size_t maxlen, | |||||
unsigned divisor, const char **prefixes, | |||||
size_t prefixCount, int precision) { | |||||
static std::string doPrefix(long long value, const char *unit, | |||||
unsigned divisor, const char **prefixes, | |||||
size_t prefixCount, int precision) { | |||||
char buffer[256]; | |||||
double newValue; | double newValue; | ||||
size_t prefix, len; | |||||
size_t prefix; | |||||
newValue = value; | newValue = value; | ||||
prefix = 0; | prefix = 0; | ||||
prefix++; | prefix++; | ||||
} | } | ||||
len = snprintf(buffer, maxlen, "%.*g %s%s", precision, newValue, | |||||
(prefix == 0) ? "" : prefixes[prefix-1], unit); | |||||
buffer[maxlen-1] = '\0'; | |||||
snprintf(buffer, sizeof(buffer), "%.*g %s%s", precision, newValue, | |||||
(prefix == 0) ? "" : prefixes[prefix-1], unit); | |||||
buffer[sizeof(buffer)-1] = '\0'; | |||||
return len; | |||||
return buffer; | |||||
} | } | ||||
static const char *siPrefixes[] = | static const char *siPrefixes[] = | ||||
static const char *iecPrefixes[] = | static const char *iecPrefixes[] = | ||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; | { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; | ||||
size_t siPrefix(long long value, const char *unit, | |||||
char *buffer, size_t maxlen, int precision) { | |||||
return doPrefix(value, unit, buffer, maxlen, 1000, siPrefixes, | |||||
std::string siPrefix(long long value, const char *unit, | |||||
int precision) { | |||||
return doPrefix(value, unit, 1000, siPrefixes, | |||||
sizeof(siPrefixes)/sizeof(*siPrefixes), | sizeof(siPrefixes)/sizeof(*siPrefixes), | ||||
precision); | precision); | ||||
} | } | ||||
size_t iecPrefix(long long value, const char *unit, | |||||
char *buffer, size_t maxlen, int precision) { | |||||
return doPrefix(value, unit, buffer, maxlen, 1024, iecPrefixes, | |||||
std::string iecPrefix(long long value, const char *unit, | |||||
int precision) { | |||||
return doPrefix(value, unit, 1024, iecPrefixes, | |||||
sizeof(iecPrefixes)/sizeof(*iecPrefixes), | sizeof(iecPrefixes)/sizeof(*iecPrefixes), | ||||
precision); | precision); | ||||
} | } |
#include <string.h> | #include <string.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <string> | |||||
#include <vector> | #include <vector> | ||||
struct timeval; | struct timeval; | ||||
char* strDup(const char* s); | char* strDup(const char* s); | ||||
void strFree(char* s); | void strFree(char* s); | ||||
void strFree(wchar_t* s); | |||||
// Returns true if split successful. Returns false otherwise. | // Returns true if split successful. Returns false otherwise. | ||||
// ALWAYS *copies* first part of string to out1 buffer. | // ALWAYS *copies* first part of string to out1 buffer. | ||||
// Conversion to and from a hex string | // Conversion to and from a hex string | ||||
void binToHex(const uint8_t* in, size_t inlen, char* out, size_t outlen); | void binToHex(const uint8_t* in, size_t inlen, char* out, size_t outlen); | ||||
char* binToHex(const uint8_t* in, size_t inlen); | |||||
std::string binToHex(const uint8_t* in, size_t inlen); | |||||
bool hexToBin(const char* in, size_t inlen, uint8_t* out, size_t outlen); | bool hexToBin(const char* in, size_t inlen, uint8_t* out, size_t outlen); | ||||
std::vector<uint8_t> hexToBin(const char* in, size_t inlen); | std::vector<uint8_t> hexToBin(const char* in, size_t inlen); | ||||
// Makes sure line endings are in a certain format | // Makes sure line endings are in a certain format | ||||
char* convertLF(const char* src, size_t bytes = (size_t)-1); | |||||
char* convertCRLF(const char* src, size_t bytes = (size_t)-1); | |||||
std::string convertLF(const char* src, size_t bytes = (size_t)-1); | |||||
std::string convertCRLF(const char* src, size_t bytes = (size_t)-1); | |||||
// Convertions between various Unicode formats. The returned strings are | |||||
// always null terminated and must be freed using strFree(). | |||||
// Convertions between various Unicode formats | |||||
size_t ucs4ToUTF8(unsigned src, char dst[5]); | size_t ucs4ToUTF8(unsigned src, char dst[5]); | ||||
size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst); | size_t utf8ToUCS4(const char* src, size_t max, unsigned* dst); | ||||
size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]); | size_t ucs4ToUTF16(unsigned src, wchar_t dst[3]); | ||||
size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst); | size_t utf16ToUCS4(const wchar_t* src, size_t max, unsigned* dst); | ||||
char* latin1ToUTF8(const char* src, size_t bytes = (size_t)-1); | |||||
char* utf8ToLatin1(const char* src, size_t bytes = (size_t)-1); | |||||
std::string latin1ToUTF8(const char* src, size_t bytes = (size_t)-1); | |||||
std::string utf8ToLatin1(const char* src, size_t bytes = (size_t)-1); | |||||
char* utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1); | |||||
wchar_t* utf8ToUTF16(const char* src, size_t bytes = (size_t)-1); | |||||
std::string utf16ToUTF8(const wchar_t* src, size_t units = (size_t)-1); | |||||
std::wstring utf8ToUTF16(const char* src, size_t bytes = (size_t)-1); | |||||
// HELPER functions for timeout handling | // HELPER functions for timeout handling | ||||
bool isBefore(const struct timeval *first, | bool isBefore(const struct timeval *first, | ||||
const struct timeval *second); | const struct timeval *second); | ||||
size_t siPrefix(long long value, const char *unit, | |||||
char *buffer, size_t maxlen, int precision=6); | |||||
size_t iecPrefix(long long value, const char *unit, | |||||
char *buffer, size_t maxlen, int precision=6); | |||||
std::string siPrefix(long long value, const char *unit, | |||||
int precision=6); | |||||
std::string iecPrefix(long long value, const char *unit, | |||||
int precision=6); | |||||
} | } | ||||
// Some platforms (e.g. Windows) include max() and min() macros in their | // Some platforms (e.g. Windows) include max() and min() macros in their |
double time[3]; | double time[3]; | ||||
double delay, rate; | double delay, rate; | ||||
char s[1024]; | |||||
// Run the test several times at different resolutions... | // Run the test several times at different resolutions... | ||||
dosubtest(win, 800, 600, &pixels[0], &frames[0], &time[0]); | dosubtest(win, 800, 600, &pixels[0], &frames[0], &time[0]); | ||||
} | } | ||||
fprintf(stderr, "Rendering delay: %g ms/frame\n", delay * 1000.0); | fprintf(stderr, "Rendering delay: %g ms/frame\n", delay * 1000.0); | ||||
if (rate == 0.0) | |||||
strcpy(s, "N/A pixels/s"); | |||||
else | |||||
rfb::siPrefix(1.0 / rate, "pixels/s", s, sizeof(s)); | |||||
fprintf(stderr, "Rendering rate: %s\n", s); | |||||
fprintf(stderr, "Rendering rate: %s\n", | |||||
(rate == 0.0) ? "N/A pixels/s" : | |||||
rfb::siPrefix(1.0 / rate, "pixels/s").c_str()); | |||||
fprintf(stderr, "Maximum FPS: %g fps @ 1920x1080\n", | fprintf(stderr, "Maximum FPS: %g fps @ 1920x1080\n", | ||||
1.0 / (delay + rate * 1920 * 1080)); | 1.0 / (delay + rate * 1920 * 1080)); | ||||
} | } |
static void testLF(const char* input, const char* expected) | static void testLF(const char* input, const char* expected) | ||||
{ | { | ||||
char* output; | |||||
std::string output; | |||||
printf("convertLF(\"%s\"): ", escape(input)); | printf("convertLF(\"%s\"): ", escape(input)); | ||||
output = rfb::convertLF(input); | output = rfb::convertLF(input); | ||||
if (strcmp(output, expected) != 0) | |||||
printf("FAILED: got \"%s\"", escape(output)); | |||||
if (output != expected) | |||||
printf("FAILED: got \"%s\"", escape(output.c_str())); | |||||
else | else | ||||
printf("OK"); | printf("OK"); | ||||
printf("\n"); | printf("\n"); | ||||
fflush(stdout); | fflush(stdout); | ||||
rfb::strFree(output); | |||||
} | } | ||||
static void testCRLF(const char* input, const char* expected) | static void testCRLF(const char* input, const char* expected) | ||||
{ | { | ||||
char* output; | |||||
std::string output; | |||||
printf("convertCRLF(\"%s\"): ", escape(input)); | printf("convertCRLF(\"%s\"): ", escape(input)); | ||||
output = rfb::convertCRLF(input); | output = rfb::convertCRLF(input); | ||||
if (strcmp(output, expected) != 0) | |||||
printf("FAILED: got \"%s\"", escape(output)); | |||||
if (output != expected) | |||||
printf("FAILED: got \"%s\"", escape(output.c_str())); | |||||
else | else | ||||
printf("OK"); | printf("OK"); | ||||
printf("\n"); | printf("\n"); | ||||
fflush(stdout); | fflush(stdout); | ||||
rfb::strFree(output); | |||||
} | } | ||||
int main(int /*argc*/, char** /*argv*/) | int main(int /*argc*/, char** /*argv*/) |
static void doTest(const char* hostAndPort, | static void doTest(const char* hostAndPort, | ||||
const char* expectedHost, int expectedPort) | const char* expectedHost, int expectedPort) | ||||
{ | { | ||||
char* host; | |||||
std::string host; | |||||
int port; | int port; | ||||
printf("\"%s\": ", hostAndPort); | printf("\"%s\": ", hostAndPort); | ||||
rfb::getHostAndPort(hostAndPort, &host, &port); | rfb::getHostAndPort(hostAndPort, &host, &port); | ||||
if (strcmp(host, expectedHost) != 0) | |||||
printf("FAILED (\"%s\" != \"%s\")", host, expectedHost); | |||||
if (host != expectedHost) | |||||
printf("FAILED (\"%s\" != \"%s\")", host.c_str(), expectedHost); | |||||
else if (port != expectedPort) | else if (port != expectedPort) | ||||
printf("FAILED (%d != %d)", port, expectedPort); | printf("FAILED (%d != %d)", port, expectedPort); | ||||
else | else | ||||
printf("OK"); | printf("OK"); | ||||
printf("\n"); | printf("\n"); | ||||
fflush(stdout); | fflush(stdout); | ||||
rfb::strFree(host); | |||||
} | } | ||||
int main(int /*argc*/, char** /*argv*/) | int main(int /*argc*/, char** /*argv*/) |
unsigned ucs4; | unsigned ucs4; | ||||
char utf8[5]; | char utf8[5]; | ||||
wchar_t utf16[3]; | wchar_t utf16[3]; | ||||
char *out; | |||||
wchar_t *wout; | |||||
std::string out; | |||||
std::wstring wout; | |||||
size_t len; | size_t len; | ||||
failures = 0; | failures = 0; | ||||
continue; | continue; | ||||
out = rfb::latin1ToUTF8(latin1utf8[i].latin1); | out = rfb::latin1ToUTF8(latin1utf8[i].latin1); | ||||
if (strcmp(out, latin1utf8[i].utf8) != 0) { | |||||
if (out != latin1utf8[i].utf8) { | |||||
printf("FAILED: latin1ToUTF8() #%d\n", (int)i+1); | printf("FAILED: latin1ToUTF8() #%d\n", (int)i+1); | ||||
failures++; | failures++; | ||||
} | } | ||||
rfb::strFree(out); | |||||
} | } | ||||
for (i = 0;i < ARRAY_SIZE(latin1utf8);i++) { | for (i = 0;i < ARRAY_SIZE(latin1utf8);i++) { | ||||
out = rfb::utf8ToLatin1(latin1utf8[i].utf8); | out = rfb::utf8ToLatin1(latin1utf8[i].utf8); | ||||
if (strcmp(out, latin1utf8[i].latin1) != 0) { | |||||
if (out != latin1utf8[i].latin1) { | |||||
printf("FAILED: utf8ToLatin1() #%d\n", (int)i+1); | printf("FAILED: utf8ToLatin1() #%d\n", (int)i+1); | ||||
failures++; | failures++; | ||||
} | } | ||||
rfb::strFree(out); | |||||
} | } | ||||
for (i = 0;i < ARRAY_SIZE(utf8utf16);i++) { | for (i = 0;i < ARRAY_SIZE(utf8utf16);i++) { | ||||
continue; | continue; | ||||
out = rfb::utf16ToUTF8(utf8utf16[i].utf16); | out = rfb::utf16ToUTF8(utf8utf16[i].utf16); | ||||
if (strcmp(out, utf8utf16[i].utf8) != 0) { | |||||
if (out != utf8utf16[i].utf8) { | |||||
printf("FAILED: utf16ToUTF8() #%d\n", (int)i+1); | printf("FAILED: utf16ToUTF8() #%d\n", (int)i+1); | ||||
failures++; | failures++; | ||||
} | } | ||||
rfb::strFree(out); | |||||
} | } | ||||
for (i = 0;i < ARRAY_SIZE(utf8utf16);i++) { | for (i = 0;i < ARRAY_SIZE(utf8utf16);i++) { | ||||
continue; | continue; | ||||
wout = rfb::utf8ToUTF16(utf8utf16[i].utf8); | wout = rfb::utf8ToUTF16(utf8utf16[i].utf8); | ||||
if (wcscmp(wout, utf8utf16[i].utf16) != 0) { | |||||
if (wout != utf8utf16[i].utf16) { | |||||
printf("FAILED: utf8ToUTF16() #%d\n", (int)i+1); | printf("FAILED: utf8ToUTF16() #%d\n", (int)i+1); | ||||
failures++; | failures++; | ||||
} | } | ||||
rfb::strFree(wout); | |||||
} | } | ||||
if (failures == 0) { | if (failures == 0) { |
char* vncGetParam(const char *name) | char* vncGetParam(const char *name) | ||||
{ | { | ||||
rfb::VoidParameter *param; | |||||
char *value; | |||||
char *ret; | |||||
VoidParameter *param; | |||||
// Hack to avoid exposing password! | // Hack to avoid exposing password! | ||||
if (strcasecmp(name, "Password") == 0) | if (strcasecmp(name, "Password") == 0) | ||||
if (param == NULL) | if (param == NULL) | ||||
return NULL; | return NULL; | ||||
value = param->getValueStr(); | |||||
if (value == NULL) | |||||
return NULL; | |||||
ret = strdup(value); | |||||
delete [] value; | |||||
return ret; | |||||
return strdup(param->getValueStr().c_str()); | |||||
} | } | ||||
const char* vncGetParamDesc(const char *name) | const char* vncGetParamDesc(const char *name) | ||||
char* vncConvertLF(const char* src, size_t bytes) | char* vncConvertLF(const char* src, size_t bytes) | ||||
{ | { | ||||
try { | try { | ||||
return convertLF(src, bytes); | |||||
return strDup(convertLF(src, bytes).c_str()); | |||||
} catch (...) { | } catch (...) { | ||||
return NULL; | return NULL; | ||||
} | } | ||||
char* vncLatin1ToUTF8(const char* src, size_t bytes) | char* vncLatin1ToUTF8(const char* src, size_t bytes) | ||||
{ | { | ||||
try { | try { | ||||
return latin1ToUTF8(src, bytes); | |||||
return strDup(latin1ToUTF8(src, bytes).c_str()); | |||||
} catch (...) { | } catch (...) { | ||||
return NULL; | return NULL; | ||||
} | } | ||||
char* vncUTF8ToLatin1(const char* src, size_t bytes) | char* vncUTF8ToLatin1(const char* src, size_t bytes) | ||||
{ | { | ||||
try { | try { | ||||
return utf8ToLatin1(src, bytes); | |||||
return strDup(utf8ToLatin1(src, bytes).c_str()); | |||||
} catch (...) { | } catch (...) { | ||||
return NULL; | return NULL; | ||||
} | } |
return 0; | return 0; | ||||
} | } | ||||
char *host; | |||||
std::string host; | |||||
int port; | int port; | ||||
getHostAndPort(addr, &host, &port, 5500); | getHostAndPort(addr, &host, &port, 5500); | ||||
try { | try { | ||||
network::Socket* sock = new network::TcpSocket(host, port); | |||||
delete [] host; | |||||
network::Socket* sock = new network::TcpSocket(host.c_str(), port); | |||||
desktop[0]->addClient(sock, true); | desktop[0]->addClient(sock, true); | ||||
} catch (rdr::Exception& e) { | } catch (rdr::Exception& e) { | ||||
vlog.error("Reverse connection: %s",e.str()); | vlog.error("Reverse connection: %s",e.str()); |
static const unsigned bpsEstimateWindow = 1000; | static const unsigned bpsEstimateWindow = 1000; | ||||
CConn::CConn(const char* vncServerName, network::Socket* socket=NULL) | CConn::CConn(const char* vncServerName, network::Socket* socket=NULL) | ||||
: serverHost(0), serverPort(0), desktop(NULL), | |||||
updateCount(0), pixelCount(0), | |||||
: serverPort(0), desktop(NULL), updateCount(0), pixelCount(0), | |||||
lastServerEncoding((unsigned int)-1), bpsEstimate(20000000) | lastServerEncoding((unsigned int)-1), bpsEstimate(20000000) | ||||
{ | { | ||||
setShared(::shared); | setShared(::shared); | ||||
#ifndef WIN32 | #ifndef WIN32 | ||||
if (strchr(vncServerName, '/') != NULL) { | if (strchr(vncServerName, '/') != NULL) { | ||||
sock = new network::UnixSocket(vncServerName); | sock = new network::UnixSocket(vncServerName); | ||||
serverHost = strDup(sock->getPeerAddress()); | |||||
vlog.info(_("Connected to socket %s"), serverHost); | |||||
serverHost = sock->getPeerAddress(); | |||||
vlog.info(_("Connected to socket %s"), serverHost.c_str()); | |||||
} else | } else | ||||
#endif | #endif | ||||
{ | { | ||||
getHostAndPort(vncServerName, &serverHost, &serverPort); | getHostAndPort(vncServerName, &serverHost, &serverPort); | ||||
sock = new network::TcpSocket(serverHost, serverPort); | |||||
vlog.info(_("Connected to host %s port %d"), serverHost, serverPort); | |||||
sock = new network::TcpSocket(serverHost.c_str(), serverPort); | |||||
vlog.info(_("Connected to host %s port %d"), | |||||
serverHost.c_str(), serverPort); | |||||
} | } | ||||
} catch (rdr::Exception& e) { | } catch (rdr::Exception& e) { | ||||
vlog.error("%s", e.str()); | vlog.error("%s", e.str()); | ||||
Fl::add_fd(sock->getFd(), FL_READ | FL_EXCEPT, socketEvent, this); | Fl::add_fd(sock->getFd(), FL_READ | FL_EXCEPT, socketEvent, this); | ||||
setServerName(serverHost); | |||||
setServerName(serverHost.c_str()); | |||||
setStreams(&sock->inStream(), &sock->outStream()); | setStreams(&sock->inStream(), &sock->outStream()); | ||||
initialiseProtocol(); | initialiseProtocol(); | ||||
if (desktop) | if (desktop) | ||||
delete desktop; | delete desktop; | ||||
delete [] serverHost; | |||||
if (sock) | if (sock) | ||||
Fl::remove_fd(sock->getFd()); | Fl::remove_fd(sock->getFd()); | ||||
delete sock; | delete sock; | ||||
strcat(infoText, "\n"); | strcat(infoText, "\n"); | ||||
snprintf(scratch, sizeof(scratch), | snprintf(scratch, sizeof(scratch), | ||||
_("Host: %.80s port: %d"), serverHost, serverPort); | |||||
_("Host: %.80s port: %d"), serverHost.c_str(), serverPort); | |||||
strcat(infoText, scratch); | strcat(infoText, scratch); | ||||
strcat(infoText, "\n"); | strcat(infoText, "\n"); | ||||
static void handleUpdateTimeout(void *data); | static void handleUpdateTimeout(void *data); | ||||
private: | private: | ||||
char* serverHost; | |||||
std::string serverHost; | |||||
int serverPort; | int serverPort; | ||||
network::Socket* sock; | network::Socket* sock; | ||||
fl_draw(buffer, 5, statsHeight - 5); | fl_draw(buffer, 5, statsHeight - 5); | ||||
fl_color(FL_YELLOW); | fl_color(FL_YELLOW); | ||||
siPrefix(self->stats[statsCount-1].pps, "pix/s", | |||||
buffer, sizeof(buffer), 3); | |||||
fl_draw(buffer, 5 + (statsWidth-10)/3, statsHeight - 5); | |||||
fl_draw(siPrefix(self->stats[statsCount-1].pps, "pix/s").c_str(), | |||||
5 + (statsWidth-10)/3, statsHeight - 5); | |||||
fl_color(FL_RED); | fl_color(FL_RED); | ||||
siPrefix(self->stats[statsCount-1].bps * 8, "bps", | |||||
buffer, sizeof(buffer), 3); | |||||
fl_draw(buffer, 5 + (statsWidth-10)*2/3, statsHeight - 5); | |||||
fl_draw(siPrefix(self->stats[statsCount-1].bps * 8, "bps").c_str(), | |||||
5 + (statsWidth-10)*2/3, statsHeight - 5); | |||||
image = surface->image(); | image = surface->image(); | ||||
delete surface; | delete surface; |
#include <FL/Fl_Return_Button.H> | #include <FL/Fl_Return_Button.H> | ||||
#include <FL/Fl_Pixmap.H> | #include <FL/Fl_Pixmap.H> | ||||
#include <rfb/util.h> | |||||
#include <rfb/Password.h> | #include <rfb/Password.h> | ||||
#include <rfb/Exception.h> | #include <rfb/Exception.h> | ||||
{ | { | ||||
} | } | ||||
void UserDialog::getUserPasswd(bool secure, char** user, char** password) | |||||
void UserDialog::getUserPasswd(bool secure, std::string* user, | |||||
std::string* password) | |||||
{ | { | ||||
const char *passwordFileName(passwordFile); | const char *passwordFileName(passwordFile); | ||||
char *envPassword = getenv("VNC_PASSWORD"); | char *envPassword = getenv("VNC_PASSWORD"); | ||||
if(user && envUsername && envPassword) { | if(user && envUsername && envPassword) { | ||||
*user = strdup(envUsername); | |||||
*password = strdup(envPassword); | |||||
*user = envUsername; | |||||
*password = envPassword; | |||||
return; | return; | ||||
} | } | ||||
if (!user && envPassword) { | if (!user && envPassword) { | ||||
*password = strdup(envPassword); | |||||
*password = envPassword; | |||||
return; | return; | ||||
} | } | ||||
fclose(fp); | fclose(fp); | ||||
PlainPasswd passwd(obfPwd); | PlainPasswd passwd(obfPwd); | ||||
*password = passwd.takeBuf(); | |||||
*password = passwd.buf; | |||||
return; | return; | ||||
} | } | ||||
if (ret_val == 0) { | if (ret_val == 0) { | ||||
if (user) | if (user) | ||||
*user = strDup(username->value()); | |||||
*password = strDup(passwd->value()); | |||||
*user = username->value(); | |||||
*password = passwd->value(); | |||||
} | } | ||||
delete win; | delete win; |
// UserPasswdGetter callbacks | // UserPasswdGetter callbacks | ||||
void getUserPasswd(bool secure, char** user, char** password); | |||||
void getUserPasswd(bool secure, std::string* user, | |||||
std::string* password); | |||||
// UserMsgBox callbacks | // UserMsgBox callbacks | ||||
int Viewport::handle(int event) | int Viewport::handle(int event) | ||||
{ | { | ||||
char *filtered; | |||||
std::string filtered; | |||||
int buttonMask, wheelMask; | int buttonMask, wheelMask; | ||||
DownMap::const_iterator iter; | DownMap::const_iterator iter; | ||||
case FL_PASTE: | case FL_PASTE: | ||||
filtered = convertLF(Fl::event_text(), Fl::event_length()); | filtered = convertLF(Fl::event_text(), Fl::event_length()); | ||||
vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(filtered)); | |||||
vlog.debug("Sending clipboard data (%d bytes)", (int)filtered.size()); | |||||
try { | try { | ||||
cc->sendClipboardData(filtered); | |||||
cc->sendClipboardData(filtered.c_str()); | |||||
} catch (rdr::Exception& e) { | } catch (rdr::Exception& e) { | ||||
vlog.error("%s", e.str()); | vlog.error("%s", e.str()); | ||||
abort_connection_with_unexpected_error(e); | abort_connection_with_unexpected_error(e); | ||||
} | } | ||||
strFree(filtered); | |||||
return 1; | return 1; | ||||
case FL_ENTER: | case FL_ENTER: |
return MsgWindow::processMessage(msg, wParam, lParam); | return MsgWindow::processMessage(msg, wParam, lParam); | ||||
}; | }; | ||||
char* | |||||
std::string | |||||
Clipboard::getClipText() { | Clipboard::getClipText() { | ||||
HGLOBAL cliphandle; | HGLOBAL cliphandle; | ||||
wchar_t* clipdata; | wchar_t* clipdata; | ||||
CharArray utf8; | |||||
std::string utf8; | |||||
// Open the clipboard | // Open the clipboard | ||||
if (!OpenClipboard(getHandle())) | if (!OpenClipboard(getHandle())) | ||||
} | } | ||||
// Convert it to UTF-8 | // Convert it to UTF-8 | ||||
utf8.replaceBuf(utf16ToUTF8(clipdata)); | |||||
utf8 = utf16ToUTF8(clipdata); | |||||
// Release the buffer and close the clipboard | // Release the buffer and close the clipboard | ||||
GlobalUnlock(cliphandle); | GlobalUnlock(cliphandle); | ||||
CloseClipboard(); | CloseClipboard(); | ||||
return convertLF(utf8.buf); | |||||
return convertLF(utf8.c_str()); | |||||
} | } | ||||
void | void | ||||
throw rdr::SystemException("unable to open Win32 clipboard", GetLastError()); | throw rdr::SystemException("unable to open Win32 clipboard", GetLastError()); | ||||
// - Convert the supplied clipboard text into UTF-16 format with CRLF | // - Convert the supplied clipboard text into UTF-16 format with CRLF | ||||
CharArray filtered(convertCRLF(text)); | |||||
wchar_t* utf16; | |||||
utf16 = utf8ToUTF16(filtered.buf); | |||||
std::string filtered(convertCRLF(text)); | |||||
std::wstring utf16(utf8ToUTF16(filtered.c_str())); | |||||
// - Allocate global memory for the data | // - Allocate global memory for the data | ||||
clip_handle = ::GlobalAlloc(GMEM_MOVEABLE, (wcslen(utf16) + 1) * 2); | |||||
clip_handle = ::GlobalAlloc(GMEM_MOVEABLE, (utf16.size() + 1) * 2); | |||||
wchar_t* data = (wchar_t*) GlobalLock(clip_handle); | wchar_t* data = (wchar_t*) GlobalLock(clip_handle); | ||||
wcscpy(data, utf16); | |||||
wcscpy(data, utf16.c_str()); | |||||
GlobalUnlock(clip_handle); | GlobalUnlock(clip_handle); | ||||
strFree(utf16); | |||||
// - Next, we must clear out any existing data | // - Next, we must clear out any existing data | ||||
if (!EmptyClipboard()) | if (!EmptyClipboard()) | ||||
throw rdr::SystemException("unable to empty Win32 clipboard", GetLastError()); | throw rdr::SystemException("unable to empty Win32 clipboard", GetLastError()); |
void setNotifier(Notifier* cbn) {notifier = cbn;} | void setNotifier(Notifier* cbn) {notifier = cbn;} | ||||
// - Get the clipboard contents | // - Get the clipboard contents | ||||
char* getClipText(); | |||||
std::string getClipText(); | |||||
// - Set the clipboard contents | // - Set the clipboard contents | ||||
void setClipText(const char* text); | void setClipText(const char* text); |
#include <rfb_win32/RegConfig.h> | #include <rfb_win32/RegConfig.h> | ||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/util.h> | |||||
//#include <rdr/HexOutStream.h> | //#include <rdr/HexOutStream.h> | ||||
using namespace rfb; | using namespace rfb; | ||||
while (1) { | while (1) { | ||||
const char *name = key.getValueName(i++); | const char *name = key.getValueName(i++); | ||||
if (!name) break; | if (!name) break; | ||||
CharArray value(key.getRepresentation(name)); | |||||
if (!value.buf || !Configuration::setParam(name, value.buf)) | |||||
std::string value = key.getRepresentation(name); | |||||
if (!Configuration::setParam(name, value.c_str())) | |||||
vlog.info("unable to process %s", name); | vlog.info("unable to process %s", name); | ||||
} | } | ||||
} catch (rdr::SystemException& e) { | } catch (rdr::SystemException& e) { |
setInt(valname, value ? 1 : 0); | setInt(valname, value ? 1 : 0); | ||||
} | } | ||||
char* RegKey::getString(const char* valname) const {return getRepresentation(valname);} | |||||
char* RegKey::getString(const char* valname, const char* def) const { | |||||
std::string RegKey::getString(const char* valname) const { | |||||
return getRepresentation(valname); | |||||
} | |||||
std::string RegKey::getString(const char* valname, const char* def) const { | |||||
try { | try { | ||||
return getString(valname); | return getString(valname); | ||||
} catch(rdr::Exception&) { | } catch(rdr::Exception&) { | ||||
return strDup(def); | |||||
return def; | |||||
} | } | ||||
} | } | ||||
std::vector<uint8_t> RegKey::getBinary(const char* valname) const { | std::vector<uint8_t> RegKey::getBinary(const char* valname) const { | ||||
CharArray hex(getRepresentation(valname)); | |||||
return hexToBin(hex.buf, strlen(hex.buf)); | |||||
std::string hex = getRepresentation(valname); | |||||
return hexToBin(hex.data(), hex.size()); | |||||
} | } | ||||
std::vector<uint8_t> RegKey::getBinary(const char* valname, const uint8_t* def, size_t deflen) const { | std::vector<uint8_t> RegKey::getBinary(const char* valname, const uint8_t* def, size_t deflen) const { | ||||
try { | try { | ||||
} | } | ||||
int RegKey::getInt(const char* valname) const { | int RegKey::getInt(const char* valname) const { | ||||
CharArray tmp(getRepresentation(valname)); | |||||
return atoi(tmp.buf); | |||||
return atoi(getRepresentation(valname).c_str()); | |||||
} | } | ||||
int RegKey::getInt(const char* valname, int def) const { | int RegKey::getInt(const char* valname, int def) const { | ||||
try { | try { | ||||
return getInt(valname, def ? 1 : 0) > 0; | return getInt(valname, def ? 1 : 0) > 0; | ||||
} | } | ||||
static inline char* terminateData(char* data, int length) | |||||
{ | |||||
// We must terminate the string, just to be sure. Stupid Win32... | |||||
int len = length/sizeof(char); | |||||
CharArray str(len+1); | |||||
memcpy(str.buf, data, length); | |||||
str.buf[len] = 0; | |||||
return str.takeBuf(); | |||||
} | |||||
char* RegKey::getRepresentation(const char* valname) const { | |||||
std::string RegKey::getRepresentation(const char* valname) const { | |||||
DWORD type, length; | DWORD type, length; | ||||
LONG result = RegQueryValueEx(key, valname, 0, &type, 0, &length); | LONG result = RegQueryValueEx(key, valname, 0, &type, 0, &length); | ||||
if (result != ERROR_SUCCESS) | if (result != ERROR_SUCCESS) | ||||
switch (type) { | switch (type) { | ||||
case REG_BINARY: | case REG_BINARY: | ||||
{ | { | ||||
CharArray hex(binToHex((const uint8_t*)data.buf, length)); | |||||
return hex.takeBuf(); | |||||
return binToHex((const uint8_t*)data.buf, length); | |||||
} | } | ||||
case REG_SZ: | case REG_SZ: | ||||
if (length) { | if (length) { | ||||
return terminateData(data.buf, length); | |||||
return std::string(data.buf, length); | |||||
} else { | } else { | ||||
return strDup(""); | |||||
return ""; | |||||
} | } | ||||
case REG_DWORD: | case REG_DWORD: | ||||
{ | { | ||||
CharArray tmp(16); | |||||
sprintf(tmp.buf, "%lu", *((DWORD*)data.buf)); | |||||
return tmp.takeBuf(); | |||||
char tmp[16]; | |||||
sprintf(tmp, "%lu", *((DWORD*)data.buf)); | |||||
return tmp; | |||||
} | } | ||||
case REG_EXPAND_SZ: | case REG_EXPAND_SZ: | ||||
{ | { | ||||
if (length) { | if (length) { | ||||
CharArray str(terminateData(data.buf, length)); | |||||
DWORD required = ExpandEnvironmentStrings(str.buf, 0, 0); | |||||
std::string str(data.buf, length); | |||||
DWORD required = ExpandEnvironmentStrings(str.c_str(), 0, 0); | |||||
if (required==0) | if (required==0) | ||||
throw rdr::SystemException("ExpandEnvironmentStrings", GetLastError()); | throw rdr::SystemException("ExpandEnvironmentStrings", GetLastError()); | ||||
CharArray result(required); | CharArray result(required); | ||||
length = ExpandEnvironmentStrings(str.buf, result.buf, required); | |||||
length = ExpandEnvironmentStrings(str.c_str(), result.buf, required); | |||||
if (required<length) | if (required<length) | ||||
throw rdr::Exception("unable to expand environment strings"); | throw rdr::Exception("unable to expand environment strings"); | ||||
return result.takeBuf(); | |||||
return result.buf; | |||||
} else { | } else { | ||||
return strDup(""); | |||||
return ""; | |||||
} | } | ||||
} | } | ||||
default: | default: | ||||
bool RegKey::isValue(const char* valname) const { | bool RegKey::isValue(const char* valname) const { | ||||
try { | try { | ||||
CharArray tmp(getRepresentation(valname)); | |||||
getRepresentation(valname); | |||||
return true; | return true; | ||||
} catch(rdr::Exception&) { | } catch(rdr::Exception&) { | ||||
return false; | return false; |
void setInt(const char* valname, int i) const; | void setInt(const char* valname, int i) const; | ||||
void setBool(const char* valname, bool b) const; | void setBool(const char* valname, bool b) const; | ||||
char* getString(const char* valname) const; | |||||
char* getString(const char* valname, const char* def) const; | |||||
std::string getString(const char* valname) const; | |||||
std::string getString(const char* valname, const char* def) const; | |||||
std::vector<uint8_t> getBinary(const char* valname) const; | std::vector<uint8_t> getBinary(const char* valname) const; | ||||
std::vector<uint8_t> getBinary(const char* valname, const uint8_t* def, size_t deflength) const; | std::vector<uint8_t> getBinary(const char* valname, const uint8_t* def, size_t deflength) const; | ||||
bool getBool(const char* valname) const; | bool getBool(const char* valname) const; | ||||
bool getBool(const char* valname, bool def) const; | bool getBool(const char* valname, bool def) const; | ||||
char* getRepresentation(const char* valname) const; | |||||
std::string getRepresentation(const char* valname) const; | |||||
bool isValue(const char* valname) const; | bool isValue(const char* valname) const; | ||||
void SDisplay::handleClipboardRequest() { | void SDisplay::handleClipboardRequest() { | ||||
CharArray data(clipboard->getClipText()); | |||||
server->sendClipboardData(data.buf); | |||||
server->sendClipboardData(clipboard->getClipText().c_str()); | |||||
} | } | ||||
void SDisplay::handleClipboardAnnounce(bool available) { | void SDisplay::handleClipboardAnnounce(bool available) { |
langId = langId >> 8; | langId = langId >> 8; | ||||
} | } | ||||
CharArray langIdStr(binToHex(langIdBuf, sizeof(langId))); | |||||
CharArray infoName(strlen("StringFileInfo") + 4 + strlen(name) + strlen(langIdStr.buf)); | |||||
sprintf(infoName.buf, "\\StringFileInfo\\%s\\%s", langIdStr.buf, name); | |||||
std::string langIdStr(binToHex(langIdBuf, sizeof(langId))); | |||||
CharArray infoName(strlen("StringFileInfo") + 4 + strlen(name) + strlen(langIdStr.c_str())); | |||||
sprintf(infoName.buf, "\\StringFileInfo\\%s\\%s", langIdStr.c_str(), name); | |||||
// Locate the required version string within the version info | // Locate the required version string within the version info | ||||
char* buffer = 0; | char* buffer = 0; |
#ifdef HAVE_GNUTLS | #ifdef HAVE_GNUTLS | ||||
if (isItemChecked(IDC_ENC_X509)) { | if (isItemChecked(IDC_ENC_X509)) { | ||||
SSecurityTLS::X509_CertFile.setParam(regKey.getString("X509Cert")); | |||||
SSecurityTLS::X509_CertFile.setParam(regKey.getString("X509Key")); | |||||
SSecurityTLS::X509_CertFile.setParam(regKey.getString("X509Cert").c_str()); | |||||
SSecurityTLS::X509_CertFile.setParam(regKey.getString("X509Key").c_str()); | |||||
} | } | ||||
#endif | #endif | ||||
try { | try { | ||||
network::TcpFilter::Pattern pat(network::TcpFilter::parsePattern(newPat.buf)); | network::TcpFilter::Pattern pat(network::TcpFilter::parsePattern(newPat.buf)); | ||||
pattern.replaceBuf(CharArray(network::TcpFilter::patternToStr(pat)).takeBuf()); | |||||
pattern.replaceBuf(strDup(network::TcpFilter::patternToStr(pat).c_str())); | |||||
} catch(rdr::Exception& e) { | } catch(rdr::Exception& e) { | ||||
MsgBox(NULL, e.str(), MB_ICONEXCLAMATION | MB_OK); | MsgBox(NULL, e.str(), MB_ICONEXCLAMATION | MB_OK); | ||||
return false; | return false; | ||||
SendMessage(listBox, LB_DELETESTRING, 0, 0); | SendMessage(listBox, LB_DELETESTRING, 0, 0); | ||||
CharArray tmp; | CharArray tmp; | ||||
tmp.buf = hosts.getData(); | |||||
tmp.buf = strDup(hosts.getValueStr().c_str()); | |||||
while (tmp.buf) { | while (tmp.buf) { | ||||
CharArray first; | CharArray first; | ||||
strSplit(tmp.buf, ',', &first.buf, &tmp.buf); | strSplit(tmp.buf, ',', &first.buf, &tmp.buf); | ||||
regKey.setInt("PortNumber", isItemChecked(IDC_RFB_ENABLE) ? getItemInt(IDC_PORT) : 0); | regKey.setInt("PortNumber", isItemChecked(IDC_RFB_ENABLE) ? getItemInt(IDC_PORT) : 0); | ||||
regKey.setInt("IdleTimeout", getItemInt(IDC_IDLE_TIMEOUT)); | regKey.setInt("IdleTimeout", getItemInt(IDC_IDLE_TIMEOUT)); | ||||
regKey.setInt("LocalHost", isItemChecked(IDC_LOCALHOST)); | regKey.setInt("LocalHost", isItemChecked(IDC_LOCALHOST)); | ||||
regKey.setString("Hosts", CharArray(getHosts()).buf); | |||||
regKey.setString("Hosts", getHosts().c_str()); | |||||
return true; | return true; | ||||
} | } | ||||
bool isChanged() { | bool isChanged() { | ||||
try { | try { | ||||
CharArray new_hosts(getHosts()); | |||||
return (strcmp(new_hosts.buf, hosts) != 0) || | |||||
std::string new_hosts = getHosts(); | |||||
return (new_hosts != (const char*)hosts) || | |||||
(localHost != isItemChecked(IDC_LOCALHOST)) || | (localHost != isItemChecked(IDC_LOCALHOST)) || | ||||
(port_number != getItemInt(IDC_PORT)) || | (port_number != getItemInt(IDC_PORT)) || | ||||
(rfb::Server::idleTimeout != getItemInt(IDC_IDLE_TIMEOUT)); | (rfb::Server::idleTimeout != getItemInt(IDC_IDLE_TIMEOUT)); | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
char* getHosts() { | |||||
std::string getHosts() { | |||||
int bufLen = 1, i; | int bufLen = 1, i; | ||||
HWND listBox = GetDlgItem(handle, IDC_HOSTS); | HWND listBox = GetDlgItem(handle, IDC_HOSTS); | ||||
for (i=0; i<SendMessage(listBox, LB_GETCOUNT, 0, 0); i++) | for (i=0; i<SendMessage(listBox, LB_GETCOUNT, 0, 0); i++) | ||||
bufLen+=SendMessage(listBox, LB_GETTEXTLEN, i, 0)+1; | bufLen+=SendMessage(listBox, LB_GETTEXTLEN, i, 0)+1; | ||||
CharArray hosts_str(bufLen); | |||||
hosts_str.buf[0] = 0; | |||||
char* outPos = hosts_str.buf; | |||||
std::vector<char> hosts_str(bufLen); | |||||
hosts_str[0] = 0; | |||||
char* outPos = hosts_str.data(); | |||||
for (i=0; i<SendMessage(listBox, LB_GETCOUNT, 0, 0); i++) { | for (i=0; i<SendMessage(listBox, LB_GETCOUNT, 0, 0); i++) { | ||||
outPos += SendMessage(listBox, LB_GETTEXT, i, (LPARAM)outPos); | outPos += SendMessage(listBox, LB_GETTEXT, i, (LPARAM)outPos); | ||||
outPos[0] = ','; | outPos[0] = ','; | ||||
outPos[1] = 0; | outPos[1] = 0; | ||||
outPos++; | outPos++; | ||||
} | } | ||||
return strDup(hosts_str.buf); | |||||
return hosts_str.data(); | |||||
} | } | ||||
protected: | protected: |
regKey.setString("Log", logSetting); | regKey.setString("Log", logSetting); | ||||
} | } | ||||
CharArray authHosts; | |||||
authHosts.buf = winvnc3.getString("AuthHosts", 0); | |||||
if (authHosts.buf) { | |||||
std::string authHosts = winvnc3.getString("AuthHosts", ""); | |||||
if (!authHosts.empty()) { | |||||
CharArray newHosts; | CharArray newHosts; | ||||
newHosts.buf = strDup(""); | newHosts.buf = strDup(""); | ||||
// Reformat AuthHosts to Hosts. Wish I'd left the format the same. :( :( :( | // Reformat AuthHosts to Hosts. Wish I'd left the format the same. :( :( :( | ||||
try { | try { | ||||
CharArray tmp(authHosts.buf); | |||||
CharArray tmp(strDup(authHosts.c_str())); | |||||
while (tmp.buf) { | while (tmp.buf) { | ||||
// Split the AuthHosts string into patterns to match | // Split the AuthHosts string into patterns to match |
prefix = "VNC Server (Service):"; | prefix = "VNC Server (Service):"; | ||||
// Fetch the list of addresses | // Fetch the list of addresses | ||||
std::list<char*> addrs; | |||||
std::list<std::string> addrs; | |||||
if (rfbSock.isListening()) | if (rfbSock.isListening()) | ||||
TcpListener::getMyAddresses(&addrs); | |||||
addrs = TcpListener::getMyAddresses(); | |||||
else | else | ||||
addrs.push_front(strDup("Not accepting connections")); | |||||
addrs.push_front("Not accepting connections"); | |||||
// Allocate space for the new tip | // Allocate space for the new tip | ||||
std::list<char*>::iterator i, next_i; | |||||
std::list<std::string>::iterator i, next_i; | |||||
int length = strlen(prefix)+1; | int length = strlen(prefix)+1; | ||||
for (i=addrs.begin(); i!= addrs.end(); i++) | for (i=addrs.begin(); i!= addrs.end(); i++) | ||||
length += strlen(*i) + 1; | |||||
length += i->size() + 1; | |||||
// Build the new tip | // Build the new tip | ||||
CharArray toolTip(length); | CharArray toolTip(length); | ||||
strcpy(toolTip.buf, prefix); | strcpy(toolTip.buf, prefix); | ||||
for (i=addrs.begin(); i!= addrs.end(); i=next_i) { | for (i=addrs.begin(); i!= addrs.end(); i=next_i) { | ||||
next_i = i; next_i ++; | next_i = i; next_i ++; | ||||
CharArray addr(*i); // Assumes ownership of string | |||||
strcat(toolTip.buf, addr.buf); | |||||
strcat(toolTip.buf, i->c_str()); | |||||
if (next_i != addrs.end()) | if (next_i != addrs.end()) | ||||
strcat(toolTip.buf, ","); | strcat(toolTip.buf, ","); | ||||
} | } | ||||
bool VNCServerWin32::addNewClient(const char* client) { | bool VNCServerWin32::addNewClient(const char* client) { | ||||
TcpSocket* sock = 0; | TcpSocket* sock = 0; | ||||
try { | try { | ||||
CharArray hostname; | |||||
std::string hostname; | |||||
int port; | int port; | ||||
getHostAndPort(client, &hostname.buf, &port, 5500); | |||||
getHostAndPort(client, &hostname, &port, 5500); | |||||
vlog.error("port=%d", port); | vlog.error("port=%d", port); | ||||
sock = new TcpSocket(hostname.buf, port); | |||||
sock = new TcpSocket(hostname.c_str(), port); | |||||
if (queueCommand(AddClient, sock, 0)) | if (queueCommand(AddClient, sock, 0)) | ||||
return true; | return true; | ||||
delete sock; | delete sock; |