/*- * Copyright (c) 2004 Jacques A. Vidrine * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include using namespace vuxml; // // AllMatcher // AllMatcher::AllMatcher(EntryProcessor &proc) : proc_(proc) {} bool AllMatcher::operator()(const Entry &entry) { return proc_(entry); } void AllMatcher::start() { proc_.start(); } void AllMatcher::end() { proc_.end(); } // // VersionMatcher // VersionMatcher::VersionMatcher(std::vector &args, EntryProcessor &proc) : args_(args), proc_(proc) { } bool VersionMatcher::operator()(const Entry &entry) { std::vector::const_iterator arg, arg_end; std::vector::const_iterator nam, nam_end; std::vector::const_iterator aff, aff_end; std::vector::const_iterator rng, rng_end; std::string name, version; std::string::size_type i, npos = std::string::npos; for (arg = args_.begin(), arg_end = args_.end(); arg != arg_end; ++arg) { i = arg->rfind('-'); if (i == npos) { name = *arg; version = VersionRange::zero; } else { name = arg->substr(0, i); version = arg->substr(i+1, npos); } for (aff = entry.affected().begin(), aff_end = entry.affected().end(); aff != aff_end; ++aff) { for (nam = aff->names.begin(), nam_end = aff->names.end(); nam != nam_end; ++nam) { if (*nam == name) break; } if (nam == nam_end) continue; for (rng = aff->ranges.begin(), rng_end = aff->ranges.end(); rng != rng_end; ++rng) if (rng->contains(version)) return proc_(entry); } } return true; } void VersionMatcher::start() { proc_.start(); } void VersionMatcher::end() { proc_.end(); } // // TextWriter // TextWriter::TextWriter(std::ostream &os) : os_(os) { } namespace { void writeTopic(std::ostream &os, const Entry &entry) { os << "Topic: " << entry.topic() << '\n'; } void writeRangeExpression(std::ostream &os, const std::string &nam, const VersionRange &rng) { os << " "; if (rng.lo == rng.hi) os << nam << " == " << rng.lo; else if (rng.lo != VersionRange::zero && rng.hi != VersionRange::infinity) os << rng.lo << " <" << (rng.lo_closed ? "=" : "") << ' ' << nam << " <" << (rng.hi_closed ? "=" : "") << ' ' << rng.hi; else if (rng.hi != VersionRange::infinity) os << nam << " <" << (rng.hi_closed ? "=" : "") << ' ' << rng.hi; else os << rng.lo << " <" << (rng.lo_closed ? "=" : "") << ' ' << nam; os << '\n'; } void writeAffected(std::ostream &os, const Entry &entry) { std::vector::const_iterator aff, aff_end; std::vector::const_iterator rng, rng_end; std::vector::const_iterator nam, nam_end; os << "Affects:\n"; aff_end = entry.affected().end(); for (aff = entry.affected().begin(); aff != aff_end; ++aff) { nam_end = aff->names.end(); for (nam = aff->names.begin(); nam != nam_end; ++nam) { rng_end = aff->ranges.end(); for (rng = aff->ranges.begin(); rng != rng_end; ++rng) writeRangeExpression(os, *nam, *rng); } } } void writeReferences(std::ostream &os, const Entry &entry) { std::vector::const_iterator ref, ref_end; os << "References:\n"; ref_end = entry.references().end(); for (ref = entry.references().begin(); ref != ref_end; ++ref) os << " " << ref->type << ':' << ref->text << '\n'; } } bool TextWriter::operator()(const Entry &entry) { writeTopic(os_, entry); writeAffected(os_, entry); writeReferences(os_, entry); os_ << "\n\n"; return true; } // // VuXMLWriter // VuXMLWriter::VuXMLWriter(std::ostream &os) : os_(os) {} void VuXMLWriter::start() { os_ << "\n" << "\n" << "\n"; } void VuXMLWriter::end() { os_ << "\n"; } namespace vuxml { namespace vuxmlwriter { struct WriteAffected : public std::unary_function { std::ostream &os_; WriteAffected(std::ostream &os) : os_(os) {} void operator()(const AffectedSet &as) { os_ << " \n"; std::vector::const_iterator nam, nam_end; for (nam = as.names.begin(), nam_end = as.names.end(); nam != nam_end; ++nam) os_ << " " << xmlescape(*nam) << "\n"; std::vector::const_iterator rng, rng_end; std::string hi, lo; for (rng = as.ranges.begin(), rng_end = as.ranges.end(); rng != rng_end; ++rng) { hi = xmlescape(rng->hi); lo = xmlescape(rng->lo); os_ << " "; if (rng->lo == rng->hi) { os_ << "" << rng->lo << ""; continue; } if (rng->lo != VersionRange::zero) os_ << (rng->lo_closed? "": "") << lo << (rng->lo_closed?"":""); if (rng->hi != VersionRange::infinity) os_ << (rng->hi_closed? "": "") << hi << (rng->hi_closed?"":""); os_ << "\n"; } os_ << " \n"; } }; struct WriteReferences : public std::unary_function { std::ostream &os_; WriteReferences(std::ostream &os) : os_(os) {} void operator()(const Reference &ref) { os_ << " <" << ref.type << ">" << xmlescape(ref.text) << "\n"; } }; }} bool VuXMLWriter::operator()(const Entry &entry) { using namespace vuxml::vuxmlwriter; os_ << " \n" << " " << xmlescape(entry.topic()) << "\n" << " \n"; std::for_each(entry.affected().begin(), entry.affected().end(), WriteAffected(os_)); os_ << " \n" << " \n" << " \n" << entry.description() << " \n" << " \n" << " \n"; std::for_each(entry.references().begin(), entry.references().end(), WriteReferences(os_)); os_ << " \n" << " \n" << " " << xmlescape(entry.discoveryDate()) << "\n" << " " << xmlescape(entry.entryDate()) << "\n"; if (entry.modifiedDate().size() != 0) os_ << " " << xmlescape(entry.modifiedDate()) << "\n"; os_ << " \n" << " \n"; return true; } // // XHTMLWriter // XHTMLWriter::XHTMLWriter(std::ostream &os, unsigned int h1) : os_(os), h1_(h1) {} void XHTMLWriter::start() { os_ << "\n" << "\n" << "\n" << " vxquery report\n" << "

vxquery report

\n"; } void XHTMLWriter::end() { os_ << "\n"; } namespace vuxml { namespace xhtmlwriter { struct WriteRangeExpression : public std::binary_function { std::ostream &os_; WriteRangeExpression(std::ostream &os) : os_(os) {} void operator()(const std::string &nam, const VersionRange &rng) { std::string s; if (rng.lo == rng.hi) { s += nam; s += " == "; s += rng.lo; } else if (rng.hi != VersionRange::infinity && rng.lo == VersionRange::zero) { s += nam; s += " <"; if (rng.hi_closed) s += "="; s += " "; s += rng.hi; } else { s += rng.lo; s += " <"; if (rng.lo_closed) s += "="; s += " "; s += nam; if (rng.hi != VersionRange::infinity) { s += " <"; if (rng.hi_closed) s += "="; s += " "; s += rng.hi; } } os_ << xmlescape(s) << "
"; } }; struct WriteAffected : public std::unary_function { std::ostream &os_; WriteAffected(std::ostream &os) : os_(os) {} void operator()(const AffectedSet &as) { std::vector::const_iterator rng, rng_end; std::vector::const_iterator nam, nam_end; WriteRangeExpression fn(os_); os_ << "

"; for (nam = as.names.begin(), nam_end = as.names.end() ; nam != nam_end; ++nam) for (rng = as.ranges.begin(), rng_end = as.ranges.end(); rng != rng_end; ++rng) fn(*nam, *rng); os_ << "

\n"; } }; struct WriteReferences : public std::unary_function { std::ostream &os_; WriteReferences(std::ostream &os) : os_(os) {} void operator()(const Reference &ref) { std::string link, tmp = xmlescape(ref.text); if (ref.type == "url") { os_ << "URL" << tmp << "\n"; } else if (ref.type == "cvename") { link = "http://cve.mitre.org/cgi-bin/cvename.cgi?name="; link += tmp; os_ << "CVE Name" << tmp << "\n"; } else if (ref.type == "bid") { link = "http://www.securityfocus.com/bid/"; link += tmp; os_ << "Bugtraq ID" << tmp << "\n"; } else if (ref.type == "certsa") { link = "http://www.cert.org/advisories/"; link += tmp; link += ".html"; os_ << "CERT/CC Advisory" << tmp << "\n"; } else if (ref.type == "certvu") { link = "http://www.kb.cert.org/vuls/id/"; link += tmp; os_ << "CERT/CC Vulnerability Note" << tmp << "\n"; } else if (ref.type == "freebsdsa") { link = "ftp://ftp.freebsd.org/pub/CERT/advisories/FreeBSD-"; link += tmp; link += ".asc"; os_ << "FreeBSD Advisory" << tmp << "\n"; } else { os_ << "" << xmlescape(ref.type) << "" << xmlescape(ref.text) << "\n"; } } }; }} bool XHTMLWriter::operator()(const Entry &entry) { using namespace vuxml::xhtmlwriter; os_ << "" << xmlescape(entry.topic()) << "\n" << "Affects\n"; std::for_each(entry.affected().begin(), entry.affected().end(), WriteAffected(os_)); os_ << "Description\n" << entry.description() << '\n' << "References\n" << "\n"; std::for_each(entry.references().begin(), entry.references().end(), WriteReferences(os_)); os_ << "
\n"; return true; } // // XHTMLFilesWriter // XHTMLFilesWriter::XHTMLFilesWriter(const std::string &dir) : dir_(dir), fails_(0) {} bool XHTMLFilesWriter::operator()(const Entry &entry) { std::string path = dir_; path += "/"; path += entry.vid(); path += ".html"; std::ofstream ofs; ofs.open(path.c_str(), std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); if (ofs.fail()) { ++fails_; if (fails_ > 10) throw except("Too many failures."); LOG << "Warning: cannot open file `" << path << "'\n" << "for output.\n"; return false; } ofs << "\n" << "\n" << "\n" << " " << xmlescape(entry.topic()) << "\n" << " \n"; XHTMLWriter w(ofs, 0); w(entry); ofs << "\n"; ofs.close(); return true; }