comparison Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp @ 69:af44dce56328

new 'auth/user-profile' Rest API route
author Alain Mazy <am@osimis.io>
date Mon, 20 Feb 2023 11:56:14 +0100
parents 1a13c4fbc9a1
children 30fb3ce960d9
comparison
equal deleted inserted replaced
68:1a13c4fbc9a1 69:af44dce56328
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-2023 Osimis S.A., Belgium 5 * Copyright (C) 2017-2022 Osimis S.A., Belgium
6 * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
6 * 7 *
7 * This program is free software: you can redistribute it and/or 8 * This program is free software: you can redistribute it and/or
8 * 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
9 * published by the Free Software Foundation, either version 3 of the 10 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version. 11 * License, or (at your option) any later version.
247 { 248 {
248 return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str())); 249 return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str()));
249 } 250 }
250 } 251 }
251 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
252 bool MemoryBuffer::RestApiGet(const std::string& uri, 286 bool MemoryBuffer::RestApiGet(const std::string& uri,
253 const std::map<std::string, std::string>& httpHeaders, 287 const std::map<std::string, std::string>& httpHeaders,
254 bool applyPlugins) 288 bool applyPlugins)
255 { 289 {
256 Clear(); 290 Clear();
257 291
258 std::vector<const char*> headersKeys; 292 PluginHttpHeaders headers(httpHeaders);
259 std::vector<const char*> headersValues;
260
261 for (std::map<std::string, std::string>::const_iterator
262 it = httpHeaders.begin(); it != httpHeaders.end(); it++)
263 {
264 headersKeys.push_back(it->first.c_str());
265 headersValues.push_back(it->second.c_str());
266 }
267 293
268 return CheckHttp(OrthancPluginRestApiGet2( 294 return CheckHttp(OrthancPluginRestApiGet2(
269 GetGlobalContext(), &buffer_, uri.c_str(), httpHeaders.size(), 295 GetGlobalContext(), &buffer_, uri.c_str(),
270 (headersKeys.empty() ? NULL : &headersKeys[0]), 296 headers.GetSize(),
271 (headersValues.empty() ? NULL : &headersValues[0]), applyPlugins)); 297 headers.GetKeys(),
298 headers.GetValues(), applyPlugins));
272 } 299 }
273 300
274 bool MemoryBuffer::RestApiPost(const std::string& uri, 301 bool MemoryBuffer::RestApiPost(const std::string& uri,
275 const void* body, 302 const void* body,
276 size_t bodySize, 303 size_t bodySize,
289 { 316 {
290 return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize)); 317 return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), b, bodySize));
291 } 318 }
292 } 319 }
293 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
294 356
295 bool MemoryBuffer::RestApiPut(const std::string& uri, 357 bool MemoryBuffer::RestApiPut(const std::string& uri,
296 const void* body, 358 const void* body,
297 size_t bodySize, 359 size_t bodySize,
298 bool applyPlugins) 360 bool applyPlugins)
508 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); 570 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
509 } 571 }
510 } 572 }
511 573
512 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
513 void MemoryBuffer::DicomToJson(Json::Value& target, 591 void MemoryBuffer::DicomToJson(Json::Value& target,
514 OrthancPluginDicomToJsonFormat format, 592 OrthancPluginDicomToJsonFormat format,
515 OrthancPluginDicomToJsonFlags flags, 593 OrthancPluginDicomToJsonFlags flags,
516 uint32_t maxStringLength) 594 uint32_t maxStringLength)
517 { 595 {
537 const std::string& body, 615 const std::string& body,
538 const std::string& username, 616 const std::string& username,
539 const std::string& password) 617 const std::string& password)
540 { 618 {
541 Clear(); 619 Clear();
620
621 if (body.size() > 0xffffffffu)
622 {
623 LogError("Cannot handle body size > 4GB");
624 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
625 }
626
542 return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(), 627 return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(),
543 body.c_str(), body.size(), 628 body.c_str(), body.size(),
544 username.empty() ? NULL : username.c_str(), 629 username.empty() ? NULL : username.c_str(),
545 password.empty() ? NULL : password.c_str())); 630 password.empty() ? NULL : password.c_str()));
546 } 631 }
550 const std::string& body, 635 const std::string& body,
551 const std::string& username, 636 const std::string& username,
552 const std::string& password) 637 const std::string& password)
553 { 638 {
554 Clear(); 639 Clear();
640
641 if (body.size() > 0xffffffffu)
642 {
643 LogError("Cannot handle body size > 4GB");
644 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
645 }
646
555 return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(), 647 return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(),
556 body.empty() ? NULL : body.c_str(), 648 body.empty() ? NULL : body.c_str(),
557 body.size(), 649 body.size(),
558 username.empty() ? NULL : username.c_str(), 650 username.empty() ? NULL : username.c_str(),
559 password.empty() ? NULL : password.c_str())); 651 password.empty() ? NULL : password.c_str()));
628 { 720 {
629 LogError("Cannot access the Orthanc configuration"); 721 LogError("Cannot access the Orthanc configuration");
630 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 722 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
631 } 723 }
632 724
633 str.ToJson(configuration_); 725 str.ToJsonWithoutComments(configuration_);
634 726
635 if (configuration_.type() != Json::objectValue) 727 if (configuration_.type() != Json::objectValue)
636 { 728 {
637 LogError("Unable to read the Orthanc configuration"); 729 LogError("Unable to read the Orthanc configuration");
638 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); 730 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1424 } 1516 }
1425 return true; 1517 return true;
1426 } 1518 }
1427 } 1519 }
1428 1520
1521 #if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
1522 bool RestApiPost(Json::Value& result,
1523 const std::string& uri,
1524 const Json::Value& body,
1525 const std::map<std::string, std::string>& httpHeaders,
1526 bool applyPlugins)
1527 {
1528 MemoryBuffer answer;
1529
1530 if (!answer.RestApiPost(uri, body, httpHeaders, applyPlugins))
1531 {
1532 return false;
1533 }
1534 else
1535 {
1536 if (!answer.IsEmpty())
1537 {
1538 answer.ToJson(result);
1539 }
1540 return true;
1541 }
1542 }
1543 #endif
1544
1429 1545
1430 bool RestApiPost(Json::Value& result, 1546 bool RestApiPost(Json::Value& result,
1431 const std::string& uri, 1547 const std::string& uri,
1432 const Json::Value& body, 1548 const Json::Value& body,
1433 bool applyPlugins) 1549 bool applyPlugins)
1513 boost::lexical_cast<std::string>(minor) + "." + 1629 boost::lexical_cast<std::string>(minor) + "." +
1514 boost::lexical_cast<std::string>(revision) + 1630 boost::lexical_cast<std::string>(revision) +
1515 " is required)"); 1631 " is required)");
1516 } 1632 }
1517 1633
1518 1634 bool CheckMinimalVersion(const char* version,
1519 bool CheckMinimalOrthancVersion(unsigned int major, 1635 unsigned int major,
1520 unsigned int minor, 1636 unsigned int minor,
1521 unsigned int revision) 1637 unsigned int revision)
1522 { 1638 {
1523 if (!HasGlobalContext()) 1639 if (!strcmp(version, "mainline"))
1524 {
1525 LogError("Bad Orthanc context in the plugin");
1526 return false;
1527 }
1528
1529 if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
1530 { 1640 {
1531 // Assume compatibility with the mainline 1641 // Assume compatibility with the mainline
1532 return true; 1642 return true;
1533 } 1643 }
1534 1644
1535 // Parse the version of the Orthanc core 1645 // Parse the version
1536 int aa, bb, cc; 1646 int aa, bb, cc;
1537 if ( 1647 if (
1538 #ifdef _MSC_VER 1648 #ifdef _MSC_VER
1539 sscanf_s 1649 sscanf_s
1540 #else 1650 #else
1541 sscanf 1651 sscanf
1542 #endif 1652 #endif
1543 (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 || 1653 (version, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
1544 aa < 0 || 1654 aa < 0 ||
1545 bb < 0 || 1655 bb < 0 ||
1546 cc < 0) 1656 cc < 0)
1547 { 1657 {
1548 return false; 1658 return false;
1562 if (a < major) 1672 if (a < major)
1563 { 1673 {
1564 return false; 1674 return false;
1565 } 1675 }
1566 1676
1567
1568 // Check the minor version number 1677 // Check the minor version number
1569 assert(a == major); 1678 assert(a == major);
1570 1679
1571 if (b > minor) 1680 if (b > minor)
1572 { 1681 {
1587 } 1696 }
1588 else 1697 else
1589 { 1698 {
1590 return false; 1699 return false;
1591 } 1700 }
1701 }
1702
1703
1704 bool CheckMinimalOrthancVersion(unsigned int major,
1705 unsigned int minor,
1706 unsigned int revision)
1707 {
1708 if (!HasGlobalContext())
1709 {
1710 LogError("Bad Orthanc context in the plugin");
1711 return false;
1712 }
1713
1714 return CheckMinimalVersion(GetGlobalContext()->orthancVersion,
1715 major, minor, revision);
1592 } 1716 }
1593 1717
1594 1718
1595 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0) 1719 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
1596 const char* AutodetectMimeType(const std::string& path) 1720 const char* AutodetectMimeType(const std::string& path)
1759 } 1883 }
1760 1884
1761 1885
1762 bool OrthancPeers::DoGet(MemoryBuffer& target, 1886 bool OrthancPeers::DoGet(MemoryBuffer& target,
1763 size_t index, 1887 size_t index,
1764 const std::string& uri) const 1888 const std::string& uri,
1889 const std::map<std::string, std::string>& headers) const
1765 { 1890 {
1766 if (index >= index_.size()) 1891 if (index >= index_.size())
1767 { 1892 {
1768 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 1893 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1769 } 1894 }
1770 1895
1771 OrthancPlugins::MemoryBuffer answer; 1896 OrthancPlugins::MemoryBuffer answer;
1772 uint16_t status; 1897 uint16_t status;
1898 PluginHttpHeaders pluginHeaders(headers);
1899
1773 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 1900 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1774 (GetGlobalContext(), *answer, NULL, &status, peers_, 1901 (GetGlobalContext(), *answer, NULL, &status, peers_,
1775 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(), 1902 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
1776 0, NULL, NULL, NULL, 0, timeout_); 1903 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_);
1777 1904
1778 if (code == OrthancPluginErrorCode_Success) 1905 if (code == OrthancPluginErrorCode_Success)
1779 { 1906 {
1780 target.Swap(answer); 1907 target.Swap(answer);
1781 return (status == 200); 1908 return (status == 200);
1787 } 1914 }
1788 1915
1789 1916
1790 bool OrthancPeers::DoGet(MemoryBuffer& target, 1917 bool OrthancPeers::DoGet(MemoryBuffer& target,
1791 const std::string& name, 1918 const std::string& name,
1792 const std::string& uri) const 1919 const std::string& uri,
1920 const std::map<std::string, std::string>& headers) const
1793 { 1921 {
1794 size_t index; 1922 size_t index;
1795 return (LookupName(index, name) && 1923 return (LookupName(index, name) &&
1796 DoGet(target, index, uri)); 1924 DoGet(target, index, uri, headers));
1797 } 1925 }
1798 1926
1799 1927
1800 bool OrthancPeers::DoGet(Json::Value& target, 1928 bool OrthancPeers::DoGet(Json::Value& target,
1801 size_t index, 1929 size_t index,
1802 const std::string& uri) const 1930 const std::string& uri,
1931 const std::map<std::string, std::string>& headers) const
1803 { 1932 {
1804 MemoryBuffer buffer; 1933 MemoryBuffer buffer;
1805 1934
1806 if (DoGet(buffer, index, uri)) 1935 if (DoGet(buffer, index, uri, headers))
1807 { 1936 {
1808 buffer.ToJson(target); 1937 buffer.ToJson(target);
1809 return true; 1938 return true;
1810 } 1939 }
1811 else 1940 else
1815 } 1944 }
1816 1945
1817 1946
1818 bool OrthancPeers::DoGet(Json::Value& target, 1947 bool OrthancPeers::DoGet(Json::Value& target,
1819 const std::string& name, 1948 const std::string& name,
1820 const std::string& uri) const 1949 const std::string& uri,
1950 const std::map<std::string, std::string>& headers) const
1821 { 1951 {
1822 MemoryBuffer buffer; 1952 MemoryBuffer buffer;
1823 1953
1824 if (DoGet(buffer, name, uri)) 1954 if (DoGet(buffer, name, uri, headers))
1825 { 1955 {
1826 buffer.ToJson(target); 1956 buffer.ToJson(target);
1827 return true; 1957 return true;
1828 } 1958 }
1829 else 1959 else
1834 1964
1835 1965
1836 bool OrthancPeers::DoPost(MemoryBuffer& target, 1966 bool OrthancPeers::DoPost(MemoryBuffer& target,
1837 const std::string& name, 1967 const std::string& name,
1838 const std::string& uri, 1968 const std::string& uri,
1839 const std::string& body) const 1969 const std::string& body,
1970 const std::map<std::string, std::string>& headers) const
1840 { 1971 {
1841 size_t index; 1972 size_t index;
1842 return (LookupName(index, name) && 1973 return (LookupName(index, name) &&
1843 DoPost(target, index, uri, body)); 1974 DoPost(target, index, uri, body, headers));
1844 } 1975 }
1845 1976
1846 1977
1847 bool OrthancPeers::DoPost(Json::Value& target, 1978 bool OrthancPeers::DoPost(Json::Value& target,
1848 size_t index, 1979 size_t index,
1849 const std::string& uri, 1980 const std::string& uri,
1850 const std::string& body) const 1981 const std::string& body,
1982 const std::map<std::string, std::string>& headers) const
1851 { 1983 {
1852 MemoryBuffer buffer; 1984 MemoryBuffer buffer;
1853 1985
1854 if (DoPost(buffer, index, uri, body)) 1986 if (DoPost(buffer, index, uri, body, headers))
1855 { 1987 {
1856 buffer.ToJson(target); 1988 buffer.ToJson(target);
1857 return true; 1989 return true;
1858 } 1990 }
1859 else 1991 else
1864 1996
1865 1997
1866 bool OrthancPeers::DoPost(Json::Value& target, 1998 bool OrthancPeers::DoPost(Json::Value& target,
1867 const std::string& name, 1999 const std::string& name,
1868 const std::string& uri, 2000 const std::string& uri,
1869 const std::string& body) const 2001 const std::string& body,
2002 const std::map<std::string, std::string>& headers) const
1870 { 2003 {
1871 MemoryBuffer buffer; 2004 MemoryBuffer buffer;
1872 2005
1873 if (DoPost(buffer, name, uri, body)) 2006 if (DoPost(buffer, name, uri, body, headers))
1874 { 2007 {
1875 buffer.ToJson(target); 2008 buffer.ToJson(target);
1876 return true; 2009 return true;
1877 } 2010 }
1878 else 2011 else
1883 2016
1884 2017
1885 bool OrthancPeers::DoPost(MemoryBuffer& target, 2018 bool OrthancPeers::DoPost(MemoryBuffer& target,
1886 size_t index, 2019 size_t index,
1887 const std::string& uri, 2020 const std::string& uri,
1888 const std::string& body) const 2021 const std::string& body,
2022 const std::map<std::string, std::string>& headers) const
1889 { 2023 {
1890 if (index >= index_.size()) 2024 if (index >= index_.size())
1891 { 2025 {
1892 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 2026 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
2027 }
2028
2029 if (body.size() > 0xffffffffu)
2030 {
2031 LogError("Cannot handle body size > 4GB");
2032 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1893 } 2033 }
1894 2034
1895 OrthancPlugins::MemoryBuffer answer; 2035 OrthancPlugins::MemoryBuffer answer;
1896 uint16_t status; 2036 uint16_t status;
2037 PluginHttpHeaders pluginHeaders(headers);
2038
1897 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 2039 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1898 (GetGlobalContext(), *answer, NULL, &status, peers_, 2040 (GetGlobalContext(), *answer, NULL, &status, peers_,
1899 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(), 2041 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
1900 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); 2042 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1901 2043
1902 if (code == OrthancPluginErrorCode_Success) 2044 if (code == OrthancPluginErrorCode_Success)
1903 { 2045 {
1904 target.Swap(answer); 2046 target.Swap(answer);
1905 return (status == 200); 2047 return (status == 200);
1911 } 2053 }
1912 2054
1913 2055
1914 bool OrthancPeers::DoPut(size_t index, 2056 bool OrthancPeers::DoPut(size_t index,
1915 const std::string& uri, 2057 const std::string& uri,
1916 const std::string& body) const 2058 const std::string& body,
2059 const std::map<std::string, std::string>& headers) const
1917 { 2060 {
1918 if (index >= index_.size()) 2061 if (index >= index_.size())
1919 { 2062 {
1920 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 2063 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
2064 }
2065
2066 if (body.size() > 0xffffffffu)
2067 {
2068 LogError("Cannot handle body size > 4GB");
2069 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
1921 } 2070 }
1922 2071
1923 OrthancPlugins::MemoryBuffer answer; 2072 OrthancPlugins::MemoryBuffer answer;
1924 uint16_t status; 2073 uint16_t status;
2074 PluginHttpHeaders pluginHeaders(headers);
2075
1925 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 2076 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1926 (GetGlobalContext(), *answer, NULL, &status, peers_, 2077 (GetGlobalContext(), *answer, NULL, &status, peers_,
1927 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(), 2078 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
1928 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); 2079 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
1929 2080
1930 if (code == OrthancPluginErrorCode_Success) 2081 if (code == OrthancPluginErrorCode_Success)
1931 { 2082 {
1932 return (status == 200); 2083 return (status == 200);
1933 } 2084 }
1938 } 2089 }
1939 2090
1940 2091
1941 bool OrthancPeers::DoPut(const std::string& name, 2092 bool OrthancPeers::DoPut(const std::string& name,
1942 const std::string& uri, 2093 const std::string& uri,
1943 const std::string& body) const 2094 const std::string& body,
2095 const std::map<std::string, std::string>& headers) const
1944 { 2096 {
1945 size_t index; 2097 size_t index;
1946 return (LookupName(index, name) && 2098 return (LookupName(index, name) &&
1947 DoPut(index, uri, body)); 2099 DoPut(index, uri, body, headers));
1948 } 2100 }
1949 2101
1950 2102
1951 bool OrthancPeers::DoDelete(size_t index, 2103 bool OrthancPeers::DoDelete(size_t index,
1952 const std::string& uri) const 2104 const std::string& uri,
2105 const std::map<std::string, std::string>& headers) const
1953 { 2106 {
1954 if (index >= index_.size()) 2107 if (index >= index_.size())
1955 { 2108 {
1956 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange); 2109 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
1957 } 2110 }
1958 2111
1959 OrthancPlugins::MemoryBuffer answer; 2112 OrthancPlugins::MemoryBuffer answer;
1960 uint16_t status; 2113 uint16_t status;
2114 PluginHttpHeaders pluginHeaders(headers);
2115
1961 OrthancPluginErrorCode code = OrthancPluginCallPeerApi 2116 OrthancPluginErrorCode code = OrthancPluginCallPeerApi
1962 (GetGlobalContext(), *answer, NULL, &status, peers_, 2117 (GetGlobalContext(), *answer, NULL, &status, peers_,
1963 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(), 2118 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(),
1964 0, NULL, NULL, NULL, 0, timeout_); 2119 pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_);
1965 2120
1966 if (code == OrthancPluginErrorCode_Success) 2121 if (code == OrthancPluginErrorCode_Success)
1967 { 2122 {
1968 return (status == 200); 2123 return (status == 200);
1969 } 2124 }
1973 } 2128 }
1974 } 2129 }
1975 2130
1976 2131
1977 bool OrthancPeers::DoDelete(const std::string& name, 2132 bool OrthancPeers::DoDelete(const std::string& name,
1978 const std::string& uri) const 2133 const std::string& uri,
2134 const std::map<std::string, std::string>& headers) const
1979 { 2135 {
1980 size_t index; 2136 size_t index;
1981 return (LookupName(index, name) && 2137 return (LookupName(index, name) &&
1982 DoDelete(index, uri)); 2138 DoDelete(index, uri, headers));
1983 } 2139 }
1984 #endif 2140 #endif
1985 2141
1986 2142
1987 2143
2014 return 0; 2170 return 0;
2015 } 2171 }
2016 } 2172 }
2017 2173
2018 2174
2175 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2176 static OrthancPluginErrorCode CopyStringToMemoryBuffer(OrthancPluginMemoryBuffer* target,
2177 const std::string& source)
2178 {
2179 if (OrthancPluginCreateMemoryBuffer(globalContext_, target, source.size()) != OrthancPluginErrorCode_Success)
2180 {
2181 return OrthancPluginErrorCode_NotEnoughMemory;
2182 }
2183 else
2184 {
2185 if (!source.empty())
2186 {
2187 memcpy(target->data, source.c_str(), source.size());
2188 }
2189
2190 return OrthancPluginErrorCode_Success;
2191 }
2192 }
2193 #endif
2194
2195
2196 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2197 OrthancPluginErrorCode OrthancJob::CallbackGetContent(OrthancPluginMemoryBuffer* target,
2198 void* job)
2199 {
2200 assert(job != NULL);
2201 OrthancJob& that = *reinterpret_cast<OrthancJob*>(job);
2202 return CopyStringToMemoryBuffer(target, that.content_);
2203 }
2204 #else
2019 const char* OrthancJob::CallbackGetContent(void* job) 2205 const char* OrthancJob::CallbackGetContent(void* job)
2020 { 2206 {
2021 assert(job != NULL); 2207 assert(job != NULL);
2022 2208
2023 try 2209 try
2027 catch (...) 2213 catch (...)
2028 { 2214 {
2029 return 0; 2215 return 0;
2030 } 2216 }
2031 } 2217 }
2032 2218 #endif
2033 2219
2220
2221 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2222 int32_t OrthancJob::CallbackGetSerialized(OrthancPluginMemoryBuffer* target,
2223 void* job)
2224 {
2225 assert(job != NULL);
2226 OrthancJob& that = *reinterpret_cast<OrthancJob*>(job);
2227
2228 if (that.hasSerialized_)
2229 {
2230 if (CopyStringToMemoryBuffer(target, that.serialized_) == OrthancPluginErrorCode_Success)
2231 {
2232 return 1;
2233 }
2234 else
2235 {
2236 return -1;
2237 }
2238 }
2239 else
2240 {
2241 return 0;
2242 }
2243 }
2244 #else
2034 const char* OrthancJob::CallbackGetSerialized(void* job) 2245 const char* OrthancJob::CallbackGetSerialized(void* job)
2035 { 2246 {
2036 assert(job != NULL); 2247 assert(job != NULL);
2037 2248
2038 try 2249 try
2051 catch (...) 2262 catch (...)
2052 { 2263 {
2053 return 0; 2264 return 0;
2054 } 2265 }
2055 } 2266 }
2267 #endif
2056 2268
2057 2269
2058 OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job) 2270 OrthancPluginJobStepStatus OrthancJob::CallbackStep(void* job)
2059 { 2271 {
2060 assert(job != NULL); 2272 assert(job != NULL);
2182 if (job == NULL) 2394 if (job == NULL)
2183 { 2395 {
2184 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer); 2396 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
2185 } 2397 }
2186 2398
2187 OrthancPluginJob* orthanc = OrthancPluginCreateJob( 2399 OrthancPluginJob* orthanc =
2188 GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(), 2400 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 11, 3)
2189 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized, 2401 OrthancPluginCreateJob2
2190 CallbackStep, CallbackStop, CallbackReset); 2402 #else
2403 OrthancPluginCreateJob
2404 #endif
2405 (GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
2406 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
2407 CallbackStep, CallbackStop, CallbackReset);
2191 2408
2192 if (orthanc == NULL) 2409 if (orthanc == NULL)
2193 { 2410 {
2194 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin); 2411 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
2195 } 2412 }
2481 { 2698 {
2482 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); 2699 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
2483 } 2700 }
2484 catch (...) 2701 catch (...)
2485 { 2702 {
2486 return OrthancPluginErrorCode_InternalError; 2703 return OrthancPluginErrorCode_Plugin;
2487 } 2704 }
2488 } 2705 }
2489 } 2706 }
2490 }; 2707 };
2491 2708
2567 } 2784 }
2568 2785
2569 2786
2570 void HttpClient::ClearCredentials() 2787 void HttpClient::ClearCredentials()
2571 { 2788 {
2572 username_.empty(); 2789 username_.clear();
2573 password_.empty(); 2790 password_.clear();
2574 } 2791 }
2575 2792
2576 2793
2577 void HttpClient::SetCertificate(const std::string& certificateFile, 2794 void HttpClient::SetCertificate(const std::string& certificateFile,
2578 const std::string& keyFile, 2795 const std::string& keyFile,
2881 { 3098 {
2882 HeadersWrapper headers(headers_); 3099 HeadersWrapper headers(headers_);
2883 3100
2884 MemoryBuffer answerBodyBuffer, answerHeadersBuffer; 3101 MemoryBuffer answerBodyBuffer, answerHeadersBuffer;
2885 3102
3103 if (body.size() > 0xffffffffu)
3104 {
3105 LogError("Cannot handle body size > 4GB");
3106 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
3107 }
3108
2886 OrthancPluginErrorCode error = OrthancPluginHttpClient( 3109 OrthancPluginErrorCode error = OrthancPluginHttpClient(
2887 GetGlobalContext(), 3110 GetGlobalContext(),
2888 *answerBodyBuffer, 3111 *answerBodyBuffer,
2889 *answerHeadersBuffer, 3112 *answerHeadersBuffer,
2890 &httpStatus, 3113 &httpStatus,
3497 result->toFree_ = true; 3720 result->toFree_ = true;
3498 return result.release(); 3721 return result.release();
3499 } 3722 }
3500 } 3723 }
3501 #endif 3724 #endif
3725
3726
3727 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3728 static std::vector<std::string> WebDavConvertPath(uint32_t pathSize,
3729 const char* const* pathItems)
3730 {
3731 std::vector<std::string> result(pathSize);
3732
3733 for (uint32_t i = 0; i < pathSize; i++)
3734 {
3735 result[i] = pathItems[i];
3736 }
3737
3738 return result;
3739 }
3740 #endif
3741
3742
3743 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3744 static OrthancPluginErrorCode WebDavIsExistingFolder(uint8_t* isExisting,
3745 uint32_t pathSize,
3746 const char* const* pathItems,
3747 void* payload)
3748 {
3749 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3750
3751 try
3752 {
3753 *isExisting = (that.IsExistingFolder(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0);
3754 return OrthancPluginErrorCode_Success;
3755 }
3756 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3757 {
3758 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3759 }
3760 catch (...)
3761 {
3762 return OrthancPluginErrorCode_Plugin;
3763 }
3764 }
3765 #endif
3766
3767
3768 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3769 static OrthancPluginErrorCode WebDavListFolder(uint8_t* isExisting,
3770 OrthancPluginWebDavCollection* collection,
3771 OrthancPluginWebDavAddFile addFile,
3772 OrthancPluginWebDavAddFolder addFolder,
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 std::list<IWebDavCollection::FileInfo> files;
3782 std::list<IWebDavCollection::FolderInfo> subfolders;
3783
3784 if (!that.ListFolder(files, subfolders, WebDavConvertPath(pathSize, pathItems)))
3785 {
3786 *isExisting = 0;
3787 }
3788 else
3789 {
3790 *isExisting = 1;
3791
3792 for (std::list<IWebDavCollection::FileInfo>::const_iterator
3793 it = files.begin(); it != files.end(); ++it)
3794 {
3795 OrthancPluginErrorCode code = addFile(
3796 collection, it->GetName().c_str(), it->GetContentSize(),
3797 it->GetMimeType().c_str(), it->GetDateTime().c_str());
3798
3799 if (code != OrthancPluginErrorCode_Success)
3800 {
3801 return code;
3802 }
3803 }
3804
3805 for (std::list<IWebDavCollection::FolderInfo>::const_iterator it =
3806 subfolders.begin(); it != subfolders.end(); ++it)
3807 {
3808 OrthancPluginErrorCode code = addFolder(
3809 collection, it->GetName().c_str(), it->GetDateTime().c_str());
3810
3811 if (code != OrthancPluginErrorCode_Success)
3812 {
3813 return code;
3814 }
3815 }
3816 }
3817
3818 return OrthancPluginErrorCode_Success;
3819 }
3820 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3821 {
3822 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3823 }
3824 catch (...)
3825 {
3826 return OrthancPluginErrorCode_Plugin;
3827 }
3828 }
3829 #endif
3830
3831
3832 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3833 static OrthancPluginErrorCode WebDavRetrieveFile(OrthancPluginWebDavCollection* collection,
3834 OrthancPluginWebDavRetrieveFile retrieveFile,
3835 uint32_t pathSize,
3836 const char* const* pathItems,
3837 void* payload)
3838 {
3839 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3840
3841 try
3842 {
3843 std::string content, mime, dateTime;
3844
3845 if (that.GetFile(content, mime, dateTime, WebDavConvertPath(pathSize, pathItems)))
3846 {
3847 return retrieveFile(collection, content.empty() ? NULL : content.c_str(),
3848 content.size(), mime.c_str(), dateTime.c_str());
3849 }
3850 else
3851 {
3852 // Inexisting file
3853 return OrthancPluginErrorCode_Success;
3854 }
3855 }
3856 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3857 {
3858 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3859 }
3860 catch (...)
3861 {
3862 return OrthancPluginErrorCode_InternalError;
3863 }
3864 }
3865 #endif
3866
3867
3868 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3869 static OrthancPluginErrorCode WebDavStoreFileCallback(uint8_t* isReadOnly, /* out */
3870 uint32_t pathSize,
3871 const char* const* pathItems,
3872 const void* data,
3873 uint64_t size,
3874 void* payload)
3875 {
3876 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3877
3878 try
3879 {
3880 if (static_cast<uint64_t>(static_cast<size_t>(size)) != size)
3881 {
3882 ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
3883 }
3884
3885 *isReadOnly = (that.StoreFile(WebDavConvertPath(pathSize, pathItems), data,
3886 static_cast<size_t>(size)) ? 1 : 0);
3887 return OrthancPluginErrorCode_Success;
3888 }
3889 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3890 {
3891 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3892 }
3893 catch (...)
3894 {
3895 return OrthancPluginErrorCode_InternalError;
3896 }
3897 }
3898 #endif
3899
3900
3901 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3902 static OrthancPluginErrorCode WebDavCreateFolderCallback(uint8_t* isReadOnly, /* out */
3903 uint32_t pathSize,
3904 const char* const* pathItems,
3905 void* payload)
3906 {
3907 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3908
3909 try
3910 {
3911 *isReadOnly = (that.CreateFolder(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0);
3912 return OrthancPluginErrorCode_Success;
3913 }
3914 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3915 {
3916 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3917 }
3918 catch (...)
3919 {
3920 return OrthancPluginErrorCode_InternalError;
3921 }
3922 }
3923 #endif
3924
3925
3926 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3927 static OrthancPluginErrorCode WebDavDeleteItemCallback(uint8_t* isReadOnly, /* out */
3928 uint32_t pathSize,
3929 const char* const* pathItems,
3930 void* payload)
3931 {
3932 IWebDavCollection& that = *reinterpret_cast<IWebDavCollection*>(payload);
3933
3934 try
3935 {
3936 *isReadOnly = (that.DeleteItem(WebDavConvertPath(pathSize, pathItems)) ? 1 : 0);
3937 return OrthancPluginErrorCode_Success;
3938 }
3939 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
3940 {
3941 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
3942 }
3943 catch (...)
3944 {
3945 return OrthancPluginErrorCode_InternalError;
3946 }
3947 }
3948 #endif
3949
3950
3951 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
3952 void IWebDavCollection::Register(const std::string& uri,
3953 IWebDavCollection& collection)
3954 {
3955 OrthancPluginErrorCode code = OrthancPluginRegisterWebDavCollection(
3956 GetGlobalContext(), uri.c_str(), WebDavIsExistingFolder, WebDavListFolder, WebDavRetrieveFile,
3957 WebDavStoreFileCallback, WebDavCreateFolderCallback, WebDavDeleteItemCallback, &collection);
3958
3959 if (code != OrthancPluginErrorCode_Success)
3960 {
3961 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
3962 }
3963 }
3964 #endif
3965
3966 void GetHttpHeaders(std::map<std::string, std::string>& result, const OrthancPluginHttpRequest* request)
3967 {
3968 result.clear();
3969
3970 for (uint32_t i = 0; i < request->headersCount; ++i)
3971 {
3972 result[request->headersKeys[i]] = request->headersValues[i];
3973 }
3974 }
3502 } 3975 }