ExecutionStatus Interpreter::caseIteratorBegin(
    Runtime *runtime,
    PinnedHermesValue *frameRegs,
    const inst::Inst *ip) {
  if (LLVM_LIKELY(vmisa<JSArray>(O2REG(IteratorBegin)))) {
    // Attempt to get the fast path for array iteration.
    NamedPropertyDescriptor desc;
    JSObject *propObj = JSObject::getNamedDescriptor(
        Handle<JSArray>::vmcast(&O2REG(IteratorBegin)),
        runtime,
        Predefined::getSymbolID(Predefined::SymbolIterator),
        desc);
    if (propObj) {
      HermesValue slotValue =
          JSObject::getNamedSlotValue(propObj, runtime, desc);
      if (slotValue.getRaw() == runtime->arrayPrototypeValues.getRaw()) {
        O1REG(IteratorBegin) = HermesValue::encodeNumberValue(0);
        return ExecutionStatus::RETURNED;
      }
    }
  }
  GCScopeMarkerRAII marker{runtime};
  CallResult<IteratorRecord> iterRecord =
      getIterator(runtime, Handle<>(&O2REG(IteratorBegin)));
  if (LLVM_UNLIKELY(iterRecord == ExecutionStatus::EXCEPTION)) {
    return ExecutionStatus::EXCEPTION;
  }
  O1REG(IteratorBegin) = iterRecord->iterator.getHermesValue();
  O2REG(IteratorBegin) = iterRecord->nextMethod.getHermesValue();
  return ExecutionStatus::RETURNED;
}

Fix CVE-2020-1914 by using NEXTINST for SaveGeneratorLong

Summary:
If `SaveGeneratorLong` was emitted, it would accidentally jump to the
wrong next instruction, based on how long SaveGenerator was.

Make a callout function to handle the common case, and handle the dispatch
within each case of the interpreter loop.

Fixes CVE-2020-1914

Reviewed By: neildhar

Differential Revision: D24024242

fbshipit-source-id: 3bcb88daa740f0d50e91771a49eb212551ce8bd8


static llvh::raw_ostream &operator<<(
    llvh::raw_ostream &OS,
    DumpHermesValue dhv) {
  OS << dhv.hv;
  // If it is a string, dump the contents, truncated to 8 characters.
  if (dhv.hv.isString()) {
    SmallU16String<32> str;
    dhv.hv.getString()->appendUTF16String(str);
    UTF16Ref ref = str.arrayRef();
    if (str.size() <= 8) {
      OS << ":'" << ref << "'";
    } else {
      OS << ":'" << ref.slice(0, 8) << "'";
      OS << "...[" << str.size() << "]";
    }
  }
  return OS;
}

#define INTERP_WRAPPER(name)                                                \
  __attribute__((__noinline__)) static llvh::CallResult<llvh::HermesValue>  \
  name(hermes::vm::Runtime *runtime, hermes::vm::CodeBlock *newCodeBlock) { \
    return runtime->interpretFunctionImpl(newCodeBlock);                    \
  }


ExecutionStatus Interpreter::caseDirectEval(
    Runtime *runtime,
    PinnedHermesValue *frameRegs,
    const Inst *ip) {
  auto *result = &O1REG(DirectEval);
  auto *input = &O2REG(DirectEval);

  GCScopeMarkerRAII gcMarker{runtime};

  // Check to see if global eval() has been overriden, in which case call it as
  // as normal function.
  auto global = runtime->getGlobal();
  auto existingEval = global->getNamed_RJS(
      global, runtime, Predefined::getSymbolID(Predefined::eval));
  if (LLVM_UNLIKELY(existingEval == ExecutionStatus::EXCEPTION)) {
    return ExecutionStatus::EXCEPTION;
  }
  auto *nativeExistingEval = dyn_vmcast<NativeFunction>(existingEval->get());
  if (LLVM_UNLIKELY(
          !nativeExistingEval ||
          nativeExistingEval->getFunctionPtr() != hermes::vm::eval)) {
    if (auto *existingEvalCallable =
            dyn_vmcast<Callable>(existingEval->get())) {
      auto evalRes = existingEvalCallable->executeCall1(
          runtime->makeHandle<Callable>(existingEvalCallable),
          runtime,
          Runtime::getUndefinedValue(),
          *input);
      if (LLVM_UNLIKELY(evalRes == ExecutionStatus::EXCEPTION)) {
        return ExecutionStatus::EXCEPTION;
      }
      *result = evalRes->get();
      evalRes->invalidate();
      return ExecutionStatus::RETURNED;
    }
    return runtime->raiseTypeErrorForValue(
        runtime->makeHandle(std::move(*existingEval)), " is not a function");
  }

  if (!input->isString()) {
    *result = *input;
    return ExecutionStatus::RETURNED;
  }

  // Create a dummy scope, so that the local eval executes in its own scope
  // (as per the spec for strict callers, which is the only thing we support).

  ScopeChain scopeChain{};
  scopeChain.functions.emplace_back();

  auto cr = vm::directEval(
      runtime, Handle<StringPrimitive>::vmcast(input), scopeChain, false);
  if (cr == ExecutionStatus::EXCEPTION)
    return ExecutionStatus::EXCEPTION;

  *result = *cr;
  return ExecutionStatus::RETURNED;
}


ExecutionStatus Interpreter::casePutOwnByVal(
    Runtime *runtime,
    PinnedHermesValue *frameRegs,
    const Inst *ip) {
  return JSObject::defineOwnComputed(
             Handle<JSObject>::vmcast(&O1REG(PutOwnByVal)),
             runtime,
             Handle<>(&O3REG(PutOwnByVal)),
             ip->iPutOwnByVal.op4
                 ? DefinePropertyFlags::getDefaultNewPropertyFlags()
                 : DefinePropertyFlags::getNewNonEnumerableFlags(),
             Handle<>(&O2REG(PutOwnByVal)))
      .getStatus();
}


void Interpreter::saveGenerator(
    Runtime *runtime,
    PinnedHermesValue *frameRegs,
    const Inst *resumeIP) {
  auto *innerFn = vmcast<GeneratorInnerFunction>(FRAME.getCalleeClosure());
  innerFn->saveStack(runtime);
  innerFn->setNextIP(resumeIP);
  innerFn->setState(GeneratorInnerFunction::State::SuspendedYield);
}


ExecutionStatus Interpreter::casePutOwnGetterSetterByVal(
    Runtime *runtime,
    PinnedHermesValue *frameRegs,
    const inst::Inst *ip) {
  DefinePropertyFlags dpFlags{};
  dpFlags.setConfigurable = 1;
  dpFlags.configurable = 1;
  dpFlags.setEnumerable = 1;
  dpFlags.enumerable = ip->iPutOwnGetterSetterByVal.op5;

  MutableHandle<Callable> getter(runtime);
  MutableHandle<Callable> setter(runtime);
  if (LLVM_LIKELY(!O3REG(PutOwnGetterSetterByVal).isUndefined())) {
    dpFlags.setGetter = 1;
    getter = vmcast<Callable>(O3REG(PutOwnGetterSetterByVal));
  }
  if (LLVM_LIKELY(!O4REG(PutOwnGetterSetterByVal).isUndefined())) {
    dpFlags.setSetter = 1;
    setter = vmcast<Callable>(O4REG(PutOwnGetterSetterByVal));
  }
  assert(
      (dpFlags.setSetter || dpFlags.setGetter) &&
      "No accessor set in PutOwnGetterSetterByVal");

  auto res = PropertyAccessor::create(runtime, getter, setter);
  if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION))
    return ExecutionStatus::EXCEPTION;

  auto accessor = runtime->makeHandle<PropertyAccessor>(*res);

  return JSObject::defineOwnComputed(
             Handle<JSObject>::vmcast(&O1REG(PutOwnGetterSetterByVal)),
             runtime,
             Handle<>(&O2REG(PutOwnGetterSetterByVal)),
             dpFlags,
             accessor)
      .getStatus();
}


rfbNewClient(rfbScreenInfoPtr rfbScreen,
             rfbSocket sock)
{
  return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE));
}

libvncserver/rfbserver: fix possible divide-by-zero

Closes #409

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}


rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_)
{
    /* Permit the server to set the version to report */
    /* TODO: sanity checking */
    if ((major_==3) && (minor_ > 2 && minor_ < 9))
    {
      rfbScreen->protocolMajorVersion = major_;
      rfbScreen->protocolMinorVersion = minor_;
    }
    else
        rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_);
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;


rfbSendKeyboardLedState(rfbClientPtr cl)
{
    rfbFramebufferUpdateRectHeader rect;

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState);
    rect.r.x = Swap16IfLE(cl->lastKeyboardLedState);
    rect.r.y = 0;
    rect.r.w = 0;
    rect.r.h = 0;

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
        sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);

    if (!rfbSendUpdateBuf(cl))
        return FALSE;

    return TRUE;
}

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

static unsigned char ptrAcceleration = 50;


rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer)
{
    char retfilename[MAX_PATH];
    char path[MAX_PATH];
    struct stat statbuf;
    RFB_FIND_DATA win32filename;
    int nOptLen = 0, retval=0;
#ifdef WIN32
    WIN32_FIND_DATAA winFindData;
    HANDLE findHandle;
    int pathLen, basePathLength;
    char *basePath;
#else
    DIR *dirp=NULL;
    struct dirent *direntp=NULL;
#endif

    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);

    /* Client thinks we are Winblows */
    if (!rfbFilenameTranslate2UNIX(cl, buffer, path, sizeof(path)))
        return FALSE;

    if (DB) rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: \"%s\"->\"%s\"\n",buffer, path);

#ifdef WIN32
    // Create a search string, like C:\folder\*

    pathLen = strlen(path);
    basePath = malloc(pathLen + 3);
    memcpy(basePath, path, pathLen);
    basePathLength = pathLen;
    basePath[basePathLength] = '\\';
    basePath[basePathLength + 1] = '*';
    basePath[basePathLength + 2] = '\0';

    // Start a search
    memset(&winFindData, 0, sizeof(winFindData));
    findHandle = FindFirstFileA(path, &winFindData);
    free(basePath);

    if (findHandle == INVALID_HANDLE_VALUE)
#else
    dirp=opendir(path);
    if (dirp==NULL)
#endif
        return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL);

    /* send back the path name (necessary for links) */
    if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE;

#ifdef WIN32
    while (findHandle != INVALID_HANDLE_VALUE)
#else
    for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp))
#endif
    {
        /* get stats */
#ifdef WIN32
    snprintf(retfilename,sizeof(retfilename),"%s/%s", path, winFindData.cFileName);
#else
    snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name);
#endif
        retval = stat(retfilename, &statbuf);

        if (retval==0)
        {
            memset((char *)&win32filename, 0, sizeof(win32filename));
#ifdef WIN32
            win32filename.dwFileAttributes = winFindData.dwFileAttributes;
            win32filename.ftCreationTime.dwLowDateTime = winFindData.ftCreationTime.dwLowDateTime;
            win32filename.ftCreationTime.dwHighDateTime = winFindData.ftCreationTime.dwHighDateTime;
            win32filename.ftLastAccessTime.dwLowDateTime = winFindData.ftLastAccessTime.dwLowDateTime;
            win32filename.ftLastAccessTime.dwHighDateTime = winFindData.ftLastAccessTime.dwHighDateTime;
            win32filename.ftLastWriteTime.dwLowDateTime = winFindData.ftLastWriteTime.dwLowDateTime;
            win32filename.ftLastWriteTime.dwHighDateTime = winFindData.ftLastWriteTime.dwHighDateTime;
            win32filename.nFileSizeLow = winFindData.nFileSizeLow;
            win32filename.nFileSizeHigh = winFindData.nFileSizeHigh;
            win32filename.dwReserved0 = winFindData.dwReserved0;
            win32filename.dwReserved1 = winFindData.dwReserved1;
            strcpy((char *)win32filename.cFileName, winFindData.cFileName);
            strcpy((char *)win32filename.cAlternateFileName, winFindData.cAlternateFileName);
#else
            win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL);
            if (S_ISDIR(statbuf.st_mode))
                win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY);
            win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime);   /* Intel Order */
            win32filename.ftCreationTime.dwHighDateTime = 0;
            win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */
            win32filename.ftLastAccessTime.dwHighDateTime = 0;
            win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime);  /* Intel Order */
            win32filename.ftLastWriteTime.dwHighDateTime = 0;
            win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */
            win32filename.nFileSizeHigh = 0;
            win32filename.dwReserved0 = 0;
            win32filename.dwReserved1 = 0;

            /* If this had the full path, we would need to translate to DOS format ("C:\") */
            /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */
            strcpy((char *)win32filename.cFileName, direntp->d_name);
#endif

            /* Do not show hidden files (but show how to move up the tree) */
            if ((strcmp((char *)win32filename.cFileName, "..")==0) || (win32filename.cFileName[0]!='.'))
            {
                nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName);
                /*
                rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName);
                */
                if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE)
                {
#ifdef WIN32
                    FindClose(findHandle);
#else
                    closedir(dirp);
#endif
                    return FALSE;
                }
            }
        }

#ifdef WIN32
        if (FindNextFileA(findHandle, &winFindData) == 0)
        {
            FindClose(findHandle);
            findHandle = INVALID_HANDLE_VALUE;
        }
#endif
    }
#ifdef WIN32
    if (findHandle != INVALID_HANDLE_VALUE)
    {
        FindClose(findHandle);
    }
#else
    closedir(dirp);
#endif
    /* End of the transfer */
    return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL);
}

#define write(sock,buf,len) send(sock,buf,len,0)

#define snprintf _snprintf /* Missing in MSVC */

#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */

#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */

#define S_ISDIR(m)	(((m) & S_IFDIR) == S_IFDIR)

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

#define MAX_PATH 260

typedef struct {
    uint32_t dwLowDateTime;
    uint32_t dwHighDateTime;
} RFB_FILETIME;

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

#define RFB_FILE_ATTRIBUTE_DIRECTORY  0x10

#define RFB_FILE_ATTRIBUTE_NORMAL     0x80

char retfilename[MAX_PATH];

char path[MAX_PATH];

struct stat statbuf;

RFB_FIND_DATA win32filename;

int nOptLen = 0, retval=0;

WIN32_FIND_DATAA winFindData;

HANDLE findHandle;

int pathLen, basePathLength;

char *basePath;

DIR *dirp=NULL;

struct dirent *direntp=NULL;

static unsigned char ptrAcceleration = 50;


rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,
                    rfbSocket sock)
{
  if (write(sock, (char*) &ptrAcceleration, 1) < 0) {
	rfbLogPerror("rfbNewUDPConnection: write");
    }
}

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

char retfilename[MAX_PATH];

char path[MAX_PATH];

char *basePath;

static unsigned char ptrAcceleration = 50;


rfbClientIteratorHead(rfbClientIteratorPtr i)
{
#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
  if(i->next != 0) {
    rfbDecrClientRef(i->next);
    rfbIncrClientRef(i->screen->clientHead);
  }
#endif
  LOCK(rfbClientListMutex);
  i->next = i->screen->clientHead;
  UNLOCK(rfbClientListMutex);
  return i->next;
}

static MUTEX(rfbClientListMutex);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}


static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h,
		rfbClientPtr cl)
{
	int x1=Swap16IfLE(*x);
	int y1=Swap16IfLE(*y);
	int w1=Swap16IfLE(*w);
	int h1=Swap16IfLE(*h);

	rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip");
	*x = x1;
	*y = y1;
	*w = w1;
	*h = h1;

	if(*w>cl->screen->width-*x)
		*w=cl->screen->width-*x;
	/* possible underflow */
	if(*w>cl->screen->width-*x)
		return FALSE;
	if(*h>cl->screen->height-*y)
		*h=cl->screen->height-*y;
	if(*h>cl->screen->height-*y)
		return FALSE;

	return TRUE;
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

static MUTEX(rfbClientListMutex);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

static unsigned char ptrAcceleration = 50;


rfbSendExtDesktopSize(rfbClientPtr cl,
                 int w,
                 int h)
{
    rfbFramebufferUpdateRectHeader rect;
    rfbExtDesktopSizeMsg edsHdr;
    rfbExtDesktopScreen eds;
    int i;
    char *logmsg;
    int numScreens = cl->screen->numberOfExtDesktopScreensHook(cl);

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
            + sz_rfbExtDesktopSizeMsg
            + sz_rfbExtDesktopScreen * numScreens > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.encoding = Swap32IfLE(rfbEncodingExtDesktopSize);
    rect.r.w = Swap16IfLE(w);
    rect.r.h = Swap16IfLE(h);
    rect.r.x = Swap16IfLE(cl->requestedDesktopSizeChange);
    rect.r.y = Swap16IfLE(cl->lastDesktopSizeChangeError);

    logmsg = "";

    if (cl->requestedDesktopSizeChange == rfbExtDesktopSize_ClientRequestedChange)
    {
        /* our client requested the resize through setDesktopSize */

        switch (cl->lastDesktopSizeChangeError)
        {
        case rfbExtDesktopSize_Success:
            logmsg = "resize successful";
            break;
        case rfbExtDesktopSize_ResizeProhibited:
            logmsg = "resize prohibited";
            break;
        case rfbExtDesktopSize_OutOfResources:
            logmsg = "resize failed: out of resources";
            break;
        case rfbExtDesktopSize_InvalidScreenLayout:
            logmsg = "resize failed: invalid screen layout";
            break;
        default:
            break;
        }
    }

    cl->requestedDesktopSizeChange = 0;
    cl->lastDesktopSizeChangeError = 0;

    rfbLog("Sending rfbEncodingExtDesktopSize for size (%dx%d) %s\n", w, h, logmsg);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
           sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    edsHdr.numberOfScreens = numScreens;
    edsHdr.pad[0] = edsHdr.pad[1] = edsHdr.pad[2] = 0;
    memcpy(&cl->updateBuf[cl->ublen], (char *)&edsHdr,
           sz_rfbExtDesktopSizeMsg);
    cl->ublen += sz_rfbExtDesktopSizeMsg;

    for (i=0; i<numScreens; i++) {
        if (!cl->screen->getExtDesktopScreenHook(i, &eds, cl))
        {
            rfbErr("Error getting ExtendedDesktopSize information for screen #%d\n", i);
            return FALSE;
        }
        eds.id = Swap32IfLE(eds.id);
        eds.x = Swap16IfLE(eds.x);
        eds.y = Swap16IfLE(eds.y);
        eds.width = Swap16IfLE(eds.width);
        eds.height = Swap16IfLE(eds.height);
        eds.flags = Swap32IfLE(eds.flags);
        memcpy(&cl->updateBuf[cl->ublen], (char *)&eds,
               sz_rfbExtDesktopScreen);
        cl->ublen += sz_rfbExtDesktopScreen;
    }

    rfbStatRecordEncodingSent(cl, rfbEncodingExtDesktopSize,
                              sz_rfbFramebufferUpdateRectHeader + sz_rfbExtDesktopSizeMsg + sz_rfbExtDesktopScreen * numScreens,
                              sz_rfbFramebufferUpdateRectHeader + sz_rfbExtDesktopSizeMsg + sz_rfbExtDesktopScreen * numScreens);

    return TRUE;
}

#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */

#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

char retfilename[MAX_PATH];

char path[MAX_PATH];

int nOptLen = 0, retval=0;

int pathLen, basePathLength;

char *basePath;

static unsigned char ptrAcceleration = 50;


rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer)
{
    rfbTextChatMsg tc;
    int bytesToSend=0;

    memset((char *)&tc, 0, sizeof(tc));
    tc.type = rfbTextChat;
    tc.length = Swap32IfLE(length);

    switch(length) {
    case rfbTextChatOpen:
    case rfbTextChatClose:
    case rfbTextChatFinished:
        bytesToSend=0;
        break;
    default:
        bytesToSend=length;
        if (bytesToSend>rfbTextMaxSize)
            bytesToSend=rfbTextMaxSize;
    }

    if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg);
    cl->ublen += sz_rfbTextChatMsg;
    if (bytesToSend>0) {
        memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend);
        cl->ublen += bytesToSend;
    }
    rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend);

    if (!rfbSendUpdateBuf(cl))
        return FALSE;

    return TRUE;
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

