Mercurial > hg > orthanc-python
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 } |