ShellBanner
System:Linux MiraNet 3.0.0-14-generic-pae #23-Ubuntu SMP Mon Nov 21 22:07:10 UTC 2011 i686
Software:Apache. PHP/5.3.6-13ubuntu3.10
ID:uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
Safe Mode:OFF
Open_Basedir:OFF
Freespace:24.22 GB of 70.42 GB (34.4%)
MySQL: ON MSSQL: OFF Oracle: OFF PostgreSQL: OFF Curl: OFF Sockets: ON Fetch: OFF Wget: ON Perl: ON
Disabled Functions: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

/ usr/ src/ courier-0.66.1/ imap/ - drwxrwxrwx

Directory:
Viewing file:     fetch.c (30.38 KB)      -rw-rw-rw-
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 1998 - 2010 Double Precision, Inc.
** See COPYING for distribution information.
*/

#if    HAVE_CONFIG_H
#include    "config.h"
#endif

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <ctype.h>
#include    <errno.h>
#if    HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    <sys/types.h>
#include    <sys/stat.h>

#include    "imaptoken.h"
#include    "imapwrite.h"
#include    "imapscanclient.h"
#include    "fetchinfo.h"
#include    "rfc822/rfc822.h"
#include    "rfc2045/rfc2045.h"
#include    "maildir/config.h"
#include    "maildir/maildirgetquota.h"
#include    "maildir/maildirquota.h"
#include    "maildir/maildiraclt.h"

#if SMAP
extern int smapflag;
#endif

static const char unavailable[]=
    "\
From: System Administrator <root@localhost>\n\
Subject: message unavailable\n\n\
This message is no longer available on the server.\n";

unsigned long header_count=0, body_count=0;    /* Total transferred */

extern int current_mailbox_ro;
extern char *current_mailbox_acl;
extern struct imapscaninfo current_maildir_info;
extern char *current_mailbox;
extern char *rfc2045id(struct rfc2045 *);

extern void snapshot_needed();

extern void msgenvelope(void (*)(const char *, size_t),
                FILE *, struct rfc2045 *);
extern void msgbodystructure( void (*)(const char *, size_t), int,
        FILE *, struct rfc2045 *);

extern int is_trash(const char *);
extern void get_message_flags(struct imapscanmessageinfo *,
    char *, struct imapflags *);
extern void append_flags(char *, struct imapflags *);

static int fetchitem(FILE **, int *, struct fetchinfo *,
    struct imapscaninfo *,  unsigned long,
    struct rfc2045 **);

static void bodystructure(FILE *, struct fetchinfo *,
    struct imapscaninfo *,  unsigned long,
    struct rfc2045 *);

static void body(FILE *, struct fetchinfo *,
    struct imapscaninfo *,  unsigned long,
    struct rfc2045 *);

static void fetchmsgbody(FILE *, struct fetchinfo *,
    struct imapscaninfo *,  unsigned long,
    struct rfc2045 *);

static void dofetchmsgbody(FILE *, struct fetchinfo *,
    struct imapscaninfo *,  unsigned long,
    struct rfc2045 *);

static void envelope(FILE *, struct fetchinfo *,
    struct imapscaninfo *,  unsigned long,
    struct rfc2045 *);

void doflags(FILE *, struct fetchinfo *,
         struct imapscaninfo *, unsigned long, struct rfc2045 *);

static void internaldate(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long, struct rfc2045 *);

static void uid(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long, struct rfc2045 *);

static void all(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long, struct rfc2045 *);

static void fast(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long, struct rfc2045 *);

static void full(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long, struct rfc2045 *);

static void rfc822size(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long, struct rfc2045 *);

#if 0
static void do_envelope(FILE *, struct fetchinfo *,
    struct imapscanmessageinfo *, struct rfc2045 *);
#endif

static void dofetchheadersbuf(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long,
    struct rfc2045 *,
    int (*)(struct fetchinfo *fi, const char *));
static void dofetchheadersfile(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long,
    struct rfc2045 *,
    int (*)(struct fetchinfo *fi, const char *));

static void print_bodysection_partial(struct fetchinfo *,
        void (*)(const char *));
static void print_bodysection_output(const char *);

static int dofetchheaderfields(struct fetchinfo *, const char *);
static int dofetchheadernotfields(struct fetchinfo *, const char *);
static int dofetchheadermime(struct fetchinfo *, const char *);

static void rfc822(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long,
    struct rfc2045 *);

static void rfc822header(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long,
    struct rfc2045 *);

static void rfc822text(FILE *, struct fetchinfo *,
    struct imapscaninfo *, unsigned long,
    struct rfc2045 *);

struct rfc2045 *fetch_alloc_rfc2045(unsigned long, FILE *);
FILE *open_cached_fp(unsigned long);

void fetchflags(unsigned long);

static void fetcherrorprt(const char *p)
{
    fprintf(stderr, "%s", p);
}

static void fetcherror(const char *errmsg,
        struct fetchinfo *fi,
        struct imapscaninfo *info, unsigned long j)
{
struct imapscanmessageinfo *mi=info->msgs+j;

