"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("<");
126 static string xml_gt(">");
127 static string xml_am("&");
128 static string xml_ap("'");
129 static string xml_qu(""");
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