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.49 GB of 70.42 GB (34.77%)
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/ maildir/ - drwxrwxrwx

Directory:
Viewing file:     maildirshared.c (16.56 KB)      -rw-rw-rw-
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 2000-2007 Double Precision, Inc.
** See COPYING for distribution information.
*/

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

#include <sys/types.h>
#if HAVE_DIRENT_H
#include <dirent.h>
#define NAMLEN(dirent) strlen((dirent)->d_name)
#else
#define dirent direct
#define NAMLEN(dirent) (dirent)->d_namlen
#if HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif
#if HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif
#if HAVE_NDIR_H
#include <ndir.h>
#endif
#endif
#include    <sys/types.h>
#include    <sys/stat.h>
#include    <string.h>
#include    <stdlib.h>
#include    <time.h>
#if    HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    <stdio.h>
#include    <ctype.h>
#include    <errno.h>
#include    <fcntl.h>

#include    "maildirmisc.h"
#include    "maildircreate.h"
#include    "maildirsharedrc.h"


/* Prerequisited for shared folder support */

#if    HAVE_READLINK
#if    HAVE_SYMLINK
#if    HAVE_DBOBJ

#define    YES_WE_CAN_DO_SHARED    1

#endif
#endif
#endif

#if    YES_WE_CAN_DO_SHARED

#include    "dbobj.h"

static void list_sharable(const char *, const char *,
    void (*)(const char *, void *),
    void *);

extern FILE *maildir_shared_fopen(const char *, const char *);
extern void maildir_shared_fparse(char *, char **, char **);

void maildir_list_sharable(const char *maildir,
    void (*func)(const char *, void *),
    void *voidp)
{
char    buf[BUFSIZ];
FILE    *fp;
char    *p;
int    pass;

    if (!maildir)    maildir=".";

    for (pass=0; pass<2; pass++)
    {
        fp=pass ? maildir_shared_fopen(maildir, "r")
            : fopen (MAILDIRSHAREDRC, "r");

        if (!fp)    continue;

        while ((p=fgets(buf, sizeof(buf), fp)) != 0)
        {
        char    *name, *dir;

            maildir_shared_fparse(p, &name, &dir);
            if (name)
                list_sharable(name, dir, func, voidp);
        }
        fclose(fp);
    }
}

static void list_sharable(const char *pfix, const char *path,
    void (*func)(const char *, void *),
    void *voidp)
{
DIR    *dirp;
struct    dirent *de;
struct    stat    stat_buf;

    dirp=opendir(path);
    while (dirp && (de=readdir(dirp)) != 0)
    {
    char    *z;

        if (de->d_name[0] != '.')    continue;
        if (strcmp(de->d_name, ".") == 0 ||
            strcmp(de->d_name, "..") == 0)    continue;

        z=malloc(strlen(path)+strlen(de->d_name)+12);
        if (!z)    continue;

        strcat(strcat(strcat(strcpy(z, path),
            "/"), de->d_name), "/cur/.");

        if (stat(z, &stat_buf))
        {
            free(z);
            continue;
        }
        free(z);
        z=malloc(strlen(pfix)+strlen(de->d_name)+1);
        if (!z)    continue;
        strcat(strcpy(z, pfix), de->d_name);
        (*func)(z, voidp);
        free(z);
    }
    if (dirp)    closedir(dirp);
}

