Input:
int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
			       const struct host_cmd_ds_command *resp)
{
	u8 *curr = (u8 *) &resp->params.get_wmm_status;
	uint16_t resp_len = le16_to_cpu(resp->size), tlv_len;
	int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
	bool valid = true;

	struct mwifiex_ie_types_data *tlv_hdr;
	struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus;
	struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
	struct mwifiex_wmm_ac_status *ac_status;

	mwifiex_dbg(priv->adapter, INFO,
		    "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
		    resp_len);

	while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
		tlv_hdr = (struct mwifiex_ie_types_data *) curr;
		tlv_len = le16_to_cpu(tlv_hdr->header.len);

		if (resp_len < tlv_len + sizeof(tlv_hdr->header))
			break;

		switch (le16_to_cpu(tlv_hdr->header.type)) {
		case TLV_TYPE_WMMQSTATUS:
			tlv_wmm_qstatus =
				(struct mwifiex_ie_types_wmm_queue_status *)
				tlv_hdr;
			mwifiex_dbg(priv->adapter, CMD,
				    "info: CMD_RESP: WMM_GET_STATUS:\t"
				    "QSTATUS TLV: %d, %d, %d\n",
				    tlv_wmm_qstatus->queue_index,
				    tlv_wmm_qstatus->flow_required,
				    tlv_wmm_qstatus->disabled);

			ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
							 queue_index];
			ac_status->disabled = tlv_wmm_qstatus->disabled;
			ac_status->flow_required =
						tlv_wmm_qstatus->flow_required;
			ac_status->flow_created = tlv_wmm_qstatus->flow_created;
			break;

		case WLAN_EID_VENDOR_SPECIFIC:
			/*
			 * Point the regular IEEE IE 2 bytes into the Marvell IE
			 *   and setup the IEEE IE type and length byte fields
			 */

			wmm_param_ie =
				(struct ieee_types_wmm_parameter *) (curr +
								    2);
			wmm_param_ie->vend_hdr.len = (u8) tlv_len;
			wmm_param_ie->vend_hdr.element_id =
						WLAN_EID_VENDOR_SPECIFIC;

			mwifiex_dbg(priv->adapter, CMD,
				    "info: CMD_RESP: WMM_GET_STATUS:\t"
				    "WMM Parameter Set Count: %d\n",
				    wmm_param_ie->qos_info_bitmap & mask);

			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
			       wmm_ie, wmm_param_ie,
			       wmm_param_ie->vend_hdr.len + 2);

			break;

		default:
			valid = false;
			break;
		}

		curr += (tlv_len + sizeof(tlv_hdr->header));
		resp_len -= (tlv_len + sizeof(tlv_hdr->header));
	}

	mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
	mwifiex_wmm_setup_ac_downgrade(priv);

	return 0;
}

int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
			       const struct host_cmd_ds_command *resp)
{
	u8 *curr = (u8 *) &resp->params.get_wmm_status;
	uint16_t resp_len = le16_to_cpu(resp->size), tlv_len;
	int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
	bool valid = true;

	struct mwifiex_ie_types_data *tlv_hdr;
	struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus;
	struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
	struct mwifiex_wmm_ac_status *ac_status;

	mwifiex_dbg(priv->adapter, INFO,
		    "info: WMM: WMM_GET_STATUS cmdresp received: %d\n",
		    resp_len);

	while ((resp_len >= sizeof(tlv_hdr->header)) && valid) {
		tlv_hdr = (struct mwifiex_ie_types_data *) curr;
		tlv_len = le16_to_cpu(tlv_hdr->header.len);

		if (resp_len < tlv_len + sizeof(tlv_hdr->header))
			break;

		switch (le16_to_cpu(tlv_hdr->header.type)) {
		case TLV_TYPE_WMMQSTATUS:
			tlv_wmm_qstatus =
				(struct mwifiex_ie_types_wmm_queue_status *)
				tlv_hdr;
			mwifiex_dbg(priv->adapter, CMD,
				    "info: CMD_RESP: WMM_GET_STATUS:\t"
				    "QSTATUS TLV: %d, %d, %d\n",
				    tlv_wmm_qstatus->queue_index,
				    tlv_wmm_qstatus->flow_required,
				    tlv_wmm_qstatus->disabled);

			ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus->
							 queue_index];
			ac_status->disabled = tlv_wmm_qstatus->disabled;
			ac_status->flow_required =
						tlv_wmm_qstatus->flow_required;
			ac_status->flow_created = tlv_wmm_qstatus->flow_created;
			break;

		case WLAN_EID_VENDOR_SPECIFIC:
			/*
			 * Point the regular IEEE IE 2 bytes into the Marvell IE
			 *   and setup the IEEE IE type and length byte fields
			 */

			wmm_param_ie =
				(struct ieee_types_wmm_parameter *) (curr +
								    2);
			wmm_param_ie->vend_hdr.len = (u8) tlv_len;
			wmm_param_ie->vend_hdr.element_id =
						WLAN_EID_VENDOR_SPECIFIC;

			mwifiex_dbg(priv->adapter, CMD,
				    "info: CMD_RESP: WMM_GET_STATUS:\t"
				    "WMM Parameter Set Count: %d\n",
				    wmm_param_ie->qos_info_bitmap & mask);

			if (wmm_param_ie->vend_hdr.len + 2 >
				sizeof(struct ieee_types_wmm_parameter))
				break;

			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
			       wmm_ie, wmm_param_ie,
			       wmm_param_ie->vend_hdr.len + 2);

			break;

		default:
			valid = false;
			break;
		}

		curr += (tlv_len + sizeof(tlv_hdr->header));
		resp_len -= (tlv_len + sizeof(tlv_hdr->header));
	}

	mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
	mwifiex_wmm_setup_ac_downgrade(priv);

	return 0;
}


Input:
static PyObject* patch(PyObject* self, PyObject* args)
{
    char *origData, *newData, *diffBlock, *extraBlock, *diffPtr, *extraPtr;
    Py_ssize_t origDataLength, newDataLength, diffBlockLength, extraBlockLength;
    PyObject *controlTuples, *tuple, *results;
    off_t oldpos, newpos, x, y, z;
    int i, j, numTuples;

    if (!PyArg_ParseTuple(args, "s#nO!s#s#",
                          &origData, &origDataLength, &newDataLength,
                          &PyList_Type, &controlTuples,
                          &diffBlock, &diffBlockLength,
                          &extraBlock, &extraBlockLength))
        return NULL;

    /* allocate the memory for the new data */
    newData = PyMem_Malloc(newDataLength + 1);
    if (!newData)
        return PyErr_NoMemory();

    oldpos = 0;
    newpos = 0;
    diffPtr = diffBlock;
    extraPtr = extraBlock;
    numTuples = PyList_GET_SIZE(controlTuples);
    for (i = 0; i < numTuples; i++) {
        tuple = PyList_GET_ITEM(controlTuples, i);
        if (!PyTuple_Check(tuple)) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_TypeError, "expecting tuple");
            return NULL;
        }
        if (PyTuple_GET_SIZE(tuple) != 3) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_TypeError, "expecting tuple of size 3");
            return NULL;
        }
        x = PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0));
        y = PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1));
        z = PyLong_AsLong(PyTuple_GET_ITEM(tuple, 2));
        if (newpos + x > newDataLength ||
                diffPtr + x > diffBlock + diffBlockLength ||
                extraPtr + y > extraBlock + extraBlockLength) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_ValueError, "corrupt patch (overflow)");
            return NULL;
        }
        memcpy(newData + newpos, diffPtr, x);
        diffPtr += x;
        for (j = 0; j < x; j++)
            if ((oldpos + j >= 0) && (oldpos + j < origDataLength))
                newData[newpos + j] += origData[oldpos + j];
        newpos += x;
        oldpos += x;
        memcpy(newData + newpos, extraPtr, y);
        extraPtr += y;
        newpos += y;
        oldpos += z;
    }

    /* confirm that a valid patch was applied */
    if (newpos != newDataLength ||
            diffPtr != diffBlock + diffBlockLength ||
            extraPtr != extraBlock + extraBlockLength) {
        PyMem_Free(newData);
        PyErr_SetString(PyExc_ValueError, "corrupt patch (underflow)");
        return NULL;
    }

    results = PyBytes_FromStringAndSize(newData, newDataLength);
    PyMem_Free(newData);
    return results;
}

static PyObject* patch(PyObject* self, PyObject* args)
{
    char *origData, *newData, *diffBlock, *extraBlock, *diffPtr, *extraPtr;
    Py_ssize_t origDataLength, newDataLength, diffBlockLength, extraBlockLength;
    PyObject *controlTuples, *tuple, *results;
    off_t oldpos, newpos, x, y, z;
    int i, j, numTuples;

    if (!PyArg_ParseTuple(args, "s#nO!s#s#",
                          &origData, &origDataLength, &newDataLength,
                          &PyList_Type, &controlTuples,
                          &diffBlock, &diffBlockLength,
                          &extraBlock, &extraBlockLength))
        return NULL;

    /* allocate the memory for the new data */
    newData = PyMem_Malloc(newDataLength + 1);
    if (!newData)
        return PyErr_NoMemory();

    oldpos = 0;
    newpos = 0;
    diffPtr = diffBlock;
    extraPtr = extraBlock;
    numTuples = PyList_GET_SIZE(controlTuples);
    for (i = 0; i < numTuples; i++) {
        tuple = PyList_GET_ITEM(controlTuples, i);
        if (!PyTuple_Check(tuple)) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_TypeError, "expecting tuple");
            return NULL;
        }
        if (PyTuple_GET_SIZE(tuple) != 3) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_TypeError, "expecting tuple of size 3");
            return NULL;
        }
        x = PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0));
        y = PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1));
        z = PyLong_AsLong(PyTuple_GET_ITEM(tuple, 2));
        if (newpos + x > newDataLength ||
                diffPtr + x > diffBlock + diffBlockLength) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_ValueError, "corrupt patch (overflow)");
            return NULL;
        }
        memcpy(newData + newpos, diffPtr, x);
        diffPtr += x;
        for (j = 0; j < x; j++)
            if ((oldpos + j >= 0) && (oldpos + j < origDataLength))
                newData[newpos + j] += origData[oldpos + j];
        newpos += x;
        oldpos += x;
        if (newpos + y > newDataLength ||
                extraPtr + y > extraBlock + extraBlockLength) {
            PyMem_Free(newData);
            PyErr_SetString(PyExc_ValueError, "corrupt patch (overflow)");
            return NULL;
        }
        memcpy(newData + newpos, extraPtr, y);
        extraPtr += y;
        newpos += y;
        oldpos += z;
    }

    /* confirm that a valid patch was applied */
    if (newpos != newDataLength ||
            diffPtr != diffBlock + diffBlockLength ||
            extraPtr != extraBlock + extraBlockLength) {
        PyMem_Free(newData);
        PyErr_SetString(PyExc_ValueError, "corrupt patch (underflow)");
        return NULL;
    }

    results = PyBytes_FromStringAndSize(newData, newDataLength);
    PyMem_Free(newData);
    return results;
}


