/** \brief SMTP Filedata Mpm prefilter callback
 *
 *  \param det_ctx detection engine thread ctx
 *  \param p packet to inspect
 *  \param f flow to inspect
 *  \param txv tx to inspect
 *  \param pectx inspection context
 *
 *  \todo check files against actual tx
 */
static void PrefilterTxSmtpFiledata(DetectEngineThreadCtx *det_ctx,
        const void *pectx,
        Packet *p, Flow *f, void *txv,
        const uint64_t idx, const uint8_t flags)
{
    SCEnter();

    const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
    SMTPState *smtp_state = f->alstate;
    FileContainer *ffc = smtp_state->files_ts;
    if (ffc != NULL) {
        File *file = ffc->head;
        for (; file != NULL; file = file->next) {
            uint32_t buffer_len = 0;
            uint32_t stream_start_offset = 0;

            const uint8_t *buffer = DetectEngineSMTPGetBufferForTX(idx,
                                                    NULL, det_ctx,
                                                    f, file,
                                                    flags,
                                                    &buffer_len,
                                                    &stream_start_offset);
            if (buffer != NULL && buffer_len >= mpm_ctx->minlen) {
                (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
                        &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
            }
        }
    }
}
int DetectEngineRunSMTPMpm(DetectEngineCtx *de_ctx,
                           DetectEngineThreadCtx *det_ctx, Flow *f,
                           SMTPState *smtp_state, uint8_t flags,
                           void *tx, uint64_t idx)
{
    FileContainer *ffc = smtp_state->files_ts;
    uint32_t cnt = 0;
    uint32_t buffer_len = 0;
    uint32_t stream_start_offset = 0;
    uint8_t *buffer = NULL;

    if (ffc != NULL) {
        File *file = ffc->head;
        for (; file != NULL; file = file->next) {
            buffer = DetectEngineSMTPGetBufferForTX(idx,
                                                    de_ctx, det_ctx,
                                                    f, file,
                                                    flags,
                                                    &buffer_len,
                                                    &stream_start_offset);
            if (buffer_len == 0)
                goto end;

            cnt += SMTPFiledataPatternSearch(det_ctx, buffer, buffer_len, flags);
        }
    }
end:
    return cnt;
}
int DetectEngineInspectSMTPFiledata(ThreadVars *tv,
                                    DetectEngineCtx *de_ctx,
                                    DetectEngineThreadCtx *det_ctx,
                                    Signature *s, Flow *f, uint8_t flags,
                                    void *alstate,
                                    void *tx, uint64_t tx_id)
{
    SMTPState *smtp_state = (SMTPState *)alstate;
    FileContainer *ffc = smtp_state->files_ts;
    int r = 0;
    int match = 0;
    uint32_t buffer_len = 0;
    uint32_t stream_start_offset = 0;
    const uint8_t *buffer = 0;

    if (ffc != NULL) {
        File *file = ffc->head;
        for (; file != NULL; file = file->next) {
            buffer = DetectEngineSMTPGetBufferForTX(tx_id,
                                                    de_ctx, det_ctx,
                                                    f, file,
                                                    flags,
                                                    &buffer_len,
                                                    &stream_start_offset);
        if (buffer_len == 0)
            goto end;

        det_ctx->buffer_offset = 0;
        det_ctx->discontinue_matching = 0;
        det_ctx->inspection_recursion_counter = 0;
        match = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_FILEDATA],
                                              f,
                                              (uint8_t *)buffer,
                                              buffer_len,
                                              stream_start_offset,
                                              DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL);
        if (match == 1)
            r = 1;
        }
    }

end:
    if (r == 1)
        return DETECT_ENGINE_INSPECT_SIG_MATCH;
    else
        return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
}