int maildir_shared_subscribe(const char *maildir, const char *folder)
{
char    linebuf[BUFSIZ];
FILE    *fp;
char    *p;
char    *name=strchr(folder, '.');
char    *s, *n, *dir;
char    *buf, *link;
unsigned l;
int    pass;

    if (!name)
    {
        errno=EINVAL;
        return (-1);
    }

    if (!maildir)    maildir=".";
    p=maildir_shareddir(maildir, folder);    /* valid folder name? */
    if (!p)
    {
        errno=EINVAL;
        return (-1);
    }
    free(p);

    p=0;

    for (pass=0; pass<2; pass++)
    {
        fp=pass ? maildir_shared_fopen(maildir, "r")
            : fopen (MAILDIRSHAREDRC, "r");

        if (!fp)    continue;

        while ((p=fgets(linebuf, sizeof(linebuf), fp)) != 0)
        {
            maildir_shared_fparse(p, &n, &dir);

            if (!n)    continue;

            if (strlen(n) == name - folder &&
                memcmp(n, folder, name-folder) == 0)    break;
        }
        fclose(fp);

        if (p)    break;
    }

    if (p)
    {
        /*
        ** We will create:
        **
        **  maildir/shared-folders/ (name-folder) /(name)
        **
        **  there we'll have subdirs cur/new/tmp  and shared link
        */

        l=sizeof("/" SHAREDSUBDIR "//shared") +
            strlen(maildir) + strlen(folder);
        buf=malloc(l);
        if (!buf)    return (-1);
        strcat(strcpy(buf, maildir), "/" SHAREDSUBDIR);
        mkdir(buf, 0700);
        strcat(buf, "/");
        strncat(buf, folder, name-folder);
        mkdir(buf, 0700);
        strcat(buf, "/");
        strcat(buf, name+1);
        if ( mkdir(buf, 0700))    return (-1);
        s=buf+strlen(buf);
        *s++='/';
        strcpy(s, "tmp");
        if ( mkdir(buf, 0700))
        {
            s[-1]=0;
            rmdir(buf);
            free(buf);
            return (-1);
        }
        strcpy(s, "cur");
        if ( mkdir(buf, 0700))
        {
            strcpy(s, "tmp");
            rmdir(buf);
            s[-1]=0;
            rmdir(buf);
            free(buf);
            return (-1);
        }
        strcpy(s, "new");
        if ( mkdir(buf, 0700))
        {
            strcpy(s, "cur");
            rmdir(buf);
            strcpy(s, "tmp");
            rmdir(buf);
            s[-1]=0;
            rmdir(buf);
            free(buf);
            return (-1);
        }

        strcpy(s, "shared");
        if ((link=malloc(strlen(dir)+strlen(name)+2)) == 0 ||
            symlink( strcat(strcat(strcpy(link, dir), "/"), name),
                buf))
        {
            if (link)    free(link);
            strcpy(s, "new");
            rmdir(buf);
            strcpy(s, "cur");
            rmdir(buf);
            strcpy(s, "tmp");
            rmdir(buf);
            s[-1]=0;
            rmdir(buf);
            free(buf);
            return (-1);
        }
        free(link);
        free(buf);
        return (0);
    }
    errno=ENOENT;
    return (-1);
}

void maildir_list_shared(const char *maildir,
    void (*func)(const char *, void *),
    void *voidp)
{
char    *sh;
DIR    *dirp;
struct    dirent *de;

    if (!maildir)    maildir=".";
    sh=malloc(strlen(maildir)+sizeof("/" SHAREDSUBDIR));
    if (!sh)    return;

    strcat(strcpy(sh, maildir), "/" SHAREDSUBDIR);

    dirp=opendir(sh);
    while (dirp && (de=readdir(dirp)) != 0)
    {
    DIR    *dirp2;
    struct    dirent *de2;
    char    *z;

        if (de->d_name[0] == '.')    continue;

        z=malloc(strlen(sh)+strlen(de->d_name)+2);
        if (!z)    continue;
        strcat(strcat(strcpy(z, sh), "/"), de->d_name);
        dirp2=opendir(z);
        free(z);

        while (dirp2 && (de2=readdir(dirp2)) != 0)
        {
        char    *s;

            if (de2->d_name[0] == '.')    continue;
            s=malloc(strlen(de->d_name)+strlen(de2->d_name)+2);
            if (!s)    continue;
            strcat(strcat(strcpy(s, de->d_name), "."), de2->d_name);
            (*func)(s, voidp);
            free(s);
        }
        if (dirp2)    closedir(dirp2);
    }
    free(sh);
    if (dirp)    closedir(dirp);
}

int maildir_shared_unsubscribe(const char *maildir, const char *folder)
{
char    *s;

    s=maildir_shareddir(maildir, folder);
    if (!s)    return (-1);

    if (maildir_del(s))
    {
        free(s);
        return (-1);
    }
    *strrchr(s, '/')=0;    /* Try to remove the whole folder dir */
    rmdir(s);
    free(s);
    return (0);
}

/*                    LET'S SYNC IT                  */

static void do_maildir_shared_sync(const char *, const char *);

void maildir_shared_sync(const char *dir)
{
char    *shareddir;
char    *buf;

    shareddir=malloc(strlen(dir)+sizeof("/shared"));
    if (!shareddir)
    {
        perror("malloc");
        return;
    }
    strcat(strcpy(shareddir, dir),"/shared");

    buf=maildir_getlink(shareddir);
    free(shareddir);
    if (buf)
    {
        do_maildir_shared_sync(dir, buf);
        free(buf);
    }
}

/* Step 1 - safely create a temporary database */

