📄 display.cpp
字号:
/***************************************************************************//* *//* Copyright (c) 2005, 2006 2X Software Ltd, http://www.2X.com., NoMachine *//* *//* NXCOMP, NX protocol compression and NX extensions to this software *//* are copyright of Nomachine. Redistribution and use of the present *//* software is allowed according to terms specified in the file LICENSE *//* which comes in the source distribution. *//* *//* NX and NoMachine are trademarks of Medialogic S.p.A. *//* *//* 2X is a trademark of 2X Software Ltd. *//* *//* All rights reserved. *//* *//***************************************************************************/#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#define PANIC#define WARNING#define TEST#define DEBUG#include "System.h"#include "Logger.h"#include "Display.h"#include "Process.h"#include "Listener.h"#include "Connector.h"#define NX_UNIX_SOCKET_DIR "/tmp/.X11-unix"#define NX_INVALID_COOKIE_DATA "Invalid MIT-MAGIC-COOKIE-1 key"#define NX_INVALID_COOKIE_SIZE ((int) sizeof(NX_INVALID_COOKIE_DATA) - 1)#define NX_NO_AUTH_PROTO_DATA "No protocol specified"#define NX_NO_AUTH_PROTO_SIZE ((int) sizeof(NX_NO_AUTH_PROTO_DATA) - 1)Display::Display(){ logTrace("Display::Display"); port_ = -1; host_ = NULL; display_ = NULL; authority_ = NULL; cookie_ = NULL; timeout_ = nullTimestamp();}Display::~Display(){ logTrace("Display::~Display"); delete [] host_; delete [] display_; delete [] authority_; delete [] cookie_;}int Display::saveHost(const char *host, int length){ logTrace("Display::saveHost"); if (host_ != NULL) { logTest("Display::saveHost", "Replacing previous " "host specification '%s'", host_); delete [] host_; } if ((host_ = new char[length + 1]) == NULL) { logError("Display::saveHost::new", ESET(ENOMEM)); return -1; } strncpy(host_, host, length); *(host_ + length) = '\0'; return 1;}int Display::savePort(int port){ logTrace("Display::savePort"); if (port < 0 || port + 6000 > 65535) { logError("Display::savePort", ESET(EINVAL)); return -1; } port_ = port; return 1;}int Display::saveDisplay(){ logTrace("Display::saveDisplay"); if (host_ == NULL || port_ < 0) { logError("Display::saveDisplay", ESET(EPERM)); return -1; } if (display_ != NULL) { logTest("Display::saveDisplay", "Replacing previous " "display '%s'", display_); delete [] display_; } char line[1024]; snprintf(line, 1023, "%s:%d", host_, port_); *(line + sizeof(line) - 1) = '\0'; if ((display_ = new char[strlen(line) + 1]) == NULL) { logError("Display::saveDisplay::new", ESET(ENOMEM)); return -1; } strcpy(display_, line); logTest("Display::saveDisplay", "Host is '%s' " "port is %d", host_, port_); logTest("Display::saveDisplay", "Set display to " "'%s'", display_); logTest("Display::saveDisplay", "Removing any " "previous cookie"); delete [] cookie_; cookie_ = NULL; return 1;}int Display::setHost(const char *host){ logTrace("Display::setHost"); if (saveHost(host, strlen(host)) < 0) { return -1; } if (port_ >= 0) { return saveDisplay(); } return 1;}int Display::setPort(int port){ logTrace("Display::setPort"); if (savePort(port) < 0) { return -1; } if (host_ != NULL) { return saveDisplay(); } return 1;}int Display::setDisplay(const char *display){ logTrace("Display::setDisplay"); if (display_ != NULL && strcmp(display_, display) == 0) { return 1; } // // Look for a host name followed // by a colon followed by port. // const char *separator = rindex(display, ':'); if (separator == NULL) { logTest("Display::setDisplay", "Invalid display " "'%s'", display); logError("Display::setDisplay", ESET(EINVAL)); return -1; } const char *check = separator + 1; while (*check != '\0' && isdigit(*check) != 0) { check++; } if (*check != '\0' || savePort(atoi(separator + 1)) < 0) { if (*check != '\0') { logTest("Display::setDisplay", "Invalid port in " "display '%s'", display); logError("Display::setDisplay", ESET(EINVAL)); } return -1; } if (saveHost(display, strlen(display) - strlen(separator)) < 0) { return -1; } return saveDisplay();}int Display::setAuthority(const char *file){ logTrace("Display::setAuthority"); if (authority_ != NULL && strcmp(authority_, file) == 0) { return 1; } if (authority_ != NULL) { logTest("Display::setAuthority", "Replacing previous " "authority file '%s'", authority_); delete [] authority_; } if ((authority_ = new char[strlen(file) + 1]) == NULL) { logError("Display::setAuthority::new", ESET(ENOMEM)); return -1; } strcpy(authority_, file); logTest("Display::setAuthority", "Removing any " "previous cookie"); delete [] cookie_; cookie_ = NULL; return 1;}const char *Display::getAuthority(){ logTrace("Display::getAuthority"); if (authority_ != NULL) { return authority_; } char *file; file = getenv("XAUTHORITY"); if (file != NULL) { if ((authority_ = new char[strlen(file) + 1]) == NULL) { logError("Display::getAuthority::new", ESET(ENOMEM)); return NULL; } strcpy(authority_, file); } else { char *home = getenv("HOME"); if (home == NULL) { logTest("Display::getAuthority", "No environment " "variable for HOME"); logError("Display::getAuthority", ESET(ENOENT)); return NULL; } if ((authority_ = new char[strlen(home) + 12 + 1]) == NULL) { logError("Display::getAuthority::new", ESET(ENOMEM)); return NULL; } strcpy(authority_, home); strcat(authority_, "/.Xauthority"); } logTest("Display::getAuthority", "Using authority " "file '%s'", authority_); return authority_;}int Display::setTimeout(const T_timestamp timeout){ logTrace("Display::setTimeout"); timeout_ = timeout; return 1;}const char *Display::authCommand(){ logTrace("Display::authCommand"); char *path; if ((path = new char[1024]) == NULL) { logError("Display::authCommand::new", ESET(ENOMEM)); return NULL; } // // Use the nxauth command on Windows and the Mac, xauth // on all the other platforms. This should be improved // by checking if any of the two are in our path and by // retrying using other well-known paths that are like- // ly to contain the program. // const char *command; #if defined(__CYGWIN32__) || defined(__APPLE__) command = "nxauth"; #else command = "xauth"; #endif // // If the user selected a NX system directory, // then search the command there. // const char *system = getSystemDir(); if (system != NULL) { strncpy(path, system, 1023); strncat(path, "/bin/", 1023 - strlen(path)); strncat(path, command, 1023 - strlen(path)); } else { strncpy(path, command, 1023); } logTest("Display::authCommand", "Using X auth " "command '%s'", path); return path;}const char *Display::getCookie(){ logTrace("Display::getCookie"); // // Return the previously acquired cookie // in the case of multiple invocations. // if (cookie_ != NULL) { return cookie_; } if (port_ < 0 || host_ == NULL) { logTest("Display::getCookie", "No display " "set for the command"); logError("Display::getCookie", ESET(EPERM)); return NULL; } Process *process = NULL; // // Get the appropriate authority file. If // the file is set to an empty string we // will let the command use its default. // const char *authority = getAuthority(); // // Get the appropriate command to be used // to get the cookie. // const char *command = NULL; if ((command = authCommand()) == NULL) { goto DisplayGetCookieError; } // // The SSH code forces using the unix:n port when passing localhost:n. // This is probably because localhost:n can fail to return a valid // entry on machines where the hostname for localhost doesn't match // exactly the 'localhost' string. For example, on a freshly installed // Fedora Core 3 I get a 'localhost.localdomain/unix:0' entry. Query- // ing 'xauth list localhost:0' results in an empty result, while the // query 'xauth list unix:0' works as expected. Note anyway that if // the cookie for the TCP connection on 'localhost' is set to a dif- // ferent cookie than the one for the Unix connections, both SSH and // NX will match the wrong cookie and session will fail. // char line[256]; if (strncmp(host_, "localhost", 9) == 0) { snprintf(line, 256, "unix:%d", port_); } else { snprintf(line, 256, "%.200s:%d", host_, port_); } *(line + sizeof(line) - 1) = '\0'; if ((process = new Process()) == NULL) { logError("Display::getCookie::new", ESET(ENOMEM)); goto DisplayGetCookieError; } process -> setCommand(command); if (*authority != '\0') { process -> addParameter("-f"); process -> addParameter(authority); } process -> addParameter("list"); process -> addParameter(line); if (process -> start() < 0) { logError("Display::getCookie", EGET()); goto DisplayGetCookieError; } logTest("Display::getCookie", "Command started " "with pid %d", process -> getPid()); FILE *stream; if ((stream = process -> getStdoutStream()) == NULL) { logError("Display::getCookie", EGET()); goto DisplayGetCookieError; } if (fgets(line, 1024, stream) == NULL) { logWarning("Display::getCookie", ESET(ENOENT)); logTest("Display::getCookie", "Failed to read " "data from the X auth command"); goto DisplayGetCookieError; } logTest("Display::getCookie", "Checking cookie " "in string '%s'", line); char cookie[512]; if (sscanf(line, "%*s %*s %511s", cookie) != 1) { logWarning("Display::getCookie", ESET(ENOENT)); logTest("Display::getCookie", "Failed to identify " "the cookie in string '%s'", line); goto DisplayGetCookieError; } if (cookie_ != NULL) { logTest("Display::getCookie", "Replacing previous " "cookie '%s'", cookie_); delete cookie_; } if ((cookie_ = new char[strlen(cookie) + 1]) == NULL) { logError("Display::getCookie::new", ESET(ENOMEM)); goto DisplayGetCookieError; } strcpy(cookie_, cookie); logTest("Display::getCookie", "Gotten cookie '%s' " "from file '%s'", cookie_, authority_);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -