void MetadataReader::doSecurity(const std::string& parentkey,
                                const std::string& prefix,
                                ::nitf::FileSecurity& security)
{
    writeField(parentkey, prefix + "SCLSY", security.getClassificationSystem());
    writeField(parentkey, prefix + "SCODE", security.getCodewords());
    writeField(parentkey, prefix + "SCTLH", security.getControlAndHandling());
    writeField(parentkey, prefix + "SREL", security.getReleasingInstructions());
    writeField(parentkey, prefix + "SDCTP", security.getDeclassificationType());
    writeField(parentkey, prefix + "SDCDT", security.getDeclassificationDate());
    writeField(parentkey, prefix + "SDCXM", security.getDeclassificationExemption());
    writeField(parentkey, prefix + "SDG", security.getDowngrade());
    writeField(parentkey, prefix + "SDGDT", security.getDowngradeDateTime());
    writeField(parentkey, prefix + "SCLTX", security.getClassificationText());
    writeField(parentkey, prefix + "SCATP", security.getClassificationAuthorityType());
    writeField(parentkey, prefix + "SCAUT", security.getClassificationAuthority());
    writeField(parentkey, prefix + "SCRSN", security.getClassificationReason());
    writeField(parentkey, prefix + "SSRDT", security.getSecuritySourceDate());
    writeField(parentkey, prefix + "SCTLN", security.getSecurityControlNumber());
}
void NITFReadControl::addSecurityOptions(nitf::FileSecurity security,
        const std::string& prefix, six::Options& options) const
{
    Parameter p;
    std::string k;

    p = security.getClassificationSystem().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CLSY, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getCodewords().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CODE, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getControlAndHandling().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CTLH, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getReleasingInstructions().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::REL, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getDeclassificationType().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DCTP, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getDeclassificationDate().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DCDT, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getDeclassificationExemption().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getDowngrade().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DG, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getDowngradeDateTime().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DGDT, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getClassificationText().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CLTX, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getClassificationAuthorityType().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CATP, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getClassificationAuthority().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CAUT, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getClassificationReason().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CRSN, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getSecuritySourceDate().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::SRDT, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));

    p = security.getSecurityControlNumber().toString();
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CTLN, prefix);
    options.setParameter(k, p);
    mLog->debug(Ctxt(FmtX("Added NITF security option: [%s]->[%s]", k.c_str(),
                          (const char*) p)));
}
void NITFWriteControl::setSecurity(const six::Classification& c,
        nitf::FileSecurity security, const std::string& prefix)
{
    std::string k;
    const Options& ops = c.fileOptions;

    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CLSY, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getClassificationSystem().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CODE, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getCodewords().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CTLH, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getControlAndHandling().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::REL, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getReleasingInstructions().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DCTP, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getDeclassificationType().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DCDT, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getDeclassificationDate().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getDeclassificationExemption().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DG, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getDowngrade().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::DGDT, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getDowngradeDateTime().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CLTX, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getClassificationText().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CATP, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getClassificationAuthorityType().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CAUT, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getClassificationAuthority().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CRSN, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getClassificationReason().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::SRDT, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getSecuritySourceDate().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }
    k = NITFImageInfo::generateFieldKey(NITFImageInfo::CTLN, prefix);
    if (ops.hasParameter(k))
    {
        Parameter p = ops.getParameter(k);
        security.getSecurityControlNumber().set(p.str());
        mLog->debug(Ctxt(FmtX("Using NITF security option: [%s]->[%s]",
                              k.c_str(), (const char*) p)));
    }

    // Now, do some specific overrides
    if (security.getClassificationSystem().toString().empty())
    {
        security.getClassificationSystem().set("US");
        mLog->debug(Ctxt("Forcing NITF Classification System to [US]"));
    }

    c.setSecurity(prefix, *mLog, security);
}
void DerivedClassification::setSecurity(const std::string& prefix,
                                        logging::Logger& log,
                                        nitf::FileSecurity security) const
{
    if (classification != "U")
    {
        if (!releasableTo.empty())
        {
            std::string releasableToStr;
            for (size_t ii = 0; ii < releasableTo.size(); ++ii)
            {
                if (ii > 0)
                {
                    releasableToStr += " ";
                }
                releasableToStr += releasableTo[ii];
            }

            security.getReleasingInstructions().set(releasableToStr);

            const std::string fieldKey =
                NITFImageInfo::generateFieldKey(NITFImageInfo::REL, prefix);
            log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                fieldKey.c_str(), releasableToStr.c_str())));
        }

        if (!classifiedBy.empty())
        {
            security.getClassificationAuthority().set(classifiedBy);

            std::string fieldKey =
                NITFImageInfo::generateFieldKey(NITFImageInfo::CAUT, prefix);
            log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                fieldKey.c_str(), classifiedBy.c_str())));

            // classifiedBy attribute represents the name of the original
            // classification authority
            const std::string classAuthorityType("O");
            security.getClassificationAuthorityType().set(classAuthorityType);

            fieldKey =
                NITFImageInfo::generateFieldKey(NITFImageInfo::CATP, prefix);
            log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                fieldKey.c_str(),
                                classAuthorityType.c_str())));
        }

        if (!classificationReason.empty())
        {
            security.getClassificationReason().set(classificationReason);

            const std::string fieldKey =
                NITFImageInfo::generateFieldKey(NITFImageInfo::CRSN, prefix);
            log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                fieldKey.c_str(),
                                classificationReason.c_str())));
        }

        // By default, mark as exempt from automatic declassification
        std::string declassType("X");

        if (declassDate.get() != NULL)
        {
            std::string declassDateStr;
            declassDate->format("%Y%m%d", declassDateStr);
            str::trim(declassDateStr);
            security.getDeclassificationDate().set(declassDateStr);

            const std::string fieldKey =
                NITFImageInfo::generateFieldKey(NITFImageInfo::DCDT, prefix);
            log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                fieldKey.c_str(),
                                declassDateStr.c_str())));

            // Declassify on a specific date
            declassType = "DD";
        }

        if (!declassEvent.empty())
        {
            security.getClassificationText().set(declassEvent);

            const std::string fieldKey =
                NITFImageInfo::generateFieldKey(NITFImageInfo::CLTX,
                                                prefix);
            log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                fieldKey.c_str(),
                                declassEvent.c_str())));

            // Declassify upon occurrence of an event
            declassType = "DE";
        }

        if (!exemptedSourceType.empty())
        {
            // Attributes are 'OADR' or 'X[1-8]'
            // TODO  Should the NITF field get set to something if this is set
            // to 'OADR'?
            if (exemptedSourceType.length() == 2 &&
                exemptedSourceType[0] == 'X' &&
                exemptedSourceType[1] >= '1' &&
                exemptedSourceType[1] <= '8')
            {
                security.getDeclassificationExemption().set(
                    exemptedSourceType);

                const std::string fieldKey =
                    NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM,
                                                    prefix);
                log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                    fieldKey.c_str(),
                                    exemptedSourceType.c_str())));

                // Exempt from automatic declassification
                declassType = "X";
            }
        }

        if (!declassException.empty())
        {
            // declassException attributes are named
            // '25X[1-9]' or '25X1-human'
            // Corresponding NITF Declassification Exemption field values are
            // named 'X25[1-9]'
            std::string declassExemption;
            if (declassException == "25X1-human")
            {
                declassExemption = "X251";
            }
            else if (declassException.length() == 4 &&
                     declassException[0] == '2' &&
                     declassException[1] == '5' &&
                     declassException[2] == 'X')
            {
                const char ch(declassException[3]);
                if (ch >= '1' && ch <= '9')
                {
                    declassExemption = "X25" + ch;
                }
            }

            if (!declassExemption.empty())
            {
                security.getDeclassificationExemption().set(declassExemption);

                const std::string fieldKey =
                    NITFImageInfo::generateFieldKey(NITFImageInfo::DCXM,
                                                    prefix);
                log.debug(Ctxt(FmtX("Setting NITF [%s] from sicd/sidd: [%s]",
                                    fieldKey.c_str(),
                                    declassExemption.c_str())));

                // Exempt from automatic declassification
                declassType = "X";
            }
        }

        // Now that we've gone through all the things that could modify the
        // declassification type, set it
        security.getDeclassificationType().set(declassType);
        log.debug(Ctxt(FmtX(
            "Setting NITF [%s] from sicd/sidd: [%s]",
            NITFImageInfo::generateFieldKey(NITFImageInfo::DCTP,
                                            prefix).c_str(),
            declassType.c_str())));
    }
}