+static int
+_zlib_compress (char *m_msg, int m_msg_len,
+ unsigned char **zlib_buf, int *zlib_bufsiz, int flags)
+{
+ int rc;
+ int len, totallen;
+
+#ifndef HAVE_LIBZ
+
+ UNUSED_VARIABLE(rc);
+ UNUSED_VARIABLE(len);
+ UNUSED_VARIABLE(totallen);
+ libspamc_log(flags, LOG_ERR, "spamc not built with zlib support");
+ return EX_SOFTWARE;
+
+#else
+ z_stream strm;
+
+ UNUSED_VARIABLE(flags);
+
+ /* worst-case, according to http://www.zlib.org/zlib_tech.html ;
+ * same as input, plus 5 bytes per 16k, plus 6 bytes. this should
+ * be plenty */
+ *zlib_bufsiz = (int) (m_msg_len * 1.0005) + 1024;
+ *zlib_buf = (unsigned char *) malloc (*zlib_bufsiz);
+ if (*zlib_buf == NULL) {
+ return EX_OSERR;
+ }
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ rc = deflateInit(&strm, 3);
+ if (rc != Z_OK) {
+ return EX_OSERR;
+ }
+
+ strm.avail_in = m_msg_len;
+ strm.next_in = (unsigned char *) m_msg;
+ strm.avail_out = *zlib_bufsiz;
+ strm.next_out = (unsigned char *) *zlib_buf;
+
+ totallen = 0;
+ do {
+ rc = deflate(&strm, Z_FINISH);
+ assert(rc != Z_STREAM_ERROR);
+ len = (size_t) (*zlib_bufsiz - strm.avail_out);
+ strm.next_out += len;
+ totallen += len;
+ } while (strm.avail_out == 0);
+
+ *zlib_bufsiz = totallen;
+ return EX_OK;
+
+#endif
+}
+
+int
+_append_original_body (struct message *m, int flags)
+{
+ char *cp, *cpend, *bodystart;
+ int bodylen, outspaceleft, towrite;
+
+ /* at this stage, m->out now contains the rewritten headers.
+ * find and append the raw message's body, up to m->priv->alloced_size
+ * bytes.
+ */
+
+#define CRNLCRNL "\r\n\r\n"
+#define CRNLCRNL_LEN 4
+#define NLNL "\n\n"
+#define NLNL_LEN 2
+
+ cpend = m->raw + m->raw_len;
+ bodystart = NULL;
+
+ for (cp = m->raw; cp < cpend; cp++) {
+ if (*cp == '\r' && cpend - cp >= CRNLCRNL_LEN &&
+ !strncmp(cp, CRNLCRNL, CRNLCRNL_LEN))
+ {
+ bodystart = cp + CRNLCRNL_LEN;
+ break;
+ }
+ else if (*cp == '\n' && cpend - cp >= NLNL_LEN &&
+ !strncmp(cp, NLNL, NLNL_LEN))
+ {
+ bodystart = cp + NLNL_LEN;
+ break;
+ }
+ }
+
+ if (bodystart == NULL) {
+ libspamc_log(flags, LOG_ERR, "failed to find end-of-headers");
+ return EX_SOFTWARE;
+ }
+
+ bodylen = cpend - bodystart;
+ outspaceleft = (m->priv->alloced_size-1) - m->out_len;
+ towrite = (bodylen < outspaceleft ? bodylen : outspaceleft);
+
+ /* copy in the body; careful not to overflow */
+ strncpy (m->out + m->out_len, bodystart, towrite);
+ m->out_len += towrite;
+ return EX_OK;
+}
+