Skip to content
pop3.c 31.7 KiB
Newer Older
    else {
#ifdef USE_SSL
      conn->handler = &Curl_handler_pop3s_proxy;
#else
      failf(data, "POP3S not supported!");
      return CURLE_UNSUPPORTED_PROTOCOL;
#endif
    }
    /*
     * We explicitly mark this connection as persistent here as we're doing
     * POP3 over HTTP and thus we accidentally avoid setting this value
     * otherwise.
     */
    conn->bits.close = FALSE;
#else
    failf(data, "POP3 over http proxy requires HTTP support built-in!");
    return CURLE_UNSUPPORTED_PROTOCOL;
#endif
  }

  data->state.path++;   /* don't include the initial slash */

  return CURLE_OK;
}

/* this is the 5-bytes End-Of-Body marker for POP3 */
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
#define POP3_EOB_LEN 5

/*
 * This function scans the body after the end-of-body and writes everything
 * until the end is found.
 */
CURLcode Curl_pop3_write(struct connectdata *conn,
                         char *str,
                         size_t nread)
{
  /* This code could be made into a special function in the handler struct. */
  CURLcode result;
  struct SessionHandle *data = conn->data;
  struct SingleRequest *k = &data->req;

  /* Detect the end-of-body marker, which is 5 bytes:
     0d 0a 2e 0d 0a. This marker can of course be spread out
     over up to 5 different data chunks.
  */
  struct pop3_conn *pop3c = &conn->proto.pop3c;
Yang Tse's avatar
Yang Tse committed
  size_t i;

  /* since the EOB string must be within the last 5 bytes, get the index
     position of where to start to scan for it */
  size_t checkstart = (nread>POP3_EOB_LEN)?nread-POP3_EOB_LEN:0;

  if(checkstart) {
    /* write out the first piece, if any */
    result = Curl_client_write(conn, CLIENTWRITE_BODY, str, checkstart);
    if(result)
      return result;
    pop3c->eob=0;
  }
  for(i=checkstart; i<nread; i++) {
    size_t prev = pop3c->eob;
    switch(str[i]) {
    case 0x0d:
      if((pop3c->eob == 0) || (pop3c->eob == 3))
        pop3c->eob++;
      else
        /* if it wasn't 0 or 3, it restarts the pattern match again */
        pop3c->eob=1;
      break;
    case 0x0a:
      if((pop3c->eob == 1) || (pop3c->eob == 4))
        pop3c->eob++;
      else
        pop3c->eob=0;
      break;
    case 0x2e:
      if(pop3c->eob == 2)
        pop3c->eob++;
      else
        pop3c->eob=0;
      break;
    default:
      pop3c->eob=0;
      break;
    }
    if(pop3c->eob == POP3_EOB_LEN) {
      /* full match, the transfer is done! */
      k->keepon &= ~KEEP_RECV;
      pop3c->eob = 0;
      return CURLE_OK;
    }
    else if(prev && (prev >= pop3c->eob)) {

      /* strip can only be non-zero for the very first mismatch after CRLF and
         then both prev and strip are equal and nothing will be output
         below */
      while(prev && pop3c->strip) {
        prev--;
        pop3c->strip--;
      }

      if(prev) {
        /* write out the body part that didn't match */
        result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
                                   prev);
        if(result)
          return result;
      }

  if(pop3c->eob)
    /* while EOB is matching, don't output it! */
    return CURLE_OK;
  while(nread && pop3c->strip) {
    nread--;
    pop3c->strip--;
    str++;
  }

  if(nread) {
    result = Curl_client_write(conn, CLIENTWRITE_BODY, str, nread);
  }