示例#1
0
/*
 * Check to see if mailbox can be appended to
 *
 * Arguments:
 *      name       - name of mailbox directory
 *      aclcheck   - user must have these rights on mailbox ACL
 *      quotastorage_check - mailbox must have this much storage quota left
 *                   (-1 means don't care about quota)
 *      quotamessage_check - mailbox must have this much message quota left
 *                   (-1 means don't care about quota)
 *
 */
EXPORTED int append_check(const char *name,
                 struct auth_state *auth_state,
                 long aclcheck,
                 const quota_t quotacheck[QUOTA_NUMRESOURCES])
{
    struct mailbox *mailbox = NULL;
    int myrights;
    int r;

    r = mailbox_open_irl(name, &mailbox);
    if (r) return r;

    myrights = cyrus_acl_myrights(auth_state, mailbox->acl);

    if ((myrights & aclcheck) != aclcheck) {
        r = (myrights & ACL_LOOKUP) ?
          IMAP_PERMISSION_DENIED : IMAP_MAILBOX_NONEXISTENT;
        goto done;
    }

    if (quotacheck)
        r = mailbox_quota_check(mailbox, quotacheck);

done:
    mailbox_close(&mailbox);

    return r;
}
示例#2
0
static int do_unuser(const char *userid)
{
    const char *cmd = "UNUSER";
    struct mailbox *mailbox = NULL;
    char buf[MAX_MAILBOX_BUFFER];
    struct dlist *kl;
    int r;

    /* check local mailbox first */
    (sync_namespace.mboxname_tointernal)(&sync_namespace, "INBOX",
					  userid, buf);
    r = mailbox_open_irl(buf, &mailbox);

    /* only remove from server if there's no local mailbox */
    if (r == IMAP_MAILBOX_NONEXISTENT) {
	kl = dlist_setatom(NULL, cmd, userid);
	sync_send_apply(kl, sync_out);
	dlist_free(&kl);

	r = sync_parse_response(cmd, sync_in, NULL);
	if (r == IMAP_MAILBOX_NONEXISTENT) r = 0;
    }

    mailbox_close(&mailbox);

    return r;
}
示例#3
0
static int do_unuser(const char *userid)
{
    const char *cmd = "UNUSER";
    struct mailbox *mailbox = NULL;
    struct dlist *kl;
    int r;

    /* nothing to do if there's no userid */
    if (!userid || !userid[0]) {
        syslog(LOG_WARNING, "ignoring attempt to %s() without userid", __func__);
        return 0;
    }

    /* check local mailbox first */
    char *inbox = mboxname_user_mbox(userid, NULL);
    r = mailbox_open_irl(inbox, &mailbox);

    /* only remove from server if there's no local mailbox */
    if (r == IMAP_MAILBOX_NONEXISTENT) {
        kl = dlist_setatom(NULL, cmd, userid);
        sync_send_apply(kl, sync_out);
        dlist_free(&kl);

        r = sync_parse_response(cmd, sync_in, NULL);
        if (r == IMAP_MAILBOX_NONEXISTENT) r = 0;
    }

    mailbox_close(&mailbox);
    free(inbox);

    return r;
}
示例#4
0
static int do_unmailbox(const char *mboxname, struct backend *sync_be,
                        unsigned flags)
{
    struct mailbox *mailbox = NULL;
    int r;

    r = mailbox_open_irl(mboxname, &mailbox);
    if (r == IMAP_MAILBOX_NONEXISTENT) {
        r = sync_folder_delete(mboxname, sync_be, flags);
        if (r) {
            syslog(LOG_ERR, "folder_delete(): failed: %s '%s'",
                   mboxname, error_message(r));
        }
    }
    mailbox_close(&mailbox);

    return r;
}
示例#5
0
static int index_single_message(const char *mboxname, uint32_t uid)
{
    int r;
    struct mailbox *mailbox = NULL;
    message_t *msg = NULL;
    int begun = 0;
    struct index_record record;

    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) goto out;

    r = rx->begin_mailbox(rx, mailbox, SEARCH_UPDATE_INCREMENTAL);
    if (r) goto out;
    begun = 1;

    r = mailbox_find_index_record(mailbox, uid, &record);
    if (r) goto out;

    if (record.system_flags & (FLAG_EXPUNGED|FLAG_UNLINKED)) goto out;

    msg = message_new_from_record(mailbox, &record);
    if (!msg) goto out;

    if (rx->is_indexed(rx, msg))
        goto out;

    if (verbose) fprintf(stderr, "squatter: indexing mailbox:%s uid:%u\n",
                         mboxname, uid);

    r = index_getsearchtext(msg, rx, 0);

