static int mailbox_buf_to_index_header(const char *buf, size_t len,
                                       struct index_header *i)
{
    uint32_t crc;
    bit32 qannot;
    size_t headerlen;

    if (len < OFFSET_MINOR_VERSION+4)
        return IMAP_MAILBOX_BADFORMAT;

    memset(i, 0, sizeof(struct index_header));

    i->generation_no = ntohl(*((bit32 *)(buf+OFFSET_GENERATION_NO)));
    i->format = ntohl(*((bit32 *)(buf+OFFSET_FORMAT)));
    i->minor_version = ntohl(*((bit32 *)(buf+OFFSET_MINOR_VERSION)));
    switch (i->minor_version) {
    case 6:
    case 7:
        headerlen = 76;
        break;
    case 8:
        headerlen = 92;
        break;
    case 9:
    case 10:
        headerlen = 96;
        break;
    case 12:
    case 13:
        headerlen = 128;
        break;
    case 14:
    case 15:
    case 16:
    case 17:
        headerlen = 160;
        break;
    default:
        return IMAP_MAILBOX_BADFORMAT;
    }
    if (len < headerlen)
        return IMAP_MAILBOX_BADFORMAT;

    i->start_offset = ntohl(*((bit32 *)(buf+OFFSET_START_OFFSET)));
    i->record_size = ntohl(*((bit32 *)(buf+OFFSET_RECORD_SIZE)));
    i->num_records = ntohl(*((bit32 *)(buf+OFFSET_NUM_RECORDS)));
    i->last_appenddate = ntohl(*((bit32 *)(buf+OFFSET_LAST_APPENDDATE)));
    i->last_uid = ntohl(*((bit32 *)(buf+OFFSET_LAST_UID)));
    i->quota_mailbox_used = align_ntohll(buf+OFFSET_QUOTA_MAILBOX_USED);
    i->pop3_last_login = ntohl(*((bit32 *)(buf+OFFSET_POP3_LAST_LOGIN)));
    i->uidvalidity = ntohl(*((bit32 *)(buf+OFFSET_UIDVALIDITY)));
    i->deleted = ntohl(*((bit32 *)(buf+OFFSET_DELETED)));
    i->answered = ntohl(*((bit32 *)(buf+OFFSET_ANSWERED)));
    i->flagged = ntohl(*((bit32 *)(buf+OFFSET_FLAGGED)));
    i->options = ntohl(*((bit32 *)(buf+OFFSET_MAILBOX_OPTIONS)));
    i->leaked_cache_records = ntohl(*((bit32 *)(buf+OFFSET_LEAKED_CACHE)));
    if (i->minor_version < 8) goto done;

    i->highestmodseq = align_ntohll(buf+OFFSET_HIGHESTMODSEQ);
    if (i->minor_version < 12) goto done;

    i->deletedmodseq = align_ntohll(buf+OFFSET_DELETEDMODSEQ);
    i->exists = ntohl(*((bit32 *)(buf+OFFSET_EXISTS)));
    i->first_expunged = ntohl(*((bit32 *)(buf+OFFSET_FIRST_EXPUNGED)));
    i->last_repack_time = ntohl(*((bit32 *)(buf+OFFSET_LAST_REPACK_TIME)));
    i->header_file_crc = ntohl(*((bit32 *)(buf+OFFSET_HEADER_FILE_CRC)));
    i->synccrcs.basic = ntohl(*((bit32 *)(buf+OFFSET_SYNCCRCS_BASIC)));
    i->recentuid = ntohl(*((bit32 *)(buf+OFFSET_RECENTUID)));
    i->recenttime = ntohl(*((bit32 *)(buf+OFFSET_RECENTTIME)));

    if (i->minor_version < 13) goto crc;

    i->pop3_show_after = ntohl(*((bit32 *)(buf+OFFSET_POP3_SHOW_AFTER)));
    qannot = ntohl(*((bit32 *)(buf+OFFSET_QUOTA_ANNOT_USED)));
    /* this field is stored as a 32b unsigned on disk but 64b signed
     * in memory, so we need to be careful about sign extension */
    i->quota_annot_used = (quota_t)((unsigned long long)qannot);
    i->synccrcs.annot = ntohl(*((bit32 *)(buf+OFFSET_SYNCCRCS_ANNOT)));

    if (i->minor_version < 14) goto crc;

    i->unseen = ntohl(*((bit32 *)(buf+OFFSET_UNSEEN)));

    if (i->minor_version < 16) goto crc;

    i->createdmodseq = align_ntohll(buf+OFFSET_MAILBOX_CREATEDMODSEQ);

    if (i->minor_version < 17) goto crc;

    i->changes_epoch = ntohl(*((bit32 *)(buf+OFFSET_CHANGES_EPOCH)));

crc:
    /* CRC is always the last 4 bytes */
    crc = ntohl(*((bit32 *)(buf+headerlen-4)));
    if (crc != crc32_map(buf, headerlen-4))
        return IMAP_MAILBOX_CHECKSUM;

done:
    if (!i->exists)
        i->options |= OPT_POP3_NEW_UIDL;

    if (!i->highestmodseq)
        i->highestmodseq = 1;

    if (i->minor_version < 12) {
        i->deletedmodseq = i->highestmodseq;
        i->exists = i->num_records;
    }

    if (i->minor_version < 17) {
        i->changes_epoch = i->last_repack_time ? i->last_repack_time : time(0);
    }