Input:
HandleRFBServerMessage(rfbClient* client)
{
  rfbServerToClientMsg msg;

  if (client->serverPort==-1)
    client->vncRec->readTimestamp = TRUE;
  if (!ReadFromRFBServer(client, (char *)&msg, 1))
    return FALSE;

  switch (msg.type) {

  case rfbSetColourMapEntries:
  {
    /* TODO:
    int i;
    uint16_t rgb[3];
    XColor xc;

    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
			   sz_rfbSetColourMapEntriesMsg - 1))
      return FALSE;

    msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour);
    msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours);

    for (i = 0; i < msg.scme.nColours; i++) {
      if (!ReadFromRFBServer(client, (char *)rgb, 6))
	return FALSE;
      xc.pixel = msg.scme.firstColour + i;
      xc.red = rfbClientSwap16IfLE(rgb[0]);
      xc.green = rfbClientSwap16IfLE(rgb[1]);
      xc.blue = rfbClientSwap16IfLE(rgb[2]);
      xc.flags = DoRed|DoGreen|DoBlue;
      XStoreColor(dpy, cmap, &xc);
    }
    */

    break;
  }

  case rfbFramebufferUpdate:
  {
    rfbFramebufferUpdateRectHeader rect;
    int linesToRead;
    int bytesPerLine;
    int i;

    if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1,
			   sz_rfbFramebufferUpdateMsg - 1))
      return FALSE;

    msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects);

    for (i = 0; i < msg.fu.nRects; i++) {
      if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader))
	return FALSE;

      rect.encoding = rfbClientSwap32IfLE(rect.encoding);
      if (rect.encoding == rfbEncodingLastRect)
	break;

      rect.r.x = rfbClientSwap16IfLE(rect.r.x);
      rect.r.y = rfbClientSwap16IfLE(rect.r.y);
      rect.r.w = rfbClientSwap16IfLE(rect.r.w);
      rect.r.h = rfbClientSwap16IfLE(rect.r.h);

      if (rect.encoding == rfbEncodingXCursor ||
	  rect.encoding == rfbEncodingRichCursor) {

	if (!HandleCursorShape(client,
			       rect.r.x, rect.r.y, rect.r.w, rect.r.h,
			       rect.encoding)) {
	  return FALSE;
	}
	continue;
      }

      if (rect.encoding == rfbEncodingPointerPos) {
	if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) {
	  return FALSE;
	}
	continue;
      }

      if (rect.encoding == rfbEncodingKeyboardLedState) {
          /* OK! We have received a keyboard state message!!! */
          client->KeyboardLedStateEnabled = 1;
          if (client->HandleKeyboardLedState!=NULL)
              client->HandleKeyboardLedState(client, rect.r.x, 0);
          /* stash it for the future */
          client->CurrentKeyboardLedState = rect.r.x;
          continue;
      }

      if (rect.encoding == rfbEncodingNewFBSize) {
	client->width = rect.r.w;
	client->height = rect.r.h;
	client->updateRect.x = client->updateRect.y = 0;
	client->updateRect.w = client->width;
	client->updateRect.h = client->height;
	if (!client->MallocFrameBuffer(client))
	  return FALSE;
	SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE);
	rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h);
	continue;
      }

      /* rect.r.w=byte count */
      if (rect.encoding == rfbEncodingSupportedMessages) {
          int loop;
          if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
              return FALSE;

          /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
          /* currently ignored by this library */

          rfbClientLog("client2server supported messages (bit flags)\n");
          for (loop=0;loop<32;loop+=8)
            rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
                client->supportedMessages.client2server[loop],   client->supportedMessages.client2server[loop+1],
                client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3],
                client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5],
                client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]);

          rfbClientLog("server2client supported messages (bit flags)\n");
          for (loop=0;loop<32;loop+=8)
            rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
                client->supportedMessages.server2client[loop],   client->supportedMessages.server2client[loop+1],
                client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3],
                client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5],
                client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]);
          continue;
      }

      /* rect.r.w=byte count, rect.r.h=# of encodings */
      if (rect.encoding == rfbEncodingSupportedEncodings) {
          char *buffer;
          buffer = malloc(rect.r.w);
          if (!ReadFromRFBServer(client, buffer, rect.r.w))
          {
              free(buffer);
              return FALSE;
          }

          /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */
          /* currently ignored by this library */
          free(buffer);
          continue;
      }

      /* rect.r.w=byte count */
      if (rect.encoding == rfbEncodingServerIdentity) {
          char *buffer;
          buffer = malloc(rect.r.w+1);
          if (!ReadFromRFBServer(client, buffer, rect.r.w))
          {
              free(buffer);
              return FALSE;
          }
          buffer[rect.r.w]=0; /* null terminate, just in case */
          rfbClientLog("Connected to Server \"%s\"\n", buffer);
          free(buffer);
          continue;
      }

      /* rfbEncodingUltraZip is a collection of subrects.   x = # of subrects, and h is always 0 */
      if (rect.encoding != rfbEncodingUltraZip)
      {
        if ((rect.r.x + rect.r.w > client->width) ||
	    (rect.r.y + rect.r.h > client->height))
	    {
	      rfbClientLog("Rect too large: %dx%d at (%d, %d)\n",
	  	  rect.r.w, rect.r.h, rect.r.x, rect.r.y);
	      return FALSE;
            }

        /* UltraVNC with scaling, will send rectangles with a zero W or H
         *
        if ((rect.encoding != rfbEncodingTight) &&
            (rect.r.h * rect.r.w == 0))
        {
	  rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
	  continue;
        }
        */

        /* If RichCursor encoding is used, we should prevent collisions
	   between framebuffer updates and cursor drawing operations. */
        client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
      }

      switch (rect.encoding) {

      case rfbEncodingRaw: {
	int y=rect.r.y, h=rect.r.h;

	bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8;
	/* RealVNC 4.x-5.x on OSX can induce bytesPerLine==0,
	   usually during GPU accel. */
	/* Regardless of cause, do not divide by zero. */
	linesToRead = bytesPerLine ? (RFB_BUFFER_SIZE / bytesPerLine) : 0;

	while (linesToRead && h > 0) {
	  if (linesToRead > h)
	    linesToRead = h;

	  if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
	    return FALSE;

	  client->GotBitmap(client, (uint8_t *)client->buffer,
			   rect.r.x, y, rect.r.w,linesToRead);

	  h -= linesToRead;
	  y += linesToRead;

	}
	break;
      }

      case rfbEncodingCopyRect:
      {
	rfbCopyRect cr;

	if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect))
	  return FALSE;

	cr.srcX = rfbClientSwap16IfLE(cr.srcX);
	cr.srcY = rfbClientSwap16IfLE(cr.srcY);

	/* If RichCursor encoding is used, we should extend our
	   "cursor lock area" (previously set to destination
	   rectangle) to the source rectangle as well. */
	client->SoftCursorLockArea(client,
				   cr.srcX, cr.srcY, rect.r.w, rect.r.h);

        client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h,
                            rect.r.x, rect.r.y);

	break;
      }

      case rfbEncodingRRE:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }

      case rfbEncodingCoRRE:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }

      case rfbEncodingHextile:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }

      case rfbEncodingUltra:
      {
        switch (client->format.bitsPerPixel) {
        case 8:
          if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 16:
          if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 32:
          if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        }
        break;
      }
      case rfbEncodingUltraZip:
      {
        switch (client->format.bitsPerPixel) {
        case 8:
          if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 16:
          if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 32:
          if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        }
        break;
      }

      case rfbEncodingTRLE:
	  {
        switch (client->format.bitsPerPixel) {
        case 8:
          if (!HandleTRLE8(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
            return FALSE;
          break;
        case 16:
          if (client->si.format.greenMax > 0x1F) {
            if (!HandleTRLE16(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          } else {
            if (!HandleTRLE15(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          }
          break;
        case 32: {
          uint32_t maxColor =
              (client->format.redMax << client->format.redShift) |
              (client->format.greenMax << client->format.greenShift) |
              (client->format.blueMax << client->format.blueShift);
          if ((client->format.bigEndian && (maxColor & 0xff) == 0) ||
              (!client->format.bigEndian && (maxColor & 0xff000000) == 0)) {
            if (!HandleTRLE24(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          } else if (!client->format.bigEndian && (maxColor & 0xff) == 0) {
            if (!HandleTRLE24Up(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          } else if (client->format.bigEndian && (maxColor & 0xff000000) == 0) {
            if (!HandleTRLE24Down(client, rect.r.x, rect.r.y, rect.r.w,
                                  rect.r.h))
              return FALSE;
          } else if (!HandleTRLE32(client, rect.r.x, rect.r.y, rect.r.w,
                                   rect.r.h))
            return FALSE;
          break;
        }
        }
        break;
      }

#ifdef LIBVNCSERVER_HAVE_LIBZ
      case rfbEncodingZlib:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
     }

#ifdef LIBVNCSERVER_HAVE_LIBJPEG
      case rfbEncodingTight:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }
#endif
      case rfbEncodingZRLE:
	/* Fail safe for ZYWRLE unsupport VNC server. */
	client->appData.qualityLevel = 9;
	/* fall through */
      case rfbEncodingZYWRLE:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (client->si.format.greenMax > 0x1F) {
	    if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else {
	    if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  }
	  break;
	case 32:
	{
	  uint32_t maxColor=(client->format.redMax<<client->format.redShift)|
		(client->format.greenMax<<client->format.greenShift)|
		(client->format.blueMax<<client->format.blueShift);
	  if ((client->format.bigEndian && (maxColor&0xff)==0) ||
	      (!client->format.bigEndian && (maxColor&0xff000000)==0)) {
	    if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else if (!client->format.bigEndian && (maxColor&0xff)==0) {
	    if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else if (client->format.bigEndian && (maxColor&0xff000000)==0) {
	    if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	}
	break;
     }

#endif

      default:
	 {
	   rfbBool handled = FALSE;
	   rfbClientProtocolExtension* e;

	   for(e = rfbClientExtensions; !handled && e; e = e->next)
	     if(e->handleEncoding && e->handleEncoding(client, &rect))
	       handled = TRUE;

	   if(!handled) {
	     rfbClientLog("Unknown rect encoding %d\n",
		 (int)rect.encoding);
	     return FALSE;
	   }
	 }
      }

      /* Now we may discard "soft cursor locks". */
      client->SoftCursorUnlockScreen(client);

      client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
    }

    if (!SendIncrementalFramebufferUpdateRequest(client))
      return FALSE;

    if (client->FinishedFrameBufferUpdate)
      client->FinishedFrameBufferUpdate(client);

    break;
  }

  case rfbBell:
  {
    client->Bell(client);

    break;
  }

  case rfbServerCutText:
  {
    char *buffer;

    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
			   sz_rfbServerCutTextMsg - 1))
      return FALSE;

    msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);

    if (msg.sct.length > 1<<20) {
	    rfbClientErr("Ignoring too big cut text length sent by server: %u B > 1 MB\n", (unsigned int)msg.sct.length);
	    return FALSE;
    }

    buffer = malloc((uint64_t)msg.sct.length+1);

    if (!ReadFromRFBServer(client, buffer, msg.sct.length)) {
      free(buffer);
      return FALSE;
    }

    buffer[msg.sct.length] = 0;

    if (client->GotXCutText)
      client->GotXCutText(client, buffer, msg.sct.length);

    free(buffer);

    break;
  }

  case rfbTextChat:
  {
      char *buffer=NULL;
      if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                             sz_rfbTextChatMsg- 1))
        return FALSE;
      msg.tc.length = rfbClientSwap32IfLE(msg.sct.length);
      switch(msg.tc.length) {
      case rfbTextChatOpen:
          rfbClientLog("Received TextChat Open\n");
          if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)rfbTextChatOpen, NULL);
          break;
      case rfbTextChatClose:
          rfbClientLog("Received TextChat Close\n");
         if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)rfbTextChatClose, NULL);
          break;
      case rfbTextChatFinished:
          rfbClientLog("Received TextChat Finished\n");
         if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
          break;
      default:
          buffer=malloc(msg.tc.length+1);
          if (!ReadFromRFBServer(client, buffer, msg.tc.length))
          {
              free(buffer);
              return FALSE;
          }
          /* Null Terminate <just in case> */
          buffer[msg.tc.length]=0;
          rfbClientLog("Received TextChat \"%s\"\n", buffer);
          if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)msg.tc.length, buffer);
          free(buffer);
          break;
      }
      break;
  }

  case rfbXvp:
  {
    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                           sz_rfbXvpMsg -1))
      return FALSE;

    SetClient2Server(client, rfbXvp);
    /* technically, we only care what we can *send* to the server
     * but, we set Server2Client Just in case it ever becomes useful
     */
    SetServer2Client(client, rfbXvp);

    if(client->HandleXvpMsg)
      client->HandleXvpMsg(client, msg.xvp.version, msg.xvp.code);

    break;
  }

  case rfbResizeFrameBuffer:
  {
    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                           sz_rfbResizeFrameBufferMsg -1))
      return FALSE;
    client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth);
    client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth);
    client->updateRect.x = client->updateRect.y = 0;
    client->updateRect.w = client->width;
    client->updateRect.h = client->height;
    if (!client->MallocFrameBuffer(client))
      return FALSE;

    SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
    rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
    break;
  }

  case rfbPalmVNCReSizeFrameBuffer:
  {
    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                           sz_rfbPalmVNCReSizeFrameBufferMsg -1))
      return FALSE;
    client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w);
    client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h);
    client->updateRect.x = client->updateRect.y = 0;
    client->updateRect.w = client->width;
    client->updateRect.h = client->height;
    if (!client->MallocFrameBuffer(client))
      return FALSE;
    SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
    rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
    break;
  }

  default:
    {
      rfbBool handled = FALSE;
      rfbClientProtocolExtension* e;

      for(e = rfbClientExtensions; !handled && e; e = e->next)
	if(e->handleMessage && e->handleMessage(client, &msg))
	  handled = TRUE;

      if(!handled) {
	char buffer[256];
	rfbClientLog("Unknown message type %d from VNC server\n",msg.type);
	ReadFromRFBServer(client, buffer, 256);
	return FALSE;
      }
    }
  }

  return TRUE;
}

