comparison Plugins/Samples/Common/OrthancPluginCppWrapper.cpp @ 3026:c358bdb37c13

more plugin helpers
author amazy
date Tue, 18 Dec 2018 12:07:52 +0100
parents 9cc3d40e389b
children ff65c925f57a
comparison
equal deleted inserted replaced
3023:c9c2faf76bec 3026:c358bdb37c13
37 #include <json/writer.h> 37 #include <json/writer.h>
38 38
39 39
40 namespace OrthancPlugins 40 namespace OrthancPlugins
41 { 41 {
42 static OrthancPluginContext* globalContext_ = NULL; 42 static OrthancPluginContext* globalContext_ = NULL;
43 43
44 44
45 void SetGlobalContext(OrthancPluginContext* context) 45 void SetGlobalContext(OrthancPluginContext* context)
46 { 46 {
47 if (context == NULL) 47 if (context == NULL)
48 {
49 ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
50 }
51 else if (globalContext_ == NULL)
52 {
53 globalContext_ = context;
54 }
55 else
56 {
57 ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
58 }
59 }
60
61
62 bool HasGlobalContext()
63 {
64 return globalContext_ != NULL;
65 }
66
67
68 OrthancPluginContext* GetGlobalContext()
69 {
70 if (globalContext_ == NULL)
71 {
72 ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
73 }
74 else
75 {
76 return globalContext_;
77 }
78 }
79
80
81 void MemoryBuffer::Check(OrthancPluginErrorCode code)
82 {
83 if (code != OrthancPluginErrorCode_Success)
84 {
85 // Prevent using garbage information
86 buffer_.data = NULL;
87 buffer_.size = 0;
88 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
89 }
90 }
91
92
93 bool MemoryBuffer::CheckHttp(OrthancPluginErrorCode code)
94 {
95 if (code != OrthancPluginErrorCode_Success)
96 {
97 // Prevent using garbage information
98 buffer_.data = NULL;
99 buffer_.size = 0;
100 }
101
102 if (code == OrthancPluginErrorCode_Success)
103 {
104 return true;
105 }
106 else if (code == OrthancPluginErrorCode_UnknownResource ||
107 code == OrthancPluginErrorCode_InexistentItem)
108 {
109 return false;
110 }
111 else
112 {
113 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
114 }
115 }
116
117
118 MemoryBuffer::MemoryBuffer()
119 {
120 buffer_.data = NULL;
121 buffer_.size = 0;
122 }
123
124
125 void MemoryBuffer::Clear()
126 {
127 if (buffer_.data != NULL)
128 {
129 OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &buffer_);
130 buffer_.data = NULL;
131 buffer_.size = 0;
132 }
133 }
134
135
136 void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other)
137 {
138 Clear();
139
140 buffer_.data = other.data;
141 buffer_.size = other.size;
142
143 other.data = NULL;
144 other.size = 0;
145 }
146
147
148 OrthancPluginMemoryBuffer MemoryBuffer::Release()
149 {
150 OrthancPluginMemoryBuffer result = buffer_;
151
152 buffer_.data = NULL;
153 buffer_.size = 0;
154
155 return result;
156 }
157
158
159 void MemoryBuffer::ToString(std::string& target) const
160 {
161 if (buffer_.size == 0)
162 {
163 target.clear();
164 }
165 else
166 {
167 target.assign(reinterpret_cast<const char*>(buffer_.data), buffer_.size);
168 }
169 }
170
171
172 void MemoryBuffer::ToJson(Json::Value& target) const
173 {
174 if (buffer_.data == NULL ||
175 buffer_.size == 0)
176 {
177 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
178 }
179
180 const char* tmp = reinterpret_cast<const char*>(buffer_.data);
181
182 Json::Reader reader;
183 if (!reader.parse(tmp, tmp + buffer_.size, target))
184 {
185 LogError("Cannot convert some memory buffer to JSON");
186 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
187 }
188 }
189
190
191 bool MemoryBuffer::RestApiGet(const std::string& uri,
192 bool applyPlugins)
193 {
194 Clear();
195
196 if (applyPlugins)
197 {
198 return CheckHttp(OrthancPluginRestApiGetAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str()));
199 }
200 else
201 {
202 return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str()));
203 }
204 }
205
206 bool MemoryBuffer::RestApiGet(const std::string& uri,
207 const std::map<std::string, std::string>& httpHeaders,
208 bool applyPlugins)
209 {
210 Clear();
211
212 std::vector<const char*> headersKeys;
213 std::vector<const char*> headersValues;
214 for (std::map<std::string, std::string>::const_iterator it = httpHeaders.begin(); it != httpHeaders.end(); it++)
215 {
216 headersKeys.push_back(it->first.c_str());
217 headersValues.push_back(it->second.c_str());
218 }
219
220 return CheckHttp(OrthancPluginRestApiGet2(GetGlobalContext(), &buffer_, uri.c_str(), httpHeaders.size(), headersKeys.data(), headersValues.data(), applyPlugins));
221 }
222
223 bool MemoryBuffer::RestApiPost(const std::string& uri,
224 const char* body,
225 size_t bodySize,
226 bool applyPlugins)
227 {
228 Clear();
229
230 if (applyPlugins)
231 {
232 return CheckHttp(OrthancPluginRestApiPostAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
233 }
234 else
235 {
236 return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
237 }
238 }
239
240
241 bool MemoryBuffer::RestApiPut(const std::string& uri,
242 const char* body,
243 size_t bodySize,
244 bool applyPlugins)
245 {
246 Clear();
247
248 if (applyPlugins)
249 {
250 return CheckHttp(OrthancPluginRestApiPutAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
251 }
252 else
253 {
254 return CheckHttp(OrthancPluginRestApiPut(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
255 }
256 }
257
258
259 bool MemoryBuffer::RestApiPost(const std::string& uri,
260 const Json::Value& body,
261 bool applyPlugins)
262 {
263 Json::FastWriter writer;
264 return RestApiPost(uri, writer.write(body), applyPlugins);
265 }
266
267
268 bool MemoryBuffer::RestApiPut(const std::string& uri,
269 const Json::Value& body,
270 bool applyPlugins)
271 {
272 Json::FastWriter writer;
273 return RestApiPut(uri, writer.write(body), applyPlugins);
274 }
275
276
277 void MemoryBuffer::CreateDicom(const Json::Value& tags,
278 OrthancPluginCreateDicomFlags flags)
279 {
280 Clear();
281
282 Json::FastWriter writer;
283 std::string s = writer.write(tags);
284
285 Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), NULL, flags));
286 }
287
288 void MemoryBuffer::CreateDicom(const Json::Value& tags,
289 const OrthancImage& pixelData,
290 OrthancPluginCreateDicomFlags flags)
291 {
292 Clear();
293
294 Json::FastWriter writer;
295 std::string s = writer.write(tags);
296
297 Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), pixelData.GetObject(), flags));
298 }
299
300
301 void MemoryBuffer::ReadFile(const std::string& path)
302 {
303 Clear();
304 Check(OrthancPluginReadFile(GetGlobalContext(), &buffer_, path.c_str()));
305 }
306
307
308 void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query)
309 {
310 Clear();
311 Check(OrthancPluginWorklistGetDicomQuery(GetGlobalContext(), &buffer_, query));
312 }
313
314
315 void OrthancString::Assign(char* str)
316 {
317 if (str == NULL)
318 {
319 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
320 }
321 else
322 {
323 Clear();
324 str_ = str;
325 }
326 }
327
328
329 void OrthancString::Clear()
330 {
331 if (str_ != NULL)
332 {
333 OrthancPluginFreeString(GetGlobalContext(), str_);
334 str_ = NULL;
335 }
336 }
337
338
339 void OrthancString::ToString(std::string& target) const
340 {
341 if (str_ == NULL)
342 {
343 target.clear();
344 }
345 else
346 {
347 target.assign(str_);
348 }
349 }
350
351
352 void OrthancString::ToJson(Json::Value& target) const
353 {
354 if (str_ == NULL)
355 {
356 LogError("Cannot convert an empty memory buffer to JSON");
357 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
358 }
359
360 Json::Reader reader;
361 if (!reader.parse(str_, target))
362 {
363 LogError("Cannot convert some memory buffer to JSON");
364 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
365 }
366 }
367
368
369 void MemoryBuffer::DicomToJson(Json::Value& target,
370 OrthancPluginDicomToJsonFormat format,
371 OrthancPluginDicomToJsonFlags flags,
372 uint32_t maxStringLength)
373 {
374 OrthancString str;
375 str.Assign(OrthancPluginDicomBufferToJson
376 (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength));
377 str.ToJson(target);
378 }
379
380
381 bool MemoryBuffer::HttpGet(const std::string& url,
382 const std::string& username,
383 const std::string& password)
384 {
385 Clear();
386 return CheckHttp(OrthancPluginHttpGet(GetGlobalContext(), &buffer_, url.c_str(),
387 username.empty() ? NULL : username.c_str(),
388 password.empty() ? NULL : password.c_str()));
389 }
390
391
392 bool MemoryBuffer::HttpPost(const std::string& url,
393 const std::string& body,
394 const std::string& username,
395 const std::string& password)
396 {
397 Clear();
398 return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(),
399 body.c_str(), body.size(),
400 username.empty() ? NULL : username.c_str(),
401 password.empty() ? NULL : password.c_str()));
402 }
403
404
405 bool MemoryBuffer::HttpPut(const std::string& url,
406 const std::string& body,
407 const std::string& username,
408 const std::string& password)
409 {
410 Clear();
411 return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(),
412 body.empty() ? NULL : body.c_str(),
413 body.size(),
414 username.empty() ? NULL : username.c_str(),
415 password.empty() ? NULL : password.c_str()));
416 }
417
418
419 void MemoryBuffer::GetDicomInstance(const std::string& instanceId)
420 {
421 Clear();
422 Check(OrthancPluginGetDicomForInstance(GetGlobalContext(), &buffer_, instanceId.c_str()));
423 }
424
425
426 bool HttpDelete(const std::string& url,
427 const std::string& username,
428 const std::string& password)
429 {
430 OrthancPluginErrorCode error = OrthancPluginHttpDelete
431 (GetGlobalContext(), url.c_str(),
432 username.empty() ? NULL : username.c_str(),
433 password.empty() ? NULL : password.c_str());
434
435 if (error == OrthancPluginErrorCode_Success)
436 {
437 return true;
438 }
439 else if (error == OrthancPluginErrorCode_UnknownResource ||
440 error == OrthancPluginErrorCode_InexistentItem)
441 {
442 return false;
443 }
444 else
445 {
446 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
447 }
448 }
449
450
451 void LogError(const std::string& message)
452 {
453 if (HasGlobalContext())
454 {
455 OrthancPluginLogError(GetGlobalContext(), message.c_str());
456 }
457 }
458
459
460 void LogWarning(const std::string& message)
461 {
462 if (HasGlobalContext())
463 {
464 OrthancPluginLogWarning(GetGlobalContext(), message.c_str());
465 }
466 }
467
468
469 void LogInfo(const std::string& message)
470 {
471 if (HasGlobalContext())
472 {
473 OrthancPluginLogInfo(GetGlobalContext(), message.c_str());
474 }
475 }
476
477
478 OrthancConfiguration::OrthancConfiguration()
479 {
480 OrthancString str;
481 str.Assign(OrthancPluginGetConfiguration(GetGlobalContext()));
482
483 if (str.GetContent() == NULL)
484 {
485 LogError("Cannot access the Orthanc configuration");
486 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
487 }
488
489 str.ToJson(configuration_);
490
491 if (configuration_.type() != Json::objectValue)
492 {
493 LogError("Unable to read the Orthanc configuration");
494 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
495 }
496 }
497
498
499 std::string OrthancConfiguration::GetPath(const std::string& key) const
500 {
501 if (path_.empty())
502 {
503 return key;
504 }
505 else
506 {
507 return path_ + "." + key;
508 }
509 }
510
511
512 bool OrthancConfiguration::IsSection(const std::string& key) const
513 {
514 assert(configuration_.type() == Json::objectValue);
515
516 return (configuration_.isMember(key) &&
517 configuration_[key].type() == Json::objectValue);
518 }
519
520
521 void OrthancConfiguration::GetSection(OrthancConfiguration& target,
522 const std::string& key) const
523 {
524 assert(configuration_.type() == Json::objectValue);
525
526 target.path_ = GetPath(key);
527
528 if (!configuration_.isMember(key))
529 {
530 target.configuration_ = Json::objectValue;
531 }
532 else
533 {
534 if (configuration_[key].type() != Json::objectValue)
48 { 535 {
49 ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer); 536 LogError("The configuration section \"" + target.path_ +
50 } 537 "\" is not an associative array as expected");
51 else if (globalContext_ == NULL) 538
539 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
540 }
541
542 target.configuration_ = configuration_[key];
543 }
544 }
545
546
547 bool OrthancConfiguration::LookupStringValue(std::string& target,
548 const std::string& key) const
549 {
550 assert(configuration_.type() == Json::objectValue);
551
552 if (!configuration_.isMember(key))
553 {
554 return false;
555 }
556
557 if (configuration_[key].type() != Json::stringValue)
558 {
559 LogError("The configuration option \"" + GetPath(key) +
560 "\" is not a string as expected");
561
562 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
563 }
564
565 target = configuration_[key].asString();
566 return true;
567 }
568
569
570 bool OrthancConfiguration::LookupIntegerValue(int& target,
571 const std::string& key) const
572 {
573 assert(configuration_.type() == Json::objectValue);
574
575 if (!configuration_.isMember(key))
576 {
577 return false;
578 }
579
580 switch (configuration_[key].type())
581 {
582 case Json::intValue:
583 target = configuration_[key].asInt();
584 return true;
585
586 case Json::uintValue:
587 target = configuration_[key].asUInt();
588 return true;
589
590 default:
591 LogError("The configuration option \"" + GetPath(key) +
592 "\" is not an integer as expected");
593
594 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
595 }
596 }
597
598
599 bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target,
600 const std::string& key) const
601 {
602 int tmp;
603 if (!LookupIntegerValue(tmp, key))
604 {
605 return false;
606 }
607
608 if (tmp < 0)
609 {
610 LogError("The configuration option \"" + GetPath(key) +
611 "\" is not a positive integer as expected");
612
613 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
614 }
615 else
616 {
617 target = static_cast<unsigned int>(tmp);
618 return true;
619 }
620 }
621
622
623 bool OrthancConfiguration::LookupBooleanValue(bool& target,
624 const std::string& key) const
625 {
626 assert(configuration_.type() == Json::objectValue);
627
628 if (!configuration_.isMember(key))
629 {
630 return false;
631 }
632
633 if (configuration_[key].type() != Json::booleanValue)
634 {
635 LogError("The configuration option \"" + GetPath(key) +
636 "\" is not a Boolean as expected");
637
638 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
639 }
640
641 target = configuration_[key].asBool();
642 return true;
643 }
644
645
646 bool OrthancConfiguration::LookupFloatValue(float& target,
647 const std::string& key) const
648 {
649 assert(configuration_.type() == Json::objectValue);
650
651 if (!configuration_.isMember(key))
652 {
653 return false;
654 }
655
656 switch (configuration_[key].type())
657 {
658 case Json::realValue:
659 target = configuration_[key].asFloat();
660 return true;
661
662 case Json::intValue:
663 target = static_cast<float>(configuration_[key].asInt());
664 return true;
665
666 case Json::uintValue:
667 target = static_cast<float>(configuration_[key].asUInt());
668 return true;
669
670 default:
671 LogError("The configuration option \"" + GetPath(key) +
672 "\" is not an integer as expected");
673
674 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
675 }
676 }
677
678
679 bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target,
680 const std::string& key,
681 bool allowSingleString) const
682 {
683 assert(configuration_.type() == Json::objectValue);
684
685 target.clear();
686
687 if (!configuration_.isMember(key))
688 {
689 return false;
690 }
691
692 switch (configuration_[key].type())
693 {
694 case Json::arrayValue:
695 {
696 bool ok = true;
697
698 for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++)
52 { 699 {
53 globalContext_ = context; 700 if (configuration_[key][i].type() == Json::stringValue)
701 {
702 target.push_back(configuration_[key][i].asString());
703 }
704 else
705 {
706 ok = false;
707 }
708 }
709
710 if (ok)
711 {
712 return true;
713 }
714
715 break;
716 }
717
718 case Json::stringValue:
719 if (allowSingleString)
720 {
721 target.push_back(configuration_[key].asString());
722 return true;
723 }
724
725 break;
726
727 default:
728 break;
729 }
730
731 LogError("The configuration option \"" + GetPath(key) +
732 "\" is not a list of strings as expected");
733
734 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
735 }
736
737
738 bool OrthancConfiguration::LookupSetOfStrings(std::set<std::string>& target,
739 const std::string& key,
740 bool allowSingleString) const
741 {
742 std::list<std::string> lst;
743
744 if (LookupListOfStrings(lst, key, allowSingleString))
745 {
746 target.clear();
747
748 for (std::list<std::string>::const_iterator
749 it = lst.begin(); it != lst.end(); ++it)
750 {
751 target.insert(*it);
752 }
753
754 return true;
755 }
756 else
757 {
758 return false;
759 }
760 }
761
762
763 std::string OrthancConfiguration::GetStringValue(const std::string& key,
764 const std::string& defaultValue) const
765 {
766 std::string tmp;
767 if (LookupStringValue(tmp, key))
768 {
769 return tmp;
770 }
771 else
772 {
773 return defaultValue;
774 }
775 }
776
777
778 int OrthancConfiguration::GetIntegerValue(const std::string& key,
779 int defaultValue) const
780 {
781 int tmp;
782 if (LookupIntegerValue(tmp, key))
783 {
784 return tmp;
785 }
786 else
787 {
788 return defaultValue;
789 }
790 }
791
792
793 unsigned int OrthancConfiguration::GetUnsignedIntegerValue(const std::string& key,
794 unsigned int defaultValue) const
795 {
796 unsigned int tmp;
797 if (LookupUnsignedIntegerValue(tmp, key))
798 {
799 return tmp;
800 }
801 else
802 {
803 return defaultValue;
804 }
805 }
806
807
808 bool OrthancConfiguration::GetBooleanValue(const std::string& key,
809 bool defaultValue) const
810 {
811 bool tmp;
812 if (LookupBooleanValue(tmp, key))
813 {
814 return tmp;
815 }
816 else
817 {
818 return defaultValue;
819 }
820 }
821
822
823 float OrthancConfiguration::GetFloatValue(const std::string& key,
824 float defaultValue) const
825 {
826 float tmp;
827 if (LookupFloatValue(tmp, key))
828 {
829 return tmp;
830 }
831 else
832 {
833 return defaultValue;
834 }
835 }
836
837
838 void OrthancConfiguration::GetDictionary(std::map<std::string, std::string>& target,
839 const std::string& key) const
840 {
841 assert(configuration_.type() == Json::objectValue);
842
843 target.clear();
844
845 if (!configuration_.isMember(key))
846 {
847 return;
848 }
849
850 if (configuration_[key].type() != Json::objectValue)
851 {
852 LogError("The configuration option \"" + GetPath(key) +
853 "\" is not a string as expected");
854
855 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
856 }
857
858 Json::Value::Members members = configuration_[key].getMemberNames();
859
860 for (size_t i = 0; i < members.size(); i++)
861 {
862 const Json::Value& value = configuration_[key][members[i]];
863
864 if (value.type() == Json::stringValue)
865 {
866 target[members[i]] = value.asString();
54 } 867 }
55 else 868 else
56 { 869 {
57 ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls); 870 LogError("The configuration option \"" + GetPath(key) +
871 "\" is not a dictionary mapping strings to strings");
872
873 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
58 } 874 }
59 } 875 }
60 876 }
61 877
62 bool HasGlobalContext() 878
63 { 879 void OrthancImage::Clear()
64 return globalContext_ != NULL; 880 {
65 } 881 if (image_ != NULL)
66 882 {
67 883 OrthancPluginFreeImage(GetGlobalContext(), image_);
68 OrthancPluginContext* GetGlobalContext() 884 image_ = NULL;
69 { 885 }
70 if (globalContext_ == NULL) 886 }
887
888
889 void OrthancImage::CheckImageAvailable()
890 {
891 if (image_ == NULL)
892 {
893 LogError("Trying to access a NULL image");
894 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
895 }
896 }
897
898
899 OrthancImage::OrthancImage() :
900 image_(NULL)
901 {
902 }
903
904
905 OrthancImage::OrthancImage(OrthancPluginImage* image) :
906 image_(image)
907 {
908 }
909
910
911 OrthancImage::OrthancImage(OrthancPluginPixelFormat format,
912 uint32_t width,
913 uint32_t height)
914 {
915 image_ = OrthancPluginCreateImage(GetGlobalContext(), format, width, height);
916
917 if (image_ == NULL)
918 {
919 LogError("Cannot create an image");
920 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
921 }
922 }
923
924
925 OrthancImage::OrthancImage(OrthancPluginPixelFormat format,
926 uint32_t width,
927 uint32_t height,
928 uint32_t pitch,
929 void* buffer)
930 {
931 image_ = OrthancPluginCreateImageAccessor
932 (GetGlobalContext(), format, width, height, pitch, buffer);
933
934 if (image_ == NULL)
935 {
936 LogError("Cannot create an image accessor");
937 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
938 }
939 }
940
941 void OrthancImage::UncompressPngImage(const void* data,
942 size_t size)
943 {
944 Clear();
945
946 image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Png);
947
948 if (image_ == NULL)
949 {
950 LogError("Cannot uncompress a PNG image");
951 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
952 }
953 }
954
955
956 void OrthancImage::UncompressJpegImage(const void* data,
957 size_t size)
958 {
959 Clear();
960 image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg);
961 if (image_ == NULL)
962 {
963 LogError("Cannot uncompress a JPEG image");
964 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
965 }
966 }
967
968
969 void OrthancImage::DecodeDicomImage(const void* data,
970 size_t size,
971 unsigned int frame)
972 {
973 Clear();
974 image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame);
975 if (image_ == NULL)
976 {
977 LogError("Cannot uncompress a DICOM image");
978 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
979 }
980 }
981
982
983 OrthancPluginPixelFormat OrthancImage::GetPixelFormat()
984 {
985 CheckImageAvailable();
986 return OrthancPluginGetImagePixelFormat(GetGlobalContext(), image_);
987 }
988
989
990 unsigned int OrthancImage::GetWidth()
991 {
992 CheckImageAvailable();
993 return OrthancPluginGetImageWidth(GetGlobalContext(), image_);
994 }
995
996
997 unsigned int OrthancImage::GetHeight()
998 {
999 CheckImageAvailable();
1000 return OrthancPluginGetImageHeight(GetGlobalContext(), image_);
1001 }
1002
1003
1004 unsigned int OrthancImage::GetPitch()
1005 {
1006 CheckImageAvailable();
1007 return OrthancPluginGetImagePitch(GetGlobalContext(), image_);
1008 }
1009
1010
1011 const void* OrthancImage::GetBuffer()
1012 {
1013 CheckImageAvailable();
1014 return OrthancPluginGetImageBuffer(GetGlobalContext(), image_);
1015 }
1016
1017
1018 void OrthancImage::CompressPngImage(MemoryBuffer& target)
1019 {
1020 CheckImageAvailable();
1021
1022 OrthancPluginMemoryBuffer tmp;
1023 OrthancPluginCompressPngImage(GetGlobalContext(), &tmp, GetPixelFormat(),
1024 GetWidth(), GetHeight(), GetPitch(), GetBuffer());
1025
1026 target.Assign(tmp);
1027 }
1028
1029
1030 void OrthancImage::CompressJpegImage(MemoryBuffer& target,
1031 uint8_t quality)
1032 {
1033 CheckImageAvailable();
1034
1035 OrthancPluginMemoryBuffer tmp;
1036 OrthancPluginCompressJpegImage(GetGlobalContext(), &tmp, GetPixelFormat(),
1037 GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
1038
1039 target.Assign(tmp);
1040 }
1041
1042
1043 void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output)
1044 {
1045 CheckImageAvailable();
1046 OrthancPluginCompressAndAnswerPngImage(GetGlobalContext(), output, GetPixelFormat(),
1047 GetWidth(), GetHeight(), GetPitch(), GetBuffer());
1048 }
1049
1050
1051 void OrthancImage::AnswerJpegImage(OrthancPluginRestOutput* output,
1052 uint8_t quality)
1053 {
1054 CheckImageAvailable();
1055 OrthancPluginCompressAndAnswerJpegImage(GetGlobalContext(), output, GetPixelFormat(),
1056 GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
1057 }
1058
1059
1060
1061 #if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
1062 FindMatcher::FindMatcher(const OrthancPluginWorklistQuery* worklist) :
1063 matcher_(NULL),
1064 worklist_(worklist)
1065 {
1066 if (worklist_ == NULL)
1067 {
1068 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
1069 }
1070 }
1071
1072
1073 void FindMatcher::SetupDicom(const void* query,
1074 uint32_t size)
1075 {
1076 worklist_ = NULL;
1077
1078 matcher_ = OrthancPluginCreateFindMatcher(GetGlobalContext(), query, size);
1079 if (matcher_ == NULL)
1080 {
1081 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1082 }
1083 }
1084
1085
1086 FindMatcher::~FindMatcher()
1087 {
1088 // The "worklist_" field
1089
1090 if (matcher_ != NULL)
1091 {
1092 OrthancPluginFreeFindMatcher(GetGlobalContext(), matcher_);
1093 }
1094 }
1095
1096
1097
1098 bool FindMatcher::IsMatch(const void* dicom,
1099 uint32_t size) const
1100 {
1101 int32_t result;
1102
1103 if (matcher_ != NULL)
1104 {
1105 result = OrthancPluginFindMatcherIsMatch(GetGlobalContext(), matcher_, dicom, size);
1106 }
1107 else if (worklist_ != NULL)
1108 {
1109 result = OrthancPluginWorklistIsMatch(GetGlobalContext(), worklist_, dicom, size);
1110 }
1111 else
1112 {
1113 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1114 }
1115
1116 if (result == 0)
1117 {
1118 return false;
1119 }
1120 else if (result == 1)
1121 {
1122 return true;
1123 }
1124 else
1125 {
1126 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1127 }
1128 }
1129
1130 #endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */
1131
1132 void AnswerJson(const Json::Value& value,
1133 OrthancPluginRestOutput* output
1134 )
1135 {
1136 Json::StyledWriter writer;
1137 std::string bodyString = writer.write(value);
1138
1139 OrthancPluginAnswerBuffer(GetGlobalContext(), output, bodyString.c_str(), bodyString.size(), "application/json");
1140 }
1141
1142 void AnswerString(const std::string& answer,
1143 const char* mimeType,
1144 OrthancPluginRestOutput* output
1145 )
1146 {
1147 OrthancPluginAnswerBuffer(GetGlobalContext(), output, answer.c_str(), answer.size(), mimeType);
1148 }
1149
1150 void AnswerHttpError(uint16_t httpError, OrthancPluginRestOutput *output)
1151 {
1152 OrthancPluginSendHttpStatusCode(GetGlobalContext(), output, httpError);
1153 }
1154
1155 void AnswerMethodNotAllowed(OrthancPluginRestOutput *output, const char* allowedMethods)
1156 {
1157 OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowedMethods);
1158 }
1159
1160 bool RestApiGetString(std::string& result,
1161 const std::string& uri,
1162 bool applyPlugins)
1163 {
1164 MemoryBuffer answer;
1165 if (!answer.RestApiGet(uri, applyPlugins))
1166 {
1167 return false;
1168 }
1169 else
1170 {
1171 answer.ToString(result);
1172 return true;
1173 }
1174 }
1175
1176 bool RestApiGetString(std::string& result,
1177 const std::string& uri,
1178 const std::map<std::string, std::string>& httpHeaders,
1179 bool applyPlugins)
1180 {
1181 MemoryBuffer answer;
1182 if (!answer.RestApiGet(uri, httpHeaders, applyPlugins))
1183 {
1184 return false;
1185 }
1186 else
1187 {
1188 answer.ToString(result);
1189 return true;
1190 }
1191 }
1192
1193
1194
1195 bool RestApiGet(Json::Value& result,
1196 const std::string& uri,
1197 bool applyPlugins)
1198 {
1199 MemoryBuffer answer;
1200
1201 if (!answer.RestApiGet(uri, applyPlugins))
1202 {
1203 return false;
1204 }
1205 else
1206 {
1207 if (!answer.IsEmpty())
71 { 1208 {
72 ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls); 1209 answer.ToJson(result);
1210 }
1211 return true;
1212 }
1213 }
1214
1215
1216 bool RestApiPost(Json::Value& result,
1217 const std::string& uri,
1218 const char* body,
1219 size_t bodySize,
1220 bool applyPlugins)
1221 {
1222 MemoryBuffer answer;
1223
1224 if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
1225 {
1226 return false;
1227 }
1228 else
1229 {
1230 if (!answer.IsEmpty())
1231 {
1232 answer.ToJson(result);
1233 }
1234 return true;
1235 }
1236 }
1237
1238
1239 bool RestApiPost(Json::Value& result,
1240 const std::string& uri,
1241 const Json::Value& body,
1242 bool applyPlugins)
1243 {
1244 Json::FastWriter writer;
1245 return RestApiPost(result, uri, writer.write(body), applyPlugins);
1246 }
1247
1248
1249 bool RestApiPut(Json::Value& result,
1250 const std::string& uri,
1251 const char* body,
1252 size_t bodySize,
1253 bool applyPlugins)
1254 {
1255 MemoryBuffer answer;
1256
1257 if (!answer.RestApiPut(uri, body, bodySize, applyPlugins))
1258 {
1259 return false;
1260 }
1261 else
1262 {
1263 if (!answer.IsEmpty()) // i.e, on a PUT to metadata/..., orthand returns an empty response
1264 {
1265 answer.ToJson(result);
1266 }
1267 return true;
1268 }
1269 }
1270
1271
1272 bool RestApiPut(Json::Value& result,
1273 const std::string& uri,
1274 const Json::Value& body,
1275 bool applyPlugins)
1276 {
1277 Json::FastWriter writer;
1278 return RestApiPut(result, uri, writer.write(body), applyPlugins);
1279 }
1280
1281
1282 bool RestApiDelete(const std::string& uri,
1283 bool applyPlugins)
1284 {
1285 OrthancPluginErrorCode error;
1286
1287 if (applyPlugins)
1288 {
1289 error = OrthancPluginRestApiDeleteAfterPlugins(GetGlobalContext(), uri.c_str());
1290 }
1291 else
1292 {
1293 error = OrthancPluginRestApiDelete(GetGlobalContext(), uri.c_str());
1294 }
1295
1296 if (error == OrthancPluginErrorCode_Success)
1297 {
1298 return true;
1299 }
1300 else if (error == OrthancPluginErrorCode_UnknownResource ||
1301 error == OrthancPluginErrorCode_InexistentItem)
1302 {
1303 return false;
1304 }
1305 else
1306 {
1307 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
1308 }
1309 }
1310
1311
1312 void ReportMinimalOrthancVersion(unsigned int major,
1313 unsigned int minor,
1314 unsigned int revision)
1315 {
1316 LogError("Your version of the Orthanc core (" +
1317 std::string(GetGlobalContext()->orthancVersion) +
1318 ") is too old to run this plugin (version " +
1319 boost::lexical_cast<std::string>(major) + "." +
1320 boost::lexical_cast<std::string>(minor) + "." +
1321 boost::lexical_cast<std::string>(revision) +
1322 " is required)");
1323 }
1324
1325
1326 bool CheckMinimalOrthancVersion(unsigned int major,
1327 unsigned int minor,
1328 unsigned int revision)
1329 {
1330 if (!HasGlobalContext())
1331 {
1332 LogError("Bad Orthanc context in the plugin");
1333 return false;
1334 }
1335
1336 if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
1337 {
1338 // Assume compatibility with the mainline
1339 return true;
1340 }
1341
1342 // Parse the version of the Orthanc core
1343 int aa, bb, cc;
1344 if (
1345 #ifdef _MSC_VER
1346 sscanf_s
1347 #else
1348 sscanf
1349 #endif
1350 (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
1351 aa < 0 ||
1352 bb < 0 ||
1353 cc < 0)
1354 {
1355 return false;
1356 }
1357
1358 unsigned int a = static_cast<unsigned int>(aa);
1359 unsigned int b = static_cast<unsigned int>(bb);
1360 unsigned int c = static_cast<unsigned int>(cc);
1361
1362 // Check the major version number
1363
1364 if (a > major)
1365 {
1366 return true;
1367 }
1368
1369 if (a < major)
1370 {
1371 return false;
1372 }
1373
1374
1375 // Check the minor version number
1376 assert(a == major);
1377
1378 if (b > minor)
1379 {
1380 return true;
1381 }
1382
1383 if (b < minor)
1384 {
1385 return false;
1386 }
1387
1388 // Check the patch level version number
1389 assert(a == major && b == minor);
1390
1391 if (c >= revision)
1392 {
1393 return true;
1394 }
1395 else
1396 {
1397 return false;
1398 }
1399 }
1400
1401
1402 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
1403 const char* AutodetectMimeType(const std::string& path)
1404 {
1405 const char* mime = OrthancPluginAutodetectMimeType(GetGlobalContext(), path.c_str());
1406
1407 if (mime == NULL)
1408 {
1409 // Should never happen, just for safety
1410 return "application/octet-stream";
1411 }
1412 else
1413 {
1414 return mime;
1415 }
1416 }
1417 #endif
1418
1419
1420 #if HAS_ORTHANC_PLUGIN_PEERS == 1
1421 size_t OrthancPeers::GetPeerIndex(const std::string& name) const
1422 {
1423 size_t index;
1424 if (LookupName(index, name))
1425 {
1426 return index;
1427 }
1428 else
1429 {
1430 LogError("Inexistent peer: " + name);
1431 ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
1432 }
1433 }
1434
1435
1436 OrthancPeers::OrthancPeers() :
1437 peers_(NULL),
1438 timeout_(0)
1439 {
1440 peers_ = OrthancPluginGetPeers(GetGlobalContext());
1441
1442 if (peers_ == NULL)
1443 {
1444 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1445 }
1446
1447 uint32_t count = OrthancPluginGetPeersCount(GetGlobalContext(), peers_);
1448
1449 for (uint32_t i = 0; i < count; i++)
1450 {
1451 const char* name = OrthancPluginGetPeerName(GetGlobalContext(), peers_, i);
1452 if (name == NULL)
1453 {
1454 OrthancPluginFreePeers(GetGlobalContext(), peers_);
1455 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1456 }
1457
1458 index_[name] = i;
1459 }
1460 }
1461
1462
1463 OrthancPeers::~OrthancPeers()
1464 {
1465 if (peers_ != NULL)
1466 {
1467 OrthancPluginFreePeers(GetGlobalContext(), peers_);
1468 }
1469 }
1470
1471
1472 bool OrthancPeers::LookupName(size_t& target,
1473 const std::string& name) const
1474 {
1475 Index::const_iterator found = index_.find(name);
1476
1477 if (found == index_.end())
1478 {
1479 return false;
1480 }
1481 else
1482 {
1483 target = found->second;
1484 return true;
1485 }
1486 }
1487
1488
1489 std::string OrthancPeers::GetPeerName(size_t index) const
1490 {
1491 if (index >= index_.size())
1492 {
1493 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1494 }
1495 else
1496 {
1497 const char* s = OrthancPluginGetPeerName(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
1498 if (s == NULL)
1499 {
1500 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
73 } 1501 }
74 else 1502 else
75 { 1503 {
76 return globalContext_; 1504 return s;
77 } 1505 }
78 } 1506 }
79 1507 }
80 1508
81 void MemoryBuffer::Check(OrthancPluginErrorCode code) 1509
82 { 1510 std::string OrthancPeers::GetPeerUrl(size_t index) const
83 if (code != OrthancPluginErrorCode_Success) 1511 {
1512 if (index >= index_.size())
1513 {
1514 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1515 }
1516 else
1517 {
1518 const char* s = OrthancPluginGetPeerUrl(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
1519 if (s == NULL)
84 { 1520 {
85 // Prevent using garbage information 1521 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
86 buffer_.data = NULL;
87 buffer_.size = 0;
88 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
89 } 1522 }
90 } 1523 else
91
92
93 bool MemoryBuffer::CheckHttp(OrthancPluginErrorCode code)
94 {
95 if (code != OrthancPluginErrorCode_Success)
96 { 1524 {
97 // Prevent using garbage information 1525 return s;
98 buffer_.data = NULL;
99 buffer_.size = 0;
100 } 1526 }
101 1527 }
102 if (code == OrthancPluginErrorCode_Success) 1528 }
103 { 1529
104 return true; 1530
105 } 1531 std::string OrthancPeers::GetPeerUrl(const std::string& name) const
106 else if (code == OrthancPluginErrorCode_UnknownResource || 1532 {
107 code == OrthancPluginErrorCode_InexistentItem) 1533 return GetPeerUrl(GetPeerIndex(name));
1534 }
1535
1536
1537 bool OrthancPeers::LookupUserProperty(std::string& value,
1538 size_t index,
1539 const std::string& key) const
1540 {
1541 if (index >= index_.size())
1542 {
1543 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1544 }
1545 else
1546 {
1547 const char* s = OrthancPluginGetPeerUserProperty(GetGlobalContext(), peers_, static_cast<uint32_t>(index), key.c_str());
1548 if (s == NULL)
108 { 1549 {
109 return false; 1550 return false;
110 } 1551 }
111 else 1552 else
112 { 1553 {
113 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); 1554 value.assign(s);
1555 return true;
114 } 1556 }
115 } 1557 }
116 1558 }
117 1559
118 MemoryBuffer::MemoryBuffer() 1560
119 { 1561 bool OrthancPeers::LookupUserProperty(std::string& value,
120 buffer_.data = NULL; 1562 const std::string& peer,
121 buffer_.size = 0; 1563 const std::string& key) const
122 } 1564 {
123 1565 return LookupUserProperty(value, GetPeerIndex(peer), key);
124 1566 }
125 void MemoryBuffer::Clear() 1567
126 { 1568
127 if (buffer_.data != NULL) 1569 bool OrthancPeers::DoGet(MemoryBuffer& target,
1570 size_t index,
1571 const std::string& uri) const
1572 {
1573 if (index >= index_.size())
1574 {
1575 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1576 }
1577
1578 OrthancPluginMemoryBuffer answer;
1579 uint16_t status;
1580 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1581 (GetGlobalContext(), &answer, NULL, &status, peers_,
1582 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
1583 0, NULL, NULL, NULL, 0, timeout_);
1584
1585 if (code == OrthancPluginErrorCode_Success)
1586 {
1587 target.Assign(answer);
1588 return (status == 200);
1589 }
1590 else
1591 {
1592 return false;
1593 }
1594 }
1595
1596
1597 bool OrthancPeers::DoGet(MemoryBuffer& target,
1598 const std::string& name,
1599 const std::string& uri) const
1600 {
1601 size_t index;
1602 return (LookupName(index, name) &&
1603 DoGet(target, index, uri));
1604 }
1605
1606
1607 bool OrthancPeers::DoGet(Json::Value& target,
1608 size_t index,
1609 const std::string& uri) const
1610 {
1611 MemoryBuffer buffer;
1612
1613 if (DoGet(buffer, index, uri))
1614 {
1615 buffer.ToJson(target);
1616 return true;
1617 }
1618 else
1619 {
1620 return false;
1621 }
1622 }
1623
1624
1625 bool OrthancPeers::DoGet(Json::Value& target,
1626 const std::string& name,
1627 const std::string& uri) const
1628 {
1629 MemoryBuffer buffer;
1630
1631 if (DoGet(buffer, name, uri))
1632 {
1633 buffer.ToJson(target);
1634 return true;
1635 }
1636 else
1637 {
1638 return false;
1639 }
1640 }
1641
1642
1643 bool OrthancPeers::DoPost(MemoryBuffer& target,
1644 const std::string& name,
1645 const std::string& uri,
1646 const std::string& body) const
1647 {
1648 size_t index;
1649 return (LookupName(index, name) &&
1650 DoPost(target, index, uri, body));
1651 }
1652
1653
1654 bool OrthancPeers::DoPost(Json::Value& target,
1655 size_t index,
1656 const std::string& uri,
1657 const std::string& body) const
1658 {
1659 MemoryBuffer buffer;
1660
1661 if (DoPost(buffer, index, uri, body))
1662 {
1663 buffer.ToJson(target);
1664 return true;
1665 }
1666 else
1667 {
1668 return false;
1669 }
1670 }
1671
1672
1673 bool OrthancPeers::DoPost(Json::Value& target,
1674 const std::string& name,
1675 const std::string& uri,
1676 const std::string& body) const
1677 {
1678 MemoryBuffer buffer;
1679
1680 if (DoPost(buffer, name, uri, body))
1681 {
1682 buffer.ToJson(target);
1683 return true;
1684 }
1685 else
1686 {
1687 return false;
1688 }
1689 }
1690
1691
1692 bool OrthancPeers::DoPost(MemoryBuffer& target,
1693 size_t index,
1694 const std::string& uri,
1695 const std::string& body) const
1696 {
1697 if (index >= index_.size())
1698 {
1699 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1700 }
1701
1702 OrthancPluginMemoryBuffer answer;
1703 uint16_t status;
1704 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1705 (GetGlobalContext(), &answer, NULL, &status, peers_,
1706 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
1707 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1708
1709 if (code == OrthancPluginErrorCode_Success)
1710 {
1711 target.Assign(answer);
1712 return (status == 200);
1713 }
1714 else
1715 {
1716 return false;
1717 }
1718 }
1719
1720
1721 bool OrthancPeers::DoPut(size_t index,
1722 const std::string& uri,
1723 const std::string& body) const
1724 {
1725 if (index >= index_.size())
1726 {
1727 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1728 }
1729
1730 OrthancPluginMemoryBuffer answer;
1731 uint16_t status;
1732 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1733 (GetGlobalContext(), &answer, NULL, &status, peers_,
1734 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
1735 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1736
1737 if (code == OrthancPluginErrorCode_Success)
1738 {
1739 OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &answer);
1740 return (status == 200);
1741 }
1742 else
1743 {
1744 return false;
1745 }
1746 }
1747
1748
1749 bool OrthancPeers::DoPut(const std::string& name,
1750 const std::string& uri,
1751 const std::string& body) const
1752 {
1753 size_t index;
1754 return (LookupName(index, name) &&
1755 DoPut(index, uri, body));
1756 }
1757
1758
1759 bool OrthancPeers::DoDelete(size_t index,
1760 const std::string& uri) const
1761 {
1762 if (index >= index_.size())
1763 {
1764 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1765 }
1766
1767 OrthancPluginMemoryBuffer answer;
1768 uint16_t status;
1769 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1770 (GetGlobalContext(), &answer, NULL, &status, peers_,
1771 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
1772 0, NULL, NULL, NULL, 0, timeout_);
1773
1774 if (code == OrthancPluginErrorCode_Success)
1775 {
1776 OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &answer);
1777 return (status == 200);
1778 }
1779 else
1780 {
1781 return false;
1782 }
1783 }
1784
1785
1786 bool OrthancPeers::DoDelete(const std::string& name,
1787 const std::string& uri) const
1788 {
1789 size_t index;
1790 return (LookupName(index, name) &&
1791 DoDelete(index, uri));
1792 }
1793 #endif
1794
1795
1796
1797 #if HAS_ORTHANC_PLUGIN_JOB == 1
1798 void OrthancJob::CallbackFinalize(void* job)
1799 {
1800 if (job != NULL)
1801 {
1802 delete reinterpret_cast<OrthancJob*>(job);
1803 }
1804 }
1805
1806
1807 float OrthancJob::CallbackGetProgress(void* job)
1808 {
1809 assert(job != NULL);
1810
1811 try
1812 {
1813 return reinterpret_cast<OrthancJob*>(job)->progress_;
1814 }
1815 catch (...)
1816 {
1817 return 0;
1818 }
1819 }
1820
1821
1822 const char* OrthancJob::CallbackGetContent(void* job)
1823 {
1824 assert(job != NULL);
1825
1826 try
1827 {
1828 return reinterpret_cast<OrthancJob*>(job)->content_.c_str();
1829 }
1830 catch (...)
1831 {
1832 return 0;
1833 }
1834 }
1835
1836
1837 const char* OrthancJob::CallbackGetSerialized(void* job)
1838 {
1839 assert(job != NULL);
1840
1841 try
1842 {
1843 const OrthancJob& tmp = *reinterpret_cast<OrthancJob*>(job);
1844
1845 if (tmp.hasSerialized_)
128 { 1846 {
129 OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &buffer_); 1847 return tmp.serialized_.c_str();
130 buffer_.data = NULL;
131 buffer_.size = 0;
132 }
133 }
134
135
136 void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other)
137 {
138 Clear();
139
140 buffer_.data = other.data;
141 buffer_.size = other.size;
142
143 other.data = NULL;
144 other.size = 0;
145 }
146
147
148 OrthancPluginMemoryBuffer MemoryBuffer::Release()
149 {
150 OrthancPluginMemoryBuffer result = buffer_;
151
152 buffer_.data = NULL;
153 buffer_.size = 0;
154
155 return result;
156 }
157
158
159 void MemoryBuffer::ToString(std::string& target) const
160 {
161 if (buffer_.size == 0)
162 {
163 target.clear();
164 } 1848 }
165 else 1849 else
166 { 1850 {
167 target.assign(reinterpret_cast<const char*>(buffer_.data), buffer_.size); 1851 return NULL;
168 } 1852 }
169 } 1853 }
170 1854 catch (...)
171 1855 {
172 void MemoryBuffer::ToJson(Json::Value& target) const 1856 return 0;
173 { 1857 }
174 if (buffer_.data == NULL || 1858 }
175 buffer_.size == 0) 1859
176 { 1860
177 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 1861 OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job)
178 } 1862 {
179 1863 assert(job != NULL);
180 const char* tmp = reinterpret_cast<const char*>(buffer_.data); 1864
181 1865 try
182 Json::Reader reader; 1866 {
183 if (!reader.parse(tmp, tmp + buffer_.size, target)) 1867 return reinterpret_cast<OrthancJob*>(job)->Step();
184 { 1868 }
185 LogError("Cannot convert some memory buffer to JSON"); 1869 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
186 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); 1870 {
187 } 1871 return OrthancPluginJobStepStatus_Failure;
188 } 1872 }
189 1873 catch (...)
190 1874 {
191 bool MemoryBuffer::RestApiGet(const std::string& uri, 1875 return OrthancPluginJobStepStatus_Failure;
192 bool applyPlugins) 1876 }
193 { 1877 }
194 Clear(); 1878
195 1879
196 if (applyPlugins) 1880 OrthancPluginErrorCode OrthancJob::CallbackStop(void* job,
197 { 1881 OrthancPluginJobStopReason reason)
198 return CheckHttp(OrthancPluginRestApiGetAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str())); 1882 {
199 } 1883 assert(job != NULL);
200 else 1884
201 { 1885 try
202 return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str())); 1886 {
203 } 1887 reinterpret_cast<OrthancJob*>(job)->Stop(reason);
204 } 1888 return OrthancPluginErrorCode_Success;
205 1889 }
206 1890 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
207 bool MemoryBuffer::RestApiPost(const std::string& uri, 1891 {
208 const char* body, 1892 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
209 size_t bodySize, 1893 }
210 bool applyPlugins) 1894 catch (...)
211 { 1895 {
212 Clear(); 1896 return OrthancPluginErrorCode_Plugin;
213 1897 }
214 if (applyPlugins) 1898 }
215 { 1899
216 return CheckHttp(OrthancPluginRestApiPostAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize)); 1900
217 } 1901 OrthancPluginErrorCode OrthancJob::CallbackReset(void* job)
218 else 1902 {
219 { 1903 assert(job != NULL);
220 return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize)); 1904
221 } 1905 try
222 } 1906 {
223 1907 reinterpret_cast<OrthancJob*>(job)->Reset();
224 1908 return OrthancPluginErrorCode_Success;
225 bool MemoryBuffer::RestApiPut(const std::string& uri, 1909 }
226 const char* body, 1910 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
227 size_t bodySize, 1911 {
228 bool applyPlugins) 1912 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
229 { 1913 }
230 Clear(); 1914 catch (...)
231 1915 {
232 if (applyPlugins) 1916 return OrthancPluginErrorCode_Plugin;
233 { 1917 }
234 return CheckHttp(OrthancPluginRestApiPutAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize)); 1918 }
235 } 1919
236 else 1920
237 { 1921 void OrthancJob::ClearContent()
238 return CheckHttp(OrthancPluginRestApiPut(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize)); 1922 {
239 } 1923 Json::Value empty = Json::objectValue;
240 } 1924 UpdateContent(empty);
241 1925 }
242 1926
243 bool MemoryBuffer::RestApiPost(const std::string& uri, 1927
244 const Json::Value& body, 1928 void OrthancJob::UpdateContent(const Json::Value& content)
245 bool applyPlugins) 1929 {
1930 if (content.type() != Json::objectValue)
1931 {
1932 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
1933 }
1934 else
246 { 1935 {
247 Json::FastWriter writer; 1936 Json::FastWriter writer;
248 return RestApiPost(uri, writer.write(body), applyPlugins); 1937 content_ = writer.write(content);
249 } 1938 }
250 1939 }
251 1940
252 bool MemoryBuffer::RestApiPut(const std::string& uri, 1941
253 const Json::Value& body, 1942 void OrthancJob::ClearSerialized()
254 bool applyPlugins) 1943 {
1944 hasSerialized_ = false;
1945 serialized_.clear();
1946 }
1947
1948
1949 void OrthancJob::UpdateSerialized(const Json::Value& serialized)
1950 {
1951 if (serialized.type() != Json::objectValue)
1952 {
1953 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
1954 }
1955 else
255 { 1956 {
256 Json::FastWriter writer; 1957 Json::FastWriter writer;
257 return RestApiPut(uri, writer.write(body), applyPlugins); 1958 serialized_ = writer.write(serialized);
258 } 1959 hasSerialized_ = true;
259 1960 }
260 1961 }
261 void MemoryBuffer::CreateDicom(const Json::Value& tags, 1962
262 OrthancPluginCreateDicomFlags flags) 1963
263 { 1964 void OrthancJob::UpdateProgress(float progress)
264 Clear(); 1965 {
265 1966 if (progress < 0 ||
266 Json::FastWriter writer; 1967 progress > 1)
267 std::string s = writer.write(tags); 1968 {
268 1969 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
269 Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), NULL, flags)); 1970 }
270 } 1971
271 1972 progress_ = progress;
272 void MemoryBuffer::CreateDicom(const Json::Value& tags, 1973 }
273 const OrthancImage& pixelData, 1974
274 OrthancPluginCreateDicomFlags flags) 1975
275 { 1976 OrthancJob::OrthancJob(const std::string& jobType) :
276 Clear(); 1977 jobType_(jobType),
277 1978 progress_(0)
278 Json::FastWriter writer; 1979 {
279 std::string s = writer.write(tags); 1980 ClearContent();
280 1981 ClearSerialized();
281 Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), pixelData.GetObject(), flags)); 1982 }
282 } 1983
283 1984
284 1985 OrthancPluginJob* OrthancJob::Create(OrthancJob* job)
285 void MemoryBuffer::ReadFile(const std::string& path) 1986 {
286 { 1987 if (job == NULL)
287 Clear(); 1988 {
288 Check(OrthancPluginReadFile(GetGlobalContext(), &buffer_, path.c_str())); 1989 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
289 } 1990 }
290 1991
291 1992 OrthancPluginJob* orthanc = OrthancPluginCreateJob(
292 void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query) 1993 GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
293 { 1994 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
294 Clear(); 1995 CallbackStep, CallbackStop, CallbackReset);
295 Check(OrthancPluginWorklistGetDicomQuery(GetGlobalContext(), &buffer_, query)); 1996
296 } 1997 if (orthanc == NULL)
297 1998 {
298 1999 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
299 void OrthancString::Assign(char* str) 2000 }
300 { 2001 else
301 if (str == NULL) 2002 {
302 { 2003 return orthanc;
303 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 2004 }
304 } 2005 }
305 else 2006
306 { 2007
307 Clear(); 2008 std::string OrthancJob::Submit(OrthancJob* job,
308 str_ = str; 2009 int priority)
309 } 2010 {
310 } 2011 OrthancPluginJob* orthanc = Create(job);
311 2012
312 2013 char* id = OrthancPluginSubmitJob(GetGlobalContext(), orthanc, priority);
313 void OrthancString::Clear() 2014
314 { 2015 if (id == NULL)
315 if (str_ != NULL) 2016 {
316 { 2017 LogError("Plugin cannot submit job");
317 OrthancPluginFreeString(GetGlobalContext(), str_); 2018 OrthancPluginFreeJob(GetGlobalContext(), orthanc);
318 str_ = NULL; 2019 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
319 } 2020 }
320 } 2021 else
321 2022 {
322 2023 std::string tmp(id);
323 void OrthancString::ToString(std::string& target) const 2024 tmp.assign(id);
324 { 2025 OrthancPluginFreeString(GetGlobalContext(), id);
325 if (str_ == NULL) 2026
326 { 2027 return tmp;
327 target.clear(); 2028 }
328 } 2029 }
329 else
330 {
331 target.assign(str_);
332 }
333 }
334
335
336 void OrthancString::ToJson(Json::Value& target) const
337 {
338 if (str_ == NULL)
339 {
340 LogError("Cannot convert an empty memory buffer to JSON");
341 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
342 }
343
344 Json::Reader reader;
345 if (!reader.parse(str_, target))
346 {
347 LogError("Cannot convert some memory buffer to JSON");
348 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
349 }
350 }
351
352
353 void MemoryBuffer::DicomToJson(Json::Value& target,
354 OrthancPluginDicomToJsonFormat format,
355 OrthancPluginDicomToJsonFlags flags,
356 uint32_t maxStringLength)
357 {
358 OrthancString str;
359 str.Assign(OrthancPluginDicomBufferToJson
360 (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength));
361 str.ToJson(target);
362 }
363
364
365 bool MemoryBuffer::HttpGet(const std::string& url,
366 const std::string& username,
367 const std::string& password)
368 {
369 Clear();
370 return CheckHttp(OrthancPluginHttpGet(GetGlobalContext(), &buffer_, url.c_str(),
371 username.empty() ? NULL : username.c_str(),
372 password.empty() ? NULL : password.c_str()));
373 }
374
375
376 bool MemoryBuffer::HttpPost(const std::string& url,
377 const std::string& body,
378 const std::string& username,
379 const std::string& password)
380 {
381 Clear();
382 return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(),
383 body.c_str(), body.size(),
384 username.empty() ? NULL : username.c_str(),
385 password.empty() ? NULL : password.c_str()));
386 }
387
388
389 bool MemoryBuffer::HttpPut(const std::string& url,
390 const std::string& body,
391 const std::string& username,
392 const std::string& password)
393 {
394 Clear();
395 return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(),
396 body.empty() ? NULL : body.c_str(),
397 body.size(),
398 username.empty() ? NULL : username.c_str(),
399 password.empty() ? NULL : password.c_str()));
400 }
401
402
403 void MemoryBuffer::GetDicomInstance(const std::string& instanceId)
404 {
405 Clear();
406 Check(OrthancPluginGetDicomForInstance(GetGlobalContext(), &buffer_, instanceId.c_str()));
407 }
408
409
410 bool HttpDelete(const std::string& url,
411 const std::string& username,
412 const std::string& password)
413 {
414 OrthancPluginErrorCode error = OrthancPluginHttpDelete
415 (GetGlobalContext(), url.c_str(),
416 username.empty() ? NULL : username.c_str(),
417 password.empty() ? NULL : password.c_str());
418
419 if (error == OrthancPluginErrorCode_Success)
420 {
421 return true;
422 }
423 else if (error == OrthancPluginErrorCode_UnknownResource ||
424 error == OrthancPluginErrorCode_InexistentItem)
425 {
426 return false;
427 }
428 else
429 {
430 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
431 }
432 }
433
434
435 void LogError(const std::string& message)
436 {
437 if (HasGlobalContext())
438 {
439 OrthancPluginLogError(GetGlobalContext(), message.c_str());
440 }
441 }
442
443
444 void LogWarning(const std::string& message)
445 {
446 if (HasGlobalContext())
447 {
448 OrthancPluginLogWarning(GetGlobalContext(), message.c_str());
449 }
450 }
451
452
453 void LogInfo(const std::string& message)
454 {
455 if (HasGlobalContext())
456 {
457 OrthancPluginLogInfo(GetGlobalContext(), message.c_str());
458 }
459 }
460
461
462 OrthancConfiguration::OrthancConfiguration()
463 {
464 OrthancString str;
465 str.Assign(OrthancPluginGetConfiguration(GetGlobalContext()));
466
467 if (str.GetContent() == NULL)
468 {
469 LogError("Cannot access the Orthanc configuration");
470 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
471 }
472
473 str.ToJson(configuration_);
474
475 if (configuration_.type() != Json::objectValue)
476 {
477 LogError("Unable to read the Orthanc configuration");
478 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
479 }
480 }
481
482
483 std::string OrthancConfiguration::GetPath(const std::string& key) const
484 {
485 if (path_.empty())
486 {
487 return key;
488 }
489 else
490 {
491 return path_ + "." + key;
492 }
493 }
494
495
496 bool OrthancConfiguration::IsSection(const std::string& key) const
497 {
498 assert(configuration_.type() == Json::objectValue);
499
500 return (configuration_.isMember(key) &&
501 configuration_[key].type() == Json::objectValue);
502 }
503
504
505 void OrthancConfiguration::GetSection(OrthancConfiguration& target,
506 const std::string& key) const
507 {
508 assert(configuration_.type() == Json::objectValue);
509
510 target.path_ = GetPath(key);
511
512 if (!configuration_.isMember(key))
513 {
514 target.configuration_ = Json::objectValue;
515 }
516 else
517 {
518 if (configuration_[key].type() != Json::objectValue)
519 {
520 LogError("The configuration section \"" + target.path_ +
521 "\" is not an associative array as expected");
522
523 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
524 }
525
526 target.configuration_ = configuration_[key];
527 }
528 }
529
530
531 bool OrthancConfiguration::LookupStringValue(std::string& target,
532 const std::string& key) const
533 {
534 assert(configuration_.type() == Json::objectValue);
535
536 if (!configuration_.isMember(key))
537 {
538 return false;
539 }
540
541 if (configuration_[key].type() != Json::stringValue)
542 {
543 LogError("The configuration option \"" + GetPath(key) +
544 "\" is not a string as expected");
545
546 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
547 }
548
549 target = configuration_[key].asString();
550 return true;
551 }
552
553
554 bool OrthancConfiguration::LookupIntegerValue(int& target,
555 const std::string& key) const
556 {
557 assert(configuration_.type() == Json::objectValue);
558
559 if (!configuration_.isMember(key))
560 {
561 return false;
562 }
563
564 switch (configuration_[key].type())
565 {
566 case Json::intValue:
567 target = configuration_[key].asInt();
568 return true;
569
570 case Json::uintValue:
571 target = configuration_[key].asUInt();
572 return true;
573
574 default:
575 LogError("The configuration option \"" + GetPath(key) +
576 "\" is not an integer as expected");
577
578 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
579 }
580 }
581
582
583 bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target,
584 const std::string& key) const
585 {
586 int tmp;
587 if (!LookupIntegerValue(tmp, key))
588 {
589 return false;
590 }
591
592 if (tmp < 0)
593 {
594 LogError("The configuration option \"" + GetPath(key) +
595 "\" is not a positive integer as expected");
596
597 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
598 }
599 else
600 {
601 target = static_cast<unsigned int>(tmp);
602 return true;
603 }
604 }
605
606
607 bool OrthancConfiguration::LookupBooleanValue(bool& target,
608 const std::string& key) const
609 {
610 assert(configuration_.type() == Json::objectValue);
611
612 if (!configuration_.isMember(key))
613 {
614 return false;
615 }
616
617 if (configuration_[key].type() != Json::booleanValue)
618 {
619 LogError("The configuration option \"" + GetPath(key) +
620 "\" is not a Boolean as expected");
621
622 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
623 }
624
625 target = configuration_[key].asBool();
626 return true;
627 }
628
629
630 bool OrthancConfiguration::LookupFloatValue(float& target,
631 const std::string& key) const
632 {
633 assert(configuration_.type() == Json::objectValue);
634
635 if (!configuration_.isMember(key))
636 {
637 return false;
638 }
639
640 switch (configuration_[key].type())
641 {
642 case Json::realValue:
643 target = configuration_[key].asFloat();
644 return true;
645
646 case Json::intValue:
647 target = static_cast<float>(configuration_[key].asInt());
648 return true;
649
650 case Json::uintValue:
651 target = static_cast<float>(configuration_[key].asUInt());
652 return true;
653
654 default:
655 LogError("The configuration option \"" + GetPath(key) +
656 "\" is not an integer as expected");
657
658 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
659 }
660 }
661
662
663 bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target,
664 const std::string& key,
665 bool allowSingleString) const
666 {
667 assert(configuration_.type() == Json::objectValue);
668
669 target.clear();
670
671 if (!configuration_.isMember(key))
672 {
673 return false;
674 }
675
676 switch (configuration_[key].type())
677 {
678 case Json::arrayValue:
679 {
680 bool ok = true;
681
682 for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++)
683 {
684 if (configuration_[key][i].type() == Json::stringValue)
685 {
686 target.push_back(configuration_[key][i].asString());
687 }
688 else
689 {
690 ok = false;
691 }
692 }
693
694 if (ok)
695 {
696 return true;
697 }
698
699 break;
700 }
701
702 case Json::stringValue:
703 if (allowSingleString)
704 {
705 target.push_back(configuration_[key].asString());
706 return true;
707 }
708
709 break;
710
711 default:
712 break;
713 }
714
715 LogError("The configuration option \"" + GetPath(key) +
716 "\" is not a list of strings as expected");
717
718 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
719 }
720
721
722 bool OrthancConfiguration::LookupSetOfStrings(std::set<std::string>& target,
723 const std::string& key,
724 bool allowSingleString) const
725 {
726 std::list<std::string> lst;
727
728 if (LookupListOfStrings(lst, key, allowSingleString))
729 {
730 target.clear();
731
732 for (std::list<std::string>::const_iterator
733 it = lst.begin(); it != lst.end(); ++it)
734 {
735 target.insert(*it);
736 }
737
738 return true;
739 }
740 else
741 {
742 return false;
743 }
744 }
745
746
747 std::string OrthancConfiguration::GetStringValue(const std::string& key,
748 const std::string& defaultValue) const
749 {
750 std::string tmp;
751 if (LookupStringValue(tmp, key))
752 {
753 return tmp;
754 }
755 else
756 {
757 return defaultValue;
758 }
759 }
760
761
762 int OrthancConfiguration::GetIntegerValue(const std::string& key,
763 int defaultValue) const
764 {
765 int tmp;
766 if (LookupIntegerValue(tmp, key))
767 {
768 return tmp;
769 }
770 else
771 {
772 return defaultValue;
773 }
774 }
775
776
777 unsigned int OrthancConfiguration::GetUnsignedIntegerValue(const std::string& key,
778 unsigned int defaultValue) const
779 {
780 unsigned int tmp;
781 if (LookupUnsignedIntegerValue(tmp, key))
782 {
783 return tmp;
784 }
785 else
786 {
787 return defaultValue;
788 }
789 }
790
791
792 bool OrthancConfiguration::GetBooleanValue(const std::string& key,
793 bool defaultValue) const
794 {
795 bool tmp;
796 if (LookupBooleanValue(tmp, key))
797 {
798 return tmp;
799 }
800 else
801 {
802 return defaultValue;
803 }
804 }
805
806
807 float OrthancConfiguration::GetFloatValue(const std::string& key,
808 float defaultValue) const
809 {
810 float tmp;
811 if (LookupFloatValue(tmp, key))
812 {
813 return tmp;
814 }
815 else
816 {
817 return defaultValue;
818 }
819 }
820
821
822 void OrthancConfiguration::GetDictionary(std::map<std::string, std::string>& target,
823 const std::string& key) const
824 {
825 assert(configuration_.type() == Json::objectValue);
826
827 target.clear();
828
829 if (!configuration_.isMember(key))
830 {
831 return;
832 }
833
834 if (configuration_[key].type() != Json::objectValue)
835 {
836 LogError("The configuration option \"" + GetPath(key) +
837 "\" is not a string as expected");
838
839 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
840 }
841
842 Json::Value::Members members = configuration_[key].getMemberNames();
843
844 for (size_t i = 0; i < members.size(); i++)
845 {
846 const Json::Value& value = configuration_[key][members[i]];
847
848 if (value.type() == Json::stringValue)
849 {
850 target[members[i]] = value.asString();
851 }
852 else
853 {
854 LogError("The configuration option \"" + GetPath(key) +
855 "\" is not a dictionary mapping strings to strings");
856
857 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
858 }
859 }
860 }
861
862
863 void OrthancImage::Clear()
864 {
865 if (image_ != NULL)
866 {
867 OrthancPluginFreeImage(GetGlobalContext(), image_);
868 image_ = NULL;
869 }
870 }
871
872
873 void OrthancImage::CheckImageAvailable()
874 {
875 if (image_ == NULL)
876 {
877 LogError("Trying to access a NULL image");
878 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
879 }
880 }
881
882
883 OrthancImage::OrthancImage() :
884 image_(NULL)
885 {
886 }
887
888
889 OrthancImage::OrthancImage(OrthancPluginImage* image) :
890 image_(image)
891 {
892 }
893
894
895 OrthancImage::OrthancImage(OrthancPluginPixelFormat format,
896 uint32_t width,
897 uint32_t height)
898 {
899 image_ = OrthancPluginCreateImage(GetGlobalContext(), format, width, height);
900
901 if (image_ == NULL)
902 {
903 LogError("Cannot create an image");
904 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
905 }
906 }
907
908
909 OrthancImage::OrthancImage(OrthancPluginPixelFormat format,
910 uint32_t width,
911 uint32_t height,
912 uint32_t pitch,
913 void* buffer)
914 {
915 image_ = OrthancPluginCreateImageAccessor
916 (GetGlobalContext(), format, width, height, pitch, buffer);
917
918 if (image_ == NULL)
919 {
920 LogError("Cannot create an image accessor");
921 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
922 }
923 }
924
925 void OrthancImage::UncompressPngImage(const void* data,
926 size_t size)
927 {
928 Clear();
929
930 image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Png);
931
932 if (image_ == NULL)
933 {
934 LogError("Cannot uncompress a PNG image");
935 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
936 }
937 }
938
939
940 void OrthancImage::UncompressJpegImage(const void* data,
941 size_t size)
942 {
943 Clear();
944 image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg);
945 if (image_ == NULL)
946 {
947 LogError("Cannot uncompress a JPEG image");
948 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
949 }
950 }
951
952
953 void OrthancImage::DecodeDicomImage(const void* data,
954 size_t size,
955 unsigned int frame)
956 {
957 Clear();
958 image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame);
959 if (image_ == NULL)
960 {
961 LogError("Cannot uncompress a DICOM image");
962 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
963 }
964 }
965
966
967 OrthancPluginPixelFormat OrthancImage::GetPixelFormat()
968 {
969 CheckImageAvailable();
970 return OrthancPluginGetImagePixelFormat(GetGlobalContext(), image_);
971 }
972
973
974 unsigned int OrthancImage::GetWidth()
975 {
976 CheckImageAvailable();
977 return OrthancPluginGetImageWidth(GetGlobalContext(), image_);
978 }
979
980
981 unsigned int OrthancImage::GetHeight()
982 {
983 CheckImageAvailable();
984 return OrthancPluginGetImageHeight(GetGlobalContext(), image_);
985 }
986
987
988 unsigned int OrthancImage::GetPitch()
989 {
990 CheckImageAvailable();
991 return OrthancPluginGetImagePitch(GetGlobalContext(), image_);
992 }
993
994
995 const void* OrthancImage::GetBuffer()
996 {
997 CheckImageAvailable();
998 return OrthancPluginGetImageBuffer(GetGlobalContext(), image_);
999 }
1000
1001
1002 void OrthancImage::CompressPngImage(MemoryBuffer& target)
1003 {
1004 CheckImageAvailable();
1005
1006 OrthancPluginMemoryBuffer tmp;
1007 OrthancPluginCompressPngImage(GetGlobalContext(), &tmp, GetPixelFormat(),
1008 GetWidth(), GetHeight(), GetPitch(), GetBuffer());
1009
1010 target.Assign(tmp);
1011 }
1012
1013
1014 void OrthancImage::CompressJpegImage(MemoryBuffer& target,
1015 uint8_t quality)
1016 {
1017 CheckImageAvailable();
1018
1019 OrthancPluginMemoryBuffer tmp;
1020 OrthancPluginCompressJpegImage(GetGlobalContext(), &tmp, GetPixelFormat(),
1021 GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
1022
1023 target.Assign(tmp);
1024 }
1025
1026
1027 void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output)
1028 {
1029 CheckImageAvailable();
1030 OrthancPluginCompressAndAnswerPngImage(GetGlobalContext(), output, GetPixelFormat(),
1031 GetWidth(), GetHeight(), GetPitch(), GetBuffer());
1032 }
1033
1034
1035 void OrthancImage::AnswerJpegImage(OrthancPluginRestOutput* output,
1036 uint8_t quality)
1037 {
1038 CheckImageAvailable();
1039 OrthancPluginCompressAndAnswerJpegImage(GetGlobalContext(), output, GetPixelFormat(),
1040 GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
1041 }
1042
1043
1044
1045 #if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
1046 FindMatcher::FindMatcher(const OrthancPluginWorklistQuery* worklist) :
1047 matcher_(NULL),
1048 worklist_(worklist)
1049 {
1050 if (worklist_ == NULL)
1051 {
1052 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
1053 }
1054 }
1055
1056
1057 void FindMatcher::SetupDicom(const void* query,
1058 uint32_t size)
1059 {
1060 worklist_ = NULL;
1061
1062 matcher_ = OrthancPluginCreateFindMatcher(GetGlobalContext(), query, size);
1063 if (matcher_ == NULL)
1064 {
1065 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1066 }
1067 }
1068
1069
1070 FindMatcher::~FindMatcher()
1071 {
1072 // The "worklist_" field
1073
1074 if (matcher_ != NULL)
1075 {
1076 OrthancPluginFreeFindMatcher(GetGlobalContext(), matcher_);
1077 }
1078 }
1079
1080
1081
1082 bool FindMatcher::IsMatch(const void* dicom,
1083 uint32_t size) const
1084 {
1085 int32_t result;
1086
1087 if (matcher_ != NULL)
1088 {
1089 result = OrthancPluginFindMatcherIsMatch(GetGlobalContext(), matcher_, dicom, size);
1090 }
1091 else if (worklist_ != NULL)
1092 {
1093 result = OrthancPluginWorklistIsMatch(GetGlobalContext(), worklist_, dicom, size);
1094 }
1095 else
1096 {
1097 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1098 }
1099
1100 if (result == 0)
1101 {
1102 return false;
1103 }
1104 else if (result == 1)
1105 {
1106 return true;
1107 }
1108 else
1109 {
1110 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1111 }
1112 }
1113
1114 #endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */
1115
1116 void AnswerJson(const Json::Value& value,
1117 OrthancPluginRestOutput* output
1118 )
1119 {
1120 Json::StyledWriter writer;
1121 std::string bodyString = writer.write(value);
1122
1123 OrthancPluginAnswerBuffer(GetGlobalContext(), output, bodyString.c_str(), bodyString.size(), "application/json");
1124 }
1125
1126 void AnswerHttpError(uint16_t httpError, OrthancPluginRestOutput *output)
1127 {
1128 OrthancPluginSendHttpStatusCode(GetGlobalContext(), output, httpError);
1129 }
1130
1131 void AnswerMethodNotAllowed(OrthancPluginRestOutput *output, const char* allowedMethods)
1132 {
1133 OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowedMethods);
1134 }
1135
1136 bool RestApiGetString(std::string& result,
1137 const std::string& uri,
1138 bool applyPlugins)
1139 {
1140 MemoryBuffer answer;
1141 if (!answer.RestApiGet(uri, applyPlugins))
1142 {
1143 return false;
1144 }
1145 else
1146 {
1147 answer.ToString(result);
1148 return true;
1149 }
1150 }
1151
1152
1153 bool RestApiGet(Json::Value& result,
1154 const std::string& uri,
1155 bool applyPlugins)
1156 {
1157 MemoryBuffer answer;
1158
1159 if (!answer.RestApiGet(uri, applyPlugins))
1160 {
1161 return false;
1162 }
1163 else
1164 {
1165 if (!answer.IsEmpty())
1166 {
1167 answer.ToJson(result);
1168 }
1169 return true;
1170 }
1171 }
1172
1173
1174 bool RestApiPost(Json::Value& result,
1175 const std::string& uri,
1176 const char* body,
1177 size_t bodySize,
1178 bool applyPlugins)
1179 {
1180 MemoryBuffer answer;
1181
1182 if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
1183 {
1184 return false;
1185 }
1186 else
1187 {
1188 if (!answer.IsEmpty())
1189 {
1190 answer.ToJson(result);
1191 }
1192 return true;
1193 }
1194 }
1195
1196
1197 bool RestApiPost(Json::Value& result,
1198 const std::string& uri,
1199 const Json::Value& body,
1200 bool applyPlugins)
1201 {
1202 Json::FastWriter writer;
1203 return RestApiPost(result, uri, writer.write(body), applyPlugins);
1204 }
1205
1206
1207 bool RestApiPut(Json::Value& result,
1208 const std::string& uri,
1209 const char* body,
1210 size_t bodySize,
1211 bool applyPlugins)
1212 {
1213 MemoryBuffer answer;
1214
1215 if (!answer.RestApiPut(uri, body, bodySize, applyPlugins))
1216 {
1217 return false;
1218 }
1219 else
1220 {
1221 if (!answer.IsEmpty()) // i.e, on a PUT to metadata/..., orthand returns an empty response
1222 {
1223 answer.ToJson(result);
1224 }
1225 return true;
1226 }
1227 }
1228
1229
1230 bool RestApiPut(Json::Value& result,
1231 const std::string& uri,
1232 const Json::Value& body,
1233 bool applyPlugins)
1234 {
1235 Json::FastWriter writer;
1236 return RestApiPut(result, uri, writer.write(body), applyPlugins);
1237 }
1238
1239
1240 bool RestApiDelete(const std::string& uri,
1241 bool applyPlugins)
1242 {
1243 OrthancPluginErrorCode error;
1244
1245 if (applyPlugins)
1246 {
1247 error = OrthancPluginRestApiDeleteAfterPlugins(GetGlobalContext(), uri.c_str());
1248 }
1249 else
1250 {
1251 error = OrthancPluginRestApiDelete(GetGlobalContext(), uri.c_str());
1252 }
1253
1254 if (error == OrthancPluginErrorCode_Success)
1255 {
1256 return true;
1257 }
1258 else if (error == OrthancPluginErrorCode_UnknownResource ||
1259 error == OrthancPluginErrorCode_InexistentItem)
1260 {
1261 return false;
1262 }
1263 else
1264 {
1265 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
1266 }
1267 }
1268
1269
1270 void ReportMinimalOrthancVersion(unsigned int major,
1271 unsigned int minor,
1272 unsigned int revision)
1273 {
1274 LogError("Your version of the Orthanc core (" +
1275 std::string(GetGlobalContext()->orthancVersion) +
1276 ") is too old to run this plugin (version " +
1277 boost::lexical_cast<std::string>(major) + "." +
1278 boost::lexical_cast<std::string>(minor) + "." +
1279 boost::lexical_cast<std::string>(revision) +
1280 " is required)");
1281 }
1282
1283
1284 bool CheckMinimalOrthancVersion(unsigned int major,
1285 unsigned int minor,
1286 unsigned int revision)
1287 {
1288 if (!HasGlobalContext())
1289 {
1290 LogError("Bad Orthanc context in the plugin");
1291 return false;
1292 }
1293
1294 if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
1295 {
1296 // Assume compatibility with the mainline
1297 return true;
1298 }
1299
1300 // Parse the version of the Orthanc core
1301 int aa, bb, cc;
1302 if (
1303 #ifdef _MSC_VER
1304 sscanf_s
1305 #else
1306 sscanf
1307 #endif
1308 (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
1309 aa < 0 ||
1310 bb < 0 ||
1311 cc < 0)
1312 {
1313 return false;
1314 }
1315
1316 unsigned int a = static_cast<unsigned int>(aa);
1317 unsigned int b = static_cast<unsigned int>(bb);
1318 unsigned int c = static_cast<unsigned int>(cc);
1319
1320 // Check the major version number
1321
1322 if (a > major)
1323 {
1324 return true;
1325 }
1326
1327 if (a < major)
1328 {
1329 return false;
1330 }
1331
1332
1333 // Check the minor version number
1334 assert(a == major);
1335
1336 if (b > minor)
1337 {
1338 return true;
1339 }
1340
1341 if (b < minor)
1342 {
1343 return false;
1344 }
1345
1346 // Check the patch level version number
1347 assert(a == major && b == minor);
1348
1349 if (c >= revision)
1350 {
1351 return true;
1352 }
1353 else
1354 {
1355 return false;
1356 }
1357 }
1358
1359
1360 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
1361 const char* AutodetectMimeType(const std::string& path)
1362 {
1363 const char* mime = OrthancPluginAutodetectMimeType(GetGlobalContext(), path.c_str());
1364
1365 if (mime == NULL)
1366 {
1367 // Should never happen, just for safety
1368 return "application/octet-stream";
1369 }
1370 else
1371 {
1372 return mime;
1373 }
1374 }
1375 #endif 2030 #endif
1376 2031 }
1377
1378 #if HAS_ORTHANC_PLUGIN_PEERS == 1
1379 size_t OrthancPeers::GetPeerIndex(const std::string& name) const
1380 {
1381 size_t index;
1382 if (LookupName(index, name))
1383 {
1384 return index;
1385 }
1386 else
1387 {
1388 LogError("Inexistent peer: " + name);
1389 ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
1390 }
1391 }
1392
1393
1394 OrthancPeers::OrthancPeers() :
1395 peers_(NULL),
1396 timeout_(0)
1397 {
1398 peers_ = OrthancPluginGetPeers(GetGlobalContext());
1399
1400 if (peers_ == NULL)
1401 {
1402 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1403 }
1404
1405 uint32_t count = OrthancPluginGetPeersCount(GetGlobalContext(), peers_);
1406
1407 for (uint32_t i = 0; i < count; i++)
1408 {
1409 const char* name = OrthancPluginGetPeerName(GetGlobalContext(), peers_, i);
1410 if (name == NULL)
1411 {
1412 OrthancPluginFreePeers(GetGlobalContext(), peers_);
1413 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1414 }
1415
1416 index_[name] = i;
1417 }
1418 }
1419
1420
1421 OrthancPeers::~OrthancPeers()
1422 {
1423 if (peers_ != NULL)
1424 {
1425 OrthancPluginFreePeers(GetGlobalContext(), peers_);
1426 }
1427 }
1428
1429
1430 bool OrthancPeers::LookupName(size_t& target,
1431 const std::string& name) const
1432 {
1433 Index::const_iterator found = index_.find(name);
1434
1435 if (found == index_.end())
1436 {
1437 return false;
1438 }
1439 else
1440 {
1441 target = found->second;
1442 return true;
1443 }
1444 }
1445
1446
1447 std::string OrthancPeers::GetPeerName(size_t index) const
1448 {
1449 if (index >= index_.size())
1450 {
1451 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1452 }
1453 else
1454 {
1455 const char* s = OrthancPluginGetPeerName(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
1456 if (s == NULL)
1457 {
1458 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1459 }
1460 else
1461 {
1462 return s;
1463 }
1464 }
1465 }
1466
1467
1468 std::string OrthancPeers::GetPeerUrl(size_t index) const
1469 {
1470 if (index >= index_.size())
1471 {
1472 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1473 }
1474 else
1475 {
1476 const char* s = OrthancPluginGetPeerUrl(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
1477 if (s == NULL)
1478 {
1479 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1480 }
1481 else
1482 {
1483 return s;
1484 }
1485 }
1486 }
1487
1488
1489 std::string OrthancPeers::GetPeerUrl(const std::string& name) const
1490 {
1491 return GetPeerUrl(GetPeerIndex(name));
1492 }
1493
1494
1495 bool OrthancPeers::LookupUserProperty(std::string& value,
1496 size_t index,
1497 const std::string& key) const
1498 {
1499 if (index >= index_.size())
1500 {
1501 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1502 }
1503 else
1504 {
1505 const char* s = OrthancPluginGetPeerUserProperty(GetGlobalContext(), peers_, static_cast<uint32_t>(index), key.c_str());
1506 if (s == NULL)
1507 {
1508 return false;
1509 }
1510 else
1511 {
1512 value.assign(s);
1513 return true;
1514 }
1515 }
1516 }
1517
1518
1519 bool OrthancPeers::LookupUserProperty(std::string& value,
1520 const std::string& peer,
1521 const std::string& key) const
1522 {
1523 return LookupUserProperty(value, GetPeerIndex(peer), key);
1524 }
1525
1526
1527 bool OrthancPeers::DoGet(MemoryBuffer& target,
1528 size_t index,
1529 const std::string& uri) const
1530 {
1531 if (index >= index_.size())
1532 {
1533 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1534 }
1535
1536 OrthancPluginMemoryBuffer answer;
1537 uint16_t status;
1538 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1539 (GetGlobalContext(), &answer, NULL, &status, peers_,
1540 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
1541 0, NULL, NULL, NULL, 0, timeout_);
1542
1543 if (code == OrthancPluginErrorCode_Success)
1544 {
1545 target.Assign(answer);
1546 return (status == 200);
1547 }
1548 else
1549 {
1550 return false;
1551 }
1552 }
1553
1554
1555 bool OrthancPeers::DoGet(MemoryBuffer& target,
1556 const std::string& name,
1557 const std::string& uri) const
1558 {
1559 size_t index;
1560 return (LookupName(index, name) &&
1561 DoGet(target, index, uri));
1562 }
1563
1564
1565 bool OrthancPeers::DoGet(Json::Value& target,
1566 size_t index,
1567 const std::string& uri) const
1568 {
1569 MemoryBuffer buffer;
1570
1571 if (DoGet(buffer, index, uri))
1572 {
1573 buffer.ToJson(target);
1574 return true;
1575 }
1576 else
1577 {
1578 return false;
1579 }
1580 }
1581
1582
1583 bool OrthancPeers::DoGet(Json::Value& target,
1584 const std::string& name,
1585 const std::string& uri) const
1586 {
1587 MemoryBuffer buffer;
1588
1589 if (DoGet(buffer, name, uri))
1590 {
1591 buffer.ToJson(target);
1592 return true;
1593 }
1594 else
1595 {
1596 return false;
1597 }
1598 }
1599
1600
1601 bool OrthancPeers::DoPost(MemoryBuffer& target,
1602 const std::string& name,
1603 const std::string& uri,
1604 const std::string& body) const
1605 {
1606 size_t index;
1607 return (LookupName(index, name) &&
1608 DoPost(target, index, uri, body));
1609 }
1610
1611
1612 bool OrthancPeers::DoPost(Json::Value& target,
1613 size_t index,
1614 const std::string& uri,
1615 const std::string& body) const
1616 {
1617 MemoryBuffer buffer;
1618
1619 if (DoPost(buffer, index, uri, body))
1620 {
1621 buffer.ToJson(target);
1622 return true;
1623 }
1624 else
1625 {
1626 return false;
1627 }
1628 }
1629
1630
1631 bool OrthancPeers::DoPost(Json::Value& target,
1632 const std::string& name,
1633 const std::string& uri,
1634 const std::string& body) const
1635 {
1636 MemoryBuffer buffer;
1637
1638 if (DoPost(buffer, name, uri, body))
1639 {
1640 buffer.ToJson(target);
1641 return true;
1642 }
1643 else
1644 {
1645 return false;
1646 }
1647 }
1648
1649
1650 bool OrthancPeers::DoPost(MemoryBuffer& target,
1651 size_t index,
1652 const std::string& uri,
1653 const std::string& body) const
1654 {
1655 if (index >= index_.size())
1656 {
1657 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1658 }
1659
1660 OrthancPluginMemoryBuffer answer;
1661 uint16_t status;
1662 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1663 (GetGlobalContext(), &answer, NULL, &status, peers_,
1664 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
1665 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1666
1667 if (code == OrthancPluginErrorCode_Success)
1668 {
1669 target.Assign(answer);
1670 return (status == 200);
1671 }
1672 else
1673 {
1674 return false;
1675 }
1676 }
1677
1678
1679 bool OrthancPeers::DoPut(size_t index,
1680 const std::string& uri,
1681 const std::string& body) const
1682 {
1683 if (index >= index_.size())
1684 {
1685 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1686 }
1687
1688 OrthancPluginMemoryBuffer answer;
1689 uint16_t status;
1690 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1691 (GetGlobalContext(), &answer, NULL, &status, peers_,
1692 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
1693 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1694
1695 if (code == OrthancPluginErrorCode_Success)
1696 {
1697 OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &answer);
1698 return (status == 200);
1699 }
1700 else
1701 {
1702 return false;
1703 }
1704 }
1705
1706
1707 bool OrthancPeers::DoPut(const std::string& name,
1708 const std::string& uri,
1709 const std::string& body) const
1710 {
1711 size_t index;
1712 return (LookupName(index, name) &&
1713 DoPut(index, uri, body));
1714 }
1715
1716
1717 bool OrthancPeers::DoDelete(size_t index,
1718 const std::string& uri) const
1719 {
1720 if (index >= index_.size())
1721 {
1722 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1723 }
1724
1725 OrthancPluginMemoryBuffer answer;
1726 uint16_t status;
1727 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1728 (GetGlobalContext(), &answer, NULL, &status, peers_,
1729 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
1730 0, NULL, NULL, NULL, 0, timeout_);
1731
1732 if (code == OrthancPluginErrorCode_Success)
1733 {
1734 OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &answer);
1735 return (status == 200);
1736 }
1737 else
1738 {
1739 return false;
1740 }
1741 }
1742
1743
1744 bool OrthancPeers::DoDelete(const std::string& name,
1745 const std::string& uri) const
1746 {
1747 size_t index;
1748 return (LookupName(index, name) &&
1749 DoDelete(index, uri));
1750 }
1751 #endif
1752
1753
1754
1755 #if HAS_ORTHANC_PLUGIN_JOB == 1
1756 void OrthancJob::CallbackFinalize(void* job)
1757 {
1758 if (job != NULL)
1759 {
1760 delete reinterpret_cast<OrthancJob*>(job);
1761 }
1762 }
1763
1764
1765 float OrthancJob::CallbackGetProgress(void* job)
1766 {
1767 assert(job != NULL);
1768
1769 try
1770 {
1771 return reinterpret_cast<OrthancJob*>(job)->progress_;
1772 }
1773 catch (...)
1774 {
1775 return 0;
1776 }
1777 }
1778
1779
1780 const char* OrthancJob::CallbackGetContent(void* job)
1781 {
1782 assert(job != NULL);
1783
1784 try
1785 {
1786 return reinterpret_cast<OrthancJob*>(job)->content_.c_str();
1787 }
1788 catch (...)
1789 {
1790 return 0;
1791 }
1792 }
1793
1794
1795 const char* OrthancJob::CallbackGetSerialized(void* job)
1796 {
1797 assert(job != NULL);
1798
1799 try
1800 {
1801 const OrthancJob& tmp = *reinterpret_cast<OrthancJob*>(job);
1802
1803 if (tmp.hasSerialized_)
1804 {
1805 return tmp.serialized_.c_str();
1806 }
1807 else
1808 {
1809 return NULL;
1810 }
1811 }
1812 catch (...)
1813 {
1814 return 0;
1815 }
1816 }
1817
1818
1819 OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job)
1820 {
1821 assert(job != NULL);
1822
1823 try
1824 {
1825 return reinterpret_cast<OrthancJob*>(job)->Step();
1826 }
1827 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
1828 {
1829 return OrthancPluginJobStepStatus_Failure;
1830 }
1831 catch (...)
1832 {
1833 return OrthancPluginJobStepStatus_Failure;
1834 }
1835 }
1836
1837
1838 OrthancPluginErrorCode OrthancJob::CallbackStop(void* job,
1839 OrthancPluginJobStopReason reason)
1840 {
1841 assert(job != NULL);
1842
1843 try
1844 {
1845 reinterpret_cast<OrthancJob*>(job)->Stop(reason);
1846 return OrthancPluginErrorCode_Success;
1847 }
1848 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
1849 {
1850 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
1851 }
1852 catch (...)
1853 {
1854 return OrthancPluginErrorCode_Plugin;
1855 }
1856 }
1857
1858
1859 OrthancPluginErrorCode OrthancJob::CallbackReset(void* job)
1860 {
1861 assert(job != NULL);
1862
1863 try
1864 {
1865 reinterpret_cast<OrthancJob*>(job)->Reset();
1866 return OrthancPluginErrorCode_Success;
1867 }
1868 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
1869 {
1870 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
1871 }
1872 catch (...)
1873 {
1874 return OrthancPluginErrorCode_Plugin;
1875 }
1876 }
1877
1878
1879 void OrthancJob::ClearContent()
1880 {
1881 Json::Value empty = Json::objectValue;
1882 UpdateContent(empty);
1883 }
1884
1885
1886 void OrthancJob::UpdateContent(const Json::Value& content)
1887 {
1888 if (content.type() != Json::objectValue)
1889 {
1890 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
1891 }
1892 else
1893 {
1894 Json::FastWriter writer;
1895 content_ = writer.write(content);
1896 }
1897 }
1898
1899
1900 void OrthancJob::ClearSerialized()
1901 {
1902 hasSerialized_ = false;
1903 serialized_.clear();
1904 }
1905
1906
1907 void OrthancJob::UpdateSerialized(const Json::Value& serialized)
1908 {
1909 if (serialized.type() != Json::objectValue)
1910 {
1911 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
1912 }
1913 else
1914 {
1915 Json::FastWriter writer;
1916 serialized_ = writer.write(serialized);
1917 hasSerialized_ = true;
1918 }
1919 }
1920
1921
1922 void OrthancJob::UpdateProgress(float progress)
1923 {
1924 if (progress < 0 ||
1925 progress > 1)
1926 {
1927 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1928 }
1929
1930 progress_ = progress;
1931 }
1932
1933
1934 OrthancJob::OrthancJob(const std::string& jobType) :
1935 jobType_(jobType),
1936 progress_(0)
1937 {
1938 ClearContent();
1939 ClearSerialized();
1940 }
1941
1942
1943 OrthancPluginJob* OrthancJob::Create(OrthancJob* job)
1944 {
1945 if (job == NULL)
1946 {
1947 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
1948 }
1949
1950 OrthancPluginJob* orthanc = OrthancPluginCreateJob(
1951 GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
1952 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
1953 CallbackStep, CallbackStop, CallbackReset);
1954
1955 if (orthanc == NULL)
1956 {
1957 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1958 }
1959 else
1960 {
1961 return orthanc;
1962 }
1963 }
1964
1965
1966 std::string OrthancJob::Submit(OrthancJob* job,
1967 int priority)
1968 {
1969 OrthancPluginJob* orthanc = Create(job);
1970
1971 char* id = OrthancPluginSubmitJob(GetGlobalContext(), orthanc, priority);
1972
1973 if (id == NULL)
1974 {
1975 LogError("Plugin cannot submit job");
1976 OrthancPluginFreeJob(GetGlobalContext(), orthanc);
1977 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
1978 }
1979 else
1980 {
1981 std::string tmp(id);
1982 tmp.assign(id);
1983 OrthancPluginFreeString(GetGlobalContext(), id);
1984
1985 return tmp;
1986 }
1987 }
1988 #endif
1989 }