typedef struct {
    uint32_t dwLowDateTime;
    uint32_t dwHighDateTime;
} RFB_FILETIME;

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

static unsigned char ptrAcceleration = 50;


rfbProcessClientProtocolVersion(rfbClientPtr cl)
{
    rfbProtocolVersionMsg pv;
    int n, major_, minor_;

    if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
        if (n == 0)
            rfbLog("rfbProcessClientProtocolVersion: client gone\n");
        else
            rfbLogPerror("rfbProcessClientProtocolVersion: read");
        rfbCloseClient(cl);
        return;
    }

    pv[sz_rfbProtocolVersionMsg] = 0;
    if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) {
	rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv);
	rfbCloseClient(cl);
	return;
    }
    rfbLog("Client Protocol Version %d.%d\n", major_, minor_);

    if (major_ != rfbProtocolMajorVersion) {
        rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
                cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion,
                major_,minor_);
        rfbCloseClient(cl);
        return;
    }

    /* Check for the minor version use either of the two standard version of RFB */
    /*
     * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions
     * 3.4, 3.6, 3.14, 3.16
     * It's a bad method, but it is what they use to enable features...
     * maintaining RFB version compatibility across multiple servers is a pain
     * Should use something like ServerIdentity encoding
     */
    cl->protocolMajorVersion = major_;
    cl->protocolMinorVersion = minor_;

    rfbLog("Protocol version sent %d.%d, using %d.%d\n",
              major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion);

    rfbAuthNewClient(cl);
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;


rfbClientListInit(rfbScreenInfoPtr rfbScreen)
{
    if(sizeof(rfbBool)!=1) {
        /* a sanity check */
        fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool));
	/* we cannot continue, because rfbBool is supposed to be char everywhere */
	exit(1);
    }
    rfbScreen->clientHead = NULL;
    INIT_MUTEX(rfbClientListMutex);
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static MUTEX(rfbClientListMutex);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

static unsigned char ptrAcceleration = 50;


rfbSendSupportedEncodings(rfbClientPtr cl)
{
    rfbFramebufferUpdateRectHeader rect;
    static uint32_t supported[] = {
        rfbEncodingRaw,
	rfbEncodingCopyRect,
	rfbEncodingRRE,
	rfbEncodingCoRRE,
	rfbEncodingHextile,
#ifdef LIBVNCSERVER_HAVE_LIBZ
	rfbEncodingZlib,
	rfbEncodingZRLE,
	rfbEncodingZYWRLE,
#endif
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
	rfbEncodingTight,
#endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
	rfbEncodingTightPng,
#endif
	rfbEncodingUltra,
	rfbEncodingUltraZip,
	rfbEncodingXCursor,
	rfbEncodingRichCursor,
	rfbEncodingPointerPos,
	rfbEncodingLastRect,
	rfbEncodingNewFBSize,
	rfbEncodingExtDesktopSize,
	rfbEncodingKeyboardLedState,
	rfbEncodingSupportedMessages,
	rfbEncodingSupportedEncodings,
	rfbEncodingServerIdentity,
    };
    uint32_t nEncodings = sizeof(supported) / sizeof(supported[0]), i;

    /* think rfbSetEncodingsMsg */

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
                  + (nEncodings * sizeof(uint32_t)) > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings);
    rect.r.x = 0;
    rect.r.y = 0;
    rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t));
    rect.r.h = Swap16IfLE(nEncodings);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
        sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    for (i = 0; i < nEncodings; i++) {
        uint32_t encoding = Swap32IfLE(supported[i]);
	memcpy(&cl->updateBuf[cl->ublen], (char *)&encoding, sizeof(encoding));
	cl->ublen += sizeof(encoding);
    }

    rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings,
        sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)),
        sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)));

    if (!rfbSendUpdateBuf(cl))
        return FALSE;

    return TRUE;
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

static MUTEX(rfbClientListMutex);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

typedef struct {
    uint32_t dwLowDateTime;
    uint32_t dwHighDateTime;
} RFB_FILETIME;

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

char retfilename[MAX_PATH];

char path[MAX_PATH];

char *basePath;

static unsigned char ptrAcceleration = 50;


rfbSendCopyRegion(rfbClientPtr cl,
                  sraRegionPtr reg,
                  int dx,
                  int dy)
{
    int x, y, w, h;
    rfbFramebufferUpdateRectHeader rect;
    rfbCopyRect cr;
    sraRectangleIterator* i;
    sraRect rect1;

    /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */
    i = sraRgnGetReverseIterator(reg,dx>0,dy>0);

    /* correct for the scale of the screen */
    dx = ScaleX(cl->screen, cl->scaledScreen, dx);
    dy = ScaleX(cl->screen, cl->scaledScreen, dy);

    while(sraRgnIteratorNext(i,&rect1)) {
      x = rect1.x1;
      y = rect1.y1;
      w = rect1.x2 - x;
      h = rect1.y2 - y;

      /* correct for scaling (if necessary) */
      rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "copyrect");

      rect.r.x = Swap16IfLE(x);
      rect.r.y = Swap16IfLE(y);
      rect.r.w = Swap16IfLE(w);
      rect.r.h = Swap16IfLE(h);
      rect.encoding = Swap32IfLE(rfbEncodingCopyRect);

      memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
	     sz_rfbFramebufferUpdateRectHeader);
      cl->ublen += sz_rfbFramebufferUpdateRectHeader;

      cr.srcX = Swap16IfLE(x - dx);
      cr.srcY = Swap16IfLE(y - dy);

      memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect);
      cl->ublen += sz_rfbCopyRect;

      rfbStatRecordEncodingSent(cl, rfbEncodingCopyRect, sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect,
          w * h  * (cl->scaledScreen->bitsPerPixel / 8));
    }
    sraRgnReleaseIterator(i);

    return TRUE;
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

static unsigned char ptrAcceleration = 50;


rfbSendServerIdentity(rfbClientPtr cl)
{
    rfbFramebufferUpdateRectHeader rect;
    char buffer[512];

    /* tack on our library version */
    snprintf(buffer,sizeof(buffer)-1, "%s (%s)",
        (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString),
        LIBVNCSERVER_PACKAGE_STRING);

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
                  + (strlen(buffer)+1) > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.encoding = Swap32IfLE(rfbEncodingServerIdentity);
    rect.r.x = 0;
    rect.r.y = 0;
    rect.r.w = Swap16IfLE(strlen(buffer)+1);
    rect.r.h = 0;

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
        sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1);
    cl->ublen += strlen(buffer)+1;

    rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity,
        sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1,
        sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1);

    if (!rfbSendUpdateBuf(cl))
        return FALSE;

    return TRUE;
}

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

static unsigned char ptrAcceleration = 50;