    fprintf(stderr, "IMAP FETCH ERROR: %s, uid=%u, filename=%s: %s",
        errmsg, (unsigned)getuid(), mi->filename, fi->name);
    if (fi->bodysection)
        print_bodysection_partial(fi, &fetcherrorprt);
    fprintf(stderr, "\n");
}

char *get_reflagged_filename(const char *fn, struct imapflags *newflags)
{
    char *p=malloc(strlen(fn)+20);
    char *q;

    if (!p)    write_error_exit(0);
    strcpy(p, fn);
    if ((q=strrchr(p, MDIRSEP[0])) != 0)    *q=0;
    strcat(p, MDIRSEP "2,");
    append_flags(p, newflags);
    return p;
}

int reflag_filename(struct imapscanmessageinfo *mi, struct imapflags *flags,
    int fd)
{
char    *p, *q, *r;
int    rc=0;
struct    imapflags old_flags;
struct    stat    stat_buf;

    get_message_flags(mi, 0, &old_flags);

    p=get_reflagged_filename(mi->filename, flags);

    q=malloc(strlen(current_mailbox)+strlen(mi->filename)+sizeof("/cur/"));
    r=malloc(strlen(current_mailbox)+strlen(p)+sizeof("/cur/"));
    if (!q || !r)    write_error_exit(0);
    strcat(strcat(strcpy(q, current_mailbox), "/cur/"), mi->filename);
    strcat(strcat(strcpy(r, current_mailbox), "/cur/"), p);
    if (strcmp(q, r))
    {
        if (maildirquota_countfolder(current_mailbox)
            && old_flags.deleted != flags->deleted
            && fstat(fd, &stat_buf) == 0)
        {
            struct maildirsize quotainfo;
            int64_t    nbytes;
            unsigned long unbytes;
            int    nmsgs=1;

            if (maildir_parsequota(mi->filename, &unbytes) == 0)
                nbytes=unbytes;
            else
                nbytes=stat_buf.st_size;
            if ( flags->deleted )
            {
                nbytes= -nbytes;
                nmsgs= -nmsgs;
            }

            if ( maildir_quota_delundel_start(current_mailbox,
                              &quotainfo,
                              nbytes, nmsgs))
                rc= -1;
            else
                maildir_quota_delundel_end(&quotainfo,
                               nbytes, nmsgs);
        }

        if (rc == 0)
            rename(q, r);

#if SMAP
        snapshot_needed();
#endif
    }
    free(q);
    free(r);
    free(mi->filename);
    mi->filename=p;

#if 0
    if (is_sharedsubdir(current_mailbox))
        maildir_shared_updateflags(current_mailbox, p);
#endif

    return (rc);
}

int do_fetch(unsigned long n, int byuid, void *p)
{
    struct fetchinfo *fi=(struct fetchinfo *)p;
    FILE    *fp;
    struct    rfc2045 *rfc2045p;
    int    seen;
    int    open_err;

    fp=NULL;
    open_err=0;

    writes("* ");
    writen(n);
    writes(" FETCH (");

    if (byuid)
    {
    struct fetchinfo *fip;

        for (fip=fi; fip; fip=fip->next)
            if (strcmp(fip->name, "UID") == 0)
                break;

        if (fip == 0)
        {
            writes("UID ");
            writen(current_maildir_info.msgs[n-1].uid);
            writes(" ");
        }
    }
    seen=0;
    rfc2045p=0;
    while (fi)
    {
        if (fetchitem(&fp, &open_err, fi, &current_maildir_info, n-1,
            &rfc2045p))    seen=1;
        if ((fi=fi->next) != 0)    writes(" ");
    }
    writes(")\r\n");

    if (open_err)
    {
        writes("* NO Cannot open message ");
        writen(n);
        writes("\r\n");
        return (0);
    }


#if SMAP
    if (!smapflag)
#endif
        if (current_mailbox_acl &&
            strchr(current_mailbox_acl, ACL_SEEN[0]) == NULL)
            seen=0; /* No permissions */

    if (seen && !current_mailbox_ro)
    {
    struct    imapflags    flags;

        get_message_flags(current_maildir_info.msgs+(n-1),
                0, &flags);
        if (!flags.seen)
        {
            flags.seen=1;
            reflag_filename(&current_maildir_info.msgs[n-1],&flags,
                fileno(fp));
            current_maildir_info.msgs[n-1].changedflags=1;
        }
    }

    if (current_maildir_info.msgs[n-1].changedflags)
        fetchflags(n-1);
    return (0);
}

