Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomParsing/DicomModification.cpp @ 4737:979ae3ea3381
DANGEROUS commit: Anonymization is now also applied to nested sequences
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 06 Jul 2021 08:12:26 +0200 |
parents | b51c08bd5c38 |
children | 51ec061516c9 |
comparison
equal
deleted
inserted
replaced
4736:bf852fd773b7 | 4737:979ae3ea3381 |
---|---|
42 static const std::string ORTHANC_DEIDENTIFICATION_METHOD_2021b = | 42 static const std::string ORTHANC_DEIDENTIFICATION_METHOD_2021b = |
43 "Orthanc " ORTHANC_VERSION " - PS 3.15-2021b Table E.1-1 Basic Profile"; | 43 "Orthanc " ORTHANC_VERSION " - PS 3.15-2021b Table E.1-1 Basic Profile"; |
44 | 44 |
45 namespace Orthanc | 45 namespace Orthanc |
46 { | 46 { |
47 namespace | |
48 { | |
49 enum TagOperation | |
50 { | |
51 TagOperation_Keep, | |
52 TagOperation_Remove | |
53 }; | |
54 } | |
55 | |
56 | |
47 DicomModification::DicomTagRange::DicomTagRange(uint16_t groupFrom, | 57 DicomModification::DicomTagRange::DicomTagRange(uint16_t groupFrom, |
48 uint16_t groupTo, | 58 uint16_t groupTo, |
49 uint16_t elementFrom, | 59 uint16_t elementFrom, |
50 uint16_t elementTo) : | 60 uint16_t elementTo) : |
51 groupFrom_(groupFrom), | 61 groupFrom_(groupFrom), |
74 bool IsManuallyModified(const DicomTag& tag) const | 84 bool IsManuallyModified(const DicomTag& tag) const |
75 { | 85 { |
76 return (that_.IsCleared(tag) || | 86 return (that_.IsCleared(tag) || |
77 that_.IsRemoved(tag) || | 87 that_.IsRemoved(tag) || |
78 that_.IsReplaced(tag)); | 88 that_.IsReplaced(tag)); |
79 } | 89 } |
90 | |
91 bool IsKeptSequence(const std::vector<DicomTag>& parentTags, | |
92 const std::vector<size_t>& parentIndexes, | |
93 const DicomTag& tag) | |
94 { | |
95 for (DicomModification::ListOfPaths::const_iterator | |
96 it = that_.keepSequences_.begin(); it != that_.keepSequences_.end(); ++it) | |
97 { | |
98 if (DicomPath::IsMatch(*it, parentTags, parentIndexes, tag)) | |
99 { | |
100 return true; | |
101 } | |
102 } | |
103 | |
104 return false; | |
105 } | |
106 | |
107 Action GetDefaultAction(const std::vector<DicomTag>& parentTags, | |
108 const std::vector<size_t>& parentIndexes, | |
109 const DicomTag& tag) | |
110 { | |
111 if (parentTags.empty() || | |
112 !that_.isAnonymization_) | |
113 { | |
114 // Don't interfere with first-level tags or with modification | |
115 return Action_None; | |
116 } | |
117 else if (IsKeptSequence(parentTags, parentIndexes, tag)) | |
118 { | |
119 return Action_None; | |
120 } | |
121 else if (that_.ArePrivateTagsRemoved() && | |
122 tag.IsPrivate()) | |
123 { | |
124 // New in Orthanc 1.9.5 | |
125 // https://groups.google.com/g/orthanc-users/c/l1mcYCC2u-k/m/jOdGYuagAgAJ | |
126 return Action_Remove; | |
127 } | |
128 else if (that_.IsCleared(tag) || | |
129 that_.IsRemoved(tag)) | |
130 { | |
131 // New in Orthanc 1.9.5 | |
132 // https://groups.google.com/g/orthanc-users/c/l1mcYCC2u-k/m/jOdGYuagAgAJ | |
133 return Action_Remove; | |
134 } | |
135 else | |
136 { | |
137 return Action_None; | |
138 } | |
139 } | |
80 | 140 |
81 public: | 141 public: |
82 explicit RelationshipsVisitor(DicomModification& that) : | 142 explicit RelationshipsVisitor(DicomModification& that) : |
83 that_(that) | 143 that_(that) |
84 { | 144 { |
87 virtual Action VisitNotSupported(const std::vector<DicomTag>& parentTags, | 147 virtual Action VisitNotSupported(const std::vector<DicomTag>& parentTags, |
88 const std::vector<size_t>& parentIndexes, | 148 const std::vector<size_t>& parentIndexes, |
89 const DicomTag& tag, | 149 const DicomTag& tag, |
90 ValueRepresentation vr) ORTHANC_OVERRIDE | 150 ValueRepresentation vr) ORTHANC_OVERRIDE |
91 { | 151 { |
92 return Action_None; | 152 return GetDefaultAction(parentTags, parentIndexes, tag); |
93 } | 153 } |
94 | 154 |
95 virtual Action VisitEmptySequence(const std::vector<DicomTag>& parentTags, | 155 virtual Action VisitSequence(const std::vector<DicomTag>& parentTags, |
96 const std::vector<size_t>& parentIndexes, | 156 const std::vector<size_t>& parentIndexes, |
97 const DicomTag& tag) ORTHANC_OVERRIDE | 157 const DicomTag& tag, |
98 { | 158 size_t countItems) ORTHANC_OVERRIDE |
99 return Action_None; | 159 { |
160 return GetDefaultAction(parentTags, parentIndexes, tag); | |
100 } | 161 } |
101 | 162 |
102 virtual Action VisitBinary(const std::vector<DicomTag>& parentTags, | 163 virtual Action VisitBinary(const std::vector<DicomTag>& parentTags, |
103 const std::vector<size_t>& parentIndexes, | 164 const std::vector<size_t>& parentIndexes, |
104 const DicomTag& tag, | 165 const DicomTag& tag, |
105 ValueRepresentation vr, | 166 ValueRepresentation vr, |
106 const void* data, | 167 const void* data, |
107 size_t size) ORTHANC_OVERRIDE | 168 size_t size) ORTHANC_OVERRIDE |
108 { | 169 { |
109 return Action_None; | 170 return GetDefaultAction(parentTags, parentIndexes, tag); |
110 } | 171 } |
111 | 172 |
112 virtual Action VisitIntegers(const std::vector<DicomTag>& parentTags, | 173 virtual Action VisitIntegers(const std::vector<DicomTag>& parentTags, |
113 const std::vector<size_t>& parentIndexes, | 174 const std::vector<size_t>& parentIndexes, |
114 const DicomTag& tag, | 175 const DicomTag& tag, |
115 ValueRepresentation vr, | 176 ValueRepresentation vr, |
116 const std::vector<int64_t>& values) ORTHANC_OVERRIDE | 177 const std::vector<int64_t>& values) ORTHANC_OVERRIDE |
117 { | 178 { |
118 return Action_None; | 179 return GetDefaultAction(parentTags, parentIndexes, tag); |
119 } | 180 } |
120 | 181 |
121 virtual Action VisitDoubles(const std::vector<DicomTag>& parentTags, | 182 virtual Action VisitDoubles(const std::vector<DicomTag>& parentTags, |
122 const std::vector<size_t>& parentIndexes, | 183 const std::vector<size_t>& parentIndexes, |
123 const DicomTag& tag, | 184 const DicomTag& tag, |
124 ValueRepresentation vr, | 185 ValueRepresentation vr, |
125 const std::vector<double>& value) ORTHANC_OVERRIDE | 186 const std::vector<double>& value) ORTHANC_OVERRIDE |
126 { | 187 { |
127 return Action_None; | 188 return GetDefaultAction(parentTags, parentIndexes, tag); |
128 } | 189 } |
129 | 190 |
130 virtual Action VisitAttributes(const std::vector<DicomTag>& parentTags, | 191 virtual Action VisitAttributes(const std::vector<DicomTag>& parentTags, |
131 const std::vector<size_t>& parentIndexes, | 192 const std::vector<size_t>& parentIndexes, |
132 const DicomTag& tag, | 193 const DicomTag& tag, |
133 const std::vector<DicomTag>& value) ORTHANC_OVERRIDE | 194 const std::vector<DicomTag>& value) ORTHANC_OVERRIDE |
134 { | 195 { |
135 return Action_None; | 196 return GetDefaultAction(parentTags, parentIndexes, tag); |
136 } | 197 } |
137 | 198 |
138 virtual Action VisitString(std::string& newValue, | 199 virtual Action VisitString(std::string& newValue, |
139 const std::vector<DicomTag>& parentTags, | 200 const std::vector<DicomTag>& parentTags, |
140 const std::vector<size_t>& parentIndexes, | 201 const std::vector<size_t>& parentIndexes, |
185 } | 246 } |
186 else | 247 else |
187 { | 248 { |
188 // We are within a sequence | 249 // We are within a sequence |
189 | 250 |
190 if (!that_.keepSequences_.empty()) | 251 if (IsKeptSequence(parentTags, parentIndexes, tag)) |
191 { | 252 { |
192 // New in Orthanc 1.9.4 - Solves issue LSD-629 | 253 // New in Orthanc 1.9.4 - Solves issue LSD-629 |
193 DicomPath path(parentTags, parentIndexes, tag); | 254 return Action_None; |
194 | 255 } |
195 for (ListOfPaths::const_iterator it = that_.keepSequences_.begin(); | 256 |
196 it != that_.keepSequences_.end(); ++it) | 257 if (that_.isAnonymization_) |
258 { | |
259 // New in Orthanc 1.9.5, similar to "GetDefaultAction()" | |
260 // https://groups.google.com/g/orthanc-users/c/l1mcYCC2u-k/m/jOdGYuagAgAJ | |
261 if (that_.ArePrivateTagsRemoved() && | |
262 tag.IsPrivate()) | |
197 { | 263 { |
198 if (DicomPath::IsMatch(*it, path)) | 264 return Action_Remove; |
199 { | 265 } |
200 return Action_None; | 266 else if (that_.IsRemoved(tag)) |
201 } | 267 { |
268 return Action_Remove; | |
269 } | |
270 else if (that_.IsCleared(tag)) | |
271 { | |
272 // This is different from "GetDefaultAction()", because we know how to clear string tags | |
273 newValue.clear(); | |
274 return Action_Replace; | |
202 } | 275 } |
203 } | 276 } |
204 | 277 |
205 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) | 278 if (tag == DICOM_TAG_STUDY_INSTANCE_UID) |
206 { | 279 { |
1104 } | 1177 } |
1105 | 1178 |
1106 | 1179 |
1107 static void ParseListOfTags(DicomModification& target, | 1180 static void ParseListOfTags(DicomModification& target, |
1108 const Json::Value& query, | 1181 const Json::Value& query, |
1109 DicomModification::TagOperation operation, | 1182 TagOperation operation, |
1110 bool force) | 1183 bool force) |
1111 { | 1184 { |
1112 if (!query.isArray()) | 1185 if (!query.isArray()) |
1113 { | 1186 { |
1114 throw OrthancException(ErrorCode_BadRequest); | 1187 throw OrthancException(ErrorCode_BadRequest); |
1129 !force && | 1202 !force && |
1130 IsDatabaseKey(path.GetFinalTag())) | 1203 IsDatabaseKey(path.GetFinalTag())) |
1131 { | 1204 { |
1132 throw OrthancException(ErrorCode_BadRequest, | 1205 throw OrthancException(ErrorCode_BadRequest, |
1133 "Marking tag \"" + name + "\" as to be " + | 1206 "Marking tag \"" + name + "\" as to be " + |
1134 (operation == DicomModification::TagOperation_Keep ? "kept" : "removed") + | 1207 (operation == TagOperation_Keep ? "kept" : "removed") + |
1135 " requires the \"Force\" option to be set to true"); | 1208 " requires the \"Force\" option to be set to true"); |
1136 } | 1209 } |
1137 | 1210 |
1138 switch (operation) | 1211 switch (operation) |
1139 { | 1212 { |
1140 case DicomModification::TagOperation_Keep: | 1213 case TagOperation_Keep: |
1141 target.Keep(path); | 1214 target.Keep(path); |
1142 LOG(TRACE) << "Keep: " << name << " = " << path.Format(); | 1215 LOG(TRACE) << "Keep: " << name << " = " << path.Format(); |
1143 break; | 1216 break; |
1144 | 1217 |
1145 case DicomModification::TagOperation_Remove: | 1218 case TagOperation_Remove: |
1146 target.Remove(path); | 1219 target.Remove(path); |
1147 LOG(TRACE) << "Remove: " << name << " = " << path.Format(); | 1220 LOG(TRACE) << "Remove: " << name << " = " << path.Format(); |
1148 break; | 1221 break; |
1149 | 1222 |
1150 default: | 1223 default: |