Commit a1311e5a authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

moved the SMTP payload escape function into Curl_smtp_escape_eob and put

it in smtp.c
parent 5e6ffe35
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -901,4 +901,67 @@ static CURLcode smtp_setup_connection(struct connectdata * conn)
  return CURLE_OK;
}

CURLcode Curl_smtp_escape_eob(struct connectdata *conn, int nread)
{
  /* When sending SMTP payload, we must detect CRLF.CRLF sequences in
   * the data and make sure it is sent as CRLF..CRLF instead, as
   * otherwise it will wrongly be detected as end of data by the server.
   */
  int i;
  int si;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  struct SessionHandle *data = conn->data;

  if(data->state.scratch == NULL)
    data->state.scratch = malloc(2*BUFSIZE);
  if(data->state.scratch == NULL) {
    failf (data, "Failed to alloc scratch buffer!");
    return CURLE_OUT_OF_MEMORY;
  }
  /* This loop can be improved by some kind of Boyer-Moore style of
     approach but that is saved for later... */
  for(i = 0, si = 0; i < nread; i++, si++) {
    int left = nread - i;

    if(left>= (SMTP_EOB_LEN-smtpc->eob)) {
      if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
                 SMTP_EOB_LEN-smtpc->eob)) {
        /* It matched, copy the replacement data to the target buffer
           instead. Note that the replacement does not contain the
           trailing CRLF but we instead continue to match on that one
           to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
        */
        memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
               SMTP_EOB_REPL_LEN);
        si+=SMTP_EOB_REPL_LEN-1; /* minus one since the for() increments
                                          it */
        i+=SMTP_EOB_LEN-smtpc->eob-1-2;
        smtpc->eob = 0; /* start over */
        continue;
      }
    }
    else if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
                    left)) {
      /* the last piece of the data matches the EOB so we can't send that
         until we know the rest of it */
      smtpc->eob += left;
      break;
    }

    data->state.scratch[si] = data->req.upload_fromhere[i];
  } /* for() */

  if(si != nread) {
    /* only use the new buffer if we replaced something */
    nread = si;

    /* upload from the new (replaced) buffer instead */
    data->req.upload_fromhere = data->state.scratch;

    /* set the new amount too */
    data->req.upload_present = nread;
  }
  return CURLE_OK;
}

#endif /* CURL_DISABLE_SMTP */
+2 −0
Original line number Diff line number Diff line
@@ -62,4 +62,6 @@ extern const struct Curl_handler Curl_handler_smtps;
#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
#define SMTP_EOB_REPL_LEN 4

CURLcode Curl_smtp_escape_eob(struct connectdata *conn, int nread);

#endif /* __SMTP_H */
+3 −56
Original line number Diff line number Diff line
@@ -786,62 +786,9 @@ static CURLcode readwrite_upload(struct SessionHandle *data,

#ifndef CURL_DISABLE_SMTP
      if(conn->protocol & PROT_SMTP) {
        /* When sending SMTP payload, we must detect CRLF.CRLF sequences in
         * the data and make sure it is sent as CRLF..CRLF instead, as
         * otherwise it will wrongly be detected as end of data by the server.
         */
        struct smtp_conn *smtpc = &conn->proto.smtpc;

        if(data->state.scratch == NULL)
          data->state.scratch = malloc(2*BUFSIZE);
        if(data->state.scratch == NULL) {
          failf (data, "Failed to alloc scratch buffer!");
          return CURLE_OUT_OF_MEMORY;
        }
        /* This loop can be improved by some kind of Boyer-Moore style of
           approach but that is saved for later... */
        for(i = 0, si = 0; i < nread; i++, si++) {
          int left = nread - i;

          if(left>= (SMTP_EOB_LEN-smtpc->eob)) {
            if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
                       SMTP_EOB_LEN-smtpc->eob)) {
              /* It matched, copy the replacement data to the target buffer
                 instead. Note that the replacement does not contain the
                 trailing CRLF but we instead continue to match on that one
                 to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
              */
              memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
                     SMTP_EOB_REPL_LEN);
              si+=SMTP_EOB_REPL_LEN-1; /* minus one since the for() increments
                                          it */
              i+=SMTP_EOB_LEN-smtpc->eob-1-2;
              smtpc->eob = 0; /* start over */
              continue;
            }
          }
          else if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
                          left)) {
            /* the last piece of the data matches the EOB so we can't send that
               until we know the rest of it */
            smtpc->eob += left;
            break;
          }

          data->state.scratch[si] = data->req.upload_fromhere[i];
        } /* for() */

        if(si != nread) {
          /* only use the new buffer if we replaced something */
          nread = si;

          /* upload from the new (replaced) buffer instead */
          data->req.upload_fromhere = data->state.scratch;

          /* set the new amount too */
          data->req.upload_present = nread;
        }

        result = Curl_smtp_escape_eob(conn, nread);
        if(result)
          return result;
      }
      else
#endif /* CURL_DISABLE_SMTP */