static int create_db(struct dbobj *obj,
    const char *dir,
    char **dbname)
{
    struct maildir_tmpcreate_info createInfo;

    maildir_tmpcreate_init(&createInfo);

    createInfo.maildir=dir;
    createInfo.uniq="sync";
    createInfo.doordie=1;

    {
        int    fd;

        fd=maildir_tmpcreate_fd(&createInfo);

        if (fd < 0)
        {
            perror(dir);
            return -1;
        }
        close(fd);

        dbobj_init(obj);
        if (dbobj_open(obj, createInfo.tmpname, "N") < 0)
        {
            perror(createInfo.tmpname);
            unlink(createInfo.tmpname);
            maildir_tmpcreate_free(&createInfo);
            return (-1);
        }
    }

    *dbname=createInfo.tmpname;
    createInfo.tmpname=NULL;
    maildir_tmpcreate_free(&createInfo);
    return (0);
}

/*
** Populate the DB by building the db with the messages in the sharable
** folder's cur.  The key is the stripped message filename, the value is
** the complete message filename.
*/

static int build_db(const char *shared, struct dbobj *obj)
{
char    *dummy=malloc(strlen(shared)+sizeof("/cur"));
DIR    *dirp;
struct    dirent *de;

    if (!dummy)
    {
        perror("malloc");
        return (-1);
    }

    strcat(strcpy(dummy, shared), "/cur");

    dirp=opendir(dummy);
    while (dirp && (de=readdir(dirp)) != 0)
    {
    char    *a, *b;
    char    *c;

        if (de->d_name[0] == '.')
            continue;
        if ((a=malloc(strlen(de->d_name)+1)) == 0)
        {
            perror("malloc");
            closedir(dirp);
            free(dummy);
            return (-1);
        }
        if ((b=malloc(strlen(de->d_name)+1)) == 0)
        {
            perror("malloc");
            closedir(dirp);
            free(dummy);
            free(a);
            return (-1);
        }
        strcpy(a, de->d_name);
        strcpy(b, de->d_name);
        c=strrchr(a, MDIRSEP[0]);
        if (c)    *c=0;

        if (dbobj_store(obj, a, strlen(a), b, strlen(b), "R"))
        {
            perror("dbobj_store");
            free(a);
            free(b);
            closedir(dirp);
            free(dummy);
            return (-1);
        }
        free(a);
        free(b);
    }
    if (dirp)    closedir(dirp);
    free(dummy);
    return (0);
}

static int update_link(const char *,
    const char *, const char *,
    const char *,
    const char *,
    size_t);

/*
**    Now, read our synced cur directory, and make sure that the soft
**    links are up to date.  Remove messages that have been deleted from
**    the sharable maildir, and make sure that the remaining links are
**    valid.
*/

static int update_cur(const char *cur, const char *shared, struct dbobj *obj)
{
DIR    *dirp;
struct    dirent *de;
char    *p;

    dirp=opendir(cur);
    while (dirp && (de=readdir(dirp)) != 0)
    {
    char    *cur_base;

    char    *cur_name_ptr;
    size_t    cur_name_len;

    char    *linked_name_buf;
    size_t    linked_name_len;
    int    n;

        if (de->d_name[0] == '.')    continue;

        /*
        ** Strip the maildir flags, and look up the message in the
        ** db.
        */

        cur_base=malloc(strlen(de->d_name)+1);
        if (!cur_base)
        {
            perror("malloc");
            closedir(dirp);
            return (-1);
        }
        strcpy(cur_base, de->d_name);
        p=strrchr(cur_base, MDIRSEP[0]);
        if (p)    *p=0;

        cur_name_ptr=dbobj_fetch(obj, cur_base, strlen(cur_base),
            &cur_name_len, "");

        /* If it's there, delete the db entry. */

        if (cur_name_ptr)
            dbobj_delete(obj, cur_base, strlen(cur_base));

        /*
        ** We'll either delete this soft link, or check its
        ** contents, so we better build its complete pathname in
        ** any case.
        */

        free(cur_base);
        cur_base=malloc(strlen(de->d_name)+strlen(cur)+2);
        if (!cur_base)
        {
            perror("malloc");
            if (cur_name_ptr)    free(cur_name_ptr);
            closedir(dirp);
            return (-1);
        }
        strcat(strcat(strcpy(cur_base, cur), "/"), de->d_name);

        if (!cur_name_ptr)    /* Removed from sharable dir */
        {
            unlink(cur_base);
            free(cur_base);
            continue;
        }

        linked_name_len=strlen(shared)+strlen(de->d_name)+100;
            /* should be enough */

        if ((linked_name_buf=malloc(linked_name_len)) == 0)
        {
            perror("malloc");
            free(cur_base);
            free(cur_name_ptr);
            closedir(dirp);
            return (-1);
        }

        if ((n=readlink(cur_base, linked_name_buf, linked_name_len))< 0)
        {
            /* This is stupid, let's just unlink this nonsense */

            n=0;
        }

        if (n == 0 || n >= linked_name_len ||
            (linked_name_buf[n]=0,
            update_link(cur,
                cur_base, linked_name_buf, shared, cur_name_ptr,
                cur_name_len)))
        {
            unlink(cur_base);
            free(linked_name_buf);
            free(cur_base);
            free(cur_name_ptr);
            closedir(dirp);
            return (-1);
        }
        free(cur_base);
        free(linked_name_buf);
        free(cur_name_ptr);
    }
    if (dirp)    closedir(dirp);
    return (0);
}