out:
    if (begun) {
        int r2 = rx->end_mailbox(rx, mailbox);
        if (r2 && !r) r = r2;
    }
    message_unref(&msg);
    mailbox_close(&mailbox);
    return r;
}
示例#6
0
static int do_search(const char *query, int single, const strarray_t *mboxnames)
{
    struct mailbox *mailbox = NULL;
    int i;
    int r;
    search_builder_t *bx;
    int opts = SEARCH_VERBOSE(verbose);

    if (!single)
        opts |= SEARCH_MULTIPLE;

    for (i = 0 ; i < mboxnames->count ; i++) {
        const char *mboxname = mboxnames->data[i];

        r = mailbox_open_irl(mboxname, &mailbox);
        if (r) {
            fprintf(stderr, "Cannot open mailbox %s: %s\n",
                    mboxname, error_message(r));
            continue;
        }
        if (single)
            printf("mailbox %s\n", mboxname);

        bx = search_begin_search(mailbox, opts);
        if (bx) {
            r = squatter_build_query(bx, query);
            if (!r)
                r = bx->run(bx, print_search_hit, &single);
            search_end_search(bx);
        }

        mailbox_close(&mailbox);
    }

    return 0;
}
示例#7
0
/* This is called once for each mailbox we're told to index. */
static int index_one(const char *name, int blocking)
{
    mbentry_t *mbentry = NULL;
    struct mailbox *mailbox = NULL;
    int r;
    int flags = 0;

    if (incremental_mode)
        flags |= SEARCH_UPDATE_INCREMENTAL;

    /* Convert internal name to external */
    char *extname = mboxname_to_external(name, &squat_namespace, NULL);

    /* Skip remote mailboxes */
    r = mboxlist_lookup(name, &mbentry, NULL);
    if (r) {
        if (verbose) {
            printf("error looking up %s: %s\n",
                   extname, error_message(r));
        }
        syslog(LOG_INFO, "error looking up %s: %s\n",
               extname, error_message(r));

        free(extname);
        return r;
    }
    if (mbentry->mbtype & MBTYPE_REMOTE) {
        mboxlist_entry_free(&mbentry);
        free(extname);
        return 0;
    }

    mboxlist_entry_free(&mbentry);

    /* make sure the mailbox (or an ancestor) has
       /vendor/cmu/cyrus-imapd/squat set to "true" */
    if (annotation_flag) {
        char buf[MAX_MAILBOX_BUFFER] = "", *p;
        struct buf attrib = BUF_INITIALIZER;
        int domainlen = 0;

        if (config_virtdomains && (p = strchr(name, '!')))
            domainlen = p - name + 1;

        strlcpy(buf, name, sizeof(buf));

        /* since mailboxes inherit /vendor/cmu/cyrus-imapd/squat,
           we need to iterate all the way up to "" (server entry) */
        while (1) {
            r = annotatemore_lookup(buf, IMAP_ANNOT_NS "squat", "",
                                    &attrib);

            if (r ||                            /* error */
                attrib.s ||                     /* found an entry */
                !buf[0]) {                      /* done recursing */
                break;
            }

            p = strrchr(buf, '.');              /* find parent mailbox */

            if (p && (p - buf > domainlen))     /* don't split subdomain */
                *p = '\0';
            else if (!buf[domainlen])           /* server entry */
                buf[0] = '\0';
            else                                /* domain entry */
                buf[domainlen] = '\0';
        }

        if (r || !attrib.s || strcasecmp(attrib.s, "true")) {
            buf_free(&attrib);
            free(extname);
            return 0;
        }
        buf_free(&attrib);
    }

again:
    if (blocking)
        r = mailbox_open_irl(name, &mailbox);
    else
        r = mailbox_open_irlnb(name, &mailbox);

    if (r == IMAP_MAILBOX_LOCKED) {
        if (verbose) syslog(LOG_INFO, "mailbox %s locked, retrying", extname);
        free(extname);
        return r;
    }
    if (r) {
        if (verbose) {
            printf("error opening %s: %s\n", extname, error_message(r));
        }
        syslog(LOG_INFO, "error opening %s: %s\n", extname, error_message(r));
        free(extname);

        return r;
    }

    syslog(LOG_INFO, "indexing mailbox %s... ", extname);
    if (verbose > 0) {
        printf("Indexing mailbox %s... ", extname);
    }

    r = search_update_mailbox(rx, mailbox, flags);

    mailbox_close(&mailbox);

    /* in non-blocking (rolling) mode, only do one batch per mailbox at
     * a time for fairness [IRIS-2471].  The squatter will re-insert the
     * mailbox in the queue */
    if (blocking && r == IMAP_AGAIN) goto again;
    free(extname);

    return r;
}
示例#8
0
static void list_expunged(const char *mboxname)
{
    struct mailbox *mailbox = NULL;
    struct index_record *records = NULL;
    int alloc = 0;
    int num = 0;
    int i;
    int r;

    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) {
        printf("Failed to open mailbox %s: %s",
               mboxname, error_message(r));
        return;
    }

    /* first pass - read the records.  Don't print until we release the
     * lock */
    struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_UNLINKED);
    const message_t *msg;
    while ((msg = mailbox_iter_step(iter))) {
        const struct index_record *record = msg_record(msg);
        /* still active */
        if (!(record->internal_flags & FLAG_INTERNAL_EXPUNGED))
            continue;

        /* pre-allocate more space */
        if (alloc <= num) {
            alloc += 64;
            records = xrealloc(records, sizeof(struct index_record) * alloc);
        }

        records[num] = *record;
        num++;
    }
    mailbox_iter_done(&iter);

    mailbox_unlock_index(mailbox, NULL);

    for (i = 0; i < num; i++) {
        const struct index_record *record = &records[i];
        printf("UID: %u\n", record->uid);
        printf("\tSize: %u\n", record->size);
        printf("\tSent: %s", ctime(&record->sentdate));
        printf("\tRecv: %s", ctime(&record->internaldate));
        printf("\tExpg: %s", ctime(&record->last_updated));

        if (mailbox_cacherecord(mailbox, record)) {
            printf("\tERROR: cache record missing or corrupt, "
                   "not printing cache details\n\n");
            continue;
        }

        printf("\tFrom: %.*s\n", cacheitem_size(record, CACHE_FROM),
                cacheitem_base(record, CACHE_FROM));
        printf("\tTo  : %.*s\n", cacheitem_size(record, CACHE_TO),
                cacheitem_base(record, CACHE_TO));
        printf("\tCc  : %.*s\n", cacheitem_size(record, CACHE_CC),
                cacheitem_base(record, CACHE_CC));
        printf("\tBcc : %.*s\n", cacheitem_size(record, CACHE_BCC),
                cacheitem_base(record, CACHE_BCC));
        printf("\tSubj: %.*s\n\n", cacheitem_size(record, CACHE_SUBJECT),
                cacheitem_base(record, CACHE_SUBJECT));
    }

    free(records);
    mailbox_close(&mailbox);
}
示例#9
0
/*
 * Performs a STATUS command - note: state MAY be NULL here.
 */
