Beispiel #1
0
bool_t check_encoding_qp(void) {

	stringer_t *qp, *binary;
	byte_t buffer[QP_CHECK_SIZE];

	for (uint64_t i = 0; status() && i < QP_CHECK_ITERATIONS; i++) {

		// Fill the buffer with random data and convert the buffer to hex.
		if (rand_write(PLACER(buffer, QP_CHECK_SIZE)) != QP_CHECK_SIZE) {
			return false;
		}
		else if (!(qp = qp_encode(PLACER(buffer, QP_CHECK_SIZE)))) {
			return false;
		}

		//log_pedantic("qp = %.*s", st_length_int(qp), st_char_get(qp));

		// Convert the buffer back to binary and compare it with the original array.
		if (!(binary = qp_decode(qp))) {
			st_free(qp);
			return false;
		}
		else if (st_cmp_cs_eq(binary, PLACER(buffer, QP_CHECK_SIZE))) {
			st_free(binary);
			st_free(qp);
			return false;
		}

		st_free(binary);
		st_free(qp);
	}

	return true;
}
Beispiel #2
0
int MailMessage::parse(const char *rfc2822, size_t len) {
    StringBuffer s(rfc2822, len);
    int rc;

    LOG.debug("MailMessage::parse START");

    size_t hdrlen = getHeadersLen(s, newline);

    StringBuffer headers = s.substr(0, hdrlen);    
    StringBuffer rfcbody;

    rc = parseHeaders(headers);
    if(rc)
        return rc;

    if(contentType.ifind(MULTIPART) != StringBuffer::npos) {
        // Multipart message
        rfcbody = s.substr(hdrlen);
        rc= parseBodyParts(rfcbody);
    }
    else {
        // go to the beginning of the body
        hdrlen = hdrlen + strlen(newline) + strlen(newline);
        rfcbody = s.substr(hdrlen);
        body.setMimeType(contentType);
        // FIXME: handle all encodings, not only quoted-printable
        if( strcmp(body.getEncoding(), "quoted-printable") == 0 ) {
            char *decoded = qp_decode( rfcbody );
            body.setContent ( decoded );
            delete [] decoded;
        }
        else if ( strcmp(body.getEncoding(), "base64") == 0 ) {
            char *decoded = NULL;
            size_t len = 0;
            rc = uudecode( rfcbody, &decoded, &len ) ;
            if( !rc ) {
                body.setContent ( decoded );
                delete [] decoded;
            }
        }
        else body.setContent(rfcbody);
    }

    LOG.debug("MailMessage::parse END");
    return rc;
}
Beispiel #3
0
int main(int argc, char **argv) {
    size_t size;
    qp_mode mode = RFC2045;
    word_t *w;

    if (argc > 1 && strcasecmp(argv[1], "rfc2047")) mode = RFC2047;
    if (argc > 1 && strcasecmp(argv[1], "rfc-2047")) mode = RFC2047;

    if (fseek(stdin, 0, SEEK_END)) die();
    size = ftell(stdin);
    if (fseek(stdin, 0, SEEK_SET)) die();
    w = word_new(NULL, size);
    if (fread(w->u.text, 1, w->leng, stdin) != w->leng) die();
    size = qp_decode(w, mode);
    if (fwrite(w->u.text, 1, size, stdout) != size) die();
    word_free(w);
    if (fflush(stdout)) die();
    if (fclose(stdout)) die();
    return EXIT_SUCCESS;
}
Beispiel #4
0
/**
 * Get the next bodypart from the message body string.
 *
 * @param rfcBody  (in)  - message content
 * @param boundary (in)  - mime boundary string
 * @param ret      (out) - parsed BodyPart
 * @param next     (i/o) - offset of the new boundary
 * @param isAttach (in)  - says if the current body part is an attachment or not
 */
