Subject: base64 decoding

From: Simon McClenahan <[email-masked]>
Date: Fri, 03 Jan 1997 16:13:56 -0600

I'm trying to base64 decode a message. I'm trying to extract a binary (video) 
file from a message. I can find the PART that contains the encoded file, but I 
don't understand how to decode it properly. Is there a way to decode it directly 
to a file rather than in memory?

I don't understand mail_fetchbody() and what a section is. Am I sending the right 
type of data to rfc822_base64() ? Right now, all I get is a file with 0 length.

    ENVELOPE *envelope=NULL;
    int found=NIL;
    PART *part=NULL;
    int sec=0;
    SIZEDTEXT *text=NULL;
    void *vdata=NULL;
    unsigned long lvdata=0;

    /* get mail structure */
    envelope = mail_fetchstructure(stream, 1, &body);

    /* find the video file */
    found = NIL;
    for (part=body->nested.part, sec=1 ; NULL != part ; part=part->next, sec++)
    {
        if ( TYPEVIDEO == part->body.type )
        {
            found = T;
            break;
        }
    }
    if ( ! found ) VfePerror(0, "video file not found in message");

    sprintf(tmp, "%d", sec);
    mail_fetchbody(stream, 1, tmp, NIL);

    /* decode it */
    text = &part->body.contents.text;
    vdata = rfc822_base64(text->data, text->size, &lvdata);

    /* save it in file */
    sprintf(vfilepath, "%s/%s", dir, VFILE_NAME);
    vfile = fopen(vfilepath, "w+");
    fwrite(vdata, 1, lvdata, vfile);
    fclose(vfile);

cheers,
-- 
                    Simon McClenahan, an Australian in Iowa
                 and an "I found my wife on the Internet" guy.
        PLEASURE          /                                 BUSINESS
mailto:[email-masked]  /                   [email-masked]
Phone:  +1 319 277 6058 /                     Phone: +1 319 375 1772
                       / USA Toll-free: 800 728 7000 Extension: 1772
http://www.freedomstarr.com/MC2776058.rep

---

From: Mark Crispin <[email-masked]>
Date: Fri, 3 Jan 1997 14:34:19 -0800 (PST)

c-client section specifiers are the same as IMAP section specifiers.  Refer to
RFC-2060 for a formal description, and to mtest.c for an example of how to run
down a BODY structure and get the section specifier.

This section of code is completely wrong:

    /* decode it */

You must *NOT* reference body.contents.text, not for any reason whatsoever!!
These are internal to c-client.  You should use the values returned from
mail_fetch????() instead.

---

From: Simon McClenahan <[email-masked]>
Date: Thu, 09 Jan 1997 11:54:58 -0600

> down a BODY structure and get the section specifier.

This is where I'm confused. RFC-2060 doesn't give me an example of a section 
specifier, and I don't understand the pfx variable in mtest.c:display_body() . Given 
that pfx is always empty, section specifiers are like "1.", "2.", etc.? Is "BODY.2.", 
"BODY.2" or "BODY2." valid?

I managed to get the rfc822_base64() to work (although I would prefer to have it 
decode to a file than in memory) by giving it the return value of mail_fetchbody() 
with a section specifier of something like "2". In my TYPEMULTIPART mail message, I am 
trying to go through each part, switch() on its body.type and do mail_fetchbody() as 
appropriate. Some code will explain better:

    for (part=body->nested.part, sec=1 ; NULL != part ; part=part->next, sec++)
    {
        switch(part->body.type) {
        case TYPETEXT:
            /* sprintf(tmp, "BODY%d.", sec); */
            sprintf(tmp, "%d", sec);
            text = mail_fetchbody(stream, 1, tmp, &ltext);

            /* save it in a file */
            sprintf(bodypath, "%s/%s", dir, BODY_NAME);
            bodyfile = fopen(bodypath, "w+");
            fputs(text, bodyfile);
            fclose(bodyfile);

            bodyfound = T;
            break;

        case TYPEVIDEO:
            /* sprintf(tmp, "BODY%d.", sec); */
            sprintf(tmp, "%d", sec);
            text = mail_fetchbody(stream, 1, tmp, &ltext);

            /* decode it */
            vdata = rfc822_base64(text, ltext, &lvdata);

            /* save it in file */

            videofound = T;
            break;

        default:
            printf("section == %d, body type == %s\n", sec, body_types[part->bod
y.type]);
            break;

	}
    }

The text returned in the case TYPETEXT contains the text for that body and all the 
text from the next MIME part! (which just happens to be the BASE64 encoded TYPEVIDEO 
part). It's as if the end of the TYPETEXT part is not detected. The mail_fetchbody() 
works fine in the case: TYPEVIDEO .

Here is the (edited) mail message I am testing with

...
Mime-Version: 1.0
Content-Type: MULTIPART/MIXED; BOUNDARY="-1507492794-2078917053-852821005=:27406"

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to [email-masked] for more info.

---1507492794-2078917053-852821005=:27406
Content-Type: TEXT/PLAIN; charset=US-ASCII

This is catlin.iba

cheers,
    Simon

---1507492794-2078917053-852821005=:27406
Content-Type: video/octet-stream; name="catlin-50.iba"
Content-Transfer-Encoding: BASE64
Content-ID: <[email-masked]>
Content-Description:

AADw8AEAAAAAAAACHwAAAAAAAAAJ4T5IMjYzRzcyMwAPAMgAABicAVUA7HwA
sACQAFVudGl0bGVkIENsaXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
...

---

From: Mark Crispin <[email-masked]>
Date: Thu, 9 Jan 1997 18:55:58 -0800 (PST)

On Thu, 09 Jan 1997 11:54:58 -0600, Simon McClenahan wrote:
> > c-client section specifiers are the same as IMAP section specifiers.
> > Refer to RFC-2060 for a formal description, and to mtest.c for an example
> > of how to run down a BODY structure and get the section specifier.

> specifier,

Section specifiers are called part specifiers in RFC 2060, and are defined
starting on page 41.  Ignore what is said on page 42 about non-numeric part
specifiers such as HEADER; that is relevant to IMAP but not to the c-client
section specifier argument.  Page 43 has an example.

> and I don't understand the pfx variable in mtest.c:display_body() . Given
> that pfx is always empty, section specifiers are like "1.", "2.", etc.?

No, pfx in mtest.c's display_body() is *not* "always empty".  display_body()
calls itself recurseively.  pfx holds the "prefix" section specifier from the
upper levels of display body() call.

A section specifier begins and ends with a digit, never a period.  A period
may be embedded, indicating nesting.  3.5.4 means "the fourth part of the
fifth part of the third part of the message."

> The text returned in the case TYPETEXT contains the text for that body and
> all the text from the next MIME part!

I suspect that you made the mistake of assuming that the value returned from
mail_fetchbody() is guaranteed to be null-terminated.  It is not.  You *must*
pay attention to the returned length count.  Anything beyond that length count
is undefined.