/* Update the link pointer */

static int update_link(const char *curdir,
    const char *linkname, const char *linkvalue,
    const char *shareddir,
    const char *msgfilename,
    size_t msgfilenamelen)
{
    char    *p=malloc(strlen(shareddir)+sizeof("/cur/")+msgfilenamelen);
    char    *q;
    int    fd;
    struct maildir_tmpcreate_info createInfo;

    if (!p)
    {
        perror("malloc");
        return (-1);
    }

    strcat(strcpy(p, shareddir), "/cur/");
    q=p+strlen(p);
    memcpy(q, msgfilename, msgfilenamelen);
    q[msgfilenamelen]=0;

    if (linkvalue && strcmp(p, linkvalue) == 0)
    {
        /* the link is good */

        free(p);
        return (0);
    }

    /* Ok, we want this to be an atomic operation. */

    maildir_tmpcreate_init(&createInfo);
    createInfo.maildir=curdir;
    createInfo.uniq="relink";
    createInfo.doordie=1;

    if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
        return -1;

    close(fd);
    unlink(createInfo.tmpname);

    if (symlink(p, createInfo.tmpname) < 0 ||
        rename(createInfo.tmpname, linkname) < 0)
    {
        perror(createInfo.tmpname);
        maildir_tmpcreate_free(&createInfo);
        return (-1);
    }

    maildir_tmpcreate_free(&createInfo);
    return (0);
}

/* and now, anything that's left in the temporary db must be new messages */

static int newmsgs(const char *cur, const char *shared, struct dbobj *obj)
{
    char    *key, *val;
    size_t    keylen, vallen;
    int fd;
    struct maildir_tmpcreate_info createInfo;

    maildir_tmpcreate_init(&createInfo);
    createInfo.maildir=cur;
    createInfo.uniq="newlink";
    createInfo.doordie=1;

    if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
        return -1;
    close(fd);

    unlink(createInfo.tmpname);

    for (key=dbobj_firstkey(obj, &keylen, &val, &vallen); key;
        key=dbobj_nextkey(obj, &keylen, &val, &vallen))
    {
    char    *slink=malloc(strlen(shared)+sizeof("/cur/")+vallen);
    char    *q;

        if (!slink)
        {
            free(val);
            maildir_tmpcreate_free(&createInfo);
            return (-1);
        }

        strcat(strcpy(slink, shared), "/cur/");
        q=slink+strlen(slink);
        memcpy(q, val, vallen);
        q[vallen]=0;
        free(val);

        if (symlink(slink, createInfo.tmpname))
        {
            perror(createInfo.tmpname);

            free(slink);
            maildir_tmpcreate_free(&createInfo);
            return (-1);
        }

        free(slink);
        slink=malloc(strlen(cur)+sizeof("/new/" MDIRSEP "2,")+keylen);
        if (!slink)
        {
            perror("malloc");
            maildir_tmpcreate_free(&createInfo);
            return (-1);
        }

        strcat(strcpy(slink, cur), "/new/");
        q=slink+strlen(slink);
        memcpy(q, key, keylen);
        strcpy(q+keylen, MDIRSEP "2,");

        if (rename(createInfo.tmpname, slink))
        {
            free(slink);
            maildir_tmpcreate_free(&createInfo);
            return (-1);
        }
        free(slink);
    }
    maildir_tmpcreate_free(&createInfo);
    return (0);
}

