"Fossies" - the Fresh Open Source Software Archive

Member "tcpflow-1.6.1/src/be13_api/dfxml/src/dfxml_writer.cpp" (19 Feb 2021, 20304 Bytes) of package /linux/misc/tcpflow-1.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dfxml_writer.cpp" see the Fossies "Dox" file reference documentation.

    1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    2 /**
    3  * implementation for C++ XML generation class
    4  *
    5  * The software provided here is released by the Naval Postgraduate
    6  * School, an agency of the U.S. Department of Navy.  The software
    7  * bears no warranty, either expressed or implied. NPS does not assume
    8  * legal liability nor responsibility for a User's use of the software
    9  * or the results of such use.
   10  *
   11  * Please note that within the United States, copyright protection,
   12  * under Section 105 of the United States Code, Title 17, is not
   13  * available for any work of the United States Government and/or for
   14  * any works created by United States Government employees. User
   15  * acknowledges that this software contains work which was created by
   16  * NPS government employees and is therefore in the public domain and
   17  * not subject to copyright.
   18  */
   19 
   20 
   21 #include "config.h"
   22 
   23 #ifdef HAVE_WINSOCK2_H
   24 #include <winsock2.h>
   25 #endif
   26 
   27 #include <errno.h>
   28 #include <unistd.h>
   29 
   30 #ifdef HAVE_SQLITE3_H
   31 #include <sqlite3.h>
   32 #endif
   33 
   34 #ifdef HAVE_BOOST_VERSION_HPP
   35 #include <boost/version.hpp>
   36 #endif
   37 
   38 #ifdef HAVE_PTHREAD
   39 #define MUTEX_INIT(M)   pthread_mutex_init(M,NULL);
   40 #define MUTEX_LOCK(M)   pthread_mutex_lock(M)
   41 #define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
   42 #else
   43 #define MUTEX_INIT(M)   {}
   44 #define MUTEX_LOCK(M)   {}
   45 #define MUTEX_UNLOCK(M) {}
   46 #endif
   47 
   48 #ifdef HAVE_TRE_TRE_H
   49 #include <tre/tre.h>
   50 #endif
   51 
   52 #include <iostream>
   53 #include <stdarg.h>
   54 #include <string.h>
   55 #include <stdlib.h>
   56 #include <sys/param.h>
   57 #include <assert.h>
   58 #include <fcntl.h>
   59 #include <stack>
   60 
   61 #include <iostream>
   62 #include <streambuf>
   63 
   64 #ifdef _MSC_VER
   65 # include <io.h>
   66 #else
   67 # include <unistd.h>
   68 #endif
   69 
   70 using namespace std;
   71 
   72 #include "dfxml_writer.h"
   73 
   74 static const char *xml_header = "<?xml version='1.0' encoding='UTF-8'?>\n";
   75 
   76 // Implementation of mkstemp for windows found on pan-devel mailing
   77 // list archive
   78 // @http://www.mail-archive.com/pan-devel@nongnu.org/msg00294.html
   79 #ifndef _S_IREAD
   80 #define _S_IREAD 256
   81 #endif
   82 
   83 #ifndef _S_IWRITE
   84 #define _S_IWRITE 128
   85 #endif
   86 
   87 #ifndef O_BINARY
   88 #define O_BINARY 0
   89 #endif
   90 
   91 #ifndef _O_SHORT_LIVED
   92 #define _O_SHORT_LIVED 0
   93 #endif
   94 
   95 #ifndef HAVE_MKSTEMP
   96 int mkstemp(char *tmpl)
   97 {
   98    int ret=-1;
   99    mktemp(tmpl);
  100    ret=open(tmpl,O_RDWR|O_BINARY|O_CREAT|O_EXCL|_O_SHORT_LIVED, _S_IREAD|_S_IWRITE);
  101    return ret;
  102 }
  103 #endif
  104 
  105 
  106 #ifndef O_BINARY
  107 #define O_BINARY 0
  108 #endif
  109 
  110 #ifndef _O_SHORT_LIVED
  111 #define _O_SHORT_LIVED 0
  112 #endif
  113 
  114 
  115 //std::string dfxml_writer::xml_PRId32("%" PRId32); // gets around compiler bug
  116 //std::string dfxml_writer::xml_PRIu32("%" PRIu32); // gets around compiler bug
  117 //std::string dfxml_writer::xml_PRId64("%" PRId64); // gets around compiler bug
  118 //std::string dfxml_writer::xml_PRIu64("%" PRIu64); // gets around compiler bug
  119 
  120 static const char *cstr(const string &str){
  121     return str.c_str();
  122 }
  123 
  124 // XML escapes
  125 static string xml_lt("&lt;");
  126 static string xml_gt("&gt;");
  127 static string xml_am("&amp;");
  128 static string xml_ap("&apos;");
  129 static string xml_qu("&quot;");
  130 
  131 // % encodings
  132 static string encoding_null("%00");
  133 static string encoding_r("%0D");
  134 static string encoding_n("%0A");
  135 static string encoding_t("%09");
  136 
  137 std::string dfxml_writer::xmlescape(const string &xml)
  138 {
  139     string ret;
  140     for(string::const_iterator i = xml.begin(); i!=xml.end(); i++){
  141         switch(*i){
  142         // XML escapes
  143         case '>':  ret += xml_gt; break;
  144         case '<':  ret += xml_lt; break;
  145         case '&':  ret += xml_am; break;
  146         case '\'': ret += xml_ap; break;
  147         case '"':  ret += xml_qu; break;
  148 
  149         // % encodings
  150         case '\000':  ret += encoding_null; break;      // retain encoded nulls
  151         case '\r':  ret += encoding_r; break;
  152         case '\n':  ret += encoding_n; break;
  153         case '\t':  ret += encoding_t; break;
  154         default:
  155             ret += *i;
  156         }
  157     }
  158     return ret;
  159 }
  160 
  161 /**
  162  * Strip an XML string as necessary for a tag name.
  163  */
  164 
  165 std::string dfxml_writer::xmlstrip(const string &xml)
  166 {
  167     string ret;
  168     for(string::const_iterator i = xml.begin(); i!=xml.end(); i++){
  169         if(isprint(*i) && !strchr("<>\r\n&'\"",*i)){
  170             ret += isspace(*i) ? '_' : tolower(*i);
  171         }
  172     }
  173     return ret;
  174 }
  175 
  176 /**
  177  * xmlmap:
  178  * Turns a map into a blob of XML.
  179  */
  180 
  181 std::string dfxml_writer::xmlmap(const dfxml_writer::strstrmap_t &m,const std::string &outer,const std::string &attrs)
  182 {
  183     std::stringstream ss;
  184     ss << "<" << outer;
  185     if(attrs.size()>0) ss << " " << attrs;
  186     ss << ">";
  187     for(std::map<std::string,std::string>::const_iterator it=m.begin();it!=m.end();it++){
  188         ss << "<" << (*it).first  << ">" << xmlescape((*it).second) << "</" << (*it).first << ">";
  189     }
  190     ss << "</" << outer << ">";
  191     return ss.str();
  192 }
  193 
  194 
  195 /* This goes to stdout */
  196 dfxml_writer::dfxml_writer():M(),outf(),out(&cout),tags(),tag_stack(),tempfilename(),tempfile_template("/tmp/xml_XXXXXXXX"),
  197            t0(),t_last_timestamp(),make_dtd(false),outfilename(),oneline()
  198 {
  199 #ifdef HAVE_PTHREAD
  200     pthread_mutex_init(&M,NULL);
  201 #endif
  202     gettimeofday(&t0,0);
  203     gettimeofday(&t_last_timestamp,0);
  204     *out << xml_header;
  205 }
  206 
  207 /* This should be rewritten so that the temp file is done on close, not on open */
  208 dfxml_writer::dfxml_writer(const std::string &outfilename_,bool makeDTD):
  209     M(),outf(outfilename_.c_str(),ios_base::out),
  210     out(),tags(),tag_stack(),tempfilename(),tempfile_template(outfilename_+"_tmp_XXXXXXXX"),
  211     t0(),t_last_timestamp(),make_dtd(false),outfilename(outfilename_),oneline()
  212 {
  213     MUTEX_INIT(&M);
  214     gettimeofday(&t0,0);
  215     gettimeofday(&t_last_timestamp,0);
  216     if(!outf.is_open()){
  217         perror(outfilename_.c_str());
  218         exit(1);
  219     }
  220     out = &outf;                                                // use this one instead
  221     *out << xml_header;
  222 }
  223 
  224 
  225 void dfxml_writer::set_tempfile_template(const std::string &temp)
  226 {
  227     tempfile_template = temp;
  228 }
  229 
  230 
  231 
  232 
  233 void dfxml_writer::close()
  234 {
  235     MUTEX_LOCK(&M);
  236     outf.close();
  237     if(make_dtd){
  238         /* If we are making the DTD, then we should close the file,
  239          * scan the output file for the tags, write to a temp file, and then
  240          * close the temp file and have it overwrite the outfile.
  241          */
  242 
  243         std::ifstream in(cstr(tempfilename));
  244         if(!in.is_open()){
  245             cerr << tempfilename << strerror(errno) << ":Cannot re-open for input\n";
  246             exit(1);
  247         }
  248         outf.open(cstr(outfilename),ios_base::out);
  249         if(!outf.is_open()){
  250             cerr << outfilename << " " << strerror(errno)
  251                  << ": Cannot open for output; will not delete " << tempfilename << "\n";
  252             exit(1);
  253         }
  254         // copy over first line --- the XML header
  255         std::string line;
  256         getline(in,line);
  257         outf << line;
  258 
  259         write_dtd();                    // write the DTD
  260         while(!in.eof()){
  261             getline(in,line);
  262             outf << line << endl;
  263         }
  264         in.close();
  265         unlink(cstr(tempfilename));
  266         outf.close();
  267     }
  268     MUTEX_UNLOCK(&M);
  269 }
  270 
  271 void dfxml_writer::write_dtd()
  272 {
  273     *out << "<!DOCTYPE fiwalk\n";
  274     *out << "[\n";
  275     for(set<string>::const_iterator it = tags.begin(); it != tags.end(); it++){
  276         *out << "<!ELEMENT " << *it << "ANY >\n";
  277     }
  278     *out << "<!ATTLIST volume startsector CDATA #IMPLIED>\n";
  279     *out << "<!ATTLIST run start CDATA #IMPLIED>\n";
  280     *out << "<!ATTLIST run len CDATA #IMPLIED>\n";
  281     *out << "]>\n";
  282 }
  283 
  284 /**
  285  * make sure that a tag is valid and, if so, add it to the list of tags we use
  286  */
  287 void dfxml_writer::verify_tag(string tag)
  288 {
  289     if(tag[0]=='/') tag = tag.substr(1);
  290     if(tag.find(" ") != string::npos){
  291         cerr << "tag '" << tag << "' contains space. Cannot continue.\n";
  292         exit(1);
  293     }
  294     tags.insert(tag);
  295 }
  296 
  297 void dfxml_writer::puts(const string &v)
  298 {
  299     *out << v;
  300 }
  301 
  302 void dfxml_writer::spaces()
  303 {
  304     for(unsigned int i=0;i<tag_stack.size() && !oneline;i++){
  305         *out << "  ";
  306     }
  307 }
  308 
  309 void dfxml_writer::tagout(const string &tag,const string &attribute)
  310 {
  311     verify_tag(tag);
  312     *out << "<" << tag;
  313     if(attribute.size()>0) *out << " " << attribute;
  314     *out << ">";
  315 }
  316 
  317 #if (!defined(HAVE_VASPRINTF)) || defined(_WIN32)
  318 #ifndef _WIN32
  319 #define ms_printf __print
  320 #define __MINGW_ATTRIB_NONNULL(x) 
  321 #endif
  322 extern "C" {
  323     /**
  324      * We do not have vasprintf.
  325      * We have determined that vsnprintf() does not perform properly on windows.
  326      * So we just allocate a huge buffer and then strdup() and hope!
  327      */
  328     int vasprintf(char **ret,const char *fmt,va_list ap)
  329         __attribute__((__format__(ms_printf, 2, 0))) 
  330         __MINGW_ATTRIB_NONNULL(2) ;
  331     int vasprintf(char **ret,const char *fmt,va_list ap) 
  332     {
  333         /* Figure out how long the result will be */
  334         char buf[65536];
  335         int size = vsnprintf(buf,sizeof(buf),fmt,ap);
  336         if(size<0) return size;
  337         /* Now allocate the memory */
  338         *ret = strcpy((char *) malloc(strlen(buf)+1), buf);
  339         return size;
  340     }
  341 }
  342 #endif
  343 
  344 
  345 void dfxml_writer::printf(const char *fmt,...)
  346 {
  347     va_list ap;
  348     va_start(ap, fmt);
  349 
  350     /** printf to stream **/
  351     char *ret = 0;
  352     if(vasprintf(&ret,fmt,ap) < 0){
  353         *out << "dfxml_writer::xmlprintf: " << strerror(errno);
  354         exit(EXIT_FAILURE);
  355     }
  356     *out << ret;
  357     free(ret);
  358     /** end printf to stream **/
  359 
  360     va_end(ap);
  361 }
  362 
  363 void dfxml_writer::push(const string &tag,const string &attribute)
  364 {
  365     spaces();
  366     tag_stack.push(tag);
  367     tagout(tag,attribute);
  368     if(!oneline) *out << '\n';
  369 }
  370 
  371 void dfxml_writer::pop()
  372 {
  373     assert(tag_stack.size()>0);
  374     string tag = tag_stack.top();
  375     tag_stack.pop();
  376     spaces();
  377     tagout("/"+tag,"");
  378     *out << '\n';
  379 }
  380 
  381 void dfxml_writer::set_oneline(bool v)
  382 {
  383     if(v==true) spaces();
  384     if(v==false) *out << "\n";
  385     oneline = v;
  386 }
  387 
  388 void dfxml_writer::cpuid(uint32_t op, unsigned long *eax, unsigned long *ebx,
  389                 unsigned long *ecx, unsigned long *edx) {
  390 #if defined(HAVE_ASM_CPUID) && defined(__i386__) 
  391 #if defined(__PIC__)
  392     __asm__ __volatile__("pushl %%ebx      \n\t" /* save %ebx */
  393                          "cpuid            \n\t"
  394                          "movl %%ebx, %1   \n\t" /* save what cpuid just put in %ebx */
  395                          "popl %%ebx       \n\t" /* restore the old %ebx */
  396                          : "=a"(*eax), "=r"(*ebx), "=c"(*ecx), "=d"(*edx)
  397                          : "a"(op)
  398                          : "cc");
  399 #else
  400     __asm__ __volatile__("cpuid"
  401                          : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
  402                          : "a"(op)
  403                          : "cc");
  404 #endif
  405 #endif
  406 }
  407 
  408 void dfxml_writer::add_cpuid()
  409 {
  410 #if defined(__i386__)
  411 #ifndef __WORDSIZE
  412 #define __WORDSIZE 32
  413 #endif
  414 #define BFIX(val, base, end) ((val << (__WORDSIZE-end-1)) >> (__WORDSIZE-end+base-1))
  415     char buf[256];
  416     unsigned long eax=0, ebx=0, ecx=0, edx=0; // =0 avoids a compiler warning
  417     cpuid(0, &eax, &ebx, &ecx, &edx);
  418     
  419     snprintf(buf,sizeof(buf),"%.4s%.4s%.4s", (char *)&ebx, (char *)&edx, (char *)&ecx);
  420     push("cpuid");
  421     xmlout("identification",buf);
  422 
  423     cpuid(1, &eax, &ebx, &ecx, &edx);
  424     xmlout("family", (int64_t) BFIX(eax, 8, 11));
  425     xmlout("model", (int64_t) BFIX(eax, 4, 7));
  426     xmlout("stepping", (int64_t) BFIX(eax, 0, 3));
  427     xmlout("efamily", (int64_t) BFIX(eax, 20, 27));
  428     xmlout("emodel", (int64_t) BFIX(eax, 16, 19));
  429     xmlout("brand", (int64_t) BFIX(ebx, 0, 7));
  430     xmlout("clflush_size", (int64_t) BFIX(ebx, 8, 15) * 8);
  431     xmlout("nproc", (int64_t) BFIX(ebx, 16, 23));
  432     xmlout("apicid", (int64_t) BFIX(ebx, 24, 31));
  433     
  434     cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
  435     xmlout("L1_cache_size", (int64_t) BFIX(ecx, 16, 31) * 1024);
  436     pop();
  437 #undef BFIX
  438 #endif
  439 }
  440 
  441 void dfxml_writer::add_DFXML_execution_environment(const std::string &command_line)
  442 {
  443 
  444     push("execution_environment");
  445 #if defined(HAVE_ASM_CPUID) && defined(__i386__)
  446     add_cpuid();
  447 #endif
  448 
  449 #ifdef HAVE_SYS_UTSNAME_H
  450     struct utsname name;
  451     if(uname(&name)==0){
  452         xmlout("os_sysname",name.sysname);
  453         xmlout("os_release",name.release);
  454         xmlout("os_version",name.version);
  455         xmlout("host",name.nodename);
  456         xmlout("arch",name.machine);
  457     }
  458 #else
  459 #ifdef UNAMES
  460     xmlout("os_sysname",UNAMES,"",false);
  461 #endif
  462 #ifdef HAVE_GETHOSTNAME
  463     {
  464         char hostname[1024];
  465         if(gethostname(hostname,sizeof(hostname))==0){
  466             xmlout("host",hostname);
  467         }
  468     }
  469 #endif
  470 #endif  
  471     
  472     xmlout("command_line", command_line); // quote it!
  473 #ifdef HAVE_GETUID
  474     xmlprintf("uid","","%d",getuid());
  475 #ifdef HAVE_GETPWUID
  476     xmlout("username",getpwuid(getuid())->pw_name);
  477 #endif
  478 #endif
  479     
  480 #define TM_FORMAT "%Y-%m-%dT%H:%M:%SZ"
  481     char buf[256];
  482     time_t t = time(0);
  483     strftime(buf,sizeof(buf),TM_FORMAT,gmtime(&t));
  484     xmlout("start_time",buf);
  485     pop();                      // <execution_environment>
  486 }
  487 
  488 #ifdef WIN32
  489 #include "psapi.h"
  490 #endif
  491 
  492 void dfxml_writer::add_rusage()
  493 {
  494 #ifdef WIN32
  495     /* Note: must link -lpsapi for this */
  496     PROCESS_MEMORY_COUNTERS_EX pmc;
  497     memset(&pmc,0,sizeof(pmc));
  498     GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc));
  499     push("PROCESS_MEMORY_COUNTERS");
  500     xmlout("cb",(int64_t)pmc.cb);
  501     xmlout("PageFaultCount",(int64_t)pmc.PageFaultCount);
  502     xmlout("WorkingSetSize",(int64_t)pmc.WorkingSetSize);
  503     xmlout("QuotaPeakPagedPoolUsage",(int64_t)pmc.QuotaPeakPagedPoolUsage);
  504     xmlout("QuotaPagedPoolUsage",(int64_t)pmc.QuotaPagedPoolUsage);
  505     xmlout("QuotaPeakNonPagedPoolUsage",(int64_t)pmc.QuotaPeakNonPagedPoolUsage);
  506     xmlout("PagefileUsage",(int64_t)pmc.PagefileUsage);
  507     xmlout("PeakPagefileUsage",(int64_t)pmc.PeakPagefileUsage);
  508     xmlout("PrivateUsage",(int64_t)pmc.PrivateUsage);
  509     pop();
  510 #endif    
  511 #ifdef HAVE_GETRUSAGE
  512     struct rusage ru;
  513     memset(&ru,0,sizeof(ru));
  514     if(getrusage(RUSAGE_SELF,&ru)==0){
  515         push("rusage");
  516         xmlout("utime",ru.ru_utime);
  517         xmlout("stime",ru.ru_stime);
  518         xmloutl("maxrss",(long)ru.ru_maxrss);
  519         xmloutl("minflt",(long)ru.ru_minflt);
  520         xmloutl("majflt",(long)ru.ru_majflt);
  521         xmloutl("nswap",(long)ru.ru_nswap);
  522         xmloutl("inblock",(long)ru.ru_inblock);
  523         xmloutl("oublock",(long)ru.ru_oublock);
  524 
  525         struct timeval t1;
  526         gettimeofday(&t1,0);
  527         struct timeval t;
  528         
  529         t.tv_sec = t1.tv_sec - t0.tv_sec;
  530         if(t1.tv_usec > t0.tv_usec){
  531             t.tv_usec = t1.tv_usec - t0.tv_usec;
  532         } else {
  533             t.tv_sec--;
  534             t.tv_usec = (t1.tv_usec+1000000) - t0.tv_usec;
  535         }
  536         xmlout("clocktime",t);
  537         pop();
  538     }
  539 #endif
  540 }
  541 
  542 void dfxml_writer::add_timestamp(const std::string &name)
  543 {
  544     struct timeval t1;
  545     gettimeofday(&t1,0);
  546     struct timeval t;
  547 
  548     // timestamp delta against t_last_timestamp
  549     t.tv_sec = t1.tv_sec - t_last_timestamp.tv_sec;
  550     if(t1.tv_usec > t_last_timestamp.tv_usec){
  551         t.tv_usec = t1.tv_usec - t_last_timestamp.tv_usec;
  552     } else {
  553         t.tv_sec--;
  554         t.tv_usec = (t1.tv_usec+1000000) - t_last_timestamp.tv_usec;
  555     }
  556     char delta[16];
  557     snprintf(delta, 16, "%d.%06d", (int)t.tv_sec, (int)t.tv_usec);
  558 
  559     // reset t_last_timestamp for the next invocation
  560     gettimeofday(&t_last_timestamp,0);
  561 
  562     // timestamp total
  563     t.tv_sec = t1.tv_sec - t0.tv_sec;
  564     if(t1.tv_usec > t0.tv_usec){
  565         t.tv_usec = t1.tv_usec - t0.tv_usec;
  566     } else {
  567         t.tv_sec--;
  568         t.tv_usec = (t1.tv_usec+1000000) - t0.tv_usec;
  569     }
  570     char total[16];
  571     snprintf(total, 16, "%d.%06d", (int)t.tv_sec, (int)t.tv_usec);
  572 
  573     // prepare attributes
  574     std::stringstream ss;
  575     ss << "name='" << name
  576        << "' delta='" << delta
  577        << "' total='" << total
  578        << "'";
  579 
  580     // add named timestamp
  581     xmlout("timestamp", "",ss.str(), true);
  582 }
  583 
  584 /****************************************************************
  585  *** THESE ARE THE ONLY THREADSAFE ROUTINES
  586  ****************************************************************/
  587 void dfxml_writer::comment(const string &comment_)
  588 {
  589     MUTEX_LOCK(&M);
  590     *out << "<!-- " << comment_ << " -->\n";
  591     out->flush();
  592     MUTEX_UNLOCK(&M);
  593 }
  594 
  595 
  596 void dfxml_writer::xmlprintf(const std::string &tag,const std::string &attribute, const char *fmt,...)
  597 {
  598     MUTEX_LOCK(&M);    
  599     spaces();
  600     tagout(tag,attribute);
  601     va_list ap;
  602     va_start(ap, fmt);
  603 
  604     /** printf to stream **/
  605     char *ret = 0;
  606     if(vasprintf(&ret,fmt,ap) < 0){
  607         cerr << "dfxml_writer::xmlprintf: " << strerror(errno) << "\n";
  608         exit(EXIT_FAILURE);
  609     }
  610     *out << ret;
  611     free(ret);
  612     /** end printf to stream **/
  613 
  614     va_end(ap);
  615     tagout("/"+tag,"");
  616     *out << '\n';
  617     out->flush();
  618     MUTEX_UNLOCK(&M);
  619 }
  620 
  621 void dfxml_writer::xmlout(const string &tag,const string &value,const string &attribute,bool escape_value)
  622 {
  623     MUTEX_LOCK(&M);
  624     spaces();
  625     if(value.size()==0){
  626         if(tag.size()) tagout(tag,attribute+"/");
  627     } else {
  628         if(tag.size()) tagout(tag,attribute);
  629         *out << (escape_value ? xmlescape(value) : value);
  630         if(tag.size()) tagout("/"+tag,"");
  631     }
  632     *out << "\n";
  633     out->flush();
  634     MUTEX_UNLOCK(&M);
  635 }
  636 
  637 #ifdef HAVE_LIBEWF_H
  638 #include <libewf.h>
  639 #endif
  640 
  641 #if defined(HAVE_EXIV2) && defined(HAVE_EXIV2_IMAGE_HPP)
  642 #ifdef DFXML_GNUC_HAS_DIAGNOSTIC_PRAGMA
  643 #pragma GCC diagnostic ignored "-Wshadow"
  644 #pragma GCC diagnostic ignored "-Weffc++"
  645 #endif
  646 #include <exiv2/image.hpp>
  647 #include <exiv2/exif.hpp>
  648 #include <exiv2/error.hpp>
  649 #endif
  650 
  651 #ifdef HAVE_HASHDB
  652 #include <hashdb.hpp>
  653 #endif
  654 
  655 #ifdef HAVE_AFFLIB_AFFLIB_H
  656 //#pragma GCC diagnostic ignored "-Wreserved-user-defined-literal"               // required for C11
  657 #include <afflib/afflib.h>
  658 #endif
  659 
  660 
  661 /* These support Digital Forensics XML and require certain variables to be defined */
  662 void dfxml_writer::add_DFXML_build_environment()
  663 {
  664     /* __DATE__ formats as: Apr 30 2011 */
  665     struct tm tm;
  666     memset(&tm,0,sizeof(tm));
  667     push("build_environment");
  668 #ifdef __GNUC__
  669     // See http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
  670     xmlprintf("compiler","","%d.%d.%d (%s)",__GNUC__, __GNUC_MINOR__,__GNUC_PATCHLEVEL__,__VERSION__);
  671 #endif
  672 #ifdef CPPFLAGS
  673     xmlout("CPPFLAGS",CPPFLAGS,"",true);
  674 #endif
  675 #ifdef CFLAGS
  676     xmlout("CFLAGS",CFLAGS,"",true);
  677 #endif
  678 #ifdef CXXFLAGS
  679     xmlout("CXXFLAGS",CXXFLAGS,"",true);
  680 #endif    
  681 #ifdef LDFLAGS
  682     xmlout("LDFLAGS",LDFLAGS,"",true);
  683 #endif    
  684 #ifdef LIBS
  685     xmlout("LIBS",LIBS,"",true);
  686 #endif    
  687 #if defined(__DATE__) && defined(__TIME__) && defined(HAVE_STRPTIME)
  688     if(strptime(__DATE__,"%b %d %Y",&tm)){
  689         char buf[64];
  690         snprintf(buf,sizeof(buf),"%4d-%02d-%02dT%s",tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,__TIME__);
  691         xmlout("compilation_date",buf);
  692     }
  693 #endif
  694 #ifdef BOOST_VERSION
  695     {
  696         char buf[64];
  697         snprintf(buf,sizeof(buf),"%d",BOOST_VERSION);
  698         xmlout("library", "", std::string("name=\"boost\" version=\"") + buf + "\"",false);
  699     }
  700 #endif
  701 #ifdef HAVE_LIBTSK3
  702     xmlout("library", "", std::string("name=\"tsk\" version=\"") + tsk_version_get_str() + "\"",false);
  703 #endif
  704 #ifdef HAVE_LIBAFFLIB
  705     xmlout("library", "", std::string("name=\"afflib\" version=\"") + af_version() +"\"",false);
  706 #endif
  707 #ifdef HAVE_LIBEWF
  708     xmlout("library", "", std::string("name=\"libewf\" version=\"") + libewf_get_version() + "\"",false);
  709 #endif
  710 #ifdef HAVE_EXIV2
  711     xmlout("library", "", std::string("name=\"exiv2\" version=\"") + Exiv2::version() + "\"",false);
  712 #endif
  713 #if defined(HAVE_LIBTRE) && defined(HAVE_TRE_VERSION) && defined(HAVE_TRE_TRE_H)
  714     xmlout("library", "", std::string("name=\"tre\" version=\"") + tre_version() + "\"",false);
  715 #endif
  716 #ifdef HAVE_HASHDB
  717     xmlout("library", "", std::string("name=\"hashdb\" version=\"") + hashdb_version() + "\"",false);
  718 #endif
  719 #ifdef SQLITE_VERSION
  720     xmlout("library", "", "name=\"sqlite\" version=\"" SQLITE_VERSION "\" source_id=\"" SQLITE_SOURCE_ID "\"",false);
  721 #endif
  722 #ifdef HAVE_GNUEXIF
  723     // gnuexif does not have a programmatically obtainable version.
  724     xmlout("library","","name=\"gnuexif\" version=\"?\"",false);
  725 #endif
  726 #ifdef GIT_COMMIT
  727     xmlout("git", "", "commit=\"" GIT_COMMIT "\"",false);
  728 #endif
  729     pop();
  730 }
  731