rfbBool rfbSendFileTransferChunk(rfbClientPtr cl)
{
    /* Allocate buffer for compression */
    char readBuf[sz_rfbBlockSize];
    int bytesRead=0;
    int retval=0;
    fd_set wfds;
    struct timeval tv;
    int n;
#ifdef LIBVNCSERVER_HAVE_LIBZ
    unsigned char compBuf[sz_rfbBlockSize + 1024];
    unsigned long nMaxCompSize = sizeof(compBuf);
    int nRetC = 0;
#endif

    /*
     * Don't close the client if we get into this one because
     * it is called from many places to service file transfers.
     * Note that permitFileTransfer is checked first.
     */
    if (cl->screen->permitFileTransfer != TRUE ||
       (cl->screen->getFileTransferPermission != NULL
        && cl->screen->getFileTransferPermission(cl) != TRUE)) {
		return TRUE;
    }

    /* If not sending, or no file open...   Return as if we sent something! */
    if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
    {
	FD_ZERO(&wfds);
        FD_SET(cl->sock, &wfds);

        /* return immediately */
	tv.tv_sec = 0;
	tv.tv_usec = 0;
	n = select(cl->sock + 1, NULL, &wfds, NULL, &tv);

	if (n<0) {
#ifdef WIN32
	    errno=WSAGetLastError();
#endif
            rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno));
	}
        /* We have space on the transmit queue */
	if (n > 0)
	{
            bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize);
            switch (bytesRead) {
            case 0:
                /*
                rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n");
                */
                retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL);
                close(cl->fileTransfer.fd);
                cl->fileTransfer.fd = -1;
                cl->fileTransfer.sending   = 0;
                cl->fileTransfer.receiving = 0;
                return retval;
            case -1:
                /* TODO : send an error msg to the client... */
#ifdef WIN32
	        errno=WSAGetLastError();
#endif
                rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno));
                retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL);
                close(cl->fileTransfer.fd);
                cl->fileTransfer.fd = -1;
                cl->fileTransfer.sending   = 0;
                cl->fileTransfer.receiving = 0;
                return retval;
            default:
                /*
                rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead);
                */
                if (!cl->fileTransfer.compressionEnabled)
                    return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, readBuf);
                else
                {
#ifdef LIBVNCSERVER_HAVE_LIBZ
                    nRetC = compress(compBuf, &nMaxCompSize, (unsigned char *)readBuf, bytesRead);
                    /*
                    rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead);
                    */

                    if ((nRetC==0) && (nMaxCompSize<bytesRead))
                        return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 1, nMaxCompSize, (char *)compBuf);
                    else
                        return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, readBuf);
#else
                    /* We do not support compression of the data stream */
                    return  rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, readBuf);
#endif
                }
            }
        }
    }
    return TRUE;
}

#define close _close

#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */

#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

typedef struct {
    uint32_t dwLowDateTime;
    uint32_t dwHighDateTime;
} RFB_FILETIME;

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

char retfilename[MAX_PATH];

char path[MAX_PATH];

struct stat statbuf;

int nOptLen = 0, retval=0;

int pathLen, basePathLength;

char *basePath;

DIR *dirp=NULL;

struct dirent *direntp=NULL;

static unsigned char ptrAcceleration = 50;


rfbProcessClientMessage(rfbClientPtr cl)
{
    switch (cl->state) {
    case RFB_PROTOCOL_VERSION:
        rfbProcessClientProtocolVersion(cl);
        return;
    case RFB_SECURITY_TYPE:
        rfbProcessClientSecurityType(cl);
        return;
    case RFB_AUTHENTICATION:
        rfbAuthProcessClientMessage(cl);
        return;
    case RFB_INITIALISATION:
    case RFB_INITIALISATION_SHARED:
        rfbProcessClientInitMessage(cl);
        return;
    default:
        rfbProcessClientNormalMessage(cl);
        return;
    }
}

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}


void rfbIncrClientRef(rfbClientPtr cl) {}

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}


rfbProcessClientNormalMessage(rfbClientPtr cl)
{
    int n=0;
    rfbClientToServerMsg msg;
    char *str;
    int i;
    uint32_t enc=0;
    uint32_t lastPreferredEncoding = -1;
    char encBuf[64];
    char encBuf2[64];
    rfbExtDesktopScreen *extDesktopScreens;
    rfbClientIteratorPtr iterator;
    rfbClientPtr clp;

    if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) {
        if (n != 0)
            rfbLogPerror("rfbProcessClientNormalMessage: read");
        rfbCloseClient(cl);
        return;
    }

    switch (msg.type) {

    case rfbSetPixelFormat:

        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                           sz_rfbSetPixelFormatMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }

        cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
        cl->format.depth = msg.spf.format.depth;
        cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE);
        cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE);
        cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
        cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
        cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
        cl->format.redShift = msg.spf.format.redShift;
        cl->format.greenShift = msg.spf.format.greenShift;
        cl->format.blueShift = msg.spf.format.blueShift;

	cl->readyForSetColourMapEntries = TRUE;
        cl->screen->setTranslateFunction(cl);

        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);

        return;

    case rfbFixColourMapEntries:
        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                           sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }
        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg);
        rfbLog("rfbProcessClientNormalMessage: %s",
                "FixColourMapEntries unsupported\n");
        rfbCloseClient(cl);
        return;

    /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features...
     * We may want to look into this...
     * Example:
     *     case rfbEncodingXCursor:
     *         cl->enableCursorShapeUpdates = TRUE;
     *
     * Currently: cl->enableCursorShapeUpdates can *never* be turned off...
     */
    case rfbSetEncodings:
    {

        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                           sz_rfbSetEncodingsMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }

        msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);

        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4));

        /*
         * UltraVNC Client has the ability to adapt to changing network environments
         * So, let's give it a change to tell us what it wants now!
         */
        if (cl->preferredEncoding!=-1)
            lastPreferredEncoding = cl->preferredEncoding;

        /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */
        cl->preferredEncoding=-1;
        cl->useCopyRect              = FALSE;
        cl->useNewFBSize             = FALSE;
        cl->useExtDesktopSize        = FALSE;
        cl->cursorWasChanged         = FALSE;
        cl->useRichCursorEncoding    = FALSE;
        cl->enableCursorPosUpdates   = FALSE;
        cl->enableCursorShapeUpdates = FALSE;
        cl->enableCursorShapeUpdates = FALSE;
        cl->enableLastRectEncoding   = FALSE;
        cl->enableKeyboardLedState   = FALSE;
        cl->enableSupportedMessages  = FALSE;
        cl->enableSupportedEncodings = FALSE;
        cl->enableServerIdentity     = FALSE;
#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
        cl->tightQualityLevel        = -1;
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
        cl->tightCompressLevel       = TIGHT_DEFAULT_COMPRESSION;
        cl->turboSubsampLevel        = TURBO_DEFAULT_SUBSAMP;
        cl->turboQualityLevel        = -1;