    return 0;
}
static int mailbox_buf_to_index_header(const char *buf, size_t len,
                                       struct index_header *i)
{
    uint32_t crc;
    bit32 qannot;
    size_t headerlen;

    if (len < OFFSET_MINOR_VERSION+4)
        return IMAP_MAILBOX_BADFORMAT;

    memset(i, 0, sizeof(struct index_header));

    i->generation_no = ntohl(*((bit32 *)(buf+OFFSET_GENERATION_NO)));
    i->format = ntohl(*((bit32 *)(buf+OFFSET_FORMAT)));
    i->minor_version = ntohl(*((bit32 *)(buf+OFFSET_MINOR_VERSION)));
    switch (i->minor_version) {
    case 6:
    case 7:
        headerlen = 76;
        break;
    case 8:
        headerlen = 92;
        break;
    case 9:
    case 10:
        headerlen = 96;
        break;
    case 12:
    case 13:
        headerlen = 128;
        break;
    case 14:
    case 15:
    case 16:
    case 17:
        headerlen = 160;
        break;
    default:
        return IMAP_MAILBOX_BADFORMAT;
    }
    if (len < headerlen)
        return IMAP_MAILBOX_BADFORMAT;

    i->start_offset = ntohl(*((bit32 *)(buf+OFFSET_START_OFFSET)));
    i->record_size = ntohl(*((bit32 *)(buf+OFFSET_RECORD_SIZE)));
    i->num_records = ntohl(*((bit32 *)(buf+OFFSET_NUM_RECORDS)));
    i->last_appenddate = ntohl(*((bit32 *)(buf+OFFSET_LAST_APPENDDATE)));
    i->last_uid = ntohl(*((bit32 *)(buf+OFFSET_LAST_UID)));
    i->quota_mailbox_used = align_ntohll(buf+OFFSET_QUOTA_MAILBOX_USED);
    i->pop3_last_login = ntohl(*((bit32 *)(buf+OFFSET_POP3_LAST_LOGIN)));
    i->uidvalidity = ntohl(*((bit32 *)(buf+OFFSET_UIDVALIDITY)));
    i->deleted = ntohl(*((bit32 *)(buf+OFFSET_DELETED)));
    i->answered = ntohl(*((bit32 *)(buf+OFFSET_ANSWERED)));
    i->flagged = ntohl(*((bit32 *)(buf+OFFSET_FLAGGED)));
    i->options = ntohl(*((bit32 *)(buf+OFFSET_MAILBOX_OPTIONS)));
    i->leaked_cache_records = ntohl(*((bit32 *)(buf+OFFSET_LEAKED_CACHE)));
    if (i->minor_version < 8) goto done;

    i->highestmodseq = align_ntohll(buf+OFFSET_HIGHESTMODSEQ);
    if (i->minor_version < 12) goto done;

    i->deletedmodseq = align_ntohll(buf+OFFSET_DELETEDMODSEQ);
    i->exists = ntohl(*((bit32 *)(buf+OFFSET_EXISTS)));
    i->first_expunged = ntohl(*((bit32 *)(buf+OFFSET_FIRST_EXPUNGED)));
    i->last_repack_time = ntohl(*((bit32 *)(buf+OFFSET_LAST_REPACK_TIME)));
    i->header_file_crc = ntohl(*((bit32 *)(buf+OFFSET_HEADER_FILE_CRC)));
    i->synccrcs.basic = ntohl(*((bit32 *)(buf+OFFSET_SYNCCRCS_BASIC)));
    i->recentuid = ntohl(*((bit32 *)(buf+OFFSET_RECENTUID)));
    i->recenttime = ntohl(*((bit32 *)(buf+OFFSET_RECENTTIME)));

    if (i->minor_version < 13) goto crc;

    i->pop3_show_after = ntohl(*((bit32 *)(buf+OFFSET_POP3_SHOW_AFTER)));
    qannot = ntohl(*((bit32 *)(buf+OFFSET_QUOTA_ANNOT_USED)));
     
    i->quota_annot_used = (quota_t)((unsigned long long)qannot);
    i->synccrcs.annot = ntohl(*((bit32 *)(buf+OFFSET_SYNCCRCS_ANNOT)));

    if (i->minor_version < 14) goto crc;

    i->unseen = ntohl(*((bit32 *)(buf+OFFSET_UNSEEN)));

    if (i->minor_version < 16) goto crc;

    i->createdmodseq = align_ntohll(buf+OFFSET_MAILBOX_CREATEDMODSEQ);

    if (i->minor_version < 17) goto crc;

    i->changes_epoch = ntohl(*((bit32 *)(buf+OFFSET_CHANGES_EPOCH)));

crc:
     
    crc = ntohl(*((bit32 *)(buf+headerlen-4)));
    if (crc != crc32_map(buf, headerlen-4))
        return IMAP_MAILBOX_CHECKSUM;

done:
    if (!i->exists)
        i->options |= OPT_POP3_NEW_UIDL;

    if (!i->highestmodseq)
        i->highestmodseq = 1;

    if (i->minor_version < 12) {
        i->deletedmodseq = i->highestmodseq;
        i->exists = i->num_records;
    }

    if (i->minor_version < 17) {
        i->changes_epoch = i->last_repack_time ? i->last_repack_time : time(0);
    }

    return 0;
}