1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 /*
15  * PS 3.15 / E.1 / Basic Application Level Confidentiality Profile
16  * Implementation of E.1.1 De-identify & E.1.2 Re-identify
17  */
18 
19 #include <memory>
20 
21 #include "gdcmReader.h"
22 #include "gdcmWriter.h"
23 #include "gdcmVersion.h"
24 #include "gdcmSystem.h"
25 #include "gdcmCryptoFactory.h"
26 #include "gdcmUIDGenerator.h"
27 #include "gdcmAnonymizer.h"
28 #include "gdcmGlobal.h"
29 #include "gdcmDefs.h"
30 #include "gdcmDirectory.h"
31 
32 #include <getopt.h>
33 
34 
PrintVersion()35 static void PrintVersion()
36 {
37   std::cout << "gdcmanon: gdcm " << gdcm::Version::GetVersion() << " ";
38   const char date[] = "$Date$";
39   std::cout << date << std::endl;
40 }
41 
42 // FIXME
43   int deidentify = 0;
44   int reidentify = 0;
45 
46 
AnonymizeOneFileDumb(gdcm::Anonymizer & anon,const char * filename,const char * outfilename,std::vector<gdcm::Tag> const & empty_tags,std::vector<gdcm::Tag> const & remove_tags,std::vector<std::pair<gdcm::Tag,std::string>> const & replace_tags,bool continuemode=false)47 static bool AnonymizeOneFileDumb(gdcm::Anonymizer &anon, const char *filename, const char *outfilename,
48   std::vector<gdcm::Tag> const &empty_tags, std::vector<gdcm::Tag> const &remove_tags, std::vector< std::pair<gdcm::Tag, std::string> > const & replace_tags, bool continuemode = false)
49 {
50   gdcm::Reader reader;
51   reader.SetFileName( filename );
52   if( !reader.Read() )
53     {
54     std::cerr << "Could not read : " << filename;
55     if( continuemode )
56       {
57       std::cerr << " -> Skipping from anonymization process (continue mode)." << std::endl;
58       return true;
59       }
60     else
61       {
62       std::cerr << " -> Check [--continue] option for skipping files." << std::endl;
63       return false;
64       }
65     }
66   gdcm::File &file = reader.GetFile();
67 
68   anon.SetFile( file );
69 
70   if( empty_tags.empty() && replace_tags.empty() && remove_tags.empty() )
71     {
72     std::cerr << "No operation to be done." << std::endl;
73     return false;
74     }
75 
76   std::vector<gdcm::Tag>::const_iterator it = empty_tags.begin();
77   bool success = true;
78   for(; it != empty_tags.end(); ++it)
79     {
80     success = success && anon.Empty( *it );
81     }
82   it = remove_tags.begin();
83   for(; it != remove_tags.end(); ++it)
84     {
85     success = success && anon.Remove( *it );
86     }
87 
88   std::vector< std::pair<gdcm::Tag, std::string> >::const_iterator it2 = replace_tags.begin();
89   for(; it2 != replace_tags.end(); ++it2)
90     {
91     success = success && anon.Replace( it2->first, it2->second.c_str() );
92     }
93 
94   gdcm::Writer writer;
95   writer.SetFileName( outfilename );
96   writer.SetFile( file );
97   if( !writer.Write() )
98     {
99     std::cerr << "Could not Write : " << outfilename << std::endl;
100     if( strcmp(filename,outfilename) != 0 )
101       {
102       gdcm::System::RemoveFile( outfilename );
103       }
104     else
105       {
106       std::cerr << "gdcmanon just corrupted: " << filename << " for you (data lost)." << std::endl;
107       }
108 
109     return false;
110     }
111   return success;
112 }
113 
AnonymizeOneFile(gdcm::Anonymizer & anon,const char * filename,const char * outfilename,bool continuemode=false)114 static bool AnonymizeOneFile(gdcm::Anonymizer &anon, const char *filename, const char *outfilename, bool continuemode = false)
115 {
116   gdcm::Reader reader;
117   reader.SetFileName( filename );
118   if( !reader.Read() )
119     {
120     std::cerr << "Could not read : " << filename << std::endl;
121     if( continuemode )
122       {
123       std::cerr << "Skipping from anonymization process (continue mode)." << std::endl;
124       return true;
125       }
126     else
127       {
128       std::cerr << "Check [--continue] option for skipping files." << std::endl;
129       return false;
130       }
131     }
132   gdcm::File &file = reader.GetFile();
133   gdcm::MediaStorage ms;
134   ms.SetFromFile(file);
135   if( !gdcm::Defs::GetIODNameFromMediaStorage(ms) )
136     {
137     std::cerr << "The Media Storage Type of your file is not supported: " << ms << std::endl;
138     std::cerr << "Please report" << std::endl;
139     return false;
140     }
141 
142   anon.SetFile( file );
143 
144   if( deidentify )
145     {
146     //anon.RemovePrivateTags();
147     //anon.RemoveRetired();
148     if( !anon.BasicApplicationLevelConfidentialityProfile( true ) )
149       {
150       std::cerr << "Could not De-indentify : " << filename << std::endl;
151       return false;
152       }
153     }
154   else if ( reidentify )
155     {
156     if( !anon.BasicApplicationLevelConfidentialityProfile( false ) )
157       {
158       std::cerr << "Could not Re-indentify : " << filename << std::endl;
159       return false;
160       }
161     }
162 
163   gdcm::FileMetaInformation &fmi = file.GetHeader();
164   fmi.Clear();
165 
166   gdcm::Writer writer;
167   writer.SetFileName( outfilename );
168   writer.SetFile( file );
169   if( !writer.Write() )
170     {
171     std::cerr << "Could not Write : " << outfilename << std::endl;
172     if( strcmp(filename,outfilename) != 0 )
173       {
174       gdcm::System::RemoveFile( outfilename );
175       }
176     else
177       {
178       std::cerr << "gdcmanon just corrupted: " << filename << " for you (data lost)." << std::endl;
179       }
180 
181     return false;
182     }
183   return true;
184 }
185 
GetRSAKeys(gdcm::CryptographicMessageSyntax & cms,const char * privpath=nullptr,const char * certpath=nullptr)186 static bool GetRSAKeys(gdcm::CryptographicMessageSyntax &cms, const char *privpath = nullptr, const char *certpath = nullptr)
187 {
188   if( privpath && *privpath )
189     {
190     if( !cms.ParseKeyFile( privpath ) )
191       {
192       std::cerr << "Could not parse Private Key: " << privpath << std::endl;
193       return false;
194       }
195     }
196 
197   if( certpath && *certpath )
198     {
199     if( !cms.ParseCertificateFile( certpath ) )
200       {
201       std::cerr << "Could not parse Certificate Key: " << certpath << std::endl;
202       return false;
203       }
204     }
205   return true;
206 }
207 
PrintHelp()208 static void PrintHelp()
209 {
210   PrintVersion();
211   std::cout << "Usage: gdcmanon [OPTION]... FILE..." << std::endl;
212   std::cout << "PS 3.15 / E.1 / Basic Application Level Confidentiality Profile" << std::endl;
213   std::cout << "Implementation of E.1.1 De-identify & E.1.2 Re-identify" << std::endl;
214   std::cout << "Parameter (required):" << std::endl;
215   std::cout << "  -e --de-identify (encrypt)  De-identify DICOM (default)" << std::endl;
216   std::cout << "  -d --re-identify (decrypt)  Re-identify DICOM" << std::endl;
217   std::cout << "     --dumb                   Dumb mode anonymizer" << std::endl;
218   std::cout << "Options:" << std::endl;
219   std::cout << "  -i --input                  DICOM filename / directory" << std::endl;
220   std::cout << "  -o --output                 DICOM filename / directory" << std::endl;
221   std::cout << "  -r --recursive              recursively process (sub-)directories." << std::endl;
222   std::cout << "     --continue               Do not stop when file found is not DICOM." << std::endl;
223   std::cout << "     --root-uid               Root UID." << std::endl;
224   std::cout << "     --resources-path         Resources path." << std::endl;
225   std::cout << "  -k --key                    Path to RSA Private Key." << std::endl;
226   std::cout << "  -c --certificate            Path to Certificate." << std::endl;
227   std::cout << "  -p --password               Encryption passphrase." << std::endl;
228   std::cout << "Crypto Library Options:" << std::endl;
229   std::cout << "  --crypto=" << std::endl;
230   std::cout << "           openssl            OpenSSL (default on non-Windows systems)." << std::endl;
231   std::cout << "           capi               Microsoft CryptoAPI (default on Windows systems)." << std::endl;
232   std::cout << "           openssl-p7         Old OpenSSL implementation." << std::endl;
233   std::cout << "Encryption Algorithm Options:" << std::endl;
234   std::cout << "     --des3                   Triple DES." << std::endl;
235   std::cout << "     --aes128                 AES 128." << std::endl;
236   std::cout << "     --aes192                 AES 192." << std::endl;
237   std::cout << "     --aes256                 AES 256 (default)." << std::endl;
238   std::cout << "Dumb mode options:" << std::endl;
239   std::cout << "     --empty   %d,%d          DICOM tag(s) to empty" << std::endl;
240   std::cout << "     --remove  %d,%d          DICOM tag(s) to remove" << std::endl;
241   std::cout << "     --replace %d,%d=%s       DICOM tag(s) to replace" << std::endl;
242   std::cout << "General Options:" << std::endl;
243   std::cout << "  -V --verbose                more verbose (warning+error)." << std::endl;
244   std::cout << "  -W --warning                print warning info." << std::endl;
245   std::cout << "  -D --debug                  print debug info." << std::endl;
246   std::cout << "  -E --error                  print error info." << std::endl;
247   std::cout << "  -h --help                   print help." << std::endl;
248   std::cout << "  -v --version                print version." << std::endl;
249   std::cout << "Env var:" << std::endl;
250   std::cout << "  GDCM_ROOT_UID Root UID" << std::endl;
251   std::cout << "  GDCM_RESOURCES_PATH path pointing to resources files (Part3.xml, ...)" << std::endl;
252 }
253 
GetFromString(const char * str)254 static gdcm::CryptographicMessageSyntax::CipherTypes GetFromString( const char * str )
255 {
256   gdcm::CryptographicMessageSyntax::CipherTypes ciphertype;
257   if( strcmp( str, "des3" ) == 0 )
258     {
259     ciphertype = gdcm::CryptographicMessageSyntax::DES3_CIPHER;
260     }
261   else if( strcmp( str, "aes128" ) == 0 )
262     {
263     ciphertype = gdcm::CryptographicMessageSyntax::AES128_CIPHER;
264     }
265   else if( strcmp( str, "aes192" ) == 0 )
266     {
267     ciphertype = gdcm::CryptographicMessageSyntax::AES192_CIPHER;
268     }
269   else if( strcmp( str, "aes256" ) == 0 )
270     {
271     ciphertype = gdcm::CryptographicMessageSyntax::AES256_CIPHER;
272     }
273   else
274     {
275     // if unrecognized return aes 256...
276     ciphertype = gdcm::CryptographicMessageSyntax::AES256_CIPHER;
277     }
278   return ciphertype;
279 }
280 
main(int argc,char * argv[])281 int main(int argc, char *argv[])
282 {
283   int c;
284   //int digit_optind = 0;
285 
286   std::string filename;
287   gdcm::Directory::FilenamesType filenames;
288   std::string outfilename;
289   gdcm::Directory::FilenamesType outfilenames;
290   std::string root;
291   std::string xmlpath;
292   std::string rsa_path;
293   std::string cert_path;
294   std::string password;
295   int resourcespath = 0;
296   int dumb_mode = 0;
297   int des3 = 0;
298   int aes128 = 0;
299   int aes192 = 0;
300   int aes256 = 0;
301   int rootuid = 0;
302   int verbose = 0;
303   int warning = 0;
304   int debug = 0;
305   int error = 0;
306   int help = 0;
307   int version = 0;
308   int recursive = 0;
309   int continuemode = 0;
310   int empty_tag = 0;
311   int remove_tag = 0;
312   int replace_tag = 0;
313   int crypto_api = 0;
314   std::vector<gdcm::Tag> empty_tags;
315   std::vector<gdcm::Tag> remove_tags;
316   std::vector< std::pair<gdcm::Tag, std::string> > replace_tags_value;
317   gdcm::Tag tag;
318   gdcm::CryptoFactory::CryptoLib crypto_lib;
319   crypto_lib = gdcm::CryptoFactory::DEFAULT;
320 
321   while (true) {
322     //int this_option_optind = optind ? optind : 1;
323     int option_index = 0;
324     static struct option long_options[] = {
325         {"input", required_argument, nullptr, 'i'},                 // i
326         {"output", required_argument, nullptr, 'o'},                // o
327         {"root-uid", required_argument, &rootuid, 1}, // specific Root (not GDCM)
328         {"resources-path", required_argument, &resourcespath, 1},
329         {"de-identify", no_argument, nullptr, 'e'},
330         {"re-identify", no_argument, nullptr, 'd'},
331         {"key", required_argument, nullptr, 'k'},
332         {"certificate", required_argument, nullptr, 'c'}, // 7
333         {"password", required_argument, nullptr, 'p'},
334 
335         {"des3", no_argument, &des3, 1},
336         {"aes128", no_argument, &aes128, 1},
337         {"aes192", no_argument, &aes192, 1},
338         {"aes256", no_argument, &aes256, 1},
339 
340         {"recursive", no_argument, nullptr, 'r'},
341         {"dumb", no_argument, &dumb_mode, 1},
342         {"empty", required_argument, &empty_tag, 1}, // 15
343         {"remove", required_argument, &remove_tag, 1},
344         {"replace", required_argument, &replace_tag, 1},
345         {"continue", no_argument, &continuemode, 1},
346         {"crypto", required_argument, &crypto_api, 1}, //19
347 
348         {"verbose", no_argument, nullptr, 'V'},
349         {"warning", no_argument, nullptr, 'W'},
350         {"debug", no_argument, nullptr, 'D'},
351         {"error", no_argument, nullptr, 'E'},
352         {"help", no_argument, nullptr, 'h'},
353         {"version", no_argument, nullptr, 'v'},
354 
355         {nullptr, 0, nullptr, 0}
356     };
357 
358     c = getopt_long (argc, argv, "i:o:rdek:c:p:VWDEhv",
359       long_options, &option_index);
360     if (c == -1)
361       {
362       break;
363       }
364 
365     switch (c)
366       {
367     case 0:
368         {
369         const char *s = long_options[option_index].name; (void)s;
370         //printf ("option %s", s);
371         if (optarg)
372           {
373           //if( option_index == 0 ) /* input */
374           //  {
375           //  assert( strcmp(s, "input") == 0 );
376           //  assert( filename.empty() );
377           //  filename = optarg;
378           //  }
379           //else if( option_index == 1 ) /* output */
380           //  {
381           //  assert( strcmp(s, "output") == 0 );
382           //  assert( outfilename.empty() );
383           //  outfilename = optarg;
384           //  }
385           /*else*/ if( option_index == 2 ) /* root-uid */
386             {
387             assert( strcmp(s, "root-uid") == 0 );
388             assert( root.empty() );
389             root = optarg;
390             }
391           else if( option_index == 3 ) /* resources-path */
392             {
393             assert( strcmp(s, "resources-path") == 0 );
394             assert( xmlpath.empty() );
395             xmlpath = optarg;
396             }
397           //else if( option_index == 6 ) /* key */
398           //  {
399           //  assert( strcmp(s, "key") == 0 );
400           //  assert( rsa_path.empty() );
401           //  rsa_path = optarg;
402           //  }
403           //else if( option_index == 7 ) /* certificate */
404           //  {
405           //  assert( strcmp(s, "certificate") == 0 );
406           //  assert( cert_path.empty() );
407           //  cert_path = optarg;
408           //  }
409           else if( option_index == 15 ) /* empty */
410             {
411             assert( strcmp(s, "empty") == 0 );
412             if( !tag.ReadFromCommaSeparatedString(optarg) )
413               {
414               std::cerr << "Could not read Tag: " << optarg << std::endl;
415               return 1;
416               }
417             empty_tags.push_back( tag );
418             }
419           else if( option_index == 16 ) /* remove */
420             {
421             assert( strcmp(s, "remove") == 0 );
422             if( !tag.ReadFromCommaSeparatedString(optarg) )
423               {
424               std::cerr << "Could not read Tag: " << optarg << std::endl;
425               return 1;
426               }
427             remove_tags.push_back( tag );
428             }
429           else if( option_index == 17 ) /* replace */
430             {
431             assert( strcmp(s, "replace") == 0 );
432             if( !tag.ReadFromCommaSeparatedString(optarg) )
433               {
434               std::cerr << "Could not read Tag: " << optarg << std::endl;
435               return 1;
436               }
437             std::stringstream ss;
438             ss.str( optarg );
439             uint16_t dummy;
440             char cdummy; // comma
441             ss >> std::hex >> dummy;
442             assert( tag.GetGroup() == dummy );
443             ss >> cdummy;
444             assert( cdummy == ',' );
445             ss >> std::hex >> dummy;
446             assert( tag.GetElement() == dummy );
447             ss >> cdummy;
448             assert( cdummy == ',' || cdummy == '=' );
449             std::string str;
450             //ss >> str;
451             std::getline(ss, str); // do not skip whitespace
452             replace_tags_value.emplace_back(tag, str );
453             }
454           else if( option_index == 19 ) /* crypto */
455             {
456             assert( strcmp(s, "crypto") == 0 );
457             if (strcmp(optarg, "openssl") == 0)
458               crypto_lib = gdcm::CryptoFactory::OPENSSL;
459             else if (strcmp(optarg, "capi") == 0)
460               crypto_lib = gdcm::CryptoFactory::CAPI;
461             else if (strcmp(optarg, "openssl-p7") == 0)
462               crypto_lib = gdcm::CryptoFactory::OPENSSLP7;
463             else
464               {
465               std::cerr << "Cryptography library id not recognized: " << optarg << std::endl;
466               return 1;
467               }
468             }
469           //printf (" with arg %s", optarg);
470           }
471         //printf ("\n");
472         }
473       break;
474 
475     case 'i':
476       assert( filename.empty() );
477       filename = optarg;
478       break;
479 
480     case 'o':
481       assert( outfilename.empty() );
482       outfilename = optarg;
483       break;
484 
485     case 'r':
486       recursive = 1;
487       break;
488 
489     case 'k': // key
490       assert( rsa_path.empty() );
491       rsa_path = optarg;
492       break;
493 
494     case 'c': // certificate
495       assert( cert_path.empty() );
496       cert_path = optarg;
497       break;
498 
499     case 'p': // password
500       assert( password.empty() );
501       password = optarg;
502       break;
503 
504     case 'e': // encrypt
505       deidentify = 1;
506       break;
507 
508     case 'd': // decrypt
509       reidentify = 1;
510       break;
511 
512     case 'V':
513       verbose = 1;
514       break;
515 
516     case 'W':
517       warning = 1;
518       break;
519 
520     case 'D':
521       debug = 1;
522       break;
523 
524     case 'E':
525       error = 1;
526       break;
527 
528     case 'h':
529       help = 1;
530       break;
531 
532     case 'v':
533       version = 1;
534       break;
535 
536     case '?':
537       break;
538 
539     default:
540       printf ("?? getopt returned character code 0%o ??\n", c);
541       }
542   }
543 
544   if (optind < argc)
545     {
546     std::vector<std::string> files;
547     while (optind < argc)
548       {
549       //printf ("%s\n", argv[optind++]);
550       files.emplace_back(argv[optind++] );
551       }
552     //printf ("\n");
553     if( files.size() == 2
554       && filename.empty()
555       && outfilename.empty()
556     )
557       {
558       filename = files[0];
559       outfilename = files[1];
560       }
561     else
562       {
563       PrintHelp();
564       return 1;
565       }
566     }
567 
568   if( version )
569     {
570     //std::cout << "version" << std::endl;
571     PrintVersion();
572     return 0;
573     }
574 
575   if( help )
576     {
577     //std::cout << "help" << std::endl;
578     PrintHelp();
579     return 0;
580     }
581 
582   if( filename.empty() )
583     {
584     //std::cerr << "Need input file (-i)\n";
585     PrintHelp();
586     return 1;
587     }
588 
589   // by default de-identify
590   if( !deidentify && !reidentify && !dumb_mode)
591     {
592     deidentify = 1;
593     }
594 
595   // one option only please
596   if( deidentify && reidentify )
597     {
598     std::cerr << "One option please" << std::endl;
599     return 1;
600     }
601   // dumb mode vs smart mode:
602   if( ( deidentify || reidentify ) && dumb_mode )
603     {
604     std::cerr << "One option please" << std::endl;
605     return 1;
606     }
607 
608   gdcm::CryptoFactory* crypto_factory = nullptr;
609   if( deidentify || reidentify )
610     {
611     crypto_factory = gdcm::CryptoFactory::GetFactoryInstance(crypto_lib);
612     if (!crypto_factory)
613       {
614       std::cerr << "Requested cryptographic library not configured." << std::endl;
615       return 1;
616       }
617     }
618 
619   // by default AES 256
620   gdcm::CryptographicMessageSyntax::CipherTypes ciphertype =
621     gdcm::CryptographicMessageSyntax::AES256_CIPHER;
622   if( !dumb_mode )
623     {
624     if( !des3 && !aes128 && !aes192 && !aes256 )
625       {
626       aes256 = 1;
627       }
628 
629     if( des3 )
630       {
631       ciphertype = GetFromString( "des3" );
632       }
633     else if( aes128 )
634       {
635       ciphertype = GetFromString( "aes128" );
636       }
637     else if( aes192 )
638       {
639       ciphertype = GetFromString( "aes192" );
640       }
641     else if( aes256 )
642       {
643       ciphertype = GetFromString( "aes256" );
644       }
645     else
646       {
647       return 1;
648       }
649     }
650 
651   if( !gdcm::System::FileExists(filename.c_str()) )
652     {
653     std::cerr << "Could not find file: " << filename << std::endl;
654     return 1;
655     }
656 
657   // Are we in single file or directory mode:
658   unsigned int nfiles = 1;
659   gdcm::Directory dir;
660   if( gdcm::System::FileIsDirectory(filename.c_str()) )
661     {
662     if( !gdcm::System::FileIsDirectory(outfilename.c_str()) )
663       {
664       if( gdcm::System::FileExists( outfilename.c_str() ) )
665         {
666         std::cerr << "Could not create directory since " << outfilename << " is already a file" << std::endl;
667         return 1;
668         }
669 
670       }
671     // For now avoid user mistake
672     if( filename == outfilename )
673       {
674       std::cerr << "Input directory should be different from output directory" << std::endl;
675       return 1;
676       }
677     if( outfilename.back() != '/' ) outfilename += '/';
678     nfiles = dir.Load(filename, (recursive > 0 ? true : false));
679     filenames = dir.GetFilenames();
680     gdcm::Directory::FilenamesType::const_iterator it = filenames.begin();
681     // Prepare outfilenames
682     for( ; it != filenames.end(); ++it )
683       {
684       std::string dup = *it; // make a copy
685       std::string &out = dup.replace(0, filename.size(), outfilename );
686       outfilenames.push_back( out );
687       }
688     // Prepare outdirectory
689     gdcm::Directory::FilenamesType const &dirs = dir.GetDirectories();
690     gdcm::Directory::FilenamesType::const_iterator itdir = dirs.begin();
691     for( ; itdir != dirs.end(); ++itdir )
692       {
693       std::string dirdup = *itdir; // make a copy
694       std::string &dirout = dirdup.replace(0, filename.size(), outfilename );
695       //std::cout << "Making directory: " << dirout << std::endl;
696       if( !gdcm::System::MakeDirectory( dirout.c_str() ) )
697         {
698         std::cerr << "Could not create directory: " << dirout << std::endl;
699         return 1;
700         }
701       }
702     }
703   else
704     {
705     filenames.push_back( filename );
706     outfilenames.push_back( outfilename );
707     }
708 
709   if( filenames.size() != outfilenames.size() )
710     {
711     std::cerr << "Something went really wrong" << std::endl;
712     return 1;
713     }
714 
715   // Debug is a little too verbose
716   gdcm::Trace::SetDebug( (debug  > 0 ? true : false));
717   gdcm::Trace::SetWarning(  (warning  > 0 ? true : false));
718   gdcm::Trace::SetError(  (error  > 0 ? true : false));
719   // when verbose is true, make sure warning+error are turned on:
720   if( verbose )
721     {
722     gdcm::Trace::SetWarning( (verbose > 0 ? true : false) );
723     gdcm::Trace::SetError( (verbose  > 0 ? true : false) );
724     }
725 
726   gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmanon" );
727   if( !dumb_mode )
728   {
729     gdcm::Global& g = gdcm::Global::GetInstance();
730     if( !resourcespath )
731       {
732       const char *xmlpathenv = getenv("GDCM_RESOURCES_PATH");
733       if( xmlpathenv )
734         {
735         // Make sure to look for XML dict in user explicitly specified dir first:
736         xmlpath = xmlpathenv;
737         resourcespath = 1;
738         }
739       }
740     if( resourcespath )
741       {
742       // xmlpath is set either by the cmd line option or the env var
743       if( !g.Prepend( xmlpath.c_str() ) )
744         {
745         std::cerr << "Specified Resources Path is not valid: " << xmlpath << std::endl;
746         return 1;
747         }
748       }
749     // All set, then load the XML files:
750     if( !g.LoadResourcesFiles() )
751       {
752       std::cerr << "Could not load XML file from specified path" << std::endl;
753       return 1;
754       }
755     const gdcm::Defs &defs = g.GetDefs(); (void)defs;
756   }
757   if( !rootuid )
758     {
759     // only read the env var if no explicit cmd line option
760     // maybe there is an env var defined... let's check
761     const char *rootuid_env = getenv("GDCM_ROOT_UID");
762     if( rootuid_env )
763       {
764       rootuid = 1;
765       root = rootuid_env;
766       }
767     }
768   if( rootuid )
769     {
770     // root is set either by the cmd line option or the env var
771     if( !gdcm::UIDGenerator::IsValid( root.c_str() ) )
772       {
773       std::cerr << "specified Root UID is not valid: " << root << std::endl;
774       return 1;
775       }
776     gdcm::UIDGenerator::SetRoot( root.c_str() );
777     }
778 
779   // Get private key/certificate
780   gdcm::CryptographicMessageSyntax *cms_ptr = nullptr;
781   if( crypto_factory )
782     {
783     cms_ptr = crypto_factory->CreateCMSProvider();
784     }
785   if( !dumb_mode )
786     {
787     if( !GetRSAKeys(*cms_ptr, rsa_path.c_str(), cert_path.c_str() ) )
788       {
789       delete cms_ptr;
790       return 1;
791       }
792     if (!password.empty() && !cms_ptr->SetPassword(password.c_str(), password.length()) )
793       {
794       std::cerr << "Could not set the password " << std::endl;
795       delete cms_ptr;
796       return 1;
797       }
798     cms_ptr->SetCipherType( ciphertype );
799     }
800 
801   // Setup gdcm::Anonymizer
802   gdcm::Anonymizer anon;
803   if( !dumb_mode )
804     {
805     anon.SetCryptographicMessageSyntax( cms_ptr );
806     }
807 
808   if( dumb_mode )
809     {
810     for(unsigned int i = 0; i < nfiles; ++i)
811       {
812       const char *in  = filenames[i].c_str();
813       const char *out = outfilenames[i].c_str();
814       if( !AnonymizeOneFileDumb(anon, in, out, empty_tags, remove_tags, replace_tags_value, (continuemode > 0 ? true: false)) )
815         {
816         //std::cerr << "Could not anonymize: " << in << std::endl;
817         delete cms_ptr;
818         return 1;
819         }
820       }
821     }
822   else
823     {
824     for(unsigned int i = 0; i < nfiles; ++i)
825       {
826       const char *in  = filenames[i].c_str();
827       const char *out = outfilenames[i].c_str();
828       if( !AnonymizeOneFile(anon, in, out, (continuemode > 0 ? true: false)) )
829         {
830         //std::cerr << "Could not anonymize: " << in << std::endl;
831         delete cms_ptr;
832         return 1;
833         }
834       }
835     }
836   delete cms_ptr;
837   return 0;
838 }
839