#endif
#endif

        for (i = 0; i < msg.se.nEncodings; i++) {
            if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) {
                if (n != 0)
                    rfbLogPerror("rfbProcessClientNormalMessage: read");
                rfbCloseClient(cl);
                return;
            }
            enc = Swap32IfLE(enc);

            switch (enc) {

            case rfbEncodingCopyRect:
		cl->useCopyRect = TRUE;
                break;
            case rfbEncodingRaw:
            case rfbEncodingRRE:
            case rfbEncodingCoRRE:
            case rfbEncodingHextile:
            case rfbEncodingUltra:
#ifdef LIBVNCSERVER_HAVE_LIBZ
	    case rfbEncodingZlib:
            case rfbEncodingZRLE:
            case rfbEncodingZYWRLE:
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
	    case rfbEncodingTight:
#endif
#endif
#ifdef LIBVNCSERVER_HAVE_LIBPNG
	    case rfbEncodingTightPng:
#endif
            /* The first supported encoding is the 'preferred' encoding */
                if (cl->preferredEncoding == -1)
                    cl->preferredEncoding = enc;

                break;
	    case rfbEncodingXCursor:
		if(!cl->screen->dontConvertRichCursorToXCursor) {
		    rfbLog("Enabling X-style cursor updates for client %s\n",
			   cl->host);
		    /* if cursor was drawn, hide the cursor */
		    if(!cl->enableCursorShapeUpdates)
		        rfbRedrawAfterHideCursor(cl,NULL);

		    cl->enableCursorShapeUpdates = TRUE;
		    cl->cursorWasChanged = TRUE;
		}
		break;
	    case rfbEncodingRichCursor:
	        rfbLog("Enabling full-color cursor updates for client %s\n",
		       cl->host);
		/* if cursor was drawn, hide the cursor */
		if(!cl->enableCursorShapeUpdates)
		    rfbRedrawAfterHideCursor(cl,NULL);

	        cl->enableCursorShapeUpdates = TRUE;
	        cl->useRichCursorEncoding = TRUE;
	        cl->cursorWasChanged = TRUE;
	        break;
	    case rfbEncodingPointerPos:
		if (!cl->enableCursorPosUpdates) {
		    rfbLog("Enabling cursor position updates for client %s\n",
			   cl->host);
		    cl->enableCursorPosUpdates = TRUE;
		    cl->cursorWasMoved = TRUE;
		}
	        break;
	    case rfbEncodingLastRect:
		if (!cl->enableLastRectEncoding) {
		    rfbLog("Enabling LastRect protocol extension for client "
			   "%s\n", cl->host);
		    cl->enableLastRectEncoding = TRUE;
		}
		break;
	    case rfbEncodingNewFBSize:
		if (!cl->useNewFBSize) {
		    rfbLog("Enabling NewFBSize protocol extension for client "
			   "%s\n", cl->host);
		    cl->useNewFBSize = TRUE;
		}
		break;
            case rfbEncodingExtDesktopSize:
                if (!cl->useExtDesktopSize) {
                    rfbLog("Enabling ExtDesktopSize protocol extension for client "
                           "%s\n", cl->host);
                    cl->useExtDesktopSize = TRUE;
                    cl->useNewFBSize = TRUE;
                }
                break;
            case rfbEncodingKeyboardLedState:
                if (!cl->enableKeyboardLedState) {
                  rfbLog("Enabling KeyboardLedState protocol extension for client "
                          "%s\n", cl->host);
                  cl->enableKeyboardLedState = TRUE;
                }
                break;
            case rfbEncodingSupportedMessages:
                if (!cl->enableSupportedMessages) {
                  rfbLog("Enabling SupportedMessages protocol extension for client "
                          "%s\n", cl->host);
                  cl->enableSupportedMessages = TRUE;
                }
                break;
            case rfbEncodingSupportedEncodings:
                if (!cl->enableSupportedEncodings) {
                  rfbLog("Enabling SupportedEncodings protocol extension for client "
                          "%s\n", cl->host);
                  cl->enableSupportedEncodings = TRUE;
                }
                break;
            case rfbEncodingServerIdentity:
                if (!cl->enableServerIdentity) {
                  rfbLog("Enabling ServerIdentity protocol extension for client "
                          "%s\n", cl->host);
                  cl->enableServerIdentity = TRUE;
                }
                break;
            case rfbEncodingXvp:
                if (cl->screen->xvpHook) {
                  rfbLog("Enabling Xvp protocol extension for client "
                          "%s\n", cl->host);
                  if (!rfbSendXvp(cl, 1, rfbXvp_Init)) {
                    rfbCloseClient(cl);
                    return;
                  }
                }
                break;
            default:
#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG)
		if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
		     enc <= (uint32_t)rfbEncodingCompressLevel9 ) {
		    cl->zlibCompressLevel = enc & 0x0F;
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
		    cl->tightCompressLevel = enc & 0x0F;
		    rfbLog("Using compression level %d for client %s\n",
			   cl->tightCompressLevel, cl->host);
#endif
		} else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 &&
			    enc <= (uint32_t)rfbEncodingQualityLevel9 ) {
		    cl->tightQualityLevel = enc & 0x0F;
		    rfbLog("Using image quality level %d for client %s\n",
			   cl->tightQualityLevel, cl->host);
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
		    cl->turboQualityLevel = tight2turbo_qual[enc & 0x0F];
		    cl->turboSubsampLevel = tight2turbo_subsamp[enc & 0x0F];
		    rfbLog("Using JPEG subsampling %d, Q%d for client %s\n",
			   cl->turboSubsampLevel, cl->turboQualityLevel, cl->host);
		} else if ( enc >= (uint32_t)rfbEncodingFineQualityLevel0 + 1 &&
			    enc <= (uint32_t)rfbEncodingFineQualityLevel100 ) {
		    cl->turboQualityLevel = enc & 0xFF;
		    rfbLog("Using fine quality level %d for client %s\n",
			   cl->turboQualityLevel, cl->host);
		} else if ( enc >= (uint32_t)rfbEncodingSubsamp1X &&
			    enc <= (uint32_t)rfbEncodingSubsampGray ) {
		    cl->turboSubsampLevel = enc & 0xFF;
		    rfbLog("Using subsampling level %d for client %s\n",
			   cl->turboSubsampLevel, cl->host);
#endif
		} else
