comparison Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp @ 113:5a60cbbe9bb0

sync
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 28 Mar 2023 17:34:20 +0200
parents e2b2e1d4e1bb
children 4cf3c2bc119f
comparison
equal deleted inserted replaced
112:b3a18e333f93 113:5a60cbbe9bb0
1 /** 1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store 2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium 4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2022 Osimis S.A., Belgium 5 * Copyright (C) 2017-2023 Osimis S.A., Belgium
6 * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium 6 * Copyright (C) 2021-2023 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 * 7 *
8 * This program is free software: you can redistribute it and/or 8 * This program is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as 9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, either version 3 of the 10 * published by the Free Software Foundation, either version 3 of the
11 * License, or (at your option) any later version. 11 * License, or (at your option) any later version.
248 { 248 {
249 return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str())); 249 return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str()));
250 } 250 }
251 } 251 }
252 252
253 // helper class to convert std::map of headers to the plugin SDK C structure
254 class PluginHttpHeaders
255 {
256 std::vector<const char*> headersKeys_;
257 std::vector<const char*> headersValues_;
258 public:
259
260 PluginHttpHeaders(const std::map<std::string, std::string>& httpHeaders)
261 {
262 for (std::map<std::string, std::string>::const_iterator
263 it = httpHeaders.begin(); it != httpHeaders.end(); it++)
264 {
265 headersKeys_.push_back(it->first.c_str());
266 headersValues_.push_back(it->second.c_str());
267 }
268 }
269
270 const char* const* GetKeys()
271 {
272 return (headersKeys_.empty() ? NULL : &headersKeys_[0]);
273 }
274
275 const char* const* GetValues()
276 {
277 return (headersValues_.empty() ? NULL : &headersValues_[0]);
278 }
279
280 uint32_t GetSize()
281 {
282 return static_cast<uint32_t>(headersKeys_.size());
283 }
284 };
285
253 bool MemoryBuffer::RestApiGet(const std::string& uri, 286 bool MemoryBuffer::RestApiGet(const std::string& uri,
254 const std::map<std::string, std::string>& httpHeaders, 287 const std::map<std::string, std::string>& httpHeaders,
255 bool applyPlugins) 288 bool applyPlugins)
256 { 289 {
257 Clear(); 290 Clear();
258 291
259 std::vector<const char*> headersKeys; 292 PluginHttpHeaders headers(httpHeaders);
260 std::vector<const char*> headersValues;
261
262 for (std::map<std::string, std::string>::const_iterator
263 it = httpHeaders.begin(); it != httpHeaders.end(); it++)
264 {
265 headersKeys.push_back(it->first.c_str());
266 headersValues.push_back(it->second.c_str());
267 }
268 293
269 return CheckHttp(OrthancPluginRestApiGet2( 294 return CheckHttp(OrthancPluginRestApiGet2(
270 GetGlobalContext(), &buffer_, uri.c_str(), httpHeaders.size(), 295 GetGlobalContext(), &buffer_, uri.c_str(),
271 (headersKeys.empty() ? NULL : &headersKeys[0]), 296 headers.GetSize(),
272 (headersValues.empty() ? NULL : &headersValues[0]), applyPlugins)); 297 headers.GetKeys(),
298 headers.GetValues(), applyPlugins));
273 } 299 }
274 300
275 bool MemoryBuffer::RestApiPost(const std::string& uri, 301 bool MemoryBuffer::RestApiPost(const std::string& uri,
276 const void* body, 302 const void* body,
277 size_t bodySize, 303 size_t bodySize,
290 { 316 {
291 return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize)); 317 return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
292 } 318 }
293 } 319 }
294 320
321 #if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
322
323 bool MemoryBuffer::RestApiPost(const std::string& uri,
324 const void* body,
325 size_t bodySize,
326 const std::map<std::string, std::string>& httpHeaders,
327 bool applyPlugins)
328 {
329 MemoryBuffer answerHeaders;
330 uint16_t httpStatus;
331
332 PluginHttpHeaders headers(httpHeaders);
333
334 return CheckHttp(OrthancPluginCallRestApi(GetGlobalContext(),
335 &buffer_,
336 *answerHeaders,
337 &httpStatus,
338 OrthancPluginHttpMethod_Post,
339 uri.c_str(),
340 headers.GetSize(), headers.GetKeys(), headers.GetValues(),
341 body, bodySize,
342 applyPlugins));
343 }
344
345
346 bool MemoryBuffer::RestApiPost(const std::string& uri,
347 const Json::Value& body,
348 const std::map<std::string, std::string>& httpHeaders,
349 bool applyPlugins)
350 {
351 std::string s;
352 WriteFastJson(s, body);
353 return RestApiPost(uri, s.c_str(), s.size(), httpHeaders, applyPlugins);
354 }
355 #endif
295 356
296 bool MemoryBuffer::RestApiPut(const std::string& uri, 357 bool MemoryBuffer::RestApiPut(const std::string& uri,
297 const void* body, 358 const void* body,
298 size_t bodySize, 359 size_t bodySize,
299 bool applyPlugins) 360 bool applyPlugins)
509 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); 570 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
510 } 571 }
511 } 572 }
512 573
513 574
575 void OrthancString::ToJsonWithoutComments(Json::Value& target) const
576 {
577 if (str_ == NULL)
578 {
579 LogError("Cannot convert an empty memory buffer to JSON");
580 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
581 }
582
583 if (!ReadJsonWithoutComments(target, str_))
584 {
585 LogError("Cannot convert some memory buffer to JSON");
586 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
587 }
588 }
589
590
514 void MemoryBuffer::DicomToJson(Json::Value& target, 591 void MemoryBuffer::DicomToJson(Json::Value& target,
515 OrthancPluginDicomToJsonFormat format, 592 OrthancPluginDicomToJsonFormat format,
516 OrthancPluginDicomToJsonFlags flags, 593 OrthancPluginDicomToJsonFlags flags,
517 uint32_t maxStringLength) 594 uint32_t maxStringLength)
518 { 595 {
643 { 720 {
644 LogError("Cannot access the Orthanc configuration"); 721 LogError("Cannot access the Orthanc configuration");
645 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 722 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
646 } 723 }
647 724
648 str.ToJson(configuration_); 725 str.ToJsonWithoutComments(configuration_);
649 726
650 if (configuration_.type() != Json::objectValue) 727 if (configuration_.type() != Json::objectValue)
651 { 728 {
652 LogError("Unable to read the Orthanc configuration"); 729 LogError("Unable to read the Orthanc configuration");
653 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 730 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
669 } 746 }
670 else 747 else
671 { 748 {
672 configuration_ = Json::objectValue; 749 configuration_ = Json::objectValue;
673 } 750 }
751 }
752
753 OrthancConfiguration::OrthancConfiguration(const Json::Value& configuration, const std::string& path) :
754 configuration_(configuration),
755 path_(path)
756 {
674 } 757 }
675 758
676 759
677 std::string OrthancConfiguration::GetPath(const std::string& key) const 760 std::string OrthancConfiguration::GetPath(const std::string& key) const
678 { 761 {
1026 } 1109 }
1027 1110
1028 if (configuration_[key].type() != Json::objectValue) 1111 if (configuration_[key].type() != Json::objectValue)
1029 { 1112 {
1030 LogError("The configuration option \"" + GetPath(key) + 1113 LogError("The configuration option \"" + GetPath(key) +
1031 "\" is not a string as expected"); 1114 "\" is not an object as expected");
1032 1115
1033 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); 1116 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
1034 } 1117 }
1035 1118
1036 Json::Value::Members members = configuration_[key].getMemberNames(); 1119 Json::Value::Members members = configuration_[key].getMemberNames();
1372 return true; 1455 return true;
1373 } 1456 }
1374 } 1457 }
1375 1458
1376 1459
1460 bool RestApiGet(Json::Value& result,
1461 const std::string& uri,
1462 const std::map<std::string, std::string>& httpHeaders,
1463 bool applyPlugins)
1464 {
1465 MemoryBuffer answer;
1466
1467 if (!answer.RestApiGet(uri, httpHeaders, applyPlugins))
1468 {
1469 return false;
1470 }
1471 else
1472 {
1473 if (!answer.IsEmpty())
1474 {
1475 answer.ToJson(result);
1476 }
1477 return true;
1478 }
1479 }
1480
1377 1481
1378 bool RestApiGet(Json::Value& result, 1482 bool RestApiGet(Json::Value& result,
1379 const std::string& uri, 1483 const std::string& uri,
1380 bool applyPlugins) 1484 bool applyPlugins)
1381 { 1485 {
1438 answer.ToJson(result); 1542 answer.ToJson(result);
1439 } 1543 }
1440 return true; 1544 return true;
1441 } 1545 }
1442 } 1546 }
1547
1548 #if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
1549 bool RestApiPost(Json::Value& result,
1550 const std::string& uri,
1551 const Json::Value& body,
1552 const std::map<std::string, std::string>& httpHeaders,
1553 bool applyPlugins)
1554 {
1555 MemoryBuffer answer;
1556
1557 if (!answer.RestApiPost(uri, body, httpHeaders, applyPlugins))
1558 {
1559 return false;
1560 }
1561 else
1562 {
1563 if (!answer.IsEmpty())
1564 {
1565 answer.ToJson(result);
1566 }
1567 return true;
1568 }
1569 }
1570 #endif
1443 1571
1444 1572
1445 bool RestApiPost(Json::Value& result, 1573 bool RestApiPost(Json::Value& result,
1446 const std::string& uri, 1574 const std::string& uri,
1447 const Json::Value& body, 1575 const Json::Value& body,
1528 boost::lexical_cast<std::string>(minor) + "." + 1656 boost::lexical_cast<std::string>(minor) + "." +
1529 boost::lexical_cast<std::string>(revision) + 1657 boost::lexical_cast<std::string>(revision) +
1530 " is required)"); 1658 " is required)");
1531 } 1659 }
1532 1660
1533 1661 bool CheckMinimalVersion(const char* version,
1534 bool CheckMinimalOrthancVersion(unsigned int major, 1662 unsigned int major,
1535 unsigned int minor, 1663 unsigned int minor,
1536 unsigned int revision) 1664 unsigned int revision)
1537 { 1665 {
1538 if (!HasGlobalContext()) 1666 if (!strcmp(version, "mainline"))
1539 {
1540 LogError("Bad Orthanc context in the plugin");
1541 return false;
1542 }
1543
1544 if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
1545 { 1667 {
1546 // Assume compatibility with the mainline 1668 // Assume compatibility with the mainline
1547 return true; 1669 return true;
1548 } 1670 }
1549 1671
1550 // Parse the version of the Orthanc core 1672 // Parse the version
1551 int aa, bb, cc; 1673 int aa, bb, cc;
1552 if ( 1674 if (
1553 #ifdef _MSC_VER 1675 #ifdef _MSC_VER
1554 sscanf_s 1676 sscanf_s
1555 #else 1677 #else
1556 sscanf 1678 sscanf
1557 #endif 1679 #endif
1558 (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 || 1680 (version, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
1559 aa < 0 || 1681 aa < 0 ||
1560 bb < 0 || 1682 bb < 0 ||
1561 cc < 0) 1683 cc < 0)
1562 { 1684 {
1563 return false; 1685 return false;
1577 if (a < major) 1699 if (a < major)
1578 { 1700 {
1579 return false; 1701 return false;
1580 } 1702 }
1581 1703
1582
1583 // Check the minor version number 1704 // Check the minor version number
1584 assert(a == major); 1705 assert(a == major);
1585 1706
1586 if (b > minor) 1707 if (b > minor)
1587 { 1708 {
1602 } 1723 }
1603 else 1724 else
1604 { 1725 {
1605 return false; 1726 return false;
1606 } 1727 }
1728 }
1729
1730
1731 bool CheckMinimalOrthancVersion(unsigned int major,
1732 unsigned int minor,
1733 unsigned int revision)
1734 {
1735 if (!HasGlobalContext())
1736 {
1737 LogError("Bad Orthanc context in the plugin");
1738 return false;
1739 }
1740
1741 return CheckMinimalVersion(GetGlobalContext()->orthancVersion,
1742 major, minor, revision);
1607 } 1743 }
1608 1744
1609 1745
1610 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0) 1746 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
1611 const char* AutodetectMimeType(const std::string& path) 1747 const char* AutodetectMimeType(const std::string& path)
1774 } 1910 }
1775 1911
1776 1912
1777 bool OrthancPeers::DoGet(MemoryBuffer& target, 1913 bool OrthancPeers::DoGet(MemoryBuffer& target,
1778 size_t index, 1914 size_t index,
1779 const std::string& uri) const 1915 const std::string& uri,
1916 const std::map<std::string, std::string>& headers) const
1780 { 1917 {
1781 if (index >= index_.size()) 1918 if (index >= index_.size())
1782 { 1919 {
1783 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 1920 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1784 } 1921 }
1785 1922
1786 OrthancPlugins::MemoryBuffer answer; 1923 OrthancPlugins::MemoryBuffer answer;
1787 uint16_t status; 1924 uint16_t status;
1925 PluginHttpHeaders pluginHeaders(headers);
1926
1788 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 1927 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1789 (GetGlobalContext(), *answer, NULL, &status, peers_, 1928 (GetGlobalContext(), *answer, NULL, &status, peers_,
1790 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(), 1929 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
1791 0, NULL, NULL, NULL, 0, timeout_); 1930 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_);
1792 1931
1793 if (code == OrthancPluginErrorCode_Success) 1932 if (code == OrthancPluginErrorCode_Success)
1794 { 1933 {
1795 target.Swap(answer); 1934 target.Swap(answer);
1796 return (status == 200); 1935 return (status == 200);
1802 } 1941 }
1803 1942
1804 1943
1805 bool OrthancPeers::DoGet(MemoryBuffer& target, 1944 bool OrthancPeers::DoGet(MemoryBuffer& target,
1806 const std::string& name, 1945 const std::string& name,
1807 const std::string& uri) const 1946 const std::string& uri,
1947 const std::map<std::string, std::string>& headers) const
1808 { 1948 {
1809 size_t index; 1949 size_t index;
1810 return (LookupName(index, name) && 1950 return (LookupName(index, name) &&
1811 DoGet(target, index, uri)); 1951 DoGet(target, index, uri, headers));
1812 } 1952 }
1813 1953
1814 1954
1815 bool OrthancPeers::DoGet(Json::Value& target, 1955 bool OrthancPeers::DoGet(Json::Value& target,
1816 size_t index, 1956 size_t index,
1817 const std::string& uri) const 1957 const std::string& uri,
1958 const std::map<std::string, std::string>& headers) const
1818 { 1959 {
1819 MemoryBuffer buffer; 1960 MemoryBuffer buffer;
1820 1961
1821 if (DoGet(buffer, index, uri)) 1962 if (DoGet(buffer, index, uri, headers))
1822 { 1963 {
1823 buffer.ToJson(target); 1964 buffer.ToJson(target);
1824 return true; 1965 return true;
1825 } 1966 }
1826 else 1967 else
1830 } 1971 }
1831 1972
1832 1973
1833 bool OrthancPeers::DoGet(Json::Value& target, 1974 bool OrthancPeers::DoGet(Json::Value& target,
1834 const std::string& name, 1975 const std::string& name,
1835 const std::string& uri) const 1976 const std::string& uri,
1977 const std::map<std::string, std::string>& headers) const
1836 { 1978 {
1837 MemoryBuffer buffer; 1979 MemoryBuffer buffer;
1838 1980
1839 if (DoGet(buffer, name, uri)) 1981 if (DoGet(buffer, name, uri, headers))
1840 { 1982 {
1841 buffer.ToJson(target); 1983 buffer.ToJson(target);
1842 return true; 1984 return true;
1843 } 1985 }
1844 else 1986 else
1849 1991
1850 1992
1851 bool OrthancPeers::DoPost(MemoryBuffer& target, 1993 bool OrthancPeers::DoPost(MemoryBuffer& target,
1852 const std::string& name, 1994 const std::string& name,
1853 const std::string& uri, 1995 const std::string& uri,
1854 const std::string& body) const 1996 const std::string& body,
1997 const std::map<std::string, std::string>& headers) const
1855 { 1998 {
1856 size_t index; 1999 size_t index;
1857 return (LookupName(index, name) && 2000 return (LookupName(index, name) &&
1858 DoPost(target, index, uri, body)); 2001 DoPost(target, index, uri, body, headers));
1859 } 2002 }
1860 2003
1861 2004
1862 bool OrthancPeers::DoPost(Json::Value& target, 2005 bool OrthancPeers::DoPost(Json::Value& target,
1863 size_t index, 2006 size_t index,
1864 const std::string& uri, 2007 const std::string& uri,
1865 const std::string& body) const 2008 const std::string& body,
2009 const std::map<std::string, std::string>& headers) const
1866 { 2010 {
1867 MemoryBuffer buffer; 2011 MemoryBuffer buffer;
1868 2012
1869 if (DoPost(buffer, index, uri, body)) 2013 if (DoPost(buffer, index, uri, body, headers))
1870 { 2014 {
1871 buffer.ToJson(target); 2015 buffer.ToJson(target);
1872 return true; 2016 return true;
1873 } 2017 }
1874 else 2018 else
1879 2023
1880 2024
1881 bool OrthancPeers::DoPost(Json::Value& target, 2025 bool OrthancPeers::DoPost(Json::Value& target,
1882 const std::string& name, 2026 const std::string& name,
1883 const std::string& uri, 2027 const std::string& uri,
1884 const std::string& body) const 2028 const std::string& body,
2029 const std::map<std::string, std::string>& headers) const
1885 { 2030 {
1886 MemoryBuffer buffer; 2031 MemoryBuffer buffer;
1887 2032
1888 if (DoPost(buffer, name, uri, body)) 2033 if (DoPost(buffer, name, uri, body, headers))
1889 { 2034 {
1890 buffer.ToJson(target); 2035 buffer.ToJson(target);
1891 return true; 2036 return true;
1892 } 2037 }
1893 else 2038 else
1898 2043
1899 2044
1900 bool OrthancPeers::DoPost(MemoryBuffer& target, 2045 bool OrthancPeers::DoPost(MemoryBuffer& target,
1901 size_t index, 2046 size_t index,
1902 const std::string& uri, 2047 const std::string& uri,
1903 const std::string& body) const 2048 const std::string& body,
2049 const std::map<std::string, std::string>& headers) const
1904 { 2050 {
1905 if (index >= index_.size()) 2051 if (index >= index_.size())
1906 { 2052 {
1907 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 2053 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1908 } 2054 }
1913 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 2059 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1914 } 2060 }
1915 2061
1916 OrthancPlugins::MemoryBuffer answer; 2062 OrthancPlugins::MemoryBuffer answer;
1917 uint16_t status; 2063 uint16_t status;
2064 PluginHttpHeaders pluginHeaders(headers);
2065
1918 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 2066 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1919 (GetGlobalContext(), *answer, NULL, &status, peers_, 2067 (GetGlobalContext(), *answer, NULL, &status, peers_,
1920 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(), 2068 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
1921 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); 2069 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1922 2070
1923 if (code == OrthancPluginErrorCode_Success) 2071 if (code == OrthancPluginErrorCode_Success)
1924 { 2072 {
1925 target.Swap(answer); 2073 target.Swap(answer);
1926 return (status == 200); 2074 return (status == 200);
1932 } 2080 }
1933 2081
1934 2082
1935 bool OrthancPeers::DoPut(size_t index, 2083 bool OrthancPeers::DoPut(size_t index,
1936 const std::string& uri, 2084 const std::string& uri,
1937 const std::string& body) const 2085 const std::string& body,
2086 const std::map<std::string, std::string>& headers) const
1938 { 2087 {
1939 if (index >= index_.size()) 2088 if (index >= index_.size())
1940 { 2089 {
1941 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 2090 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1942 } 2091 }
1947 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 2096 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1948 } 2097 }
1949 2098
1950 OrthancPlugins::MemoryBuffer answer; 2099 OrthancPlugins::MemoryBuffer answer;
1951 uint16_t status; 2100 uint16_t status;
2101 PluginHttpHeaders pluginHeaders(headers);
2102
1952 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 2103 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1953 (GetGlobalContext(), *answer, NULL, &status, peers_, 2104 (GetGlobalContext(), *answer, NULL, &status, peers_,
1954 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(), 2105 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
1955 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); 2106 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1956 2107
1957 if (code == OrthancPluginErrorCode_Success) 2108 if (code == OrthancPluginErrorCode_Success)
1958 { 2109 {
1959 return (status == 200); 2110 return (status == 200);
1960 } 2111 }
1965 } 2116 }
1966 2117
1967 2118
1968 bool OrthancPeers::DoPut(const std::string& name, 2119 bool OrthancPeers::DoPut(const std::string& name,
1969 const std::string& uri, 2120 const std::string& uri,
1970 const std::string& body) const 2121 const std::string& body,
2122 const std::map<std::string, std::string>& headers) const
1971 { 2123 {
1972 size_t index; 2124 size_t index;
1973 return (LookupName(index, name) && 2125 return (LookupName(index, name) &&
1974 DoPut(index, uri, body)); 2126 DoPut(index, uri, body, headers));
1975 } 2127 }
1976 2128
1977 2129
1978 bool OrthancPeers::DoDelete(size_t index, 2130 bool OrthancPeers::DoDelete(size_t index,
1979 const std::string& uri) const 2131 const std::string& uri,
2132 const std::map<std::string, std::string>& headers) const
1980 { 2133 {
1981 if (index >= index_.size()) 2134 if (index >= index_.size())
1982 { 2135 {
1983 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 2136 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1984 } 2137 }
1985 2138
1986 OrthancPlugins::MemoryBuffer answer; 2139 OrthancPlugins::MemoryBuffer answer;
1987 uint16_t status; 2140 uint16_t status;
2141 PluginHttpHeaders pluginHeaders(headers);
2142
1988 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 2143 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1989 (GetGlobalContext(), *answer, NULL, &status, peers_, 2144 (GetGlobalContext(), *answer, NULL, &status, peers_,
1990 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(), 2145 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(),
1991 0, NULL, NULL, NULL, 0, timeout_); 2146 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_);
1992 2147
1993 if (code == OrthancPluginErrorCode_Success) 2148 if (code == OrthancPluginErrorCode_Success)
1994 { 2149 {
1995 return (status == 200); 2150 return (status == 200);
1996 } 2151 }
2000 } 2155 }
2001 } 2156 }
2002 2157
2003 2158
2004 bool OrthancPeers::DoDelete(const std::string& name, 2159 bool OrthancPeers::DoDelete(const std::string& name,
2005 const std::string& uri) const 2160 const std::string& uri,
2161 const std::map<std::string, std::string>& headers) const
2006 { 2162 {
2007 size_t index; 2163 size_t index;
2008 return (LookupName(index, name) && 2164 return (LookupName(index, name) &&
2009 DoDelete(index, uri)); 2165 DoDelete(index, uri, headers));
2010 } 2166 }
2011 #endif 2167 #endif
2012 2168
2013 2169
2014 2170
2041 return 0; 2197 return 0;
2042 } 2198 }
2043 } 2199 }
2044 2200
2045 2201
2202 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2203 static OrthancPluginErrorCode CopyStringToMemoryBuffer(OrthancPluginMemoryBuffer* target,
2204 const std::string& source)
2205 {
2206 if (OrthancPluginCreateMemoryBuffer(globalContext_, target, source.size()) != OrthancPluginErrorCode_Success)
2207 {
2208 return OrthancPluginErrorCode_NotEnoughMemory;
2209 }
2210 else
2211 {
2212 if (!source.empty())
2213 {
2214 memcpy(target->data, source.c_str(), source.size());
2215 }
2216
2217 return OrthancPluginErrorCode_Success;
2218 }
2219 }
2220 #endif
2221
2222
2223 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2224 OrthancPluginErrorCode OrthancJob::CallbackGetContent(OrthancPluginMemoryBuffer* target,
2225 void* job)
2226 {
2227 assert(job != NULL);
2228 OrthancJob& that = *reinterpret_cast<OrthancJob*>(job);
2229 return CopyStringToMemoryBuffer(target, that.content_);
2230 }
2231 #else
2046 const char* OrthancJob::CallbackGetContent(void* job) 2232 const char* OrthancJob::CallbackGetContent(void* job)
2047 { 2233 {
2048 assert(job != NULL); 2234 assert(job != NULL);
2049 2235
2050 try 2236 try
2054 catch (...) 2240 catch (...)
2055 { 2241 {
2056 return 0; 2242 return 0;
2057 } 2243 }
2058 } 2244 }
2059 2245 #endif
2060 2246
2247
2248 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2249 int32_t OrthancJob::CallbackGetSerialized(OrthancPluginMemoryBuffer* target,
2250 void* job)
2251 {
2252 assert(job != NULL);
2253 OrthancJob& that = *reinterpret_cast<OrthancJob*>(job);
2254
2255 if (that.hasSerialized_)
2256 {
2257 if (CopyStringToMemoryBuffer(target, that.serialized_) == OrthancPluginErrorCode_Success)
2258 {
2259 return 1;
2260 }
2261 else
2262 {
2263 return -1;
2264 }
2265 }
2266 else
2267 {
2268 return 0;
2269 }
2270 }
2271 #else
2061 const char* OrthancJob::CallbackGetSerialized(void* job) 2272 const char* OrthancJob::CallbackGetSerialized(void* job)
2062 { 2273 {
2063 assert(job != NULL); 2274 assert(job != NULL);
2064 2275
2065 try 2276 try
2078 catch (...) 2289 catch (...)
2079 { 2290 {
2080 return 0; 2291 return 0;
2081 } 2292 }
2082 } 2293 }
2294 #endif
2083 2295
2084 2296
2085 OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job) 2297 OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job)
2086 { 2298 {
2087 assert(job != NULL); 2299 assert(job != NULL);
2209 if (job == NULL) 2421 if (job == NULL)
2210 { 2422 {
2211 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer); 2423 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
2212 } 2424 }
2213 2425
2214 OrthancPluginJob* orthanc = OrthancPluginCreateJob( 2426 OrthancPluginJob* orthanc =
2215 GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(), 2427 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2216 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized, 2428 OrthancPluginCreateJob2
2217 CallbackStep, CallbackStop, CallbackReset); 2429 #else
2430 OrthancPluginCreateJob
2431 #endif
2432 (GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
2433 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
2434 CallbackStep, CallbackStop, CallbackReset);
2218 2435
2219 if (orthanc == NULL) 2436 if (orthanc == NULL)
2220 { 2437 {
2221 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin); 2438 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
2222 } 2439 }
2508 { 2725 {
2509 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); 2726 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
2510 } 2727 }
2511 catch (...) 2728 catch (...)
2512 { 2729 {
2513 return OrthancPluginErrorCode_InternalError; 2730 return OrthancPluginErrorCode_Plugin;
2514 } 2731 }
2515 } 2732 }
2516 } 2733 }
2517 }; 2734 };
2518 2735
3530 result->toFree_ = true; 3747 result->toFree_ = true;
3531 return result.release(); 3748 return result.release();
3532 } 3749 }
3533 } 3750 }
3534 #endif 3751 #endif
3752
3753
3754 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3755 static std::vector<std::string> WebDavConvertPath(uint32_t pathSize,
3756 const char* const* pathItems)
3757 {
3758 std::vector<std::string> result(pathSize);
3759
3760 for (uint32_t i = 0; i < pathSize; i++)
3761 {
3762 result[i] = pathItems[i];
3763 }
3764
3765 return result;
3766 }
3767 #endif
3768
3769
3770 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3771 static OrthancPluginErrorCode WebDavIsExistingFolder(uint8_t* isExisting,
3772 uint32_t pathSize,
3773 const char* const* pathItems,
3774 void* payload)
3775 {
3776 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3777
3778 try
3779 {
3780 *isExisting = (that.IsExistingFolder(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0);
3781 return OrthancPluginErrorCode_Success;
3782 }
3783 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3784 {
3785 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3786 }
3787 catch (...)
3788 {
3789 return OrthancPluginErrorCode_Plugin;
3790 }
3791 }
3792 #endif
3793
3794
3795 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3796 static OrthancPluginErrorCode WebDavListFolder(uint8_t* isExisting,
3797 OrthancPluginWebDavCollection* collection,
3798 OrthancPluginWebDavAddFile addFile,
3799 OrthancPluginWebDavAddFolder addFolder,
3800 uint32_t pathSize,
3801 const char* const* pathItems,
3802 void* payload)
3803 {
3804 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3805
3806 try
3807 {
3808 std::list<IWebDavCollection::FileInfo> files;
3809 std::list<IWebDavCollection::FolderInfo> subfolders;
3810
3811 if (!that.ListFolder(files, subfolders, WebDavConvertPath(pathSize, pathItems)))
3812 {
3813 *isExisting = 0;
3814 }
3815 else
3816 {
3817 *isExisting = 1;
3818
3819 for (std::list<IWebDavCollection::FileInfo>::const_iterator
3820 it = files.begin(); it != files.end(); ++it)
3821 {
3822 OrthancPluginErrorCode code = addFile(
3823 collection, it->GetName().c_str(), it->GetContentSize(),
3824 it->GetMimeType().c_str(), it->GetDateTime().c_str());
3825
3826 if (code != OrthancPluginErrorCode_Success)
3827 {
3828 return code;
3829 }
3830 }
3831
3832 for (std::list<IWebDavCollection::FolderInfo>::const_iterator it =
3833 subfolders.begin(); it != subfolders.end(); ++it)
3834 {
3835 OrthancPluginErrorCode code = addFolder(
3836 collection, it->GetName().c_str(), it->GetDateTime().c_str());
3837
3838 if (code != OrthancPluginErrorCode_Success)
3839 {
3840 return code;
3841 }
3842 }
3843 }
3844
3845 return OrthancPluginErrorCode_Success;
3846 }
3847 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3848 {
3849 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3850 }
3851 catch (...)
3852 {
3853 return OrthancPluginErrorCode_Plugin;
3854 }
3855 }
3856 #endif
3857
3858
3859 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3860 static OrthancPluginErrorCode WebDavRetrieveFile(OrthancPluginWebDavCollection* collection,
3861 OrthancPluginWebDavRetrieveFile retrieveFile,
3862 uint32_t pathSize,
3863 const char* const* pathItems,
3864 void* payload)
3865 {
3866 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3867
3868 try
3869 {
3870 std::string content, mime, dateTime;
3871
3872 if (that.GetFile(content, mime, dateTime, WebDavConvertPath(pathSize, pathItems)))
3873 {
3874 return retrieveFile(collection, content.empty() ? NULL : content.c_str(),
3875 content.size(), mime.c_str(), dateTime.c_str());
3876 }
3877 else
3878 {
3879 // Inexisting file
3880 return OrthancPluginErrorCode_Success;
3881 }
3882 }
3883 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3884 {
3885 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3886 }
3887 catch (...)
3888 {
3889 return OrthancPluginErrorCode_InternalError;
3890 }
3891 }
3892 #endif
3893
3894
3895 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3896 static OrthancPluginErrorCode WebDavStoreFileCallback(uint8_t* isReadOnly, /* out */
3897 uint32_t pathSize,
3898 const char* const* pathItems,
3899 const void* data,
3900 uint64_t size,
3901 void* payload)
3902 {
3903 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3904
3905 try
3906 {
3907 if (static_cast<uint64_t>(static_cast<size_t>(size)) != size)
3908 {
3909 ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
3910 }
3911
3912 *isReadOnly = (that.StoreFile(WebDavConvertPath(pathSize, pathItems), data,
3913 static_cast<size_t>(size)) ? 1 : 0);
3914 return OrthancPluginErrorCode_Success;
3915 }
3916 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3917 {
3918 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3919 }
3920 catch (...)
3921 {
3922 return OrthancPluginErrorCode_InternalError;
3923 }
3924 }
3925 #endif
3926
3927
3928 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3929 static OrthancPluginErrorCode WebDavCreateFolderCallback(uint8_t* isReadOnly, /* out */
3930 uint32_t pathSize,
3931 const char* const* pathItems,
3932 void* payload)
3933 {
3934 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3935
3936 try
3937 {
3938 *isReadOnly = (that.CreateFolder(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0);
3939 return OrthancPluginErrorCode_Success;
3940 }
3941 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3942 {
3943 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3944 }
3945 catch (...)
3946 {
3947 return OrthancPluginErrorCode_InternalError;
3948 }
3949 }
3950 #endif
3951
3952
3953 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3954 static OrthancPluginErrorCode WebDavDeleteItemCallback(uint8_t* isReadOnly, /* out */
3955 uint32_t pathSize,
3956 const char* const* pathItems,
3957 void* payload)
3958 {
3959 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3960
3961 try
3962 {
3963 *isReadOnly = (that.DeleteItem(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0);
3964 return OrthancPluginErrorCode_Success;
3965 }
3966 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3967 {
3968 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3969 }
3970 catch (...)
3971 {
3972 return OrthancPluginErrorCode_InternalError;
3973 }
3974 }
3975 #endif
3976
3977
3978 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3979 void IWebDavCollection::Register(const std::string& uri,
3980 IWebDavCollection& collection)
3981 {
3982 OrthancPluginErrorCode code = OrthancPluginRegisterWebDavCollection(
3983 GetGlobalContext(), uri.c_str(), WebDavIsExistingFolder, WebDavListFolder, WebDavRetrieveFile,
3984 WebDavStoreFileCallback, WebDavCreateFolderCallback, WebDavDeleteItemCallback, &collection);
3985
3986 if (code != OrthancPluginErrorCode_Success)
3987 {
3988 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
3989 }
3990 }
3991 #endif
3992
3993 void GetHttpHeaders(std::map<std::string, std::string>& result, const OrthancPluginHttpRequest* request)
3994 {
3995 result.clear();
3996
3997 for (uint32_t i = 0; i < request->headersCount; ++i)
3998 {
3999 result[request->headersKeys[i]] = request->headersValues[i];
4000 }
4001 }
3535 } 4002 }