comparison Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp @ 405:1938ba8fba35

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