#endif
		{
			rfbExtensionData* e;
			for(e = cl->extensions; e;) {
				rfbExtensionData* next = e->next;
				if(e->extension->enablePseudoEncoding &&
					e->extension->enablePseudoEncoding(cl,
						&e->data, (int)enc))
					/* ext handles this encoding */
					break;
				e = next;
			}
			if(e == NULL) {
				rfbBool handled = FALSE;
				/* if the pseudo encoding is not handled by the
				   enabled extensions, search through all
				   extensions. */
				rfbProtocolExtension* e;

				for(e = rfbGetExtensionIterator(); e;) {
					int* encs = e->pseudoEncodings;
					while(encs && *encs!=0) {
						if(*encs==(int)enc) {
							void* data = NULL;
							if(!e->enablePseudoEncoding(cl, &data, (int)enc)) {
								rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc);
							} else {
								rfbEnableExtension(cl, e, data);
								handled = TRUE;
								e = NULL;
								break;
							}
						}
						encs++;
					}

					if(e)
						e = e->next;
				}
				rfbReleaseExtensionIterator();

				if(!handled)
					rfbLog("rfbProcessClientNormalMessage: "
					    "ignoring unsupported encoding type %s\n",
					    encodingName(enc,encBuf,sizeof(encBuf)));
			}
		}
            }
        }

        if (cl->preferredEncoding == -1) {
            if (lastPreferredEncoding==-1) {
                cl->preferredEncoding = rfbEncodingRaw;
                rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
            }
            else {
                cl->preferredEncoding = lastPreferredEncoding;
                rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
            }
        }
        else
        {
          if (lastPreferredEncoding==-1) {
              rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host);
          } else {
              rfbLog("Switching from %s to %s Encoding for client %s\n",
                  encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)),
                  encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host);
          }
        }

	if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
	  rfbLog("Disabling cursor position updates for client %s\n",
		 cl->host);
	  cl->enableCursorPosUpdates = FALSE;
	}

        return;
    }

    case rfbFramebufferUpdateRequest:
    {
        sraRegionPtr tmpRegion;

        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                           sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }

        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbFramebufferUpdateRequestMsg,sz_rfbFramebufferUpdateRequestMsg);

        /* The values come in based on the scaled screen, we need to convert them to
         * values based on the main screen's coordinate system
         */
	if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,cl))
	{
	        rfbLog("Warning, ignoring rfbFramebufferUpdateRequest: %dXx%dY-%dWx%dH\n",msg.fur.x, msg.fur.y, msg.fur.w, msg.fur.h);
		return;
        }

        if (cl->clientFramebufferUpdateRequestHook)
            cl->clientFramebufferUpdateRequestHook(cl, &msg.fur);

	tmpRegion =
	  sraRgnCreateRect(msg.fur.x,
			   msg.fur.y,
			   msg.fur.x+msg.fur.w,
			   msg.fur.y+msg.fur.h);

        LOCK(cl->updateMutex);
	sraRgnOr(cl->requestedRegion,tmpRegion);

	if (!cl->readyForSetColourMapEntries) {
	    /* client hasn't sent a SetPixelFormat so is using server's */
	    cl->readyForSetColourMapEntries = TRUE;
	    if (!cl->format.trueColour) {
		if (!rfbSetClientColourMap(cl, 0, 0)) {
		    sraRgnDestroy(tmpRegion);
		    TSIGNAL(cl->updateCond);
		    UNLOCK(cl->updateMutex);
		    return;
		}
	    }
	}

       if (!msg.fur.incremental) {
	    sraRgnOr(cl->modifiedRegion,tmpRegion);
	    sraRgnSubtract(cl->copyRegion,tmpRegion);
            if (cl->useExtDesktopSize)
                cl->newFBSizePending = TRUE;
       }
       TSIGNAL(cl->updateCond);
       UNLOCK(cl->updateMutex);

       sraRgnDestroy(tmpRegion);

       return;
    }

    case rfbKeyEvent:

	if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
			   sz_rfbKeyEventMsg - 1)) <= 0) {
	    if (n != 0)
		rfbLogPerror("rfbProcessClientNormalMessage: read");
	    rfbCloseClient(cl);
	    return;
	}

	rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbKeyEventMsg, sz_rfbKeyEventMsg);

	if(!cl->viewOnly) {
	    cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl);
	}

        return;

    case rfbPointerEvent:

	if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
			   sz_rfbPointerEventMsg - 1)) <= 0) {
	    if (n != 0)
		rfbLogPerror("rfbProcessClientNormalMessage: read");
	    rfbCloseClient(cl);
	    return;
	}

	rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbPointerEventMsg, sz_rfbPointerEventMsg);

	if (cl->screen->pointerClient && cl->screen->pointerClient != cl)
	    return;

	if (msg.pe.buttonMask == 0)
	    cl->screen->pointerClient = NULL;
	else
	    cl->screen->pointerClient = cl;

	if(!cl->viewOnly) {
	    if (msg.pe.buttonMask != cl->lastPtrButtons ||
		    cl->screen->deferPtrUpdateTime == 0) {
		cl->screen->ptrAddEvent(msg.pe.buttonMask,
			ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)),
			ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)),
			cl);
		cl->lastPtrButtons = msg.pe.buttonMask;
	    } else {
		cl->lastPtrX = ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x));
		cl->lastPtrY = ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y));
		cl->lastPtrButtons = msg.pe.buttonMask;
	    }
      }
      return;

    case rfbFileTransfer:
        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                              sz_rfbFileTransferMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }
        msg.ft.size         = Swap32IfLE(msg.ft.size);
        msg.ft.length       = Swap32IfLE(msg.ft.length);
        /* record statistics in rfbProcessFileTransfer as length is filled with garbage when it is not valid */
        rfbProcessFileTransfer(cl, msg.ft.contentType, msg.ft.contentParam, msg.ft.size, msg.ft.length);
        return;

    case rfbSetSW:
        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                              sz_rfbSetSWMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }
        msg.sw.x = Swap16IfLE(msg.sw.x);
        msg.sw.y = Swap16IfLE(msg.sw.y);
        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetSWMsg, sz_rfbSetSWMsg);
        /* msg.sw.status is not initialized in the ultraVNC viewer and contains random numbers (why???) */

        rfbLog("Received a rfbSetSingleWindow(%d x, %d y)\n", msg.sw.x, msg.sw.y);
        if (cl->screen->setSingleWindow!=NULL)
            cl->screen->setSingleWindow(cl, msg.sw.x, msg.sw.y);
        return;

    case rfbSetServerInput:
        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                              sz_rfbSetServerInputMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }
        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetServerInputMsg, sz_rfbSetServerInputMsg);

        /* msg.sim.pad is not initialized in the ultraVNC viewer and contains random numbers (why???) */
        /* msg.sim.pad = Swap16IfLE(msg.sim.pad); */

        rfbLog("Received a rfbSetServerInput(%d status)\n", msg.sim.status);
        if (cl->screen->setServerInput!=NULL)
            cl->screen->setServerInput(cl, msg.sim.status);
        return;

    case rfbTextChat:
        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
                              sz_rfbTextChatMsg - 1)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }

        msg.tc.pad2   = Swap16IfLE(msg.tc.pad2);
        msg.tc.length = Swap32IfLE(msg.tc.length);

        switch (msg.tc.length) {
        case rfbTextChatOpen:
        case rfbTextChatClose:
        case rfbTextChatFinished:
            /* commands do not have text following */
            /* Why couldn't they have used the pad byte??? */
            str=NULL;
            rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg, sz_rfbTextChatMsg);
            break;
        default:
            if ((msg.tc.length>0) && (msg.tc.length<rfbTextMaxSize))
            {
                str = (char *)malloc(msg.tc.length);
                if (str==NULL)
                {
                    rfbLog("Unable to malloc %d bytes for a TextChat Message\n", msg.tc.length);
                    rfbCloseClient(cl);
                    return;
                }
                if ((n = rfbReadExact(cl, str, msg.tc.length)) <= 0) {
                    if (n != 0)
                        rfbLogPerror("rfbProcessClientNormalMessage: read");
                    free(str);
                    rfbCloseClient(cl);
                    return;
                }
                rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg+msg.tc.length, sz_rfbTextChatMsg+msg.tc.length);
            }
            else
            {
                /* This should never happen */
                rfbLog("client sent us a Text Message that is too big %d>%d\n", msg.tc.length, rfbTextMaxSize);
                rfbCloseClient(cl);
                return;
            }
        }

        /* Note: length can be commands: rfbTextChatOpen, rfbTextChatClose, and rfbTextChatFinished
         * at which point, the str is NULL (as it is not sent)
         */
        if (cl->screen->setTextChat!=NULL)
            cl->screen->setTextChat(cl, msg.tc.length, str);

        free(str);
        return;

    case rfbClientCutText:

	if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
			   sz_rfbClientCutTextMsg - 1)) <= 0) {
	    if (n != 0)
		rfbLogPerror("rfbProcessClientNormalMessage: read");
	    rfbCloseClient(cl);
	    return;
	}

	msg.cct.length = Swap32IfLE(msg.cct.length);

	/* uint32_t input is passed to malloc()'s size_t argument,
	 * to rfbReadExact()'s int argument, to rfbStatRecordMessageRcvd()'s int
	 * argument increased of sz_rfbClientCutTextMsg, and to setXCutText()'s int
	 * argument. Here we impose a limit of 1 MB so that the value fits
	 * into all of the types to prevent from misinterpretation and thus
	 * from accessing uninitialized memory (CVE-2018-7225) and also to
	 * prevent from a denial-of-service by allocating too much memory in
	 * the server. */
	if (msg.cct.length > 1<<20) {
	    rfbLog("rfbClientCutText: too big cut text length requested: %u B > 1 MB\n", (unsigned int)msg.cct.length);
	    rfbCloseClient(cl);
	    return;
	}

	/* Allow zero-length client cut text. */
	str = (char *)calloc(msg.cct.length ? msg.cct.length : 1, 1);
	if (str == NULL) {
		rfbLogPerror("rfbProcessClientNormalMessage: not enough memory");
		rfbCloseClient(cl);
		return;
	}

	if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) {
	    if (n != 0)
	        rfbLogPerror("rfbProcessClientNormalMessage: read");
	    free(str);
	    rfbCloseClient(cl);
	    return;
	}
	rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbClientCutTextMsg+msg.cct.length, sz_rfbClientCutTextMsg+msg.cct.length);
	if(!cl->viewOnly) {
	    cl->screen->setXCutText(str, msg.cct.length, cl);
	}
	free(str);

        return;

    case rfbPalmVNCSetScaleFactor:
      cl->PalmVNC = TRUE;
      if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
          sz_rfbSetScaleMsg - 1)) <= 0) {
          if (n != 0)
            rfbLogPerror("rfbProcessClientNormalMessage: read");
          rfbCloseClient(cl);
          return;
      }

      if (msg.ssc.scale == 0) {
          rfbLogPerror("rfbProcessClientNormalMessage: will not accept a scale factor of zero");
          rfbCloseClient(cl);
          return;
      }

      rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg);
      rfbLog("rfbSetScale(%d)\n", msg.ssc.scale);
      rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale);

      rfbSendNewScaleSize(cl);
      return;

    case rfbSetScale:

      if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
          sz_rfbSetScaleMsg - 1)) <= 0) {
          if (n != 0)
            rfbLogPerror("rfbProcessClientNormalMessage: read");
          rfbCloseClient(cl);
          return;
      }

      if (msg.ssc.scale == 0) {
          rfbLogPerror("rfbProcessClientNormalMessage: will not accept a scale factor of zero");
          rfbCloseClient(cl);
          return;
      }

      rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg);
      rfbLog("rfbSetScale(%d)\n", msg.ssc.scale);
      rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale);

      rfbSendNewScaleSize(cl);
      return;

    case rfbXvp:

      if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
          sz_rfbXvpMsg - 1)) <= 0) {
          if (n != 0)
            rfbLogPerror("rfbProcessClientNormalMessage: read");
          rfbCloseClient(cl);
          return;
      }
      rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbXvpMsg, sz_rfbXvpMsg);

      /* only version when is defined, so echo back a fail */
      if(msg.xvp.version != 1) {
	rfbSendXvp(cl, msg.xvp.version, rfbXvp_Fail);
      }
      else {
	/* if the hook exists and fails, send a fail msg */
	if(cl->screen->xvpHook && !cl->screen->xvpHook(cl, msg.xvp.version, msg.xvp.code))
	  rfbSendXvp(cl, 1, rfbXvp_Fail);
      }
      return;

    case rfbSetDesktopSize:

        if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
            sz_rfbSetDesktopSizeMsg - 1)) <= 0) {
            if (n != 0)
              rfbLogPerror("rfbProcessClientNormalMessage: read");
            rfbCloseClient(cl);
            return;
        }

        if (msg.sdm.numberOfScreens == 0) {
            rfbLog("Ignoring setDesktopSize message from client that defines zero screens\n");
            return;
        }

        extDesktopScreens = (rfbExtDesktopScreen *) malloc(msg.sdm.numberOfScreens * sz_rfbExtDesktopScreen);
        if (extDesktopScreens == NULL) {
                rfbLogPerror("rfbProcessClientNormalMessage: not enough memory");
                rfbCloseClient(cl);
                return;
        }

        if ((n = rfbReadExact(cl, ((char *)extDesktopScreens), msg.sdm.numberOfScreens * sz_rfbExtDesktopScreen)) <= 0) {
            if (n != 0)
                rfbLogPerror("rfbProcessClientNormalMessage: read");
            free(extDesktopScreens);
            rfbCloseClient(cl);
            return;
        }
        rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetDesktopSizeMsg + msg.sdm.numberOfScreens * sz_rfbExtDesktopScreen,
                                 sz_rfbSetDesktopSizeMsg + msg.sdm.numberOfScreens * sz_rfbExtDesktopScreen);

        for (i=0; i < msg.sdm.numberOfScreens; i++) {
            extDesktopScreens[i].id = Swap32IfLE(extDesktopScreens[i].id);
            extDesktopScreens[i].x = Swap16IfLE(extDesktopScreens[i].x);
            extDesktopScreens[i].y = Swap16IfLE(extDesktopScreens[i].y);
            extDesktopScreens[i].width = Swap16IfLE(extDesktopScreens[i].width);
            extDesktopScreens[i].height = Swap16IfLE(extDesktopScreens[i].height);
            extDesktopScreens[i].flags = Swap32IfLE(extDesktopScreens[i].flags);
        }
        msg.sdm.width = Swap16IfLE(msg.sdm.width);
        msg.sdm.height = Swap16IfLE(msg.sdm.height);

        rfbLog("Client requested resolution change to (%dx%d)\n", msg.sdm.width, msg.sdm.height);
        cl->requestedDesktopSizeChange = rfbExtDesktopSize_ClientRequestedChange;
        cl->lastDesktopSizeChangeError = cl->screen->setDesktopSizeHook(msg.sdm.width, msg.sdm.height, msg.sdm.numberOfScreens,
                                           extDesktopScreens, cl);

        if (cl->lastDesktopSizeChangeError == 0) {
            /* Let other clients know it was this client that requested the change */
            iterator = rfbGetClientIterator(cl->screen);
            while ((clp = rfbClientIteratorNext(iterator)) != NULL) {
                LOCK(clp->updateMutex);
                if (clp != cl)
                    clp->requestedDesktopSizeChange = rfbExtDesktopSize_OtherClientRequestedChange;
                UNLOCK(clp->updateMutex);
            }
        }
        else
        {
            /* Force ExtendedDesktopSize message to be sent with result code in case of error.
               (In case of success, it is delayed until the new framebuffer is created) */
            cl->newFBSizePending = TRUE;
        }

        free(extDesktopScreens);
        return;

    default:
	{
	    rfbExtensionData *e,*next;

	    for(e=cl->extensions; e;) {
		next = e->next;
		if(e->extension->handleMessage &&
			e->extension->handleMessage(cl, e->data, &msg))
                {
                    rfbStatRecordMessageRcvd(cl, msg.type, 0, 0); /* Extension should handle this */
		    return;
                }
		e = next;
	    }

	    rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
		    msg.type);
	    rfbLog(" ... closing connection\n");
	    rfbCloseClient(cl);
	    return;
	}
    }
}

