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