static bool getBodyPart(StringBuffer &rfcBody, StringBuffer &boundary,
                       BodyPart &ret, size_t &next, bool isAttach)
{
    LOG.debug("getBodyPart START");
    StringBuffer newline;

    // The part starts on the next line
    size_t begin = findNewLine(rfcBody, next);
    if (begin == StringBuffer::npos)
       return false;
    // find the end of the part
    next = rfcBody.find(boundary, begin);
    if (next == StringBuffer::npos)
       return false;
    // get the part
    StringBuffer part = rfcBody.substr(begin, next-begin);
    // If it is a multipart alternative part, get the text part only.
    // check only until the first new line not on all the message (it could be
    // a message inside another message)
    size_t headers_len = getHeadersLen(part, newline);
    StringBuffer headers_part = part.substr(0, headers_len);
    if (headers_part.ifind("Content-Type: multipart/alternative") != StringBuffer::npos) {
        if(part.ifind("Content-Type: multipart/alternative") != StringBuffer::npos) {
            size_t b_pos = part.ifind("boundary=");
            if( b_pos != StringBuffer::npos ) {
                size_t begin = part.find("=\"", b_pos) + 2 ;
                size_t end = part.find("\"", begin) ;

                StringBuffer inner_boundary("\n--");
                inner_boundary += part.substr( begin, end-begin );

                begin = part.find(inner_boundary, end);
                begin += inner_boundary.length();
                end = part.find(inner_boundary, begin);
                if (begin != StringBuffer::npos && end != StringBuffer::npos) {
                    part = part.substr(begin, end-begin);
                    LOG.debug("Bodypart is multipart/alternative: "
                        "getting first alternative only: \n%s\n", part.c_str() );
                }
            }
        }
    }

    // Split headers and body
    size_t hdrlen = getHeadersLen(part, newline);

    // Get headers
    StringBuffer headers = part.substr(0, hdrlen);

    // Join header parts using \t or 8 blank
    StringBuffer joinlinetab("\t");
    headers.replaceAll(joinlinetab, " ");
    StringBuffer joinlinespaces(newline);
    joinlinespaces+=" ";  // 8 blanks
    headers.replaceAll(joinlinespaces, " ");

    ArrayList lines;
    const StringBuffer *line;

    // parse the bodypart headers
    headers.split(lines, newline);

    for ( line=(StringBuffer *)lines.front();
          line;
          line=(StringBuffer *)lines.next() ) {
        if( *line == "\r" )
            continue;
        // The first empty line marks the end of the header section
        //if( line->empty() ){
        //    break;
        //}
        // Process the headers
        if( line->ifind(MIMETYPE) == 0 ) {  // it must at the beginning
            ret.setMimeType(getTokenValue(line, MIMETYPE));
            if (line->ifind(CT_NAME) != StringBuffer::npos) {
                ret.setName(MailMessage::decodeHeader(getTokenValue(line, CT_NAME,false)));
            }
            if (line->ifind(CT_CHARSET) != StringBuffer::npos ) {
                ret.setCharset(getTokenValue(line, CT_CHARSET));
            }
        }   
        else if( line->ifind(DISPOSITION) == 0 ) {
            ret.setDisposition( getTokenValue(line, DISPOSITION));
            if (line->ifind(CD_FILENAME) != StringBuffer::npos ) {
                ret.setFilename( MailMessage::decodeHeader(  getTokenValue(line, CD_FILENAME, false) ) );
            }
        }

        else if( line->ifind(ENCODING) == 0 ) {
            ret.setEncoding( getTokenValue(line, ENCODING));
        }

    }
    // move to the beginning of the content
    hdrlen += strlen(newline) + strlen(newline); // added 2 new line that separate the bodyparts
    // get bodypart content
    if( isAttach == false) { // || !ret.getFilename() ) {
        // this is not an attachment
        if(ret.getEncoding() && strcmp(ret.getEncoding(), "quoted-printable") == 0 ) {
            char *decoded = qp_decode( part.substr(hdrlen) );
            ret.setContent ( decoded );
            delete [] decoded;
        }
        else if (ret.getEncoding() && strcmp(ret.getEncoding(), "base64") == 0 ) {
            char *decoded = "";
            size_t len = 0;
            if( uudecode( part.substr(hdrlen), &decoded, &len ) ) {
                LOG.error("Error decoding content");
            }
            ret.setContent ( decoded );
            delete [] decoded;
        }
        else {
            bool found = true;
            if (part.substr(hdrlen).length() < 6) {
                StringBuffer s(part.substr(hdrlen));
                for (unsigned int i = 0; i < s.length(); i++) {
                    if (s.c_str()[i] != '\r' && s.c_str()[i] != '\n') {
                        found = true;
                        break;
                    } else {
                        found = false;
                    }
                }
            }
            if (found) {
                ret.setContent ( part.substr(hdrlen) );
            }
        }
    }
    else {
        LOG.debug("Attachment");
        ret.setContent( mkTempFileName( ret.getFilename() ) );
        LOG.debug("%s", ret.getContent());
        StringBuffer p = part.substr(hdrlen);
        if (p.length()) {
            LOG.debug("Saving...");
            if( convertAndSave(ret.getContent(), p.c_str(), ret.getEncoding()) ) {
                LOG.error("Error in convertAndSave");
            }
            else {
                LOG.debug("convertAndSave success");
            }
        }
    }
    LOG.debug("getBodyPart END");

    // return true if there are more parts
    return (next != StringBuffer::npos);
}
Beispiel #5
0
StringBuffer MailMessage::decodeHeader(StringBuffer line) {

    if (!line || line.empty()) {
        return line;
    }

    size_t startPos = 0;
    StringBuffer ret;
    StringBuffer charset;
    while( (startPos = line.find("=?", startPos)) != StringBuffer::npos) {
        // Skip the '=?'
        startPos += 2;
        // Find the first '?'
        size_t firstMark = line.find("?", startPos);
        if (firstMark == StringBuffer::npos) {
            LOG.error("Invalid encoded header");
            return line;
        }
        // Find the second '?'
        size_t secondMark = line.find("?", firstMark+1);
        if (secondMark == StringBuffer::npos) {
            LOG.error("Invalid encoded header");
            return line;
        }
        // Find the final '?='
        size_t endPos = line.find("?=", secondMark+1);
        if (endPos == StringBuffer::npos) {
            LOG.error("Invalid encoded header");
            return line;
        }

        charset = line.substr(startPos, firstMark - startPos);
        StringBuffer encoding = line.substr(firstMark+1, secondMark - (firstMark + 1));
        StringBuffer text = line.substr(secondMark+1, endPos - (secondMark + 1));

        if (encoding.icmp("Q")) {
            // quoted-printable
            text.replaceAll("_", " ");
            char* dec = qp_decode(text);
            if (startPos >= 2 &&  ret.length() == 0) {
                ret += line.substr(0, startPos - 2);
            }

            ret += dec;
            delete [] dec;
        }
        else if (encoding.icmp("B")){
        // base64
            char* dec = new char[text.length()];
            int len = b64_decode((void *)dec, text);
            dec[len]=0;
            if (startPos >= 2 &&  ret.length() == 0) {
                ret += line.substr(0, startPos - 2);
            }
            ret += dec;
            delete [] dec;
        }

        startPos = endPos;
    }

    if (ret.length() == 0) {
        ret += line;
    }

    WCHAR* wret = toWideChar(ret, charset);
    ret.set(NULL);
    char* t = toMultibyte(wret);
    ret.set(t);
    if (wret) {delete [] wret;}
    if (t) {delete [] t;}
    return ret;
}
int MailData::parse(const char *msg, size_t /* len */)
{
    int ret = 0;
    unsigned int start = 0, end = 0;
    isMailPartial = false;

    // Get attributes
    read      = checkFlag(msg, EMAIL_READ);
    forwarded = checkFlag(msg, EMAIL_FORW);
    replied   = checkFlag(msg, EMAIL_REPL);
    deleted   = checkFlag(msg, EMAIL_DELE);
    flagged   = checkFlag(msg, EMAIL_FLAG);

    if( XMLProcessor::getElementContent (msg, EMAIL_TREC, NULL, &start, &end) ) {
        received = StringBuffer(msg+start, end-start);
    }
    else received = "";

    if( XMLProcessor::getElementContent (msg, EMAIL_TCRE, NULL, &start, &end) ) {
        created = StringBuffer(msg+start, end-start);
    }
    else created = "";

    if( XMLProcessor::getElementContent (msg, EMAIL_TMOD, NULL, &start, &end) ) {
        modified = StringBuffer(msg+start, end-start);
    }
    else modified = "";

    // Get content
    StringBuffer itemtmp(msg);
    start = itemtmp.find(EMAIL_ITEM_START);
    end = itemtmp.rfind(EMAIL_ITEM_END);
    if (start != StringBuffer::npos && end != StringBuffer::npos) {
        totalEmailSize = itemtmp.length(); // the size of the current piece of mail
        itemtmp = NULL;
        //if( XMLProcessor::getElementContent(msg, EMAIL_ITEM, NULL, &start, &end) ) {
        StringBuffer item(msg+start, end-start);
        unsigned int startAttr=0, endAttr=0;

        //currently emailitem is not escaped so false!!
        if(XMLProcessor::getElementAttributes(msg, EMAIL_ITEM, &startAttr,
                                              &endAttr, false)) {
            StringBuffer attrlist(msg+startAttr, endAttr-startAttr);
            if(attrlist.ifind("quoted-printable") != StringBuffer::npos) {
                char *decoded = qp_decode(item);
                item = decoded;
                delete [] decoded;
            }
        }
        // item must start with CDATA
        size_t item_start = item.find("![CDATA");
        if(item_start > 50){ // it could be <emailitem ENC="QUOTED-PRINTABLE"><![CDATA[
            LOG.error("MailData: can't find inner CDATA section.");
            return -1;
        }
        size_t item_end = item.rfind("]]>");

        // In emailitem the last &gt; close the CDATA of emailitem tag and is escaped, so it is needed
        // to be found the follow. Usually the first is skipped
        //
        if(item.length() - item_end > 10){
            item_end = item.rfind("]]&gt;");
            if(item.length() - item_end > 10){
                LOG.error("MailData: can't find CDATA end tag.");
                return -2;
            }
        }
        // okay, move the start pointer to the end of
        item_start += strlen("![CDATA[");

        ret=emailItem.parse( item.c_str()+item_start, item_end - item_start );

    }
    else {
        // LOG.info("MailData: no <emailitem> tag.");
        // It is not an error, just log it for info.
    }
    /*
    char tmpExt[] = "<Ext><XNam>x-funambol-body</XNam><XVal>15000</XVal></Ext> \
                     <Ext><XNam>x-funambol-attach-n</XNam><XVal>1</XVal></Ext> \
                     <Ext><XNam>x-funambol-attach</XNam><XVal>att1.txt</XVal><XVal>10000</XVal></Ext>";
    */
    //char tmpExt[] = "";
    // find the Ext stuffs
    if (end != StringBuffer::npos) {
        unsigned int pos = end;
        unsigned int previous = end;
        start = 0, end = 0;
        char* ext = NULL;

        // for try
        //pos = 0;

        //while( (ext = XMLProcessor::copyElementContent(&tmpExt[pos], "Ext", &pos)) ) { // for try
        while( (ext = XMLProcessor::copyElementContent(&msg[pos], "Ext", &pos)) ) {
            char* xnam = XMLProcessor::copyElementContent(ext, "XNam", 0);
            if (!xnam)
                break;

            if (strcmp(xnam, "x-funambol-body") == 0) {
                char* val = XMLProcessor::copyElementContent(ext, "XVal", 0);
                if (val) {
                    setRemainingBodySize(atol(val));
                    totalEmailSize += atol(val);
                    delete [] val; val = NULL;
                    isMailPartial = true;
                }
            } else if (strcmp(xnam, "x-funambol-attach-n") == 0) {
                char* val = XMLProcessor::copyElementContent(ext, "XVal", 0);
                if (val) {
                    setRemainingAttachNumber(atol(val));
                    delete [] val; val = NULL;
                    isMailPartial = true;
                }
            } else if (strcmp(xnam, "x-funambol-attach") == 0) {
                if (!remainingAttachments) {
                    remainingAttachments = new ArrayList();
                }
                extMailData = new ExtMailData();
                unsigned int from = 0;
                int prev = 0;
                char* val = XMLProcessor::copyElementContent(ext, "XVal", &from);
                if (val) {
                    extMailData->attachName = stringdup(MailMessage::decodeHeader(val).c_str());
                    delete [] val; val = NULL;
                }
                prev = from;
                val = XMLProcessor::copyElementContent(&ext[from], "XVal", &from);
                if (val) {
                    extMailData->attachSize = atol(val);
                    totalEmailSize += atol(val);
                    delete [] val; val = NULL;
                }
                from += prev;
                prev = from;
                val = XMLProcessor::copyElementContent(&ext[from], "XVal", &from);
                if (val) {
                    extMailData->attachMime = stringdup(MailMessage::decodeHeader(val).c_str());                    
                    delete [] val; val = NULL;
                }
                from += prev;
                prev = from;
                val = XMLProcessor::copyElementContent(&ext[from], "XVal", &from);
                if (val) {
                    extMailData->attachURL = stringdup(MailMessage::decodeHeader(val).c_str());                    
                    delete [] val; val = NULL;
                }
                if (extMailData->attachName && extMailData->attachSize != 0) {
                    remainingAttachments->add(*extMailData);
                    isMailPartial = true;
                } else {
                    setRemainingAttachNumber(getRemainingAttachNumber() == 0 ? 0 
                        : (getRemainingAttachNumber() - 1));
                }
                delete extMailData;
                extMailData = NULL;
            }

            pos += previous;
            previous = pos;

            if (xnam) {
                delete [] xnam; xnam = NULL;
            }
            if (ext) {
                delete [] ext; ext = NULL;
            }

        }

    }



    return ret;
}
Beispiel #7
0
bool VConverter::readFieldBody(WCHAR* buffer, VProperty* vprop) {

    int i      = 0;
    int j      = 0;
    int len    = 0;
    int offset = 0;
    bool ret   = false;
    WCHAR* value     = NULL;
    WCHAR* allValues = NULL;
    WCHAR* c         = NULL;

    // Get length of all values
    while (buffer[i] != '\0') {
        if ((buffer[i] == '\r') || buffer[i] == '\n') {

            // Get offset of next property
            for (j=i+1; buffer[j] != '\0'; j++) {
                if((buffer[j] != '\r') && (buffer[j] != '\n'))
                    break;
            }
            offset = j;
            break;
        }
        i++;
    }
    len = i;


    if (!len) {
        // This field is empty, we MUST consider it adding an empty value
        // so any value on client will be deleted.
        vprop->addValue(TEXT(""));
        ret = true;
        goto finally;
    }

    // This is a string with all values for this property (to parse)
    allValues = new WCHAR[len + 1];
    wcsncpy(allValues, buffer, len);
    allValues[len] = 0;


    //
    // If needed, decode QP string and copy to 'allValues'.
    //
    if(vprop->equalsEncoding(TEXT("QUOTED-PRINTABLE"))) {

        char* buf = toMultibyte(allValues);
        char* dec = qp_decode(buf);
        len = strlen(dec);
        delete [] buf;

        if (dec) {
            char* t = toMultibyte(vprop->getParameterValue(TEXT("CHARSET")));
            WCHAR* wdecoded = toWideChar(dec, t);
            delete [] dec;
            delete [] t;

            if (wdecoded) {
                wcsncpy(allValues, wdecoded, len);
                allValues[len] = 0;
                delete [] wdecoded;
            }
        }
        if (!len) {
            goto finally;
        }
    }

    /*
    --- base64 is not decoded ----
    IT IS NOT POSSIBLE TO DECODE BASE64 PARAMETERS IN A WCHAR
    AND TAKE THE LENGHT OF A BINARY!!
    */

    // This is a buffer for each single value
    value = new WCHAR[len + 1];
    wcscpy(value, TEXT(""));

    //
    // Extract values and add to Vproperty
    //
    j=0;
    c = allValues;
    for (i=0; i<len; i++) {

        // End of value
        if (c[i] == ';') {
            vprop->addValue(value);
            j = 0;
            wcscpy(value, TEXT(""));
        }

        else {
            // Manage escaped chars: jump back-slash
            if (c[i] == '\\') {
                if (c[i+1]=='n') {
                    // none: this is "\n" sequence (formatted line ending for 3.0)
                }
                else {
                    i++;
                    if (c[i] == '\0')
                        break;
                }
            }
            value[j] = c[i];
            j++;
            value[j] = '\0';
        }
    }

    vprop->addValue(value);
    ret = true;

finally:

    // Shift buffer for next property to parse
    //wcscpy(buffer, buffer+offset);
    memmove(buffer, buffer+offset, (wcslen(buffer+offset) + 1)*sizeof(*buffer));

    if (value) {
        delete [] value;     value = NULL;
    }
    if (allValues) {
        delete [] allValues; allValues = NULL;
    }

    return ret;
}