HandleRFBServerMessage(rfbClient* client)
{
  rfbServerToClientMsg msg;

  if (client->serverPort==-1)
    client->vncRec->readTimestamp = TRUE;
  if (!ReadFromRFBServer(client, (char *)&msg, 1))
    return FALSE;

  switch (msg.type) {

  case rfbSetColourMapEntries:
  {
    /* TODO:
    int i;
    uint16_t rgb[3];
    XColor xc;

    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
			   sz_rfbSetColourMapEntriesMsg - 1))
      return FALSE;

    msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour);
    msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours);

    for (i = 0; i < msg.scme.nColours; i++) {
      if (!ReadFromRFBServer(client, (char *)rgb, 6))
	return FALSE;
      xc.pixel = msg.scme.firstColour + i;
      xc.red = rfbClientSwap16IfLE(rgb[0]);
      xc.green = rfbClientSwap16IfLE(rgb[1]);
      xc.blue = rfbClientSwap16IfLE(rgb[2]);
      xc.flags = DoRed|DoGreen|DoBlue;
      XStoreColor(dpy, cmap, &xc);
    }
    */

    break;
  }

  case rfbFramebufferUpdate:
  {
    rfbFramebufferUpdateRectHeader rect;
    int linesToRead;
    int bytesPerLine;
    int i;

    if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1,
			   sz_rfbFramebufferUpdateMsg - 1))
      return FALSE;

    msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects);

    for (i = 0; i < msg.fu.nRects; i++) {
      if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader))
	return FALSE;

      rect.encoding = rfbClientSwap32IfLE(rect.encoding);
      if (rect.encoding == rfbEncodingLastRect)
	break;

      rect.r.x = rfbClientSwap16IfLE(rect.r.x);
      rect.r.y = rfbClientSwap16IfLE(rect.r.y);
      rect.r.w = rfbClientSwap16IfLE(rect.r.w);
      rect.r.h = rfbClientSwap16IfLE(rect.r.h);

      if (rect.encoding == rfbEncodingXCursor ||
	  rect.encoding == rfbEncodingRichCursor) {

	if (!HandleCursorShape(client,
			       rect.r.x, rect.r.y, rect.r.w, rect.r.h,
			       rect.encoding)) {
	  return FALSE;
	}
	continue;
      }

      if (rect.encoding == rfbEncodingPointerPos) {
	if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) {
	  return FALSE;
	}
	continue;
      }

      if (rect.encoding == rfbEncodingKeyboardLedState) {
          /* OK! We have received a keyboard state message!!! */
          client->KeyboardLedStateEnabled = 1;
          if (client->HandleKeyboardLedState!=NULL)
              client->HandleKeyboardLedState(client, rect.r.x, 0);
          /* stash it for the future */
          client->CurrentKeyboardLedState = rect.r.x;
          continue;
      }

      if (rect.encoding == rfbEncodingNewFBSize) {
	client->width = rect.r.w;
	client->height = rect.r.h;
	client->updateRect.x = client->updateRect.y = 0;
	client->updateRect.w = client->width;
	client->updateRect.h = client->height;
	if (!client->MallocFrameBuffer(client))
	  return FALSE;
	SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE);
	rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h);
	continue;
      }

      /* rect.r.w=byte count */
      if (rect.encoding == rfbEncodingSupportedMessages) {
          int loop;
          if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages))
              return FALSE;

          /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */
          /* currently ignored by this library */

          rfbClientLog("client2server supported messages (bit flags)\n");
          for (loop=0;loop<32;loop+=8)
            rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
                client->supportedMessages.client2server[loop],   client->supportedMessages.client2server[loop+1],
                client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3],
                client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5],
                client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]);

          rfbClientLog("server2client supported messages (bit flags)\n");
          for (loop=0;loop<32;loop+=8)
            rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop,
                client->supportedMessages.server2client[loop],   client->supportedMessages.server2client[loop+1],
                client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3],
                client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5],
                client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]);
          continue;
      }

      /* rect.r.w=byte count, rect.r.h=# of encodings */
      if (rect.encoding == rfbEncodingSupportedEncodings) {
          char *buffer;
          buffer = malloc(rect.r.w);
          if (!ReadFromRFBServer(client, buffer, rect.r.w))
          {
              free(buffer);
              return FALSE;
          }

          /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */
          /* currently ignored by this library */
          free(buffer);
          continue;
      }

      /* rect.r.w=byte count */
      if (rect.encoding == rfbEncodingServerIdentity) {
          char *buffer;
          buffer = malloc(rect.r.w+1);
          if (!ReadFromRFBServer(client, buffer, rect.r.w))
          {
              free(buffer);
              return FALSE;
          }
          buffer[rect.r.w]=0; /* null terminate, just in case */
          rfbClientLog("Connected to Server \"%s\"\n", buffer);
          free(buffer);
          continue;
      }

      /* rfbEncodingUltraZip is a collection of subrects.   x = # of subrects, and h is always 0 */
      if (rect.encoding != rfbEncodingUltraZip)
      {
        if ((rect.r.x + rect.r.w > client->width) ||
	    (rect.r.y + rect.r.h > client->height))
	    {
	      rfbClientLog("Rect too large: %dx%d at (%d, %d)\n",
	  	  rect.r.w, rect.r.h, rect.r.x, rect.r.y);
	      return FALSE;
            }

        /* UltraVNC with scaling, will send rectangles with a zero W or H
         *
        if ((rect.encoding != rfbEncodingTight) &&
            (rect.r.h * rect.r.w == 0))
        {
	  rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
	  continue;
        }
        */

        /* If RichCursor encoding is used, we should prevent collisions
	   between framebuffer updates and cursor drawing operations. */
        client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
      }

      switch (rect.encoding) {

      case rfbEncodingRaw: {
	int y=rect.r.y, h=rect.r.h;

	bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8;
	/* RealVNC 4.x-5.x on OSX can induce bytesPerLine==0,
	   usually during GPU accel. */
	/* Regardless of cause, do not divide by zero. */
	linesToRead = bytesPerLine ? (RFB_BUFFER_SIZE / bytesPerLine) : 0;

	while (linesToRead && h > 0) {
	  if (linesToRead > h)
	    linesToRead = h;

	  if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead))
	    return FALSE;

	  client->GotBitmap(client, (uint8_t *)client->buffer,
			   rect.r.x, y, rect.r.w,linesToRead);

	  h -= linesToRead;
	  y += linesToRead;

	}
	break;
      }

      case rfbEncodingCopyRect:
      {
	rfbCopyRect cr;

	if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect))
	  return FALSE;

	cr.srcX = rfbClientSwap16IfLE(cr.srcX);
	cr.srcY = rfbClientSwap16IfLE(cr.srcY);

	/* If RichCursor encoding is used, we should extend our
	   "cursor lock area" (previously set to destination
	   rectangle) to the source rectangle as well. */
	client->SoftCursorLockArea(client,
				   cr.srcX, cr.srcY, rect.r.w, rect.r.h);

        client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h,
                            rect.r.x, rect.r.y);

	break;
      }

      case rfbEncodingRRE:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }

      case rfbEncodingCoRRE:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }

      case rfbEncodingHextile:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }

      case rfbEncodingUltra:
      {
        switch (client->format.bitsPerPixel) {
        case 8:
          if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 16:
          if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 32:
          if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        }
        break;
      }
      case rfbEncodingUltraZip:
      {
        switch (client->format.bitsPerPixel) {
        case 8:
          if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 16:
          if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        case 32:
          if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
            return FALSE;
          break;
        }
        break;
      }

      case rfbEncodingTRLE:
	  {
        switch (client->format.bitsPerPixel) {
        case 8:
          if (!HandleTRLE8(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
            return FALSE;
          break;
        case 16:
          if (client->si.format.greenMax > 0x1F) {
            if (!HandleTRLE16(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          } else {
            if (!HandleTRLE15(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          }
          break;
        case 32: {
          uint32_t maxColor =
              (client->format.redMax << client->format.redShift) |
              (client->format.greenMax << client->format.greenShift) |
              (client->format.blueMax << client->format.blueShift);
          if ((client->format.bigEndian && (maxColor & 0xff) == 0) ||
              (!client->format.bigEndian && (maxColor & 0xff000000) == 0)) {
            if (!HandleTRLE24(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          } else if (!client->format.bigEndian && (maxColor & 0xff) == 0) {
            if (!HandleTRLE24Up(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h))
              return FALSE;
          } else if (client->format.bigEndian && (maxColor & 0xff000000) == 0) {
            if (!HandleTRLE24Down(client, rect.r.x, rect.r.y, rect.r.w,
                                  rect.r.h))
              return FALSE;
          } else if (!HandleTRLE32(client, rect.r.x, rect.r.y, rect.r.w,
                                   rect.r.h))
            return FALSE;
          break;
        }
        }
        break;
      }

#ifdef LIBVNCSERVER_HAVE_LIBZ
      case rfbEncodingZlib:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
     }

#ifdef LIBVNCSERVER_HAVE_LIBJPEG
      case rfbEncodingTight:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 32:
	  if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	break;
      }
#endif
      case rfbEncodingZRLE:
	/* Fail safe for ZYWRLE unsupport VNC server. */
	client->appData.qualityLevel = 9;
	/* fall through */
      case rfbEncodingZYWRLE:
      {
	switch (client->format.bitsPerPixel) {
	case 8:
	  if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	case 16:
	  if (client->si.format.greenMax > 0x1F) {
	    if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else {
	    if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  }
	  break;
	case 32:
	{
	  uint32_t maxColor=(client->format.redMax<<client->format.redShift)|
		(client->format.greenMax<<client->format.greenShift)|
		(client->format.blueMax<<client->format.blueShift);
	  if ((client->format.bigEndian && (maxColor&0xff)==0) ||
	      (!client->format.bigEndian && (maxColor&0xff000000)==0)) {
	    if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else if (!client->format.bigEndian && (maxColor&0xff)==0) {
	    if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else if (client->format.bigEndian && (maxColor&0xff000000)==0) {
	    if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	      return FALSE;
	  } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h))
	    return FALSE;
	  break;
	}
	}
	break;
     }

#endif

      default:
	 {
	   rfbBool handled = FALSE;
	   rfbClientProtocolExtension* e;

	   for(e = rfbClientExtensions; !handled && e; e = e->next)
	     if(e->handleEncoding && e->handleEncoding(client, &rect))
	       handled = TRUE;

	   if(!handled) {
	     rfbClientLog("Unknown rect encoding %d\n",
		 (int)rect.encoding);
	     return FALSE;
	   }
	 }
      }

      /* Now we may discard "soft cursor locks". */
      client->SoftCursorUnlockScreen(client);

      client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
    }

    if (!SendIncrementalFramebufferUpdateRequest(client))
      return FALSE;

    if (client->FinishedFrameBufferUpdate)
      client->FinishedFrameBufferUpdate(client);

    break;
  }

  case rfbBell:
  {
    client->Bell(client);

    break;
  }

  case rfbServerCutText:
  {
    char *buffer;

    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
			   sz_rfbServerCutTextMsg - 1))
      return FALSE;

    msg.sct.length = rfbClientSwap32IfLE(msg.sct.length);

    if (msg.sct.length > 1<<20) {
	    rfbClientErr("Ignoring too big cut text length sent by server: %u B > 1 MB\n", (unsigned int)msg.sct.length);
	    return FALSE;
    }

    buffer = malloc(msg.sct.length+1);

    if (!ReadFromRFBServer(client, buffer, msg.sct.length)) {
      free(buffer);
      return FALSE;
    }

    buffer[msg.sct.length] = 0;

    if (client->GotXCutText)
      client->GotXCutText(client, buffer, msg.sct.length);

    free(buffer);

    break;
  }

  case rfbTextChat:
  {
      char *buffer=NULL;
      if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                             sz_rfbTextChatMsg- 1))
        return FALSE;
      msg.tc.length = rfbClientSwap32IfLE(msg.sct.length);
      switch(msg.tc.length) {
      case rfbTextChatOpen:
          rfbClientLog("Received TextChat Open\n");
          if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)rfbTextChatOpen, NULL);
          break;
      case rfbTextChatClose:
          rfbClientLog("Received TextChat Close\n");
         if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)rfbTextChatClose, NULL);
          break;
      case rfbTextChatFinished:
          rfbClientLog("Received TextChat Finished\n");
         if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
          break;
      default:
          buffer=malloc(msg.tc.length+1);
          if (!ReadFromRFBServer(client, buffer, msg.tc.length))
          {
              free(buffer);
              return FALSE;
          }
          /* Null Terminate <just in case> */
          buffer[msg.tc.length]=0;
          rfbClientLog("Received TextChat \"%s\"\n", buffer);
          if (client->HandleTextChat!=NULL)
              client->HandleTextChat(client, (int)msg.tc.length, buffer);
          free(buffer);
          break;
      }
      break;
  }

  case rfbXvp:
  {
    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                           sz_rfbXvpMsg -1))
      return FALSE;

    SetClient2Server(client, rfbXvp);
    /* technically, we only care what we can *send* to the server
     * but, we set Server2Client Just in case it ever becomes useful
     */
    SetServer2Client(client, rfbXvp);

    if(client->HandleXvpMsg)
      client->HandleXvpMsg(client, msg.xvp.version, msg.xvp.code);

    break;
  }

  case rfbResizeFrameBuffer:
  {
    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                           sz_rfbResizeFrameBufferMsg -1))
      return FALSE;
    client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth);
    client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth);
    client->updateRect.x = client->updateRect.y = 0;
    client->updateRect.w = client->width;
    client->updateRect.h = client->height;
    if (!client->MallocFrameBuffer(client))
      return FALSE;

    SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
    rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
    break;
  }

  case rfbPalmVNCReSizeFrameBuffer:
  {
    if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
                           sz_rfbPalmVNCReSizeFrameBufferMsg -1))
      return FALSE;
    client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w);
    client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h);
    client->updateRect.x = client->updateRect.y = 0;
    client->updateRect.w = client->width;
    client->updateRect.h = client->height;
    if (!client->MallocFrameBuffer(client))
      return FALSE;
    SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE);
    rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height);
    break;
  }

  default:
    {
      rfbBool handled = FALSE;
      rfbClientProtocolExtension* e;

      for(e = rfbClientExtensions; !handled && e; e = e->next)
	if(e->handleMessage && e->handleMessage(client, &msg))
	  handled = TRUE;

      if(!handled) {
	char buffer[256];
	rfbClientLog("Unknown message type %d from VNC server\n",msg.type);
	ReadFromRFBServer(client, buffer, 256);
	return FALSE;
      }
    }
  }

  return TRUE;
}