static int fetchitem(FILE **fp, int *open_err, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 **mimep)
{
    void (*fetchfunc)(FILE *, struct fetchinfo *,
              struct imapscaninfo *, unsigned long,
              struct rfc2045 *);
    int    parsemime=0;
    int    rc=0;
    int    do_open=1;

    if (strcmp(fi->name, "ALL") == 0)
    {
        parsemime=1;
        fetchfunc= &all;
    }
    else if (strcmp(fi->name, "BODYSTRUCTURE") == 0)
    {
        parsemime=1;
        fetchfunc= &bodystructure;
    }
    else if (strcmp(fi->name, "BODY") == 0)
    {
        parsemime=1;
        fetchfunc= &body;
        if (fi->bodysection)
        {
            fetchfunc= &fetchmsgbody;
            rc=1;
        }
    }
    else if (strcmp(fi->name, "BODY.PEEK") == 0)
    {
        parsemime=1;
        fetchfunc= &body;
        if (fi->bodysection)
            fetchfunc= &fetchmsgbody;
    }
    else if (strcmp(fi->name, "ENVELOPE") == 0)
    {
        parsemime=1;
        fetchfunc= &envelope;
    }
    else if (strcmp(fi->name, "FAST") == 0)
    {
        parsemime=1;
        fetchfunc= &fast;
    }
    else if (strcmp(fi->name, "FULL") == 0)
    {
        parsemime=1;
        fetchfunc= &full;
    }
    else if (strcmp(fi->name, "FLAGS") == 0)
    {
        fetchfunc= &doflags;
        do_open=0;
    }
    else if (strcmp(fi->name, "INTERNALDATE") == 0)
    {
        fetchfunc= &internaldate;
    }
    else if (strcmp(fi->name, "RFC822") == 0)
    {
        fetchfunc= &rfc822;
        rc=1;
    }
    else if (strcmp(fi->name, "RFC822.HEADER") == 0)
    {
        fetchfunc= &rfc822header;
    }
    else if (strcmp(fi->name, "RFC822.SIZE") == 0)
    {
        parsemime=1;
        fetchfunc= &rfc822size;
    }
    else if (strcmp(fi->name, "RFC822.TEXT") == 0)
    {
        parsemime=1;
        fetchfunc= &rfc822text;
    }
    else if (strcmp(fi->name, "UID") == 0)
    {
        fetchfunc= &uid;
        do_open=0;
    }
    else    return (0);

    if (do_open && *fp == NULL)
    {
        *fp=open_cached_fp(msgnum);
        if (!*fp)
        {
            *open_err=1;
            return rc;
        }
    }

    if (parsemime && !*mimep)
    {
        *mimep=fetch_alloc_rfc2045(msgnum, *fp);
    }

    (*fetchfunc)(*fp, fi, i, msgnum, *mimep);
    return (rc);
}

static void bodystructure(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    writes("BODYSTRUCTURE ");
    msgbodystructure(writemem, 1, fp, mimep);
}

static void body(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    writes("BODY ");
    msgbodystructure(writemem, 0, fp, mimep);
}

static void envelope(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    writes("ENVELOPE ");
    msgenvelope( &writemem, fp, mimep);
}

void fetchflags(unsigned long n)
{
#if SMAP
    if (smapflag)
    {
        writes("* FETCH ");
        writen(n+1);
    }
    else
#endif
    {
        writes("* ");
        writen(n+1);
        writes(" FETCH (");
    }

    doflags(0, 0, &current_maildir_info, n, 0);

#if SMAP
    if (smapflag)
    {
        writes("\n");
    }
    else
#endif
        writes(")\r\n");
}

void fetchflags_byuid(unsigned long n)
{
    writes("* ");
    writen(n+1);
    writes(" FETCH (");
    uid(0, 0, &current_maildir_info, n, 0);
    writes(" ");
    doflags(0, 0, &current_maildir_info, n, 0);
    writes(")\r\n");
}

void doflags(FILE *fp, struct fetchinfo *fi,
         struct imapscaninfo *i, unsigned long msgnum,
         struct rfc2045 *mimep)
{
    struct libmail_kwMessageEntry *kme;

    char    buf[256];

#if SMAP
    if (smapflag)
    {
        writes(" FLAGS=");
        get_message_flags(i->msgs+msgnum, buf, 0);
        writes(buf);
    }
    else
#endif
    {
        struct libmail_kwMessage *km;

        writes("FLAGS ");

        get_message_flags(i->msgs+msgnum, buf, 0);

        writes("(");
        writes(buf);

        if (buf[0])
            strcpy(buf, " ");

        if ((km=i->msgs[msgnum].keywordMsg) != NULL)
            for (kme=km->firstEntry; kme; kme=kme->next)
            {
                writes(buf);
                strcpy(buf, " ");
                writes(keywordName(kme->libmail_keywordEntryPtr));
            }
        writes(")");
    }

    i->msgs[msgnum].changedflags=0;
}

static void internaldate(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
struct    stat    stat_buf;
char    buf[256];
char    *p, *q;

    writes("INTERNALDATE ");
    if (fstat(fileno(fp), &stat_buf) == 0)
    {
        rfc822_mkdate_buf(stat_buf.st_mtime, buf);

        /* Convert RFC822 date to imap date */

        p=strchr(buf, ',');
        if (p)    ++p;
        else    p=buf;
        while (*p == ' ')    ++p;
        if ((q=strchr(p, ' ')) != 0)    *q++='-';
        if ((q=strchr(p, ' ')) != 0)    *q++='-';
        writes("\"");
        writes(p);
        writes("\"");
    }
    else
        writes("NIL");
}