#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */

#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

typedef struct {
    uint32_t dwLowDateTime;
    uint32_t dwHighDateTime;
} RFB_FILETIME;

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

char retfilename[MAX_PATH];

char path[MAX_PATH];

int nOptLen = 0, retval=0;

int pathLen, basePathLength;

char *basePath;

DIR *dirp=NULL;

struct dirent *direntp=NULL;

static unsigned char ptrAcceleration = 50;


rfbSendXvp(rfbClientPtr cl, uint8_t version, uint8_t code)
{
    rfbXvpMsg xvp;

    xvp.type = rfbXvp;
    xvp.pad = 0;
    xvp.version = version;
    xvp.code = code;

    LOCK(cl->sendMutex);
    if (rfbWriteExact(cl, (char *)&xvp, sz_rfbXvpMsg) < 0) {
      rfbLogPerror("rfbSendXvp: write");
      rfbCloseClient(cl);
    }
    UNLOCK(cl->sendMutex);

    rfbStatRecordMessageSent(cl, rfbXvp, sz_rfbXvpMsg, sz_rfbXvpMsg);

    return TRUE;
}

#define write(sock,buf,len) send(sock,buf,len,0)

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

static unsigned char ptrAcceleration = 50;


rfbSendSupportedMessages(rfbClientPtr cl)
{
    rfbFramebufferUpdateRectHeader rect;
    rfbSupportedMessages msgs;

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
                  + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages);
    rect.r.x = 0;
    rect.r.y = 0;
    rect.r.w = Swap16IfLE(sz_rfbSupportedMessages);
    rect.r.h = 0;

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
        sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    memset((char *)&msgs, 0, sz_rfbSupportedMessages);
    rfbSetBit(msgs.client2server, rfbSetPixelFormat);
    rfbSetBit(msgs.client2server, rfbFixColourMapEntries);
    rfbSetBit(msgs.client2server, rfbSetEncodings);
    rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest);
    rfbSetBit(msgs.client2server, rfbKeyEvent);
    rfbSetBit(msgs.client2server, rfbPointerEvent);
    rfbSetBit(msgs.client2server, rfbClientCutText);
    rfbSetBit(msgs.client2server, rfbFileTransfer);
    rfbSetBit(msgs.client2server, rfbSetScale);
    /*rfbSetBit(msgs.client2server, rfbSetServerInput);  */
    /*rfbSetBit(msgs.client2server, rfbSetSW);           */
    /*rfbSetBit(msgs.client2server, rfbTextChat);        */
    rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);

    rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
    rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
    rfbSetBit(msgs.server2client, rfbBell);
    rfbSetBit(msgs.server2client, rfbServerCutText);
    rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
    rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
    rfbSetBit(msgs.client2server, rfbSetDesktopSize);

    if (cl->screen->xvpHook) {
        rfbSetBit(msgs.client2server, rfbXvp);
        rfbSetBit(msgs.server2client, rfbXvp);
    }

    memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
    cl->ublen += sz_rfbSupportedMessages;

    rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages,
        sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages,
        sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages);
    if (!rfbSendUpdateBuf(cl))
        return FALSE;

    return TRUE;
}

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

char retfilename[MAX_PATH];

char path[MAX_PATH];

char *basePath;

static unsigned char ptrAcceleration = 50;


void rfbIncrClientRef(rfbClientPtr cl)
{
  LOCK(cl->refCountMutex);
  cl->refCount++;
  UNLOCK(cl->refCountMutex);
}


rfbSendLastRectMarker(rfbClientPtr cl)
{
    rfbFramebufferUpdateRectHeader rect;

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
	if (!rfbSendUpdateBuf(cl))
	    return FALSE;
    }

    rect.encoding = Swap32IfLE(rfbEncodingLastRect);
    rect.r.x = 0;
    rect.r.y = 0;
    rect.r.w = 0;
    rect.r.h = 0;

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    rfbStatRecordEncodingSent(cl, rfbEncodingLastRect, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader);

    return TRUE;
}

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

static unsigned char ptrAcceleration = 50;


rfbReverseConnection(rfbScreenInfoPtr rfbScreen,
                     char *host,
                     int port)
{
    rfbSocket sock;
    rfbClientPtr cl;

    if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
        return (rfbClientPtr)NULL;

    cl = rfbNewClient(rfbScreen, sock);

    if (cl) {
        cl->reverseConnection = TRUE;
    }

    return cl;
}

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

char retfilename[MAX_PATH];

char path[MAX_PATH];

int nOptLen = 0, retval=0;

int pathLen, basePathLength;

char *basePath;

DIR *dirp=NULL;

struct dirent *direntp=NULL;

static unsigned char ptrAcceleration = 50;


rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, /* in */ char *path, /* out */ char *unixPath, size_t unixPathMaxLen)
{
    int x;
    char *home=NULL;

    FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE);

    /*
     * Do not use strncpy() - truncating the file name would probably have undesirable side effects
     * Instead check if destination buffer is big enough
     */
    if (strlen(path) >= unixPathMaxLen)
      return FALSE;

    /* C: */
    if (path[0]=='C' && path[1]==':')
      strcpy(unixPath, &path[2]);
    else
    {
      home = getenv("HOME");
      if (home!=NULL)
      {
        /* Re-check buffer size */
        if ((strlen(path) + strlen(home) + 1) >= unixPathMaxLen)
          return FALSE;

        strcpy(unixPath, home);
        strcat(unixPath,"/");
        strcat(unixPath, path);
      }
      else
        strcpy(unixPath, path);
    }
    for (x=0;x<strlen(unixPath);x++)
      if (unixPath[x]=='\\') unixPath[x]='/';
    return TRUE;
}

#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */

#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

char retfilename[MAX_PATH];

char path[MAX_PATH];

int nOptLen = 0, retval=0;

int pathLen, basePathLength;

char *basePath;

DIR *dirp=NULL;

struct dirent *direntp=NULL;

static unsigned char ptrAcceleration = 50;


rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...)
{
    char buffer[256];
    va_list ap;

    va_start(ap, fmt);
    vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
    va_end(ap);

    if (screen->versionString!=NULL) free(screen->versionString);
    screen->versionString = strdup(buffer);
}

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

static unsigned char ptrAcceleration = 50;


rfbClientConnFailed(rfbClientPtr cl,
                    const char *reason)
{
    char *buf;
    int len = strlen(reason);

    rfbLog("rfbClientConnFailed(\"%s\")\n", reason);

    buf = (char *)malloc(8 + len);
    ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
    ((uint32_t *)buf)[1] = Swap32IfLE(len);
    memcpy(buf + 8, reason, len);

    if (rfbWriteExact(cl, buf, 8 + len) < 0)
        rfbLogPerror("rfbClientConnFailed: write");
    free(buf);

    rfbCloseClient(cl);
}

#define write(sock,buf,len) send(sock,buf,len,0)

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

typedef struct {
    uint32_t dwLowDateTime;
    uint32_t dwHighDateTime;
} RFB_FILETIME;

