/* * 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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
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); }
/* * 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; }
/* 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; }
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;
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); }