static void uid(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    writes("UID ");
    writen(i->msgs[msgnum].uid);
}

static void rfc822size(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;

    writes("RFC822.SIZE ");

    rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
        &nlines, &nbodylines);

    writen(end_pos - start_pos + nlines);
}

static void all(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    doflags(fp, fi, i, msgnum, mimep);
    writes(" ");
    internaldate(fp, fi, i, msgnum, mimep);
    writes(" ");
    rfc822size(fp, fi, i, msgnum, mimep);
    writes(" ");
    envelope(fp, fi, i, msgnum, mimep);
}

static void fast(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    doflags(fp, fi, i, msgnum, mimep);
    writes(" ");
    internaldate(fp, fi, i, msgnum, mimep);
    writes(" ");
    rfc822size(fp, fi, i, msgnum, mimep);
}

static void full(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    doflags(fp, fi, i, msgnum, mimep);
    writes(" ");
    internaldate(fp, fi, i, msgnum, mimep);
    writes(" ");
    rfc822size(fp, fi, i, msgnum, mimep);
    writes(" ");
    envelope(fp, fi, i, msgnum, mimep);
    writes(" ");
    body(fp, fi, i, msgnum, mimep);
}

static void fetchmsgbody(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
    writes("BODY");
    print_bodysection_partial(fi, &print_bodysection_output);
    writes(" ");
    dofetchmsgbody(fp, fi, i, msgnum, mimep);
}

static void print_bodysection_output(const char *p)
{
    writes(p);
}

static void print_bodysection_partial(struct fetchinfo *fi,
    void (*func)(const char *))
{
    (*func)("[");
    if (fi->bodysection)
    {
    struct fetchinfo *subl;

        (*func)(fi->bodysection);
        if (fi->bodysublist)
        {
        char    *p=" (";

            for (subl=fi->bodysublist; subl; subl=subl->next)
            {
                (*func)(p);
                p=" ";
                (*func)("\"");
                (*func)(subl->name);
                (*func)("\"");
            }
            (*func)(")");
        }
    }
    (*func)("]");
    if (fi->ispartial)
    {
    char    buf[80];

        sprintf(buf, "<%lu>", (unsigned long)fi->partialstart);
        (*func)(buf);
    }
}

static void dofetchmsgbody(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *i, unsigned long msgnum,
    struct rfc2045 *mimep)
{
const char *p=fi->bodysection;
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
unsigned long cnt;
char    buf[BUFSIZ];
char    rbuf[BUFSIZ];
char    *rbufptr;
int    rbufleft;
unsigned long bufptr;
unsigned long skipping;
int    ismsgrfc822=1;

off_t start_seek_pos;
 struct rfc2045 *headermimep;

/*
** To optimize consecutive FETCHes, we cache our virtual and physical
** position.  What we do is that on the first fetch we count off the
** characters we read, and keep track of both the physical and the CRLF-based
** offset into the message.  Then, on subsequent FETCHes, we attempt to
** use that information.
*/

off_t cnt_virtual_chars;
off_t cnt_phys_chars;

off_t cache_virtual_chars;
off_t cache_phys_chars;

    headermimep=mimep;
 
    while (p && isdigit((int)(unsigned char)*p))
    {
    unsigned long n=0;

        headermimep=mimep;

        do
        {
            n=n*10 + (*p++ - '0');
        } while (isdigit((int)(unsigned char)*p));

        if (mimep)
        {
            if (ismsgrfc822)
            {
                const char *ct, *dummy;

                if (mimep->firstpart == 0)
                {
                    /* Not a multipart, n must be 1 */
                    if (n != 1)
                        mimep=0;
                    if (*p == '.')
                        ++p;
                    continue;
                }
                ismsgrfc822=0;

                rfc2045_mimeinfo(mimep, &ct,
                         &dummy,
                         &dummy);

                if (ct && strcasecmp(ct, "message/rfc822"
                             ) == 0)
                    ismsgrfc822=1;
                /* The content is another message/rfc822 */
            }

            mimep=mimep->firstpart;
            while (mimep)
            {
                if (!mimep->isdummy && --n == 0)
                    break;
                mimep=mimep->next;
            }
            headermimep=mimep;

            if (mimep && mimep->firstpart &&
                !mimep->firstpart->isdummy)
                /* This is a message/rfc822 part */
            {
                if (!*p)
                    break;

                mimep=mimep->firstpart;
                ismsgrfc822=1;
            }
        }
        if (*p == '.')
            ++p;
    }

    if (p && strcmp(p, "MIME") == 0)
        mimep=headermimep;

    if (mimep == 0)
    {
        writes("{0}\r\n");
        return;
    }

    rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
        &nlines, &nbodylines);


    if (p && strcmp(p, "TEXT") == 0)
    {
        start_seek_pos=start_body;
        cnt=end_pos - start_body + nbodylines;
    }
    else if (p && strcmp(p, "HEADER") == 0)
    {
        start_seek_pos=start_pos;
        cnt= start_body - start_pos + (nlines - nbodylines);
    }
    else if (p && strcmp(p, "HEADER.FIELDS") == 0)
    {
        if (start_body - start_pos <= BUFSIZ)
            dofetchheadersbuf(fp, fi, i, msgnum, mimep,
                &dofetchheaderfields);
        else
            dofetchheadersfile(fp, fi, i, msgnum, mimep,
                &dofetchheaderfields);
        return;
    }
    else if (p && strcmp(p, "HEADER.FIELDS.NOT") == 0)
    {
        if (start_body - start_pos <= BUFSIZ)
            dofetchheadersbuf(fp, fi, i, msgnum, mimep,
                &dofetchheadernotfields);
        else
            dofetchheadersfile(fp, fi, i, msgnum, mimep,
                &dofetchheadernotfields);
        return;
    }
    else if (p && strcmp(p, "MIME") == 0)
    {
        if (start_body - start_pos <= BUFSIZ)
            dofetchheadersbuf(fp, fi, i, msgnum, mimep,
                &dofetchheadermime);
        else
            dofetchheadersfile(fp, fi, i, msgnum, mimep,
                &dofetchheadermime);
        return;
    }
    else if (*fi->bodysection == 0)
    {
        start_seek_pos=start_pos;

        cnt= end_pos - start_pos + nlines;
    }
    else    /* Last possibility: entire body */
    {
        start_seek_pos=start_body;

        cnt= end_pos - start_body + nbodylines;
    }

    skipping=0;
    if (fi->ispartial)
    {
        skipping=fi->partialstart;
        if (skipping > cnt)    skipping=cnt;
        cnt -= skipping;
        if (fi->ispartial > 1 && cnt > fi->partialend)
            cnt=fi->partialend;
    }

    if (get_cached_offsets(start_seek_pos, &cnt_virtual_chars,
                   &cnt_phys_chars) == 0 &&
        cnt_virtual_chars <= skipping)    /* Yeah - cache it, baby! */
    {
        if (fseek(fp, start_seek_pos+cnt_phys_chars, SEEK_SET) == -1)
        {
            writes("{0}\r\n");
            fetcherror("fseek", fi, i, msgnum);
            return;
        }
        skipping -= cnt_virtual_chars;
    }
    else
    {
        if (fseek(fp, start_seek_pos, SEEK_SET) == -1)
        {
            writes("{0}\r\n");
            fetcherror("fseek", fi, i, msgnum);
            return;
        }

        cnt_virtual_chars=0;
        cnt_phys_chars=0;
    }

    cache_virtual_chars=cnt_virtual_chars;
    cache_phys_chars=cnt_phys_chars;

    writes("{");
    writen(cnt);
    writes("}\r\n");
    bufptr=0;
    writeflush();

    rbufptr=0;
    rbufleft=0;

    while (cnt)
    {
    int    c;

        if (!rbufleft)
        {
            rbufleft=fread(rbuf, 1, sizeof(rbuf), fp);
            if (rbufleft < 0)    rbufleft=0;
            rbufptr=rbuf;
        }

        if (!rbufleft)
        {
            fetcherror("unexpected EOF", fi, i, msgnum);
            _exit(1);
        }

        --rbufleft;
        c=(int)(unsigned char)*rbufptr++;
        ++cnt_phys_chars;

        if (c == '\n')
        {
            ++cnt_virtual_chars;

            if (skipping)
                --skipping;
            else
            {
                if (bufptr >= sizeof(buf))
                {
                    writemem(buf, sizeof(buf));
                    bufptr=0;
                    /*writeflush();*/
                }
                buf[bufptr++]='\r';
                --cnt;

                if (cnt == 0)
                    break;
            }
        }

        ++cnt_virtual_chars;
        if (skipping)
            --skipping;
        else
        {
            ++body_count;

            if (bufptr >= sizeof(buf))
            {
                writemem(buf, sizeof(buf));
                bufptr=0;
                /*writeflush();*/
            }
            buf[bufptr++]=c;
            --cnt;
        }
        cache_virtual_chars=cnt_virtual_chars;
        cache_phys_chars=cnt_phys_chars;
    }
    writemem(buf, bufptr);
    writeflush();
    save_cached_offsets(start_seek_pos, cache_virtual_chars,
                cache_phys_chars);
}

static int dofetchheaderfields(struct fetchinfo *fi, const char *name)
{
    for (fi=fi->bodysublist; fi; fi=fi->next)
    {
    int    i, a, b;

        if (fi->name == 0)    continue;
        for (i=0; fi->name[i] && name[i]; i++)
        {
            a=(unsigned char)name[i];
            a=toupper(a);
            b=fi->name[i];
            b=toupper(b);
            if (a != b)    break;
        }
        if (fi->name[i] == 0 && name[i] == 0)    return (1);
    }

    return (0);
}

static int dofetchheadernotfields(struct fetchinfo *fi, const char *name)
{
    return (!dofetchheaderfields(fi, name));
}

