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