Input:
int32_t *enc_untrusted_create_wait_queue() {
  MessageWriter input;
  MessageReader output;
  input.Push<uint64_t>(sizeof(int32_t));
  const auto status = NonSystemCallDispatcher(
      ::asylo::host_call::kLocalLifetimeAllocHandler, &input, &output);
  CheckStatusAndParamCount(status, output, "enc_untrusted_create_wait_queue",
                           2);
  int32_t *queue = reinterpret_cast<int32_t *>(output.next<uintptr_t>());
  int klinux_errno = output.next<int>();
  if (queue == nullptr) {
    errno = FromkLinuxErrorNumber(klinux_errno);
  }
  enc_untrusted_disable_waiting(queue);
  return queue;
}

int32_t *enc_untrusted_create_wait_queue() {
  MessageWriter input;
  MessageReader output;
  input.Push<uint64_t>(sizeof(int32_t));
  const auto status = NonSystemCallDispatcher(
      ::asylo::host_call::kLocalLifetimeAllocHandler, &input, &output);
  CheckStatusAndParamCount(status, output, "enc_untrusted_create_wait_queue",
                           2);
  int32_t *queue = reinterpret_cast<int32_t *>(output.next<uintptr_t>());
  if (!TrustedPrimitives::IsOutsideEnclave(queue, sizeof(int32_t))) {
    TrustedPrimitives::BestEffortAbort(
        "enc_untrusted_create_wait_queue: queue should be in untrusted memory");
  }
  int klinux_errno = output.next<int>();
  if (queue == nullptr) {
    errno = FromkLinuxErrorNumber(klinux_errno);
  }
  enc_untrusted_disable_waiting(queue);
  return queue;
}


Input:
bool FromkLinuxSockAddr(const struct klinux_sockaddr *input,
                        socklen_t input_len, struct sockaddr *output,
                        socklen_t *output_len,
                        void (*abort_handler)(const char *)) {
  if (!input || !output || !output_len || input_len == 0) {
    output = nullptr;
    return false;
  }

  int16_t klinux_family = input->klinux_sa_family;
  if (klinux_family == kLinux_AF_UNIX) {
    struct klinux_sockaddr_un *klinux_sockaddr_un_in =
        const_cast<struct klinux_sockaddr_un *>(
            reinterpret_cast<const struct klinux_sockaddr_un *>(input));

    struct sockaddr_un sockaddr_un_out;
    sockaddr_un_out.sun_family = AF_UNIX;
    InitializeToZeroArray(sockaddr_un_out.sun_path);
    ReinterpretCopyArray(
        sockaddr_un_out.sun_path, klinux_sockaddr_un_in->klinux_sun_path,
        std::min(sizeof(sockaddr_un_out.sun_path),
                 sizeof(klinux_sockaddr_un_in->klinux_sun_path)));
    CopySockaddr(&sockaddr_un_out, sizeof(sockaddr_un_out), output, output_len);
  } else if (klinux_family == kLinux_AF_INET) {
    struct klinux_sockaddr_in *klinux_sockaddr_in_in =
        const_cast<struct klinux_sockaddr_in *>(
            reinterpret_cast<const struct klinux_sockaddr_in *>(input));

    struct sockaddr_in sockaddr_in_out;
    sockaddr_in_out.sin_family = AF_INET;
    sockaddr_in_out.sin_port = klinux_sockaddr_in_in->klinux_sin_port;
    InitializeToZeroSingle(&sockaddr_in_out.sin_addr);
    ReinterpretCopySingle(&sockaddr_in_out.sin_addr,
                          &klinux_sockaddr_in_in->klinux_sin_addr);
    InitializeToZeroArray(sockaddr_in_out.sin_zero);
    ReinterpretCopyArray(sockaddr_in_out.sin_zero,
                         klinux_sockaddr_in_in->klinux_sin_zero);
    CopySockaddr(&sockaddr_in_out, sizeof(sockaddr_in_out), output, output_len);
  } else if (klinux_family == kLinux_AF_INET6) {
    struct klinux_sockaddr_in6 *klinux_sockaddr_in6_in =
        const_cast<struct klinux_sockaddr_in6 *>(
            reinterpret_cast<const struct klinux_sockaddr_in6 *>(input));

    struct sockaddr_in6 sockaddr_in6_out;
    sockaddr_in6_out.sin6_family = AF_INET6;
    sockaddr_in6_out.sin6_port = klinux_sockaddr_in6_in->klinux_sin6_port;
    sockaddr_in6_out.sin6_flowinfo =
        klinux_sockaddr_in6_in->klinux_sin6_flowinfo;
    sockaddr_in6_out.sin6_scope_id =
        klinux_sockaddr_in6_in->klinux_sin6_scope_id;
    InitializeToZeroSingle(&sockaddr_in6_out.sin6_addr);
    ReinterpretCopySingle(&sockaddr_in6_out.sin6_addr,
                          &klinux_sockaddr_in6_in->klinux_sin6_addr);
    CopySockaddr(&sockaddr_in6_out, sizeof(sockaddr_in6_out), output,
                 output_len);
  } else if (klinux_family == kLinux_AF_UNSPEC) {
    output = nullptr;
    *output_len = 0;
  } else {
    if (abort_handler != nullptr) {
      std::string message = absl::StrCat(
          "Type conversion error - Unsupported AF family: ", klinux_family);
      abort_handler(message.c_str());
    } else {
      abort();
    }
  }
  return true;
}

bool FromkLinuxSockAddr(const struct klinux_sockaddr *input,
                        socklen_t input_len, struct sockaddr *output,
                        socklen_t *output_len,
                        void (*abort_handler)(const char *)) {
  if (!input || !output || !output_len || input_len == 0) {
    output = nullptr;
    return false;
  }

  int16_t klinux_family = input->klinux_sa_family;
  if (klinux_family == kLinux_AF_UNIX) {
    if (input_len < sizeof(struct klinux_sockaddr_un)) {
      return false;
    }

    struct klinux_sockaddr_un *klinux_sockaddr_un_in =
        const_cast<struct klinux_sockaddr_un *>(
            reinterpret_cast<const struct klinux_sockaddr_un *>(input));

    struct sockaddr_un sockaddr_un_out;
    sockaddr_un_out.sun_family = AF_UNIX;
    InitializeToZeroArray(sockaddr_un_out.sun_path);
    ReinterpretCopyArray(
        sockaddr_un_out.sun_path, klinux_sockaddr_un_in->klinux_sun_path,
        std::min(sizeof(sockaddr_un_out.sun_path),
                 sizeof(klinux_sockaddr_un_in->klinux_sun_path)));
    CopySockaddr(&sockaddr_un_out, sizeof(sockaddr_un_out), output, output_len);
  } else if (klinux_family == kLinux_AF_INET) {
    if (input_len < sizeof(struct klinux_sockaddr_in)) {
      return false;
    }
    struct klinux_sockaddr_in *klinux_sockaddr_in_in =
        const_cast<struct klinux_sockaddr_in *>(
            reinterpret_cast<const struct klinux_sockaddr_in *>(input));

    struct sockaddr_in sockaddr_in_out;
    sockaddr_in_out.sin_family = AF_INET;
    sockaddr_in_out.sin_port = klinux_sockaddr_in_in->klinux_sin_port;
    InitializeToZeroSingle(&sockaddr_in_out.sin_addr);
    ReinterpretCopySingle(&sockaddr_in_out.sin_addr,
                          &klinux_sockaddr_in_in->klinux_sin_addr);
    InitializeToZeroArray(sockaddr_in_out.sin_zero);
    ReinterpretCopyArray(sockaddr_in_out.sin_zero,
                         klinux_sockaddr_in_in->klinux_sin_zero);
    CopySockaddr(&sockaddr_in_out, sizeof(sockaddr_in_out), output, output_len);
  } else if (klinux_family == kLinux_AF_INET6) {
    if (input_len < sizeof(struct klinux_sockaddr_in6)) {
      return false;
    }

    struct klinux_sockaddr_in6 *klinux_sockaddr_in6_in =
        const_cast<struct klinux_sockaddr_in6 *>(
            reinterpret_cast<const struct klinux_sockaddr_in6 *>(input));

    struct sockaddr_in6 sockaddr_in6_out;
    sockaddr_in6_out.sin6_family = AF_INET6;
    sockaddr_in6_out.sin6_port = klinux_sockaddr_in6_in->klinux_sin6_port;
    sockaddr_in6_out.sin6_flowinfo =
        klinux_sockaddr_in6_in->klinux_sin6_flowinfo;
    sockaddr_in6_out.sin6_scope_id =
        klinux_sockaddr_in6_in->klinux_sin6_scope_id;
    InitializeToZeroSingle(&sockaddr_in6_out.sin6_addr);
    ReinterpretCopySingle(&sockaddr_in6_out.sin6_addr,
                          &klinux_sockaddr_in6_in->klinux_sin6_addr);
    CopySockaddr(&sockaddr_in6_out, sizeof(sockaddr_in6_out), output,
                 output_len);
  } else if (klinux_family == kLinux_AF_UNSPEC) {
    output = nullptr;
    *output_len = 0;
  } else {
    if (abort_handler != nullptr) {
      std::string message = absl::StrCat(
          "Type conversion error - Unsupported AF family: ", klinux_family);
      abort_handler(message.c_str());
    } else {
      abort();
    }
  }
  return true;
}