static int dofetchheadermime(struct fetchinfo *fi, const char *name)
{
int    i, a;
static const char mv[]="MIME-VERSION";

    for (i=0; i<sizeof(mv)-1; i++)
    {
        a= (unsigned char)name[i];
        a=toupper(a);
        if (a != mv[i])    break;
    }
    if (mv[i] == 0 && name[i] == 0)    return (1);

    for (i=0; i<8; i++)
    {
        a= (unsigned char)name[i];
        a=toupper(a);
        if (a != "CONTENT-"[i])    return (0);
    }
    return (1);
}

static void dofetchheadersbuf(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *info, unsigned long msgnum,
    struct rfc2045 *mimep,
    int (*headerfunc)(struct fetchinfo *fi, const char *))
{
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
size_t i,j,k,l;
char    buf[BUFSIZ+2];
int    goodheader;
unsigned long skipping;
unsigned long cnt;
char    *p;
int    ii;

    rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
        &nlines, &nbodylines);
    if (fseek(fp, start_pos, SEEK_SET) == -1)
    {
        writes("{0}\r\n");
        fetcherror("fseek", fi, info, msgnum);
        return;
    }

    ii=fread(buf, 1, start_body - start_pos, fp);
    if (ii < 0 || (i=ii) != start_body - start_pos)
    {
        fetcherror("unexpected EOF", fi, info, msgnum);
        exit(1);
    }
    goodheader= (*headerfunc)(fi, "");

    l=0;
    for (j=0; j<i; )
    {
        if (buf[j] != '\n' && buf[j] != '\r' &&
            !isspace((int)(unsigned char)buf[j]))
        {
            goodheader= (*headerfunc)(fi, "");

            for (k=j; k<i; k++)
            {
                if (buf[k] == '\n' || buf[k] == ':')
                    break;
            }

            if (k < i && buf[k] == ':')
            {
                buf[k]=0;
                goodheader=(*headerfunc)(fi, buf+j);
                buf[k]=':';
            }
        }
        else if (buf[j] == '\n')
            goodheader=0;

        for (k=j; k<i; k++)
            if (buf[k] == '\n')
            {
                ++k;
                break;
            }

        if (goodheader)
        {
            while (j<k)
                buf[l++]=buf[j++];
        }
        j=k;
    }

    buf[l++]='\n';    /* Always append a blank line */

    cnt=l;
    for (i=0; i<l; i++)
        if (buf[i] == '\n')    ++cnt;

    skipping=0;
    if (fi->ispartial)
    {
        skipping=fi->partialstart;
        if (skipping > cnt)    skipping=cnt;
        cnt -= skipping;
        if (fi->ispartial > 1 && cnt > fi->partialend)
            cnt=fi->partialend;
    }

    writes("{");
    writen(cnt);
    writes("}\r\n");
    p=buf;
    while (skipping)
    {
        if (*p == '\n')
        {
            --skipping;
            if (skipping == 0)
            {
                if (cnt)
                {
                    writes("\n");
                    --cnt;
                }
                break;
            }
        }
        --skipping;
        ++p;
    }

    while (cnt)
    {
        if (*p == '\n')
        {
            writes("\r");
            if (--cnt == 0)    break;
            writes("\n");
            --cnt;
            ++p;
            continue;
        }
        for (i=0; i<cnt; i++)
            if (p[i] == '\n')
                break;
        writemem(p, i);
        p += i;
        cnt -= i;
        header_count += i;
    }
}

struct fetchheaderinfo {
    unsigned long skipping;
    unsigned long cnt;
    } ;

static void countheader(struct fetchheaderinfo *, const char *, size_t);

static void printheader(struct fetchheaderinfo *, const char *, size_t);