typedef struct {
    uint32_t dwFileAttributes;
    RFB_FILETIME ftCreationTime;
    RFB_FILETIME ftLastAccessTime;
    RFB_FILETIME ftLastWriteTime;
    uint32_t nFileSizeHigh;
    uint32_t nFileSizeLow;
    uint32_t dwReserved0;
    uint32_t dwReserved1;
    uint8_t  cFileName[ MAX_PATH ];
    uint8_t  cAlternateFileName[ 14 ];
} RFB_FIND_DATA;

static unsigned char ptrAcceleration = 50;


rfbSendSetColourMapEntries(rfbClientPtr cl,
                           int firstColour,
                           int nColours)
{
    char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
    char *wbuf = buf;
    rfbSetColourMapEntriesMsg *scme;
    uint16_t *rgb;
    rfbColourMap* cm = &cl->screen->colourMap;
    int i, len;

    if (nColours > 256) {
	/* some rare hardware has, e.g., 4096 colors cells: PseudoColor:12 */
    	wbuf = (char *) malloc(sz_rfbSetColourMapEntriesMsg + nColours * 3 * 2);
    }

    scme = (rfbSetColourMapEntriesMsg *)wbuf;
    rgb = (uint16_t *)(&wbuf[sz_rfbSetColourMapEntriesMsg]);

    scme->type = rfbSetColourMapEntries;

    scme->firstColour = Swap16IfLE(firstColour);
    scme->nColours = Swap16IfLE(nColours);

    len = sz_rfbSetColourMapEntriesMsg;

    for (i = 0; i < nColours; i++) {
      if(i<(int)cm->count) {
	if(cm->is16) {
	  rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]);
	  rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]);
	  rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]);
	} else {
	  rgb[i*3] = Swap16IfLE((unsigned short)cm->data.bytes[i*3]);
	  rgb[i*3+1] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+1]);
	  rgb[i*3+2] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+2]);
	}
      }
    }

    len += nColours * 3 * 2;

    LOCK(cl->sendMutex);
    if (rfbWriteExact(cl, wbuf, len) < 0) {
	rfbLogPerror("rfbSendSetColourMapEntries: write");
	rfbCloseClient(cl);
        if (wbuf != buf) free(wbuf);
        UNLOCK(cl->sendMutex);
	return FALSE;
    }
    UNLOCK(cl->sendMutex);

    rfbStatRecordMessageSent(cl, rfbSetColourMapEntries, len, len);
    if (wbuf != buf) free(wbuf);
    return TRUE;
}

#define write(sock,buf,len) send(sock,buf,len,0)

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

static unsigned char ptrAcceleration = 50;


rfbClientSendString(rfbClientPtr cl, const char *reason)
{
    char *buf;
    int len = strlen(reason);

    rfbLog("rfbClientSendString(\"%s\")\n", reason);

    buf = (char *)malloc(4 + len);
    ((uint32_t *)buf)[0] = Swap32IfLE(len);
    memcpy(buf + 4, reason, len);

    if (rfbWriteExact(cl, buf, 4 + len) < 0)
        rfbLogPerror("rfbClientSendString: write");
    free(buf);

    rfbCloseClient(cl);
}


rfbProcessClientInitMessage(rfbClientPtr cl)
{
    rfbClientInitMsg ci;
    union {
        char buf[256];
        rfbServerInitMsg si;
    } u;
    int len, n;
    rfbClientIteratorPtr iterator;
    rfbClientPtr otherCl;
    rfbExtensionData* extension;

    if (cl->state == RFB_INITIALISATION_SHARED) {
        /* In this case behave as though an implicit ClientInit message has
         * already been received with a shared-flag of true. */
        ci.shared = 1;
        /* Avoid the possibility of exposing the RFB_INITIALISATION_SHARED
         * state to calling software. */
        cl->state = RFB_INITIALISATION;
    } else {
        if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
            if (n == 0)
                rfbLog("rfbProcessClientInitMessage: client gone\n");
            else
                rfbLogPerror("rfbProcessClientInitMessage: read");
            rfbCloseClient(cl);
            return;
        }
    }

    memset(u.buf,0,sizeof(u.buf));

    u.si.framebufferWidth = Swap16IfLE(cl->screen->width);
    u.si.framebufferHeight = Swap16IfLE(cl->screen->height);
    u.si.format = cl->screen->serverFormat;
    u.si.format.redMax = Swap16IfLE(u.si.format.redMax);
    u.si.format.greenMax = Swap16IfLE(u.si.format.greenMax);
    u.si.format.blueMax = Swap16IfLE(u.si.format.blueMax);

    strncpy(u.buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127);
    len = strlen(u.buf + sz_rfbServerInitMsg);
    u.si.nameLength = Swap32IfLE(len);

    if (rfbWriteExact(cl, u.buf, sz_rfbServerInitMsg + len) < 0) {
        rfbLogPerror("rfbProcessClientInitMessage: write");
        rfbCloseClient(cl);
        return;
    }

    for(extension = cl->extensions; extension;) {
	rfbExtensionData* next = extension->next;
	if(extension->extension->init &&
		!extension->extension->init(cl, extension->data))
	    /* extension requested that it be removed */
	    rfbDisableExtension(cl, extension->extension);
	extension = next;
    }

    cl->state = RFB_NORMAL;

    if (!cl->reverseConnection &&
                        (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) {

        if (cl->screen->dontDisconnect) {
            iterator = rfbGetClientIterator(cl->screen);
            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
                    rfbLog("-dontdisconnect: Not shared & existing client\n");
                    rfbLog("  refusing new client %s\n", cl->host);
                    rfbCloseClient(cl);
                    rfbReleaseClientIterator(iterator);
                    return;
                }
            }
            rfbReleaseClientIterator(iterator);
        } else {
            iterator = rfbGetClientIterator(cl->screen);
            while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) {
                if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
                    rfbLog("Not shared - closing connection to client %s\n",
                           otherCl->host);
                    rfbCloseClient(otherCl);
                }
            }
            rfbReleaseClientIterator(iterator);
        }
    }
}


rfbSendRectEncodingRaw(rfbClientPtr cl,
                       int x,
                       int y,
                       int w,
                       int h)
{
    rfbFramebufferUpdateRectHeader rect;
    int nlines;
    int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
    char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
                   + (x * (cl->scaledScreen->bitsPerPixel / 8)));

    if(!h || !w)
	return TRUE; /* nothing to send */

    /* Flush the buffer to guarantee correct alignment for translateFn(). */
    if (cl->ublen > 0) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    rect.r.x = Swap16IfLE(x);
    rect.r.y = Swap16IfLE(y);
    rect.r.w = Swap16IfLE(w);
    rect.r.h = Swap16IfLE(h);
    rect.encoding = Swap32IfLE(rfbEncodingRaw);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    rfbStatRecordEncodingSent(cl, rfbEncodingRaw, sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h,
        sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h);

    nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;

    while (TRUE) {
        if (nlines > h)
            nlines = h;

        (*cl->translateFn)(cl->translateLookupTable,
			   &(cl->screen->serverFormat),
                           &cl->format, fbptr, &cl->updateBuf[cl->ublen],
                           cl->scaledScreen->paddedWidthInBytes, w, nlines);

        cl->ublen += nlines * bytesPerLine;
        h -= nlines;

        if (h == 0)     /* rect fitted in buffer, do next one */
            return TRUE;

        /* buffer full - flush partial rect and do another nlines */

        if (!rfbSendUpdateBuf(cl))
            return FALSE;

        fbptr += (cl->scaledScreen->paddedWidthInBytes * nlines);

        nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine;
        if (nlines == 0) {
            rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d "
                   "bytes per line\n", bytesPerLine);
            rfbCloseClient(cl);
            return FALSE;
        }
    }
}

#define mkdir(path, perms) mkdir(path) /* Omit the perms argument to match POSIX signature */

#define mkdir(path, perms) _mkdir(path) /* Omit the perms argument to match POSIX signature */

static const int tight2turbo_qual[10] = {
   15, 29, 41, 42, 62, 77, 79, 86, 92, 100
};

static const int tight2turbo_subsamp[10] = {
   1, 1, 1, 2, 2, 2, 0, 0, 0, 0
};

static void rfbProcessClientProtocolVersion(rfbClientPtr cl);

static void rfbProcessClientNormalMessage(rfbClientPtr cl);

static void rfbProcessClientInitMessage(rfbClientPtr cl);

struct rfbClientIterator {
  rfbClientPtr next;
  rfbScreenInfoPtr screen;
  rfbBool closedToo;
}

#define rfbSetBit(buffer, position)  (buffer[(position & 255) / 8] |= (1 << (position % 8)))

#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \
	if ((cl->screen->getFileTransferPermission != NULL \
	    && cl->screen->getFileTransferPermission(cl) != TRUE) \
	    || cl->screen->permitFileTransfer != TRUE) { \
		rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \
		rfbCloseClient(cl); \
		return ret; \
	}

int DB = 1;

char retfilename[MAX_PATH];

char path[MAX_PATH];

int nOptLen = 0, retval=0;

int pathLen, basePathLength;

char *basePath;

static unsigned char ptrAcceleration = 50;