Mercurial > hg > orthanc
comparison Resources/WebAssembly/dcdict.h @ 2513:97a74f0eac7a
loading DICOM dictionaries in sandboxed environments
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 28 Mar 2018 18:02:07 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2512:4dcafa8d6633 | 2513:97a74f0eac7a |
---|---|
1 /* | |
2 * | |
3 * Copyright (C) 1994-2015, OFFIS e.V. | |
4 * All rights reserved. See COPYRIGHT file for details. | |
5 * | |
6 * This software and supporting documentation were developed by | |
7 * | |
8 * OFFIS e.V. | |
9 * R&D Division Health | |
10 * Escherweg 2 | |
11 * D-26121 Oldenburg, Germany | |
12 * | |
13 * | |
14 * Module: dcmdata | |
15 * | |
16 * Author: Andrew Hewett | |
17 * | |
18 * Purpose: Interface for loadable DICOM data dictionary | |
19 * | |
20 */ | |
21 | |
22 | |
23 #ifndef DCMDICT_H | |
24 #define DCMDICT_H | |
25 | |
26 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ | |
27 | |
28 #include "dcmtk/ofstd/ofthread.h" | |
29 #include "dcmtk/dcmdata/dchashdi.h" | |
30 | |
31 /// maximum length of a line in the loadable DICOM dictionary | |
32 #define DCM_MAXDICTLINESIZE 2048 | |
33 | |
34 /// maximum number of fields per entry in the loadable DICOM dictionary | |
35 #define DCM_MAXDICTFIELDS 6 | |
36 | |
37 /// environment variable pointing to the data dictionary file | |
38 #define DCM_DICT_ENVIRONMENT_VARIABLE "DCMDICTPATH" | |
39 | |
40 #ifndef DCM_DICT_DEFAULT_PATH | |
41 /* | |
42 ** The default dictionary path is system dependent. It should | |
43 ** be defined in a configuration file included from "osconfig.h" | |
44 */ | |
45 #error "DCM_DICT_DEFAULT_PATH is not defined via osconfig.h" | |
46 #endif /* !DCM_DICT_DEFAULT_PATH */ | |
47 | |
48 #ifndef ENVIRONMENT_PATH_SEPARATOR | |
49 #define ENVIRONMENT_PATH_SEPARATOR '\n' /* at least define something unlikely */ | |
50 #endif | |
51 | |
52 | |
53 /** this class implements a loadable DICOM Data Dictionary | |
54 */ | |
55 class DCMTK_DCMDATA_EXPORT DcmDataDictionary | |
56 { | |
57 public: | |
58 | |
59 /** constructor | |
60 * @param loadBuiltin flag indicating if a built-in data dictionary | |
61 * (if any) should be loaded. | |
62 * @param loadExternal flag indicating if an external data dictionary | |
63 * should be read from file. | |
64 */ | |
65 DcmDataDictionary(OFBool loadBuiltin, OFBool loadExternal); | |
66 | |
67 /// destructor | |
68 ~DcmDataDictionary(); | |
69 | |
70 /** checks if a data dictionary is loaded (excluding the skeleton dictionary) | |
71 * @return true if loaded, false if no dictionary is present | |
72 */ | |
73 OFBool isDictionaryLoaded() const { return dictionaryLoaded; } | |
74 | |
75 /// returns the number of normal (non-repeating) tag entries | |
76 int numberOfNormalTagEntries() const { return hashDict.size(); } | |
77 | |
78 /// returns the number of repeating tag entries | |
79 int numberOfRepeatingTagEntries() const { return OFstatic_cast(int, repDict.size()); } | |
80 | |
81 /** returns the number of dictionary entries that were loaded | |
82 * either from file or from a built-in dictionary or both. | |
83 */ | |
84 int numberOfEntries() const | |
85 { return numberOfNormalTagEntries() | |
86 + numberOfRepeatingTagEntries() - skeletonCount; } | |
87 | |
88 /** returns the number of skeleton entries. The skeleton is a collection | |
89 * of dictionary entries which are always present, even if neither internal | |
90 * nor external dictionary have been loaded. It contains very basic | |
91 * things like item delimitation and sequence delimitation. | |
92 */ | |
93 int numberOfSkeletonEntries() const { return skeletonCount; } | |
94 | |
95 /** reload data dictionaries. First, all dictionary entries are deleted. | |
96 * @param loadBuiltin flag indicating if a built-in data dictionary | |
97 * (if any) should be loaded. | |
98 * @param loadExternal flag indicating if an external data dictionary | |
99 * should be read from file. | |
100 * @return true if reload was successful, false if an error occurred | |
101 */ | |
102 OFBool reloadDictionaries(OFBool loadBuiltin, OFBool loadExternal); | |
103 | |
104 /** load a particular dictionary from file. | |
105 * @param fileName filename | |
106 * @param errorIfAbsent causes the method to return false | |
107 * if the file cannot be opened | |
108 * @return false if the file contains a parse error or if the file could | |
109 * not be opened and errorIfAbsent was set, true otherwise. | |
110 */ | |
111 OFBool loadDictionary(const char* fileName, OFBool errorIfAbsent = OFTrue); | |
112 | |
113 /** dictionary lookup for the given tag key and private creator name. | |
114 * First the normal tag dictionary is searched. If not found | |
115 * then the repeating tag dictionary is searched. | |
116 * @param key tag key | |
117 * @param privCreator private creator name, may be NULL | |
118 */ | |
119 const DcmDictEntry* findEntry(const DcmTagKey& key, const char *privCreator) const; | |
120 | |
121 /** dictionary lookup for the given attribute name. | |
122 * First the normal tag dictionary is searched. If not found | |
123 * then the repeating tag dictionary is searched. | |
124 * Only considers standard attributes (i. e. without private creator) | |
125 * @param name attribute name | |
126 */ | |
127 const DcmDictEntry* findEntry(const char *name) const; | |
128 | |
129 /// deletes all dictionary entries | |
130 void clear(); | |
131 | |
132 /** adds an entry to the dictionary. Must be allocated via new. | |
133 * The entry becomes the property of the dictionary and will be | |
134 * deallocated (via delete) upon clear() or dictionary destruction. | |
135 * If an equivalent entry already exists it will be replaced by | |
136 * the new entry and the old entry deallocated (via delete). | |
137 * @param entry pointer to new entry | |
138 */ | |
139 void addEntry(DcmDictEntry* entry); | |
140 | |
141 /* Iterators to access the normal and the repeating entries */ | |
142 | |
143 /// returns an iterator to the start of the normal (non-repeating) dictionary | |
144 DcmHashDictIterator normalBegin() { return hashDict.begin(); } | |
145 | |
146 /// returns an iterator to the end of the normal (non-repeating) dictionary | |
147 DcmHashDictIterator normalEnd() { return hashDict.end(); } | |
148 | |
149 /// returns an iterator to the start of the repeating tag dictionary | |
150 DcmDictEntryListIterator repeatingBegin() { return repDict.begin(); } | |
151 | |
152 /// returns an iterator to the end of the repeating tag dictionary | |
153 DcmDictEntryListIterator repeatingEnd() { return repDict.end(); } | |
154 | |
155 // Function by the Orthanc project to load a dictionary from a | |
156 // memory buffer, which is necessary in sandboxed | |
157 // environments. This is an adapted version of | |
158 // DcmDataDictionary::loadDictionary(). | |
159 OFBool loadFromMemory(const std::string& content, OFBool errorIfAbsent = OFTrue); | |
160 | |
161 private: | |
162 | |
163 /** private undefined assignment operator | |
164 */ | |
165 DcmDataDictionary &operator=(const DcmDataDictionary &); | |
166 | |
167 /** private undefined copy constructor | |
168 */ | |
169 DcmDataDictionary(const DcmDataDictionary &); | |
170 | |
171 /** loads external dictionaries defined via environment variables | |
172 * @return true if successful | |
173 */ | |
174 OFBool loadExternalDictionaries(); | |
175 | |
176 /** loads a builtin (compiled) data dictionary. | |
177 * Depending on which code is in use, this function may not | |
178 * do anything. | |
179 */ | |
180 void loadBuiltinDictionary(); | |
181 | |
182 /** loads the skeleton dictionary (the bare minimum needed to run) | |
183 * @return true if successful | |
184 */ | |
185 OFBool loadSkeletonDictionary(); | |
186 | |
187 /** looks up the given directory entry in the two dictionaries. | |
188 * @return pointer to entry if found, NULL otherwise | |
189 */ | |
190 const DcmDictEntry* findEntry(const DcmDictEntry& entry) const; | |
191 | |
192 /** deletes the given entry from either dictionary | |
193 */ | |
194 void deleteEntry(const DcmDictEntry& entry); | |
195 | |
196 | |
197 /** dictionary of normal tags | |
198 */ | |
199 DcmHashDict hashDict; | |
200 | |
201 /** dictionary of repeating tags | |
202 */ | |
203 DcmDictEntryList repDict; | |
204 | |
205 /** the number of skeleton entries | |
206 */ | |
207 int skeletonCount; | |
208 | |
209 /** is a dictionary loaded (more than skeleton) | |
210 */ | |
211 OFBool dictionaryLoaded; | |
212 | |
213 }; | |
214 | |
215 | |
216 /** global singleton dicom dictionary that is used by DCMTK in order to lookup | |
217 * attribute VR, tag names and so on. The dictionary is internally populated | |
218 * on first use, if the user accesses it via rdlock() or wrlock(). The | |
219 * dictionary allows safe read (shared) and write (exclusive) access from | |
220 * multiple threads in parallel. | |
221 */ | |
222 class DCMTK_DCMDATA_EXPORT GlobalDcmDataDictionary | |
223 { | |
224 public: | |
225 /** constructor. | |
226 */ | |
227 GlobalDcmDataDictionary(); | |
228 | |
229 /** destructor | |
230 */ | |
231 ~GlobalDcmDataDictionary(); | |
232 | |
233 /** acquires a read lock and returns a const reference to | |
234 * the dictionary. | |
235 * @return const reference to dictionary | |
236 */ | |
237 const DcmDataDictionary& rdlock(); | |
238 | |
239 /** acquires a write lock and returns a non-const reference | |
240 * to the dictionary. | |
241 * @return non-const reference to dictionary. | |
242 */ | |
243 DcmDataDictionary& wrlock(); | |
244 | |
245 /** unlocks the read or write lock which must have been acquired previously. | |
246 */ | |
247 void unlock(); | |
248 | |
249 /** checks if a data dictionary has been loaded. This method acquires and | |
250 * releases a read lock. It must not be called with another lock on the | |
251 * dictionary being held by the calling thread. | |
252 * @return OFTrue if dictionary has been loaded, OFFalse otherwise. | |
253 */ | |
254 OFBool isDictionaryLoaded(); | |
255 | |
256 /** erases the contents of the dictionary. This method acquires and | |
257 * releases a write lock. It must not be called with another lock on the | |
258 * dictionary being held by the calling thread. This method is intended | |
259 * as a help for debugging memory leaks. | |
260 */ | |
261 void clear(); | |
262 | |
263 private: | |
264 /** private undefined assignment operator | |
265 */ | |
266 GlobalDcmDataDictionary &operator=(const GlobalDcmDataDictionary &); | |
267 | |
268 /** private undefined copy constructor | |
269 */ | |
270 GlobalDcmDataDictionary(const GlobalDcmDataDictionary &); | |
271 | |
272 /** create the data dictionary instance for this class. Used for first | |
273 * intialization. The caller must not have dataDictLock locked. | |
274 */ | |
275 void createDataDict(); | |
276 | |
277 /** the data dictionary managed by this class | |
278 */ | |
279 DcmDataDictionary *dataDict; | |
280 | |
281 #ifdef WITH_THREADS | |
282 /** the read/write lock used to protect access from multiple threads | |
283 */ | |
284 OFReadWriteLock dataDictLock; | |
285 #endif | |
286 }; | |
287 | |
288 | |
289 /** The Global DICOM Data Dictionary. | |
290 * Will be created before main() starts and gets populated on its first use. | |
291 * Tries to load a builtin data dictionary (if compiled in). | |
292 * Tries to load data dictionaries from files specified by | |
293 * the DCMDICTPATH environment variable. If this environment | |
294 * variable does not exist then a default file is loaded (if | |
295 * it exists). | |
296 * It is possible that no data dictionary gets loaded. This | |
297 * is likely to cause unexpected behaviour in the dcmdata | |
298 * toolkit classes. | |
299 */ | |
300 extern DCMTK_DCMDATA_EXPORT GlobalDcmDataDictionary dcmDataDict; | |
301 | |
302 #endif |