static void dofetchheadersfile(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *info, unsigned long msgnum,
    struct rfc2045 *mimep,
    int (*headerfunc)(struct fetchinfo *fi, const char *))
{
off_t start_pos, end_pos, start_body, left;
off_t nlines, nbodylines;
size_t i;
int    c, pass;
char    buf1[256];
int    goodheader;
struct    fetchheaderinfo finfo;

    finfo.cnt=0;
    for (pass=0; pass<2; pass++)
    {
    void (*func)(struct fetchheaderinfo *, const char *, size_t)=
            pass ? printheader:countheader;

        rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
            &nlines, &nbodylines);
        if (fseek(fp, start_pos, SEEK_SET) == -1)
        {
            writes("{0}\r\n");
            fetcherror("fseek", fi, info, msgnum);
            return;
        }
        if (pass)
        {
            finfo.skipping=0;
            if (fi->ispartial)
            {
                finfo.skipping=fi->partialstart;
                if (finfo.skipping > finfo.cnt)
                    finfo.skipping=finfo.cnt;
                finfo.cnt -= finfo.skipping;
                if (fi->ispartial > 1 &&
                    finfo.cnt > fi->partialend)
                    finfo.cnt=fi->partialend;
            }

            writes("{");
            writen(finfo.cnt+2);    /* BUG */
            writes("}\r\n");
        }
        left=start_body - start_pos;

        goodheader= (*headerfunc)(fi, "");
        while (left)
        {
            for (i=0; i<sizeof(buf1)-1 && i<left; i++)
            {
                c=getc(fp);
                if (c == EOF)
                {
                    fetcherror("unexpected EOF", fi, info, msgnum);
                    _exit(1);
                }

                if (c == '\n' || c == ':')
                {
                    ungetc(c, fp);
                    break;
                }
                buf1[i]=c;
            }
            buf1[i]=0;
            left -= i;

            if (buf1[0] != '\n' && buf1[0] != '\r' &&
                !isspace((int)(unsigned char)buf1[0]))
                goodheader= (*headerfunc)(fi, buf1);
            else if (buf1[0] == '\n')
                goodheader=0;

            if (!goodheader)
            {
                while (left)
                {
                    c=getc(fp);
                    --left;
                    if (c == EOF)
                    {
                        fetcherror("unexpected EOF", fi, info, msgnum);
                        _exit(1);
                    }
                    if (c == '\n')    break;
                }
                continue;
            }

            (*func)(&finfo, buf1, i);

            i=0;
            while (left)
            {
                c=getc(fp);
                if (c == EOF)
                {
                    fetcherror("unexpected EOF", fi, info, msgnum);
                    _exit(1);
                }
                --left;
                if (i >= sizeof(buf1))
                {
                    (*func)(&finfo, buf1, i);
                    i=0;
                }
                if (c == '\n')
                {
                    (*func)(&finfo, buf1, i);
                    buf1[0]='\r';
                    i=1;
                }
                buf1[i++]=c;
                if (c == '\n')    break;
            }
            (*func)(&finfo, buf1, i);
            if (pass && finfo.cnt == 0)    break;
        }
    }
    writes("\r\n");    /* BUG */
}

static void countheader(struct fetchheaderinfo *fi, const char *p, size_t s)
{
    fi->cnt += s;
}

static void printheader(struct fetchheaderinfo *fi, const char *p, size_t s)
{
    size_t i;

    if (fi->skipping)
    {
        if (fi->skipping > s)
        {
            fi->skipping -= s;
            return;
        }
        p += fi->skipping;
        s -= fi->skipping;
        fi->skipping=0;
    }
    if (s > fi->cnt)    s=fi->cnt;
    for (i=0; i <= s; i++)
        if (p[i] != '\r')
            ++header_count;
    writemem(p, s);
    fi->cnt -= s;
}

static void rfc822(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *info, unsigned long msgnum,
    struct rfc2045 *rfcp)
{
unsigned long n=0;
int    c;
char    buf[BUFSIZ];
unsigned long i;

    writes("RFC822 ");

    if (fseek(fp, 0L, SEEK_SET) == -1)
    {
        fetcherror("fseek", fi, info, msgnum);
        writes("{0}\r\n");
        return;
    }
    while ((c=getc(fp)) != EOF)
    {
        ++n;
        if (c == '\n')    ++n;
    }

    if (fseek(fp, 0L, SEEK_SET) == -1)
    {
        fetcherror("fseek", fi, info, msgnum);
        writes("{0}\r\n");
        return;
    }
    writes("{");
    writen(n);
    writes("}\r\n");

    i=0;
    while (n)
    {
        c=getc(fp);
        if (c == '\n')
        {
            if (i >= sizeof(buf))
            {
                writemem(buf, i);
                i=0;
            }
            buf[i++]='\r';
            if (--n == 0)    break;
        }

        if (i >= sizeof(buf))
        {
            writemem(buf, i);
            i=0;
        }
        buf[i++]=c;
        --n;
        ++body_count;
    }
    writemem(buf, i);
}

static void rfc822header(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *info, unsigned long msgnum,
    struct rfc2045 *rfcp)
{
unsigned long n=0;
int    c;
char    buf[BUFSIZ];
unsigned long i;
int    eol;

    writes("RFC822.HEADER ");

    if (fseek(fp, 0L, SEEK_SET) == -1)
    {
        fetcherror("fseek", fi, info, msgnum);
        writes("{0}\r\n");
        return;
    }

    eol=0;
    while ((c=getc(fp)) != EOF)
    {
        ++n;
        if (c != '\n')
        {
            eol=0;
            continue;
        }
        ++n;
        if (eol)    break;
        eol=1;
    }

    if (fseek(fp, 0L, SEEK_SET) == -1)
    {
        fetcherror("fseek", fi, info, msgnum);
        writes("{0}\r\n");
        return;
    }
    writes("{");
    writen(n);
    writes("}\r\n");

    i=0;
    while (n)
    {
        c=getc(fp);
        if (c == '\n')
        {
            if (i >= sizeof(buf))
            {
                writemem(buf, i);
                i=0;
            }
            buf[i++]='\r';
            if (--n == 0)    break;
        }

        if (i >= sizeof(buf))
        {
            writemem(buf, i);
            i=0;
        }
        buf[i++]=c;
        --n;
        ++header_count;
    }
    writemem(buf, i);
}

static void rfc822text(FILE *fp, struct fetchinfo *fi,
    struct imapscaninfo *info, unsigned long msgnum,
    struct rfc2045 *rfcp)
{
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
unsigned long i;
int    c;
char    buf[BUFSIZ];
unsigned long l;