static void do_maildir_shared_sync(const char *dir, const char *shared)
{
struct    dbobj obj;
char    *dbname;
char    *cur;
char    *shared_update_name;

struct    stat    stat1, stat2;
int    fd;

    maildir_purgetmp(dir);    /* clean up after myself */
    maildir_getnew(dir, 0, NULL, NULL);

    maildir_purgetmp(shared);
    maildir_getnew(shared, 0, NULL, NULL);

    /* Figure out if we REALLY need to sync something */

    shared_update_name=malloc(strlen(dir)+sizeof("/shared-timestamp"));
    if (!shared_update_name)    return;
    strcat(strcpy(shared_update_name, dir), "/shared-timestamp");
    cur=malloc(strlen(shared)+sizeof("/new"));
    if (!cur)
    {
        free(shared_update_name);
        return;
    }

    if (stat(shared_update_name, &stat1) == 0)
    {
        if ( stat( strcat(strcpy(cur, shared), "/new"), &stat2) == 0 &&
            stat2.st_mtime < stat1.st_mtime &&
            stat( strcat(strcpy(cur, shared), "/cur"), &stat2)
            == 0 && stat2.st_mtime < stat1.st_mtime)
        {
            free(shared_update_name);
            free(cur);
            return;
        }
    }
    if ((fd=maildir_safeopen(shared_update_name, O_RDWR|O_CREAT, 0600))>= 0)
    {
        if (write(fd, "", 1) < 0)
            perror("write");
        close(fd);
    }

    free(cur);
    free(shared_update_name);

    if (create_db(&obj, dir, &dbname))    return;

    if (build_db(shared, &obj))
    {
        dbobj_close(&obj);
        unlink(dbname);
        free(dbname);
        return;
    }

    if ((cur=malloc(strlen(dir)+sizeof("/cur"))) == 0)
    {
        perror("malloc");
        dbobj_close(&obj);
        unlink(dbname);
        free(dbname);
        return;
    }
    strcat(strcpy(cur, dir), "/cur");
    if (update_cur(cur, shared, &obj) == 0)
    {
        strcat(strcpy(cur, dir), "/new");
        if (update_cur(cur, shared, &obj) == 0)
        {
            *strrchr(cur, '/')=0;    /* Chop off the /new */
            newmsgs(cur, shared, &obj);
        }
    }

    free(cur);
    dbobj_close(&obj);
    unlink(dbname);
    free(dbname);
}

int maildir_sharedisro(const char *maildir)
{
char    *p=malloc(strlen(maildir)+sizeof("/shared/cur"));

    if (!p)
    {
        perror("malloc");
        return (-1);
    }
    strcat(strcpy(p, maildir), "/shared/cur");

    if (access(p, W_OK) == 0)
    {
        free(p);
        return (0);
    }
    free(p);
    return (1);
}

int maildir_unlinksharedmsg(const char *filename)
{
char    *buf=maildir_getlink(filename);

    if (buf)
    {
        struct stat stat_buf;
        int rc=unlink(buf);

        /*
        ** If we FAILED to unlink the real message in the real
        ** sharable folder, but the message still exists, it means
        ** that we do not have the permission to do so, so do not
        ** purge this folder.  Instead, remove the T flag from
        ** this message.
        */

        if (rc && stat(buf, &stat_buf) == 0)
        {
            char *cpy=strdup(filename);

            if (cpy)
            {
                char *p=strrchr(cpy, MDIRSEP[0]);

                if (p && strchr(p, '/') == 0 &&
                    strncmp(p, MDIRSEP "2,", 3) == 0 &&
                    (p=strchr(p, 'T')) != 0)
                {
                    while ((*p=p[1]) != 0)
                        ++p;
                    rename(filename, cpy);
                }
                free(cpy);
            }
                        
            free(buf);
            return (0);
        }
        free(buf);
    }
    unlink(filename);
    return (0);
}


#else

/* We cannot implement sharing */

void maildir_list_sharable(const char *maildir,
    void (*func)(const char *, void *),
    void *voidp)
{
}

int maildir_shared_subscribe(const char *maildir, const char *folder)
{
    errno=EINVAL;
    return (-1);
}

void maildir_list_shared(const char *maildir,
    void (*func)(const char *, void *),
    void *voidp)
{
}

int maildir_shared_unsubscribe(const char *maildir, const char *folder)
{
    errno=EINVAL;
    return (-1);
}

#if 0
char *maildir_shareddir(const char *maildir, const char *sharedname)
{
    errno=EINVAL;
    return (0);
}
#endif

void maildir_shared_sync(const char *maildir)
{
}

int maildir_sharedisro(const char *maildir)
{
    return (-1);
}

int maildir_unlinksharedmsg(const char *filename)
{
    return (-1);
}
#endif
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.3126 seconds