Input:
opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image,
										opj_cp_t *p_cp,
										OPJ_UINT32 p_tile_no)
{
	/* loop */
	OPJ_UINT32 pino;
	OPJ_UINT32 compno, resno;

	/* to store w, h, dx and dy fro all components and resolutions */
	OPJ_UINT32 * l_tmp_data;
	OPJ_UINT32 ** l_tmp_ptr;

	/* encoding prameters to set */
	OPJ_UINT32 l_max_res;
	OPJ_UINT32 l_max_prec;
	OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1;
	OPJ_UINT32 l_dx_min,l_dy_min;
	OPJ_UINT32 l_bound;
	OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ;
	OPJ_UINT32 l_data_stride;

	/* pointers */
	opj_pi_iterator_t *l_pi = 00;
	opj_tcp_t *l_tcp = 00;
	const opj_tccp_t *l_tccp = 00;
	opj_pi_comp_t *l_current_comp = 00;
	opj_image_comp_t * l_img_comp = 00;
	opj_pi_iterator_t * l_current_pi = 00;
	OPJ_UINT32 * l_encoding_value_ptr = 00;

	/* preconditions in debug */
	assert(p_cp != 00);
	assert(p_image != 00);
	assert(p_tile_no < p_cp->tw * p_cp->th);

	/* initializations */
	l_tcp = &p_cp->tcps[p_tile_no];
	l_bound = l_tcp->numpocs+1;

	l_data_stride = 4 * OPJ_J2K_MAXRLVLS;
	l_tmp_data = (OPJ_UINT32*)opj_malloc(
		l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
	if
		(! l_tmp_data)
	{
		return 00;
	}
	l_tmp_ptr = (OPJ_UINT32**)opj_malloc(
		p_image->numcomps * sizeof(OPJ_UINT32 *));
	if
		(! l_tmp_ptr)
	{
		opj_free(l_tmp_data);
		return 00;
	}

	/* memory allocation for pi */
	l_pi = opj_pi_create(p_image, p_cp, p_tile_no);
	if (!l_pi) {
		opj_free(l_tmp_data);
		opj_free(l_tmp_ptr);
		return 00;
	}

	l_encoding_value_ptr = l_tmp_data;
	/* update pointer array */
	for
		(compno = 0; compno < p_image->numcomps; ++compno)
	{
		l_tmp_ptr[compno] = l_encoding_value_ptr;
		l_encoding_value_ptr += l_data_stride;
	}
	/* get encoding parameters */
	opj_get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr);

	/* step calculations */
	l_step_p = 1;
	l_step_c = l_max_prec * l_step_p;
	l_step_r = p_image->numcomps * l_step_c;
	l_step_l = l_max_res * l_step_r;

	/* set values for first packet iterator */
	l_current_pi = l_pi;

	/* memory allocation for include */
	l_current_pi->include = (OPJ_INT16*) opj_calloc((l_tcp->numlayers +1) * l_step_l, sizeof(OPJ_INT16));
	if
		(!l_current_pi->include)
	{
		opj_free(l_tmp_data);
		opj_free(l_tmp_ptr);
		opj_pi_destroy(l_pi, l_bound);
		return 00;
	}

	/* special treatment for the first packet iterator */
	l_current_comp = l_current_pi->comps;
	l_img_comp = p_image->comps;
	l_tccp = l_tcp->tccps;

	l_current_pi->tx0 = l_tx0;
	l_current_pi->ty0 = l_ty0;
	l_current_pi->tx1 = l_tx1;
	l_current_pi->ty1 = l_ty1;

	/*l_current_pi->dx = l_img_comp->dx;*/
	/*l_current_pi->dy = l_img_comp->dy;*/

	l_current_pi->step_p = l_step_p;
	l_current_pi->step_c = l_step_c;
	l_current_pi->step_r = l_step_r;
	l_current_pi->step_l = l_step_l;

	/* allocation for components and number of components has already been calculated by opj_pi_create */
	for
		(compno = 0; compno < l_current_pi->numcomps; ++compno)
	{
		opj_pi_resolution_t *l_res = l_current_comp->resolutions;
		l_encoding_value_ptr = l_tmp_ptr[compno];

		l_current_comp->dx = l_img_comp->dx;
		l_current_comp->dy = l_img_comp->dy;
		/* resolutions have already been initialized */
		for
			(resno = 0; resno < l_current_comp->numresolutions; resno++)
		{
			l_res->pdx = *(l_encoding_value_ptr++);
			l_res->pdy = *(l_encoding_value_ptr++);
			l_res->pw =  *(l_encoding_value_ptr++);
			l_res->ph =  *(l_encoding_value_ptr++);
			++l_res;
		}
		++l_current_comp;
		++l_img_comp;
		++l_tccp;
	}
	++l_current_pi;

	for (pino = 1 ; pino<l_bound ; ++pino )
	{
		l_current_comp = l_current_pi->comps;
		l_img_comp = p_image->comps;
		l_tccp = l_tcp->tccps;

		l_current_pi->tx0 = l_tx0;
		l_current_pi->ty0 = l_ty0;
		l_current_pi->tx1 = l_tx1;
		l_current_pi->ty1 = l_ty1;
		/*l_current_pi->dx = l_dx_min;*/
		/*l_current_pi->dy = l_dy_min;*/
		l_current_pi->step_p = l_step_p;
		l_current_pi->step_c = l_step_c;
		l_current_pi->step_r = l_step_r;
		l_current_pi->step_l = l_step_l;

		/* allocation for components and number of components has already been calculated by opj_pi_create */
		for
			(compno = 0; compno < l_current_pi->numcomps; ++compno)
		{
			opj_pi_resolution_t *l_res = l_current_comp->resolutions;
			l_encoding_value_ptr = l_tmp_ptr[compno];

			l_current_comp->dx = l_img_comp->dx;
			l_current_comp->dy = l_img_comp->dy;
			/* resolutions have already been initialized */
			for
				(resno = 0; resno < l_current_comp->numresolutions; resno++)
			{
				l_res->pdx = *(l_encoding_value_ptr++);
				l_res->pdy = *(l_encoding_value_ptr++);
				l_res->pw =  *(l_encoding_value_ptr++);
				l_res->ph =  *(l_encoding_value_ptr++);
				++l_res;
			}
			++l_current_comp;
			++l_img_comp;
			++l_tccp;
		}
		/* special treatment*/
		l_current_pi->include = (l_current_pi-1)->include;
		++l_current_pi;
	}
	opj_free(l_tmp_data);
	l_tmp_data = 00;
	opj_free(l_tmp_ptr);
	l_tmp_ptr = 00;
	if
		(l_tcp->POC)
	{
		opj_pi_update_decode_poc (l_pi,l_tcp,l_max_prec,l_max_res);
	}
	else
	{
		opj_pi_update_decode_not_poc(l_pi,l_tcp,l_max_prec,l_max_res);
	}
	return l_pi;
}

opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image,
										opj_cp_t *p_cp,
										OPJ_UINT32 p_tile_no)
{
	/* loop */
	OPJ_UINT32 pino;
	OPJ_UINT32 compno, resno;

	/* to store w, h, dx and dy fro all components and resolutions */
	OPJ_UINT32 * l_tmp_data;
	OPJ_UINT32 ** l_tmp_ptr;

	/* encoding prameters to set */
	OPJ_UINT32 l_max_res;
	OPJ_UINT32 l_max_prec;
	OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1;
	OPJ_UINT32 l_dx_min,l_dy_min;
	OPJ_UINT32 l_bound;
	OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ;
	OPJ_UINT32 l_data_stride;

	/* pointers */
	opj_pi_iterator_t *l_pi = 00;
	opj_tcp_t *l_tcp = 00;
	const opj_tccp_t *l_tccp = 00;
	opj_pi_comp_t *l_current_comp = 00;
	opj_image_comp_t * l_img_comp = 00;
	opj_pi_iterator_t * l_current_pi = 00;
	OPJ_UINT32 * l_encoding_value_ptr = 00;

	/* preconditions in debug */
	assert(p_cp != 00);
	assert(p_image != 00);
	assert(p_tile_no < p_cp->tw * p_cp->th);

	/* initializations */
	l_tcp = &p_cp->tcps[p_tile_no];
	l_bound = l_tcp->numpocs+1;

	l_data_stride = 4 * OPJ_J2K_MAXRLVLS;
	l_tmp_data = (OPJ_UINT32*)opj_malloc(
		l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
	if
		(! l_tmp_data)
	{
		return 00;
	}
	l_tmp_ptr = (OPJ_UINT32**)opj_malloc(
		p_image->numcomps * sizeof(OPJ_UINT32 *));
	if
		(! l_tmp_ptr)
	{
		opj_free(l_tmp_data);
		return 00;
	}

	/* memory allocation for pi */
	l_pi = opj_pi_create(p_image, p_cp, p_tile_no);
	if (!l_pi) {
		opj_free(l_tmp_data);
		opj_free(l_tmp_ptr);
		return 00;
	}

	l_encoding_value_ptr = l_tmp_data;
	/* update pointer array */
	for
		(compno = 0; compno < p_image->numcomps; ++compno)
	{
		l_tmp_ptr[compno] = l_encoding_value_ptr;
		l_encoding_value_ptr += l_data_stride;
	}
	/* get encoding parameters */
	opj_get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr);

	/* step calculations */
	l_step_p = 1;
	l_step_c = l_max_prec * l_step_p;
	l_step_r = p_image->numcomps * l_step_c;
	l_step_l = l_max_res * l_step_r;

	/* set values for first packet iterator */
	l_current_pi = l_pi;

	/* memory allocation for include */
	/* prevent an integer overflow issue */
	l_current_pi->include = 00;
	if (l_step_l <= (SIZE_MAX / (l_tcp->numlayers + 1U)))
	{
		l_current_pi->include = (OPJ_INT16*) opj_calloc((l_tcp->numlayers +1) * l_step_l, sizeof(OPJ_INT16));
	}

	if
		(!l_current_pi->include)
	{
		opj_free(l_tmp_data);
		opj_free(l_tmp_ptr);
		opj_pi_destroy(l_pi, l_bound);
		return 00;
	}

	/* special treatment for the first packet iterator */
	l_current_comp = l_current_pi->comps;
	l_img_comp = p_image->comps;
	l_tccp = l_tcp->tccps;

	l_current_pi->tx0 = l_tx0;
	l_current_pi->ty0 = l_ty0;
	l_current_pi->tx1 = l_tx1;
	l_current_pi->ty1 = l_ty1;

	/*l_current_pi->dx = l_img_comp->dx;*/
	/*l_current_pi->dy = l_img_comp->dy;*/

	l_current_pi->step_p = l_step_p;
	l_current_pi->step_c = l_step_c;
	l_current_pi->step_r = l_step_r;
	l_current_pi->step_l = l_step_l;

	/* allocation for components and number of components has already been calculated by opj_pi_create */
	for
		(compno = 0; compno < l_current_pi->numcomps; ++compno)
	{
		opj_pi_resolution_t *l_res = l_current_comp->resolutions;
		l_encoding_value_ptr = l_tmp_ptr[compno];

		l_current_comp->dx = l_img_comp->dx;
		l_current_comp->dy = l_img_comp->dy;
		/* resolutions have already been initialized */
		for
			(resno = 0; resno < l_current_comp->numresolutions; resno++)
		{
			l_res->pdx = *(l_encoding_value_ptr++);
			l_res->pdy = *(l_encoding_value_ptr++);
			l_res->pw =  *(l_encoding_value_ptr++);
			l_res->ph =  *(l_encoding_value_ptr++);
			++l_res;
		}
		++l_current_comp;
		++l_img_comp;
		++l_tccp;
	}
	++l_current_pi;

	for (pino = 1 ; pino<l_bound ; ++pino )
	{
		l_current_comp = l_current_pi->comps;
		l_img_comp = p_image->comps;
		l_tccp = l_tcp->tccps;

		l_current_pi->tx0 = l_tx0;
		l_current_pi->ty0 = l_ty0;
		l_current_pi->tx1 = l_tx1;
		l_current_pi->ty1 = l_ty1;
		/*l_current_pi->dx = l_dx_min;*/
		/*l_current_pi->dy = l_dy_min;*/
		l_current_pi->step_p = l_step_p;
		l_current_pi->step_c = l_step_c;
		l_current_pi->step_r = l_step_r;
		l_current_pi->step_l = l_step_l;

		/* allocation for components and number of components has already been calculated by opj_pi_create */
		for
			(compno = 0; compno < l_current_pi->numcomps; ++compno)
		{
			opj_pi_resolution_t *l_res = l_current_comp->resolutions;
			l_encoding_value_ptr = l_tmp_ptr[compno];

			l_current_comp->dx = l_img_comp->dx;
			l_current_comp->dy = l_img_comp->dy;
			/* resolutions have already been initialized */
			for
				(resno = 0; resno < l_current_comp->numresolutions; resno++)
			{
				l_res->pdx = *(l_encoding_value_ptr++);
				l_res->pdy = *(l_encoding_value_ptr++);
				l_res->pw =  *(l_encoding_value_ptr++);
				l_res->ph =  *(l_encoding_value_ptr++);
				++l_res;
			}
			++l_current_comp;
			++l_img_comp;
			++l_tccp;
		}
		/* special treatment*/
		l_current_pi->include = (l_current_pi-1)->include;
		++l_current_pi;
	}
	opj_free(l_tmp_data);
	l_tmp_data = 00;
	opj_free(l_tmp_ptr);
	l_tmp_ptr = 00;
	if
		(l_tcp->POC)
	{
		opj_pi_update_decode_poc (l_pi,l_tcp,l_max_prec,l_max_res);
	}
	else
	{
		opj_pi_update_decode_not_poc(l_pi,l_tcp,l_max_prec,l_max_res);
	}
	return l_pi;
}


Input:
static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters,
        opj_image_t *image, opj_event_mgr_t *p_manager)
{
    /* Configure cinema parameters */
    int i;

    /* No tiling */
    parameters->tile_size_on = OPJ_FALSE;
    parameters->cp_tdx = 1;
    parameters->cp_tdy = 1;

    /* One tile part for each component */
    parameters->tp_flag = 'C';
    parameters->tp_on = 1;

    /* Tile and Image shall be at (0,0) */
    parameters->cp_tx0 = 0;
    parameters->cp_ty0 = 0;
    parameters->image_offset_x0 = 0;
    parameters->image_offset_y0 = 0;

    /* Codeblock size= 32*32 */
    parameters->cblockw_init = 32;
    parameters->cblockh_init = 32;

    /* Codeblock style: no mode switch enabled */
    parameters->mode = 0;

    /* No ROI */
    parameters->roi_compno = -1;

    /* No subsampling */
    parameters->subsampling_dx = 1;
    parameters->subsampling_dy = 1;

    /* 9-7 transform */
    parameters->irreversible = 1;

    /* Number of layers */
    if (parameters->tcp_numlayers > 1) {
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "1 single quality layer"
                      "-> Number of layers forced to 1 (rather than %d)\n"
                      "-> Rate of the last layer (%3.1f) will be used",
                      parameters->tcp_numlayers,
                      parameters->tcp_rates[parameters->tcp_numlayers - 1]);
        parameters->tcp_rates[0] = parameters->tcp_rates[parameters->tcp_numlayers - 1];
        parameters->tcp_numlayers = 1;
    }

    /* Resolution levels */
    switch (parameters->rsiz) {
    case OPJ_PROFILE_CINEMA_2K:
        if (parameters->numresolution > 6) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "JPEG 2000 Profile-3 (2k dc profile) requires:\n"
                          "Number of decomposition levels <= 5\n"
                          "-> Number of decomposition levels forced to 5 (rather than %d)\n",
                          parameters->numresolution + 1);
            parameters->numresolution = 6;
        }
        break;
    case OPJ_PROFILE_CINEMA_4K:
        if (parameters->numresolution < 2) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "JPEG 2000 Profile-4 (4k dc profile) requires:\n"
                          "Number of decomposition levels >= 1 && <= 6\n"
                          "-> Number of decomposition levels forced to 1 (rather than %d)\n",
                          parameters->numresolution + 1);
            parameters->numresolution = 1;
        } else if (parameters->numresolution > 7) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "JPEG 2000 Profile-4 (4k dc profile) requires:\n"
                          "Number of decomposition levels >= 1 && <= 6\n"
                          "-> Number of decomposition levels forced to 6 (rather than %d)\n",
                          parameters->numresolution + 1);
            parameters->numresolution = 7;
        }
        break;
    default :
        break;
    }

    /* Precincts */
    parameters->csty |= 0x01;
    parameters->res_spec = parameters->numresolution - 1;
    for (i = 0; i < parameters->res_spec; i++) {
        parameters->prcw_init[i] = 256;
        parameters->prch_init[i] = 256;
    }

    /* The progression order shall be CPRL */
    parameters->prog_order = OPJ_CPRL;

    /* Progression order changes for 4K, disallowed for 2K */
    if (parameters->rsiz == OPJ_PROFILE_CINEMA_4K) {
        parameters->numpocs = (OPJ_UINT32)opj_j2k_initialise_4K_poc(parameters->POC,
                              parameters->numresolution);
    } else {
        parameters->numpocs = 0;
    }

    /* Limited bit-rate */
    parameters->cp_disto_alloc = 1;
    if (parameters->max_cs_size <= 0) {
        /* No rate has been introduced, 24 fps is assumed */
        parameters->max_cs_size = OPJ_CINEMA_24_CS;
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1302083 compressed bytes @ 24fps\n"
                      "As no rate has been given, this limit will be used.\n");
    } else if (parameters->max_cs_size > OPJ_CINEMA_24_CS) {
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1302083 compressed bytes @ 24fps\n"
                      "-> Specified rate exceeds this limit. Rate will be forced to 1302083 bytes.\n");
        parameters->max_cs_size = OPJ_CINEMA_24_CS;
    }

    if (parameters->max_comp_size <= 0) {
        /* No rate has been introduced, 24 fps is assumed */
        parameters->max_comp_size = OPJ_CINEMA_24_COMP;
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1041666 compressed bytes @ 24fps\n"
                      "As no rate has been given, this limit will be used.\n");
    } else if (parameters->max_comp_size > OPJ_CINEMA_24_COMP) {
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1041666 compressed bytes @ 24fps\n"
                      "-> Specified rate exceeds this limit. Rate will be forced to 1041666 bytes.\n");
        parameters->max_comp_size = OPJ_CINEMA_24_COMP;
    }

    parameters->tcp_rates[0] = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w *
                               image->comps[0].h * image->comps[0].prec) /
                               (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx *
                                       image->comps[0].dy);

}

static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters,
        opj_image_t *image, opj_event_mgr_t *p_manager)
{
    /* Configure cinema parameters */
    int i;

    /* No tiling */
    parameters->tile_size_on = OPJ_FALSE;
    parameters->cp_tdx = 1;
    parameters->cp_tdy = 1;

    /* One tile part for each component */
    parameters->tp_flag = 'C';
    parameters->tp_on = 1;

    /* Tile and Image shall be at (0,0) */
    parameters->cp_tx0 = 0;
    parameters->cp_ty0 = 0;
    parameters->image_offset_x0 = 0;
    parameters->image_offset_y0 = 0;

    /* Codeblock size= 32*32 */
    parameters->cblockw_init = 32;
    parameters->cblockh_init = 32;

    /* Codeblock style: no mode switch enabled */
    parameters->mode = 0;

    /* No ROI */
    parameters->roi_compno = -1;

    /* No subsampling */
    parameters->subsampling_dx = 1;
    parameters->subsampling_dy = 1;

    /* 9-7 transform */
    parameters->irreversible = 1;

    /* Number of layers */
    if (parameters->tcp_numlayers > 1) {
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "1 single quality layer"
                      "-> Number of layers forced to 1 (rather than %d)\n"
                      "-> Rate of the last layer (%3.1f) will be used",
                      parameters->tcp_numlayers,
                      parameters->tcp_rates[parameters->tcp_numlayers - 1]);
        parameters->tcp_rates[0] = parameters->tcp_rates[parameters->tcp_numlayers - 1];
        parameters->tcp_numlayers = 1;
    }

    /* Resolution levels */
    switch (parameters->rsiz) {
    case OPJ_PROFILE_CINEMA_2K:
        if (parameters->numresolution > 6) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "JPEG 2000 Profile-3 (2k dc profile) requires:\n"
                          "Number of decomposition levels <= 5\n"
                          "-> Number of decomposition levels forced to 5 (rather than %d)\n",
                          parameters->numresolution + 1);
            parameters->numresolution = 6;
        }
        break;
    case OPJ_PROFILE_CINEMA_4K:
        if (parameters->numresolution < 2) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "JPEG 2000 Profile-4 (4k dc profile) requires:\n"
                          "Number of decomposition levels >= 1 && <= 6\n"
                          "-> Number of decomposition levels forced to 1 (rather than %d)\n",
                          parameters->numresolution + 1);
            parameters->numresolution = 1;
        } else if (parameters->numresolution > 7) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "JPEG 2000 Profile-4 (4k dc profile) requires:\n"
                          "Number of decomposition levels >= 1 && <= 6\n"
                          "-> Number of decomposition levels forced to 6 (rather than %d)\n",
                          parameters->numresolution + 1);
            parameters->numresolution = 7;
        }
        break;
    default :
        break;
    }

    /* Precincts */
    parameters->csty |= 0x01;
    if (parameters->numresolution == 1) {
        parameters->res_spec = 1;
        parameters->prcw_init[0] = 128;
        parameters->prch_init[0] = 128;
    } else {
        parameters->res_spec = parameters->numresolution - 1;
        for (i = 0; i < parameters->res_spec; i++) {
            parameters->prcw_init[i] = 256;
            parameters->prch_init[i] = 256;
        }
    }

    /* The progression order shall be CPRL */
    parameters->prog_order = OPJ_CPRL;

    /* Progression order changes for 4K, disallowed for 2K */
    if (parameters->rsiz == OPJ_PROFILE_CINEMA_4K) {
        parameters->numpocs = (OPJ_UINT32)opj_j2k_initialise_4K_poc(parameters->POC,
                              parameters->numresolution);
    } else {
        parameters->numpocs = 0;
    }

    /* Limited bit-rate */
    parameters->cp_disto_alloc = 1;
    if (parameters->max_cs_size <= 0) {
        /* No rate has been introduced, 24 fps is assumed */
        parameters->max_cs_size = OPJ_CINEMA_24_CS;
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1302083 compressed bytes @ 24fps\n"
                      "As no rate has been given, this limit will be used.\n");
    } else if (parameters->max_cs_size > OPJ_CINEMA_24_CS) {
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1302083 compressed bytes @ 24fps\n"
                      "-> Specified rate exceeds this limit. Rate will be forced to 1302083 bytes.\n");
        parameters->max_cs_size = OPJ_CINEMA_24_CS;
    }

    if (parameters->max_comp_size <= 0) {
        /* No rate has been introduced, 24 fps is assumed */
        parameters->max_comp_size = OPJ_CINEMA_24_COMP;
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1041666 compressed bytes @ 24fps\n"
                      "As no rate has been given, this limit will be used.\n");
    } else if (parameters->max_comp_size > OPJ_CINEMA_24_COMP) {
        opj_event_msg(p_manager, EVT_WARNING,
                      "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n"
                      "Maximum 1041666 compressed bytes @ 24fps\n"
                      "-> Specified rate exceeds this limit. Rate will be forced to 1041666 bytes.\n");
        parameters->max_comp_size = OPJ_CINEMA_24_COMP;
    }

    parameters->tcp_rates[0] = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w *
                               image->comps[0].h * image->comps[0].prec) /
                               (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx *
                                       image->comps[0].dy);

}