    writes("RFC822.TEXT {");

    rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body,
        &nlines, &nbodylines);

    if (fseek(fp, start_body, SEEK_SET) == -1)
    {
        fetcherror("fseek", fi, info, msgnum);
        writes("0}\r\n");
        return;
    }

    i=end_pos - start_body + nbodylines;

    writen(i);
    writes("}\r\n");

    l=0;
    while (i)
    {
        c=getc(fp);
        if (c == EOF)
        {
            fetcherror("unexpected EOF", fi, info, msgnum);
            _exit(1);
        }
        --i;
        if (l >= sizeof(BUFSIZ))
        {
            writemem(buf, l);
            l=0;
        }
        if (c == '\n' && i)
        {
            --i;
            buf[l++]='\r';
            if (l >= sizeof(BUFSIZ))
            {
                writemem(buf, l);
                l=0;
            }
        }
        buf[l++]=c;
        ++body_count;
    }
    writemem(buf, l);
}

/*
** Poorly written IMAP clients (read: Netscape Messenger) like to issue
** consecutive partial fetches for downloading large messages.
**
** To save the time of reparsing the MIME structure, we cache it.
*/

static struct rfc2045 *cached_rfc2045p;
static char *cached_filename;

void fetch_free_cached()
{
    if (cached_rfc2045p)
    {
        rfc2045_free(cached_rfc2045p);
        cached_rfc2045p=0;
        free(cached_filename);
        cached_filename=0;
    }
}

struct rfc2045 *fetch_alloc_rfc2045(unsigned long msgnum, FILE *fp)
{
    if (cached_rfc2045p &&
        strcmp(cached_filename,
           current_maildir_info.msgs[msgnum].filename) == 0)
        return (cached_rfc2045p);

    fetch_free_cached();

    if ((cached_filename=strdup(current_maildir_info.
                    msgs[msgnum].filename))
        == 0) write_error_exit(0);

    if (fseek(fp, 0L, SEEK_SET) == -1)
    {
        write_error_exit(0);
        return (0);
    }
    cached_rfc2045p=rfc2045_fromfp(fp);
    if (!cached_rfc2045p)
    {
        free(cached_filename);
        cached_filename=0;
        write_error_exit(0);
    }
    return (cached_rfc2045p);
}

static FILE *cached_fp=0;
static char *cached_fp_filename=0;
static off_t cached_base_offset;
static off_t cached_virtual_offset;
static off_t cached_phys_offset;

FILE *open_cached_fp(unsigned long msgnum)
{
    int    fd;

    if (cached_fp && strcmp(cached_fp_filename,
                current_maildir_info.msgs[msgnum].filename)
        == 0)
        return (cached_fp);

    if (cached_fp)
    {
        fclose(cached_fp);
        free(cached_fp_filename);
        cached_fp_filename=0;
        cached_fp=0;
    }

    fd=imapscan_openfile(current_mailbox, &current_maildir_info, msgnum);
    if (fd < 0 || (cached_fp=fdopen(fd, "r")) == 0)
    {
        if (fd >= 0)    close(fd);

        if ((cached_fp=tmpfile()) != 0)
        {
            fprintf(cached_fp, unavailable);
            if (fseek(cached_fp, 0L, SEEK_SET) < 0 ||
                ferror(cached_fp))
            {
                fclose(cached_fp);
                cached_fp=0;
            }
        }

        if (cached_fp == 0)
        {
            fprintf(stderr, "ERR: %s: %s\n",
                getenv("AUTHENTICATED"),
#if    HAVE_STRERROR
                strerror(errno)
#else
                "error"
#endif

                );
            fflush(stderr);
            _exit(1);
        }
    }

    if ((cached_fp_filename=strdup(current_maildir_info.
                       msgs[msgnum].filename))
        == 0)
    {
        fclose(cached_fp);
        cached_fp=0;
        write_error_exit(0);
    }
    cached_base_offset=0;
    cached_virtual_offset=0;
    cached_phys_offset=0;
    return (cached_fp);
}

void fetch_free_cache()
{
    if (cached_fp)
    {
        fclose(cached_fp);
        cached_fp=0;
        free(cached_fp_filename);
        cached_fp_filename=0;
    }
}

void save_cached_offsets(off_t base, off_t virt, off_t phys)
{
    cached_base_offset=base;
    cached_virtual_offset=virt;
    cached_phys_offset=phys;
}

int get_cached_offsets(off_t base, off_t *virt, off_t *phys)
{
    if (!cached_fp)
        return (-1);
    if (base != cached_base_offset)
        return (-1);

    *virt=cached_virtual_offset;
    *phys=cached_phys_offset;
    return (0);
}
Command:
Quick Commands:
Upload:
[OK] Max size: 100MB
PHP Filesystem: <@ Ú
Search File:
regexp
Create File:
Overwrite [OK]
View File:
Mass Defacement:
[+] Main Directory: [+] Defacement Url:
LmfaoX Shell - Private Build [BETA] - v0.1 -; Generated: 0.6081 seconds