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