Input:
void * adminchild(struct clientparam* param) {
 int i, res;
 char * buf;
 char username[256];
 char *sb;
 char *req = NULL;
 struct printparam pp;
 int contentlen = 0;
 int isform = 0;

 pp.inbuf = 0;
 pp.cp = param;

 buf = myalloc(LINESIZE);
 if(!buf) {RETURN(555);}
 i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S]);
 if(i<5 || ((buf[0]!='G' || buf[1]!='E' || buf[2]!='T' || buf[3]!=' ' || buf[4]!='/') &&
	   (buf[0]!='P' || buf[1]!='O' || buf[2]!='S' || buf[3]!='T' || buf[4]!=' ' || buf[5]!='/')))
 {
	RETURN(701);
 }
 buf[i] = 0;
 sb = strchr(buf+5, ' ');
 if(!sb){
	RETURN(702);
 }
 *sb = 0;
 req = mystrdup(buf + ((*buf == 'P')? 6 : 5));
 while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){
	buf[i] = 0;
	if(i > 19 && (!strncasecmp(buf, "authorization", 13))){
		sb = strchr(buf, ':');
		if(!sb)continue;
		++sb;
		while(isspace(*sb))sb++;
		if(!*sb || strncasecmp(sb, "basic", 5)){
			continue;
		}
		sb+=5;
		while(isspace(*sb))sb++;
		i = de64((unsigned char *)sb, (unsigned char *)username, 255);
		if(i<=0)continue;
		username[i] = 0;
		sb = strchr((char *)username, ':');
		if(sb){
			*sb = 0;
			if(param->password)myfree(param->password);
			param->password = (unsigned char *)mystrdup(sb+1);
		}
		if(param->username) myfree(param->username);
		param->username = (unsigned char *)mystrdup(username);
		continue;
	}
	else if(i > 15 && (!strncasecmp(buf, "content-length:", 15))){
		sb = buf + 15;
		while(isspace(*sb))sb++;
		contentlen = atoi(sb);
	}
	else if(i > 13 && (!strncasecmp(buf, "content-type:", 13))){
		sb = buf + 13;
		while(isspace(*sb))sb++;
		if(!strncasecmp(sb, "x-www-form-urlencoded", 21)) isform = 1;
	}
 }
 param->operation = ADMIN;
 if(isform && contentlen) {
	printstr(&pp, "HTTP/1.0 100 Continue\r\n\r\n");
	stdpr(&pp, NULL, 0);
 }
 res = (*param->srv->authfunc)(param);
 if(res && res != 10) {
	printstr(&pp, authreq);
	RETURN(res);
 }
 if(param->srv->singlepacket || param->redirected){
	if(*req == 'C') req[1] = 0;
	else *req = 0;
 }
 sprintf(buf, ok, conf.stringtable?(char *)conf.stringtable[2]:"3proxy", conf.stringtable?(char *)conf.stringtable[2]:"3[APA3A] tiny proxy", conf.stringtable?(char *)conf.stringtable[3]:"");
 if(*req != 'S') printstr(&pp, buf);
 switch(*req){
	case 'C':
		printstr(&pp, counters);
		{
			struct trafcount *cp;
			int num = 0;
			for(cp = conf.trafcounter; cp; cp = cp->next, num++){
			 int inbuf = 0;

			 if(cp->ace && (param->srv->singlepacket || param->redirected)){
				if(!ACLmatches(cp->ace, param))continue;
			 }
			 if(req[1] == 'S' && atoi(req+2) == num) cp->disabled=0;
			 if(req[1] == 'D' && atoi(req+2) == num) cp->disabled=1;
			 inbuf += sprintf(buf,	"
"
						"%s	%s	",
						(cp->comment)?cp->comment:" ",
						(cp->disabled)?'S':'D',
						num,
						(cp->disabled)?"NO":"YES"
					);
			 if(!cp->ace || !cp->ace->users){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printuserlist(buf+inbuf, LINESIZE-800, cp->ace->users, ",
\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "	");
			 if(!cp->ace || !cp->ace->src){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->src, ",
\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "	");
			 if(!cp->ace || !cp->ace->dst){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->dst, ",
\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "	");
			 if(!cp->ace || !cp->ace->ports){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printportlist(buf+inbuf, LINESIZE-128, cp->ace->ports, ",
\r\n");
			 }
			 if(cp->type == NONE) {
			  inbuf += sprintf(buf+inbuf,
					"	exclude from limitation
\r\n"
				 );
			 }
			 else {
			  inbuf += sprintf(buf+inbuf,
					"	%"PRINTF_INT64_MODIFIER"u	"
					"MB%s	"
					"%"PRINTF_INT64_MODIFIER"u	"
					"%s	",
				 cp->traflim64 / (1024 * 1024),
				 rotations[cp->type],
				 cp->traf64,
				 cp->cleared?ctime(&cp->cleared):"never"
				);
			 inbuf += sprintf(buf + inbuf,
					"%s	"
					"%i	"
					"
\r\n",

				 cp->updated?ctime(&cp->updated):"never",
				 cp->number
				);
			 }
			 printstr(&pp, buf);
			}

		}
		printstr(&pp, counterstail);
		break;

	case 'R':
		conf.needreload = 1;
		printstr(&pp, "
Reload scheduled
");
		break;
	case 'S':
		{
			if(req[1] == 'X'){
				printstr(&pp, style);
				break;
			}
			printstr(&pp, xml);
			printval(conf.services, TYPE_SERVER, 0, &pp);
			printstr(&pp, postxml);
		}
			break;
	case 'F':
		{
			FILE *fp;
			char buf[256];

			fp = confopen();
			if(!fp){
				printstr(&pp, "
Failed to open config file
");
				break;
			}
				printstr(&pp, "
Please be careful editing config file remotely
");
				printstr(&pp, "<form method=\"POST\" action=\"/U\"><textarea cols=\"80\" rows=\"30\" name=\"conffile\">");
				while(fgets(buf, 256, fp)){
					printstr(&pp, buf);
				}
				if(!writable) fclose(fp);
				printstr(&pp, "</textarea>
<input type=\"Submit\"></form>");
			break;
		}
	case 'U':
		{
			int l=0;
			int error = 0;

			if(!writable || fseek(writable, 0, 0)){
				error = 1;
			}
			while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '+', conf.timeouts[STRING_S])) > 0){
				if(i > (contentlen - l)) i = (contentlen - l);
				buf[i] = 0;
				if(!l){
					if(strncasecmp(buf, "conffile=", 9)) error = 1;
				}
				if(!error){
					decodeurl((unsigned char *)buf, 1);
					fprintf(writable, "%s", l? buf : buf + 9);
				}
				l += i;
				if(l >= contentlen) break;
			}
			if(writable && !error){
				fflush(writable);
#ifndef _WINCE
				ftruncate(fileno(writable), ftell(writable));
#endif
			}
			printstr(&pp, error?    "
Config file is not writable
Make sure you have \"writable\" command in configuration file":
						"
Configuration updated
");

		}
		break;
	default:
		printstr(&pp, (char *)conf.stringtable[WEBBANNERS]);
		break;
 }
 if(*req != 'S') printstr(&pp, tail);

CLEANRET:

 printstr(&pp, NULL);
 if(buf) myfree(buf);
 (*param->srv->logfunc)(param, (unsigned char *)req);
 if(req)myfree(req);
 freeparam(param);
 return (NULL);
}

void * adminchild(struct clientparam* param) {
 int i, res;
 char * buf;
 char username[256];
 char *sb;
 char *req = NULL;
 struct printparam pp;
 unsigned contentlen = 0;
 int isform = 0;

 pp.inbuf = 0;
 pp.cp = param;

 buf = myalloc(LINESIZE);
 if(!buf) {RETURN(555);}
 i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S]);
 if(i<5 || ((buf[0]!='G' || buf[1]!='E' || buf[2]!='T' || buf[3]!=' ' || buf[4]!='/') &&
	   (buf[0]!='P' || buf[1]!='O' || buf[2]!='S' || buf[3]!='T' || buf[4]!=' ' || buf[5]!='/')))
 {
	RETURN(701);
 }
 buf[i] = 0;
 sb = strchr(buf+5, ' ');
 if(!sb){
	RETURN(702);
 }
 *sb = 0;
 req = mystrdup(buf + ((*buf == 'P')? 6 : 5));
 while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){
	buf[i] = 0;
	if(i > 19 && (!strncasecmp(buf, "authorization", 13))){
		sb = strchr(buf, ':');
		if(!sb)continue;
		++sb;
		while(isspace(*sb))sb++;
		if(!*sb || strncasecmp(sb, "basic", 5)){
			continue;
		}
		sb+=5;
		while(isspace(*sb))sb++;
		i = de64((unsigned char *)sb, (unsigned char *)username, 255);
		if(i<=0)continue;
		username[i] = 0;
		sb = strchr((char *)username, ':');
		if(sb){
			*sb = 0;
			if(param->password)myfree(param->password);
			param->password = (unsigned char *)mystrdup(sb+1);
		}
		if(param->username) myfree(param->username);
		param->username = (unsigned char *)mystrdup(username);
		continue;
	}
	else if(i > 15 && (!strncasecmp(buf, "content-length:", 15))){
		sb = buf + 15;
		while(isspace(*sb))sb++;
		sscanf(sb, "%u", &contentlen);
		if(contentlen > LINESIZE*1024) contentlen = 0;
	}
	else if(i > 13 && (!strncasecmp(buf, "content-type:", 13))){
		sb = buf + 13;
		while(isspace(*sb))sb++;
		if(!strncasecmp(sb, "x-www-form-urlencoded", 21)) isform = 1;
	}
 }
 param->operation = ADMIN;
 if(isform && contentlen) {
	printstr(&pp, "HTTP/1.0 100 Continue\r\n\r\n");
	stdpr(&pp, NULL, 0);
 }
 res = (*param->srv->authfunc)(param);
 if(res && res != 10) {
	printstr(&pp, authreq);
	RETURN(res);
 }
 if(param->srv->singlepacket || param->redirected){
	if(*req == 'C') req[1] = 0;
	else *req = 0;
 }
 sprintf(buf, ok, conf.stringtable?(char *)conf.stringtable[2]:"3proxy", conf.stringtable?(char *)conf.stringtable[2]:"3[APA3A] tiny proxy", conf.stringtable?(char *)conf.stringtable[3]:"");
 if(*req != 'S') printstr(&pp, buf);
 switch(*req){
	case 'C':
		printstr(&pp, counters);
		{
			struct trafcount *cp;
			int num = 0;
			for(cp = conf.trafcounter; cp; cp = cp->next, num++){
			 int inbuf = 0;

			 if(cp->ace && (param->srv->singlepacket || param->redirected)){
				if(!ACLmatches(cp->ace, param))continue;
			 }
			 if(req[1] == 'S' && atoi(req+2) == num) cp->disabled=0;
			 if(req[1] == 'D' && atoi(req+2) == num) cp->disabled=1;
			 inbuf += sprintf(buf,	"
"
						"%s	%s	",
						(cp->comment)?cp->comment:" ",
						(cp->disabled)?'S':'D',
						num,
						(cp->disabled)?"NO":"YES"
					);
			 if(!cp->ace || !cp->ace->users){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printuserlist(buf+inbuf, LINESIZE-800, cp->ace->users, ",
\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "	");
			 if(!cp->ace || !cp->ace->src){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->src, ",
\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "	");
			 if(!cp->ace || !cp->ace->dst){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->dst, ",
\r\n");
			 }
			 inbuf += sprintf(buf+inbuf, "	");
			 if(!cp->ace || !cp->ace->ports){
				inbuf += sprintf(buf+inbuf, "ANY");
			 }
			 else {
				inbuf += printportlist(buf+inbuf, LINESIZE-128, cp->ace->ports, ",
\r\n");
			 }
			 if(cp->type == NONE) {
			  inbuf += sprintf(buf+inbuf,
					"	exclude from limitation
\r\n"
				 );
			 }
			 else {
			  inbuf += sprintf(buf+inbuf,
					"	%"PRINTF_INT64_MODIFIER"u	"
					"MB%s	"
					"%"PRINTF_INT64_MODIFIER"u	"
					"%s	",
				 cp->traflim64 / (1024 * 1024),
				 rotations[cp->type],
				 cp->traf64,
				 cp->cleared?ctime(&cp->cleared):"never"
				);
			 inbuf += sprintf(buf + inbuf,
					"%s	"
					"%i	"
					"
\r\n",

				 cp->updated?ctime(&cp->updated):"never",
				 cp->number
				);
			 }
			 printstr(&pp, buf);
			}

		}
		printstr(&pp, counterstail);
		break;

	case 'R':
		conf.needreload = 1;
		printstr(&pp, "
Reload scheduled
");
		break;
	case 'S':
		{
			if(req[1] == 'X'){
				printstr(&pp, style);
				break;
			}
			printstr(&pp, xml);
			printval(conf.services, TYPE_SERVER, 0, &pp);
			printstr(&pp, postxml);
		}
			break;
	case 'F':
		{
			FILE *fp;
			char buf[256];

			fp = confopen();
			if(!fp){
				printstr(&pp, "
Failed to open config file
");
				break;
			}
				printstr(&pp, "
Please be careful editing config file remotely
");
				printstr(&pp, "<form method=\"POST\" action=\"/U\" enctype=\"application/x-www-form-urlencoded\"><textarea cols=\"80\" rows=\"30\" name=\"conffile\">");
				while(fgets(buf, 256, fp)){
					printstr(&pp, buf);
				}
				if(!writable) fclose(fp);
				printstr(&pp, "</textarea>
<input type=\"Submit\"></form>");
			break;
		}
	case 'U':
		{
			unsigned l=0;
			int error = 0;

			if(!writable || !contentlen || fseek(writable, 0, 0)){
				error = 1;
			}
			while(l < contentlen && (i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, (contentlen - l) > LINESIZE - 1?LINESIZE - 1:contentlen - l, '+', conf.timeouts[STRING_S])) > 0){
				if(i > (contentlen - l)) i = (contentlen - l);
				if(!l){
					if(i<9 || strncasecmp(buf, "conffile=", 9)) error = 1;
				}
				if(!error){
					buf[i] = 0;
					decodeurl((unsigned char *)buf, 1);
					fprintf(writable, "%s", l? buf : buf + 9);
				}
				l += i;
			}
			if(writable && !error){
				fflush(writable);
#ifndef _WINCE
				ftruncate(fileno(writable), ftell(writable));
#endif
			}
			printstr(&pp, error?    "
Config file is not writable
Make sure you have \"writable\" command in configuration file":
						"
Configuration updated
");

		}
		break;
	default:
		printstr(&pp, (char *)conf.stringtable[WEBBANNERS]);
		break;
 }
 if(*req != 'S') printstr(&pp, tail);

CLEANRET:

 printstr(&pp, NULL);
 if(buf) myfree(buf);
 (*param->srv->logfunc)(param, (unsigned char *)req);
 if(req)myfree(req);
 freeparam(param);
 return (NULL);
}


Input:
int ecall_restore(const char *input, uint64_t input_len, char **output,
                  uint64_t *output_len) {
  if (!asylo::primitives::TrustedPrimitives::IsOutsideEnclave(input,
                                                              input_len) ||
      !asylo::primitives::TrustedPrimitives::IsOutsideEnclave(
          output_len, sizeof(uint64_t))) {
    asylo::primitives::TrustedPrimitives::BestEffortAbort(
        "ecall_restore: input/output found to not be in untrusted memory.");
  }
  int result = 0;
  size_t tmp_output_len;
  try {
    result = asylo::Restore(input, static_cast<size_t>(input_len), output,
                            &tmp_output_len);
  } catch (...) {
    LOG(FATAL) << "Uncaught exception in enclave";
  }

  if (output_len) {
    *output_len = static_cast<uint64_t>(tmp_output_len);
  }
  return result;
}

int ecall_restore(const char *input, uint64_t input_len, char **output,
                  uint64_t *output_len) {
  if (!asylo::primitives::TrustedPrimitives::IsOutsideEnclave(input,
                                                              input_len) ||
      !asylo::primitives::TrustedPrimitives::IsOutsideEnclave(
          output_len, sizeof(uint64_t)) ||
      !asylo::primitives::TrustedPrimitives::IsOutsideEnclave(output,
                                                              *output_len)) {
    asylo::primitives::TrustedPrimitives::BestEffortAbort(
        "ecall_restore: input/output found to not be in untrusted memory.");
  }
  int result = 0;
  size_t tmp_output_len;
  try {
    result = asylo::Restore(input, static_cast<size_t>(input_len), output,
                            &tmp_output_len);
  } catch (...) {
    LOG(FATAL) << "Uncaught exception in enclave";
  }

  if (output_len) {
    *output_len = static_cast<uint64_t>(tmp_output_len);
  }
  return result;
}


Input:
static void handle_PORT(ctrl_t *ctrl, char *str)
{
	int a, b, c, d, e, f;
	char addr[INET_ADDRSTRLEN];
	struct sockaddr_in sin;

	if (ctrl->data_sd > 0) {
		uev_io_stop(&ctrl->data_watcher);
		close(ctrl->data_sd);
		ctrl->data_sd = -1;
	}

	/* Convert PORT command's argument to IP address + port */
	sscanf(str, "%d,%d,%d,%d,%d,%d", &a, &b, &c, &d, &e, &f);
	sprintf(addr, "%d.%d.%d.%d", a, b, c, d);

	/* Check IPv4 address using inet_aton(), throw away converted result */
	if (!inet_aton(addr, &(sin.sin_addr))) {
		ERR(0, "Invalid address '%s' given to PORT command", addr);
		send_msg(ctrl->sd, "500 Illegal PORT command.\r\n");
		return;
	}

	strlcpy(ctrl->data_address, addr, sizeof(ctrl->data_address));
	ctrl->data_port = e * 256 + f;

	DBG("Client PORT command accepted for %s:%d", ctrl->data_address, ctrl->data_port);
	send_msg(ctrl->sd, "200 PORT command successful.\r\n");
}

static void handle_PORT(ctrl_t *ctrl, char *str)
{
	int a, b, c, d, e, f;
	char addr[INET_ADDRSTRLEN];
	struct sockaddr_in sin;

	if (ctrl->data_sd > 0) {
		uev_io_stop(&ctrl->data_watcher);
		close(ctrl->data_sd);
		ctrl->data_sd = -1;
	}

	/* Convert PORT command's argument to IP address + port */
	sscanf(str, "%d,%d,%d,%d,%d,%d", &a, &b, &c, &d, &e, &f);
	snprintf(addr, sizeof(addr), "%d.%d.%d.%d", a, b, c, d);

	/* Check IPv4 address using inet_aton(), throw away converted result */
	if (!inet_aton(addr, &(sin.sin_addr))) {
		ERR(0, "Invalid address '%s' given to PORT command", addr);
		send_msg(ctrl->sd, "500 Illegal PORT command.\r\n");
		return;
	}

	strlcpy(ctrl->data_address, addr, sizeof(ctrl->data_address));
	ctrl->data_port = e * 256 + f;

	DBG("Client PORT command accepted for %s:%d", ctrl->data_address, ctrl->data_port);
	send_msg(ctrl->sd, "200 PORT command successful.\r\n");
}


Input:
int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
{
    hwaddr end = addr + size;
    uint8_t *s, *d = dest;
    size_t l = 0;
    Rom *rom;

    QTAILQ_FOREACH(rom, &roms, next) {
        if (rom->fw_file) {
            continue;
        }
        if (rom->mr) {
            continue;
        }
        if (rom->addr + rom->romsize < addr) {
            continue;
        }
        if (rom->addr > end) {
            break;
        }

        d = dest + (rom->addr - addr);
        s = rom->data;
        l = rom->datasize;

        if ((d + l) > (dest + size)) {
            l = dest - d;
        }

        if (l > 0) {
            memcpy(d, s, l);
        }

        if (rom->romsize > rom->datasize) {
            /* If datasize is less than romsize, it means that we didn't
             * allocate all the ROM because the trailing data are only zeros.
             */

            d += l;
            l = rom->romsize - rom->datasize;

            if ((d + l) > (dest + size)) {
                /* Rom size doesn't fit in the destination area. Adjust to avoid
                 * overflow.
                 */
                l = dest - d;
            }

            if (l > 0) {
                memset(d, 0x0, l);
            }
        }
    }

    return (d + l) - dest;
}

int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
{
    hwaddr end = addr + size;
    uint8_t *s, *d = dest;
    size_t l = 0;
    Rom *rom;

    QTAILQ_FOREACH(rom, &roms, next) {
        if (rom->fw_file) {
            continue;
        }
        if (rom->mr) {
            continue;
        }
        if (rom->addr + rom->romsize < addr) {
            continue;
        }
        if (rom->addr > end || rom->addr < addr) {
            break;
        }

        d = dest + (rom->addr - addr);
        s = rom->data;
        l = rom->datasize;

        if ((d + l) > (dest + size)) {
            l = dest - d;
        }

        if (l > 0) {
            memcpy(d, s, l);
        }

        if (rom->romsize > rom->datasize) {
            /* If datasize is less than romsize, it means that we didn't
             * allocate all the ROM because the trailing data are only zeros.
             */

            d += l;
            l = rom->romsize - rom->datasize;

            if ((d + l) > (dest + size)) {
                /* Rom size doesn't fit in the destination area. Adjust to avoid
                 * overflow.
                 */
                l = dest - d;
            }

            if (l > 0) {
                memset(d, 0x0, l);
            }
        }
    }

    return (d + l) - dest;
}