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