Skip to content
pop3.c 30.8 KiB
Newer Older
     * 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;
  unsigned int 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)) {
      /* 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;

  result = Curl_client_write(conn, CLIENTWRITE_BODY, str, nread);

  return result;
}

#endif /* CURL_DISABLE_POP3 */