int status_lookup(const char *mboxname, const char *userid,
		  unsigned statusitems, struct statusdata *sdata)
{
    struct mailbox *mailbox = NULL;
    unsigned numrecent = 0;
    unsigned numunseen = 0;
    unsigned c_statusitems;
    int r;

    /* Check status cache if possible */
    if (config_getswitch(IMAPOPT_STATUSCACHE)) {
	/* Do actual lookup of cache item. */
	r = statuscache_lookup(mboxname, userid, statusitems, sdata);

	/* Seen/recent status uses "push" invalidation events from
	 * seen_db.c.   This avoids needing to open cyrus.header to get
	 * the mailbox uniqueid to open the seen db and get the
	 * unseen_mtime and recentuid.
	 */

	if (!r) {
	    syslog(LOG_DEBUG, "statuscache, '%s', '%s', '0x%02x', 'yes'",
		   mboxname, userid, statusitems);
	    return 0;
	}

	syslog(LOG_DEBUG, "statuscache, '%s', '%s', '0x%02x', 'no'",
	       mboxname, userid, statusitems);
    }

    /* Missing or invalid cache entry */
    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) return r;

    /* We always have message count, uidnext,
       uidvalidity, and highestmodseq for cache */
     c_statusitems = STATUS_MESSAGES | STATUS_UIDNEXT |
		     STATUS_UIDVALIDITY | STATUS_HIGHESTMODSEQ;

    if (!mailbox->i.exists) {
	/* no messages, so these two must also be zero */
	c_statusitems |= STATUS_RECENT | STATUS_UNSEEN;
    }
    else if (statusitems & (STATUS_RECENT | STATUS_UNSEEN)) {
	/* Read \Seen state */
	struct seqset *seq = NULL;
	uint32_t recno;
	struct index_record record;
	int internalseen = mailbox_internal_seen(mailbox, userid);
	unsigned recentuid;

	if (internalseen) {
	    recentuid = mailbox->i.recentuid;
	} else {
	    struct seen *seendb = NULL;
	    struct seendata sd = SEENDATA_INITIALIZER;

	    r = seen_open(userid, SEEN_CREATE, &seendb);
	    if (!r) r = seen_read(seendb, mailbox->uniqueid, &sd);
	    seen_close(&seendb);
	    if (r) goto done;

	    recentuid = sd.lastuid;
	    seq = seqset_parse(sd.seenuids, NULL, recentuid);
	    seen_freedata(&sd);
	}

	for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	    if (mailbox_read_index_record(mailbox, recno, &record))
		continue;
	    if (record.system_flags & FLAG_EXPUNGED)
		continue;
	    if (record.uid > recentuid)
		numrecent++;
	    if (internalseen) {
		if (!(record.system_flags & FLAG_SEEN))
		    numunseen++;
	    }
	    else {
		if (!seqset_ismember(seq, record.uid))
		    numunseen++;
	    }
	}

	/* we've calculated the correct values for both */
	c_statusitems |= STATUS_RECENT | STATUS_UNSEEN;
    }

    statuscache_fill(sdata, userid, mailbox, c_statusitems,
		     numrecent, numunseen);

    /* cache the new value while unlocking */
    mailbox_unlock_index(mailbox, sdata);

  done:
    mailbox_close(&mailbox);
    return r;
}
示例#10
0
/* config.c stuff */
static int do_remove = 0;

static void usage(void)
{
    fprintf(stderr, "cyr_userseen [-C <altconfig>] -d\n");
    exit(-1);
}

/* Callback for use by delete_seen */
static int deluserseen(const mbentry_t *mbentry, void *rock __attribute__((unused)))
{
    struct mailbox *mailbox = NULL;
    int r = 0;

    r = mailbox_open_irl(mbentry->name, &mailbox);
    if (r) goto done;

    char *userid = mboxname_to_userid(mbentry->name);
    if (userid) {
        printf("removing seen for %s on %s\n", userid, mailbox->name);
        if (do_remove) seen_delete_mailbox(userid, mailbox);
        free(userid);
    }

    mailbox_close(&mailbox);

done:
    return r;
}
示例#11
0
    int r = 0;
    int flag = 0;
    char ext_name_buf[MAX_MAILBOX_PATH+1];
    struct mailbox *mailbox = NULL;
    struct index_record record;
    int j;
    
    signals_poll();

    /* Convert internal name to external */
    (*recon_namespace.mboxname_toexternal)(&recon_namespace, name,
					   "cyrus", ext_name_buf);
    printf("Examining %s...\n", ext_name_buf);

    /* Open/lock header */
    r = mailbox_open_irl(name, &mailbox);
    if (r) return r;

    if (chdir(mailbox_datapath(mailbox)) == -1) {
	r = IMAP_IOERROR;
	goto done;
    }

    printf(" Mailbox Header Info:\n");
    printf("  Path to mailbox: %s\n", mailbox_datapath(mailbox));
    printf("  Mailbox ACL: %s\n", mailbox->acl); /* xxx parse */
    printf("  Unique ID: %s\n", mailbox->uniqueid);
    printf("  User Flags: ");

    for (i = 0; i < MAX_USER_FLAGS; i++) {
	if (!mailbox->flagname[i]) break;
示例#12
0
static void list_expunged(const char *mboxname)
{
    struct mailbox *mailbox = NULL;
    struct index_record *records = NULL;
    struct index_record *record;
    uint32_t recno;
    int alloc = 0;
    int num = 0;
    int i;
    int r;

    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) {
	printf("Failed to open mailbox %s: %s",
	       mboxname, error_message(r));
	return;
    }

    /* first pass - read the records.  Don't print until we release the
     * lock */
    for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	/* pre-allocate more space */
	if (alloc <= num) {
	    alloc += 64;
	    records = xrealloc(records, sizeof(struct index_record) * alloc);
	}
	record = &records[num];

	if (mailbox_read_index_record(mailbox, recno, record))
	    continue;

	/* still active */
	if (!(record->system_flags & FLAG_EXPUNGED))
	    continue;
	/* no file, unrescuable */
	if (record->system_flags & FLAG_UNLINKED)
	    continue;

	num++;
    }

    mailbox_unlock_index(mailbox, NULL);

    for (i = 0; i < num; i++) {
	record = &records[i];
	printf("UID: %u\n", record->uid);
	printf("\tSize: %u\n", record->size);
	printf("\tSent: %s", ctime(&record->sentdate));
	printf("\tRecv: %s", ctime(&record->internaldate));
	printf("\tExpg: %s", ctime(&record->last_updated));

	if (mailbox_cacherecord(mailbox, record)) {
	    printf("\tERROR: cache record missing or corrupt, "
		   "not printing cache details\n\n");
	    continue;
	}

	printf("\tFrom: %.*s\n", cacheitem_size(record, CACHE_FROM),
		cacheitem_base(record, CACHE_FROM));
	printf("\tTo  : %.*s\n", cacheitem_size(record, CACHE_TO),
		cacheitem_base(record, CACHE_TO));
	printf("\tCc  : %.*s\n", cacheitem_size(record, CACHE_CC),
		cacheitem_base(record, CACHE_CC));
	printf("\tBcc : %.*s\n", cacheitem_size(record, CACHE_BCC),
		cacheitem_base(record, CACHE_BCC));
	printf("\tSubj: %.*s\n\n", cacheitem_size(record, CACHE_SUBJECT),
		cacheitem_base(record, CACHE_SUBJECT));
    }

    free(records);
    mailbox_close(&mailbox);
}