fixed an SSL issue; doc fixes

This commit is contained in:
Guenter Obiltschnig
2010-11-24 08:37:28 +00:00
parent 69a219dfd6
commit 897a1428da
7 changed files with 94 additions and 57 deletions

View File

@@ -1,7 +1,7 @@
// //
// SSLException.h // SSLException.h
// //
// $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SSLException.h#2 $ // $Id: //poco/1.3/NetSSL_OpenSSL/include/Poco/Net/SSLException.h#3 $
// //
// Library: NetSSL_OpenSSL // Library: NetSSL_OpenSSL
// Package: SSLCore // Package: SSLCore
@@ -52,6 +52,7 @@ POCO_DECLARE_EXCEPTION(NetSSL_API, SSLException, NetException)
POCO_DECLARE_EXCEPTION(NetSSL_API, SSLContextException, SSLException) POCO_DECLARE_EXCEPTION(NetSSL_API, SSLContextException, SSLException)
POCO_DECLARE_EXCEPTION(NetSSL_API, InvalidCertificateException, SSLException) POCO_DECLARE_EXCEPTION(NetSSL_API, InvalidCertificateException, SSLException)
POCO_DECLARE_EXCEPTION(NetSSL_API, CertificateValidationException, SSLException) POCO_DECLARE_EXCEPTION(NetSSL_API, CertificateValidationException, SSLException)
POCO_DECLARE_EXCEPTION(NetSSL_API, SSLConnectionUnexpectedlyClosedException, SSLException)
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -1,7 +1,7 @@
// //
// TimeServer.cpp // TimeServer.cpp
// //
// $Id: //poco/1.3/NetSSL_OpenSSL/samples/HTTPSTimeServer/src/HTTPSTimeServer.cpp#4 $ // $Id: //poco/1.3/NetSSL_OpenSSL/samples/HTTPSTimeServer/src/HTTPSTimeServer.cpp#5 $
// //
// This sample demonstrates the HTTPServer and related classes. // This sample demonstrates the HTTPServer and related classes.
// //
@@ -225,7 +225,7 @@ protected:
else else
{ {
// get parameters from configuration file // get parameters from configuration file
unsigned short port = (unsigned short) config().getInt("HTTPSTimeServer.port", 9980); unsigned short port = (unsigned short) config().getInt("HTTPSTimeServer.port", 9443);
std::string format(config().getString("HTTPSTimeServer.format", DateTimeFormat::SORTABLE_FORMAT)); std::string format(config().getString("HTTPSTimeServer.format", DateTimeFormat::SORTABLE_FORMAT));
// set-up a server socket // set-up a server socket

View File

@@ -1,7 +1,7 @@
// //
// SSLException.cpp // SSLException.cpp
// //
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SSLException.cpp#2 $ // $Id: //poco/1.3/NetSSL_OpenSSL/src/SSLException.cpp#3 $
// //
// Library: NetSSL_OpenSSL // Library: NetSSL_OpenSSL
// Package: SSLCore // Package: SSLCore
@@ -46,6 +46,7 @@ POCO_IMPLEMENT_EXCEPTION(SSLException, NetException, "SSL Exception")
POCO_IMPLEMENT_EXCEPTION(SSLContextException, SSLException, "SSL context exception") POCO_IMPLEMENT_EXCEPTION(SSLContextException, SSLException, "SSL context exception")
POCO_IMPLEMENT_EXCEPTION(InvalidCertificateException, SSLException, "Invalid certficate") POCO_IMPLEMENT_EXCEPTION(InvalidCertificateException, SSLException, "Invalid certficate")
POCO_IMPLEMENT_EXCEPTION(CertificateValidationException, SSLException, "Certificate validation error") POCO_IMPLEMENT_EXCEPTION(CertificateValidationException, SSLException, "Certificate validation error")
POCO_IMPLEMENT_EXCEPTION(SSLConnectionUnexpectedlyClosedException, SSLException, "SSL connection unexpectedly closed")
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -1,7 +1,7 @@
// //
// SecureSocketImpl.cpp // SecureSocketImpl.cpp
// //
// $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureSocketImpl.cpp#23 $ // $Id: //poco/1.3/NetSSL_OpenSSL/src/SecureSocketImpl.cpp#24 $
// //
// Library: NetSSL_OpenSSL // Library: NetSSL_OpenSSL
// Package: SSLSockets // Package: SSLSockets
@@ -251,6 +251,8 @@ int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
rc = completeHandshake(); rc = completeHandshake();
if (rc == 1) if (rc == 1)
verifyPeerCertificate(); verifyPeerCertificate();
else if (rc == 0)
throw SSLConnectionUnexpectedlyClosedException();
else else
return rc; return rc;
} }
@@ -261,7 +263,8 @@ int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR); while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
if (rc <= 0) if (rc <= 0)
{ {
return handleError(rc); rc = handleError(rc);
if (rc == 0) throw SSLConnectionUnexpectedlyClosedException();
} }
return rc; return rc;
} }
@@ -403,7 +406,7 @@ int SecureSocketImpl::handleError(int rc)
{ {
if (rc == 0) if (rc == 0)
{ {
throw SSLException("The underlying socket connection has been unexpectedly closed"); throw SSLConnectionUnexpectedlyClosedException();
} }
else else
{ {

View File

@@ -1,7 +1,7 @@
// //
// Units.h // Units.h
// //
// $Id: //poco/1.3/Util/include/Poco/Util/Units.h#2 $ // $Id: //poco/1.3/Util/include/Poco/Util/Units.h#3 $
// //
// Library: Util // Library: Util
// Package: Units // Package: Units
@@ -374,7 +374,7 @@ namespace Internal
/// specialize this template. /// specialize this template.
/// The default implementation falls through to Convert2. /// The default implementation falls through to Convert2.
{ {
static_assert<Convertible<T1,T2>::Value> check_convertible; static_assert<Convertible<T1,T2>::Value> checkConvertible;
/// If this fails, then T1 is not Convertible to T2: /// If this fails, then T1 is not Convertible to T2:
template <typename V> template <typename V>
@@ -386,7 +386,7 @@ namespace Internal
template <typename T> template <typename T>
struct Convert<T, T> struct Convert<T, T>
/// Trivial conversion to the same type. // Trivial conversion to the same type.
{ {
template <typename U> template <typename U>
static const U& fn(const U& u) { return u; } static const U& fn(const U& u) { return u; }
@@ -394,7 +394,7 @@ namespace Internal
template <typename T> template <typename T>
struct Convert3<T, T> struct Convert3<T, T>
/// Convert to same type. // Convert to same type.
{ {
template <typename U> template <typename U>
static const U& fn(const U& u) { return u; } static const U& fn(const U& u) { return u; }
@@ -402,7 +402,7 @@ namespace Internal
template <typename T, typename U, int Num, int Den> template <typename T, typename U, int Num, int Den>
struct Convert2<Scale<T, Num, Den>, U> struct Convert2<Scale<T, Num, Den>, U>
/// Convert from a scaled Unit // Convert from a scaled Unit.
{ {
template <typename V> template <typename V>
static V fn(const V& v) static V fn(const V& v)
@@ -413,7 +413,7 @@ namespace Internal
template <typename T, typename U, int Num, int Den> template <typename T, typename U, int Num, int Den>
struct Convert3<T, Scale<U, Num, Den> > struct Convert3<T, Scale<U, Num, Den> >
/// Convert to a scaled Unit // Convert to a scaled Unit.
{ {
template <typename V> template <typename V>
static V fn(const V& v) static V fn(const V& v)
@@ -424,7 +424,7 @@ namespace Internal
template <typename T, typename U, int Num, int Den> template <typename T, typename U, int Num, int Den>
struct Convert2<Translate<T, Num, Den>, U> struct Convert2<Translate<T, Num, Den>, U>
/// Convert from a translated Unit // Convert from a translated Unit.
{ {
template <typename V> template <typename V>
static V fn(const V& v) static V fn(const V& v)
@@ -435,7 +435,7 @@ namespace Internal
template <typename T, typename U, int Num, int Den> template <typename T, typename U, int Num, int Den>
struct Convert3<T, Translate<U, Num, Den> > struct Convert3<T, Translate<U, Num, Den> >
/// Convert to a translated Unit // Convert to a translated Unit.
{ {
template <typename V> template <typename V>
static V fn(const V& v) static V fn(const V& v)
@@ -448,7 +448,7 @@ namespace Internal
struct CountTerms struct CountTerms
/// Count the power to which Unit Term is raised in the Unit List. /// Count the power to which Unit Term is raised in the Unit List.
/// Returns a rational num/den of the power of term Term in List. /// Returns a rational num/den of the power of term Term in List.
/// The default assumes that Term is not found (num/den=0) /// The default assumes that Term is not found (num/den=0).
{ {
static const int num = 0; static const int num = 0;
static const int den = 1; static const int den = 1;
@@ -463,7 +463,7 @@ namespace Internal
template <typename Term, typename U, int N, int D> template <typename Term, typename U, int N, int D>
struct CountTerms<Term, Scale<U, N, D> > struct CountTerms<Term, Scale<U, N, D> >
/// CountTerms ignores scaling factors - that is taken care of by ScalingFactor. // CountTerms ignores scaling factors - that is taken care of by ScalingFactor.
{ {
typedef CountTerms<Term, U> result; typedef CountTerms<Term, U> result;
static const int num = result::num; static const int num = result::num;
@@ -472,7 +472,7 @@ namespace Internal
template <typename Term, typename U, int N, int D> template <typename Term, typename U, int N, int D>
struct CountTerms<Term, Translate<U, N, D> > struct CountTerms<Term, Translate<U, N, D> >
/// CountTerms ignores translation. // CountTerms ignores translation.
{ {
typedef CountTerms<Term, U> result; typedef CountTerms<Term, U> result;
static const int num = result::num; static const int num = result::num;
@@ -481,19 +481,17 @@ namespace Internal
template <typename Term, typename T1, typename T2> template <typename Term, typename T1, typename T2>
struct CountTerms<Term, Compose<T1,T2> > struct CountTerms<Term, Compose<T1,T2> >
/// Addition of fractions. // Addition of fractions.
{ {
typedef CountTerms<Term, T1> result1; typedef CountTerms<Term, T1> result1;
typedef CountTerms<Term, T2> result2; typedef CountTerms<Term, T2> result2;
static const int num = static const int num = result1::num * result2::den + result1::den * result2::num;
result1::num * result2::den + result1::den * result2::num; static const int den = result1::den * result2::den;
static const int den =
result1::den * result2::den;
}; };
template <typename Term, typename U, int N, int D> template <typename Term, typename U, int N, int D>
struct CountTerms<Term, Power<U, N, D> > struct CountTerms<Term, Power<U, N, D> >
/// Multiplication of fractions. // Multiplication of fractions.
{ {
typedef CountTerms<Term, U> result; typedef CountTerms<Term, U> result;
static const int num = N * result::num; static const int num = N * result::num;
@@ -543,7 +541,7 @@ namespace Internal
template <typename T1, typename T2> template <typename T1, typename T2>
struct Convertible struct Convertible
/// Determines whether two types are Convertible /// Determines whether two types are Convertible.
/// Counts the powers in the LHS and RHS and ensures they are equal. /// Counts the powers in the LHS and RHS and ensures they are equal.
{ {
static const bool Value = static const bool Value =
@@ -555,7 +553,7 @@ namespace Internal
struct FixedPower struct FixedPower
/// A functor that raises a Value to the power Num/Den. /// A functor that raises a Value to the power Num/Den.
/// The template is specialised for efficiency /// The template is specialised for efficiency
/// so that we don't always have to call the std::Power function. /// so that we don't always have to call the std::power function.
{ {
template <typename T> static T Power(const T& t) template <typename T> static T Power(const T& t)
{ {
@@ -688,8 +686,14 @@ namespace Internal
#define UNIT_DISPLAY_NAME(Unit, string) \ #define UNIT_DISPLAY_NAME(Unit, string) \
template <> struct OutputUnit<Unit> { \ template <> \
template <typename Stream> static void fn(Stream& os) { os << string; } \ struct OutputUnit<Unit> \
{ \
template <typename Stream> \
static void fn(Stream& os) \
{ \
os << string; \
} \
} }
@@ -697,20 +701,26 @@ namespace Internal
{ {
template <typename U> template <typename U>
struct OutputUnit2 struct OutputUnit2
/// The default Unit formatting mechanism /// The default Unit formatting mechanism.
{ {
template <typename Stream> template <typename Stream>
static void fn(Stream &os) { os << "Units"; } static void fn(Stream &os)
{
os << "Units";
}
}; };
} }
template <typename U> template <typename U>
struct OutputUnit struct OutputUnit
/// Functor to write Unit text to stream /// Functor to write Unit text to stream.
{ {
template <typename Stream> template <typename Stream>
static void fn(Stream &os) { Internal::OutputUnit2<U>::fn(os); } static void fn(Stream &os)
{
Internal::OutputUnit2<U>::fn(os);
}
}; };
@@ -913,16 +923,23 @@ namespace Units
_pHolder(new Holder<T>(val)), _pHolder(new Holder<T>(val)),
_multiplier(multiplier), _multiplier(multiplier),
_prefix(prefix) _prefix(prefix)
{ } {
}
double value() const double value() const
{ return _pHolder->get() * _multiplier; } {
return _pHolder->get() * _multiplier;
}
void addPrefix(std::ostream& os) const void addPrefix(std::ostream& os) const
{ os << _prefix; } {
os << _prefix;
}
void addUnit(std::ostream& os) const void addUnit(std::ostream& os) const
{ _pHolder->appendUnit(os); } {
_pHolder->appendUnit(os);
}
private: private:
Prefix(); Prefix();
@@ -940,13 +957,19 @@ namespace Units
{ {
typedef Value<typename U::ValueType, typename U::Unit> ValueType; typedef Value<typename U::ValueType, typename U::Unit> ValueType;
Holder (const U& val): _val(ValueType(val)) { } Holder (const U& val): _val(ValueType(val))
{
}
double get() const double get() const
{ return _val.get(); } {
return _val.get();
}
void appendUnit(std::ostream& os) const void appendUnit(std::ostream& os) const
{ OutputUnit<typename U::Unit>::fn(os); } {
OutputUnit<typename U::Unit>::fn(os);
}
ValueType _val; ValueType _val;
}; };
@@ -1197,10 +1220,19 @@ namespace Values
typedef Value<double, Units::dozen> dozen; typedef Value<double, Units::dozen> dozen;
typedef Value<double, Units::bakers_dozen> bakers_dozen; typedef Value<double, Units::bakers_dozen> bakers_dozen;
#define DEFINE_PREFIX_CLASS(name, scale, prefix) struct name: public Units::Prefix \ #define DEFINE_PREFIX_CLASS(name, scale, prefix) \
{ template <typename T> name(const T& val): Prefix(val, scale, prefix) { } }; \ struct name: public Units::Prefix \
template <typename Str> Str& operator << (Str& os, const name& val) \ { \
{ return streamOp<Str>(os, val); } template <typename T> \
name(const T& val): Prefix(val, scale, prefix) \
{ \
} \
}; \
template <typename Str> \
Str& operator << (Str& os, const name& val) \
{ \
return streamOp<Str>(os, val); \
}
DEFINE_PREFIX_CLASS (deca, .1, "da") DEFINE_PREFIX_CLASS (deca, .1, "da")
DEFINE_PREFIX_CLASS (hecto, .01, "h") DEFINE_PREFIX_CLASS (hecto, .01, "h")

View File

@@ -12,22 +12,22 @@ AAAIntroduction
- added Poco::Net::Socket::secure() to find out whether a given socket supports SSL/TLS - added Poco::Net::Socket::secure() to find out whether a given socket supports SSL/TLS
- added Poco::Net::SecureStreamSocket::havePeerCertificate() - added Poco::Net::SecureStreamSocket::havePeerCertificate()
- NetSSL: added support for turning off extended certificate validation (hostname matching) - NetSSL: added support for turning off extended certificate validation (hostname matching)
- fixed SF# 2941228: ICMPClient::ping() issues on Mac OS X - fixed SF# 2941228: Poco::Net::ICMPClient::ping() issues on Mac OS X
- fixed SF# 2941231: ICMPEventArgs out of bounds array access - fixed SF# 2941231: Poco::Net::ICMPEventArgs out of bounds array access
- added PageCompiler sample - added PageCompiler sample
- added missing newline at end of xmlparse.c - added missing newline at end of xmlparse.c
- Poco::Glob can now be used with an empty pattern which will match nothing (patch from Kim Graesman) - Poco::Glob can now be used with an empty pattern which will match nothing (patch from Kim Graesman)
- added support for HTTP proxy authentication (Basic authentication only) - added support for HTTP proxy authentication (Basic authentication only)
- fixed SF# 2958959: Poco::XML::XMLWriter must encode CR, LF and TAB in attribute values as character entities. - fixed SF# 2958959: Poco::XML::XMLWriter must encode CR, LF and TAB in attribute values as character entities.
- Poco::Net::HTMLForm now supports PUT requests as well (see <http://pocoproject.org/forum/viewtopic.php?f=12&t=2163&p=3930#p3930>) - Poco::Net::HTMLForm now supports PUT requests as well (see <http://pocoproject.org/forum/viewtopic.php?f=12&t=2163&p=3930#p3930>)
- fixed SF# #2970521: FileOutputStream and file permissions. - fixed SF# #2970521: Poco::FileOutputStream and file permissions.
(also fixed in File class) (also fixed in File class)
- removed an unused (and wrong) default parameter from EventImpl constructor for WIN32. - removed an unused (and wrong) default parameter from EventImpl constructor for WIN32.
- added full support for session caching to NetSSL_OpenSSL - added full support for session caching to NetSSL_OpenSSL
- fixed SF# 2984454: Poco::Util::Timer::scheduleAtFixedRate() works incorrectly - fixed SF# 2984454: Poco::Util::Timer::scheduleAtFixedRate() works incorrectly
- fixed a bug in Poco::Util::Timer that could lead to high CPU load if - fixed a bug in Poco::Util::Timer that could lead to high CPU load if
the system clock is moved forward. the system clock is moved forward.
- added system.nodeId to SystemConfiguration - added "system.nodeId" property to Poco::Util::SystemConfiguration
- added a note to Poco::Util::ServerApplication documentation regarding - added a note to Poco::Util::ServerApplication documentation regarding
creation of threads creation of threads
- added Poco::Net::IPAddress::broadcast() and Poco::Net::IPAddress::wildcard() to - added Poco::Net::IPAddress::broadcast() and Poco::Net::IPAddress::wildcard() to
@@ -54,11 +54,11 @@ AAAIntroduction
- fixed SF# 3003875: SQLite data binding is broken - fixed SF# 3003875: SQLite data binding is broken
- fixed SF# 2993988: Issue with multiple calls to open()/close() on File*Stream - fixed SF# 2993988: Issue with multiple calls to open()/close() on File*Stream
- fixed SF# 2990256: Poco::Net::HTMLForm and file uploads - fixed SF# 2990256: Poco::Net::HTMLForm and file uploads
- fixed SF# 2969227: DateTimeParser bug - fixed SF# 2969227: Poco::DateTimeParser bug
- fixed SF# 2966698: Socket connect with timeout issue - fixed SF# 2966698: Socket connect with timeout issue
- fixed SF# 2981041: Bind NULL to a query (patch supplied) - fixed SF# 2981041: Bind NULL to a query (patch supplied)
- fixed SF# 2961419: Poco::UTF8Encoding::convert() doesn't work properly in DEBUG mode - fixed SF# 2961419: Poco::UTF8Encoding::convert() doesn't work properly in DEBUG mode
- fixed SF# 2957068: Timeout value not picked up by proxy in HTTPSClientSession - fixed SF# 2957068: Timeout value not picked up by proxy in Poco::Net::HTTPSClientSession
- fixed NetSSL_OpenSSL test runner for Poco::Util::Application class changes - fixed NetSSL_OpenSSL test runner for Poco::Util::Application class changes
- Poco::AbstractEvent, Poco::AbstractCache and related classes now accept a Mutex class as additional template argument. - Poco::AbstractEvent, Poco::AbstractCache and related classes now accept a Mutex class as additional template argument.
Poco::NullMutex can be used if no synchronization is desired. Poco::NullMutex can be used if no synchronization is desired.
@@ -77,12 +77,12 @@ AAAIntroduction
- fixed SF# 2902029: zlib flush support (Z_SYNC_FLUSH) - fixed SF# 2902029: zlib flush support (Z_SYNC_FLUSH)
- added Poco::TextBufferIterator class - added Poco::TextBufferIterator class
- fixed SF# 2977249: Use epoll instead select under Linux - fixed SF# 2977249: Use epoll instead select under Linux
Socket::select() and Socket::poll() will use epoll under Linux if the Net library is compiled Poco::Net::Socket::select() and Poco::Net::Socket::poll() will use epoll under Linux if the Net library is compiled
with -DPOCO_HAVE_FD_EPOLL. This is the default for the Linux build configuration (but not for with -DPOCO_HAVE_FD_EPOLL. This is the default for the Linux build configuration (but not for
the various build configurations targeting embedded Linux platforms). the various build configurations targeting embedded Linux platforms).
- fixed SF# 2941664: Memory leak in DeflatingStream with zero-length streams (also fixed some other potential, - fixed SF# 2941664: Memory leak in Poco::DeflatingStream with zero-length streams (also fixed some other potential,
but unlikely, memory leaks) but unlikely, memory leaks)
- fixed SF# 2946457: added RejectCertificateHandler - fixed SF# 2946457: added Poco::Net::RejectCertificateHandler
- fixed SF# 2946621: Poco::Path bug with POCO_WIN32_UTF8 - fixed SF# 2946621: Poco::Path bug with POCO_WIN32_UTF8
- fixed SF# 2929805: Environment::nodeId() does not work if no eth0 device exists - fixed SF# 2929805: Environment::nodeId() does not work if no eth0 device exists
- Poco::Environment::nodeId() no longer throws if no hardware ethernet address can be determined. - Poco::Environment::nodeId() no longer throws if no hardware ethernet address can be determined.
@@ -120,8 +120,8 @@ AAAIntroduction
- fixed SF# 3031530: Ping and possible no timeout - fixed SF# 3031530: Ping and possible no timeout
- added Poco::Net::SocketReactor::onBusy(), called whenever at least one notification will - added Poco::Net::SocketReactor::onBusy(), called whenever at least one notification will
be dispatched. be dispatched.
- fixed SF# 3034863: Compiler warning in net/IPAddress.h with poco 1.3.2 - fixed SF# 3034863: Compiler warning in Net/IPAddress.h with poco 1.3.2
- added support for CRAM-SHA1 authentication to SMTPClientSession - added support for CRAM-SHA1 authentication to Poco::Net::SMTPClientSession
- Poco::format(): arguments can now be addressed by their index, e.g. %[2]d - Poco::format(): arguments can now be addressed by their index, e.g. %[2]d
- Poco::Util::Timer::cancel() now accepts an optional boolean argument. - Poco::Util::Timer::cancel() now accepts an optional boolean argument.
If true is passed, cancel() waits until the task queue has been purged. If true is passed, cancel() waits until the task queue has been purged.
@@ -196,7 +196,7 @@ AAAIntroduction
can be optionally passed to the constructor). can be optionally passed to the constructor).
- Windows Embedded CE (5.0 and newer) is now a supported platform. - Windows Embedded CE (5.0 and newer) is now a supported platform.
- Poco::UUID::nil() and Poco::UUID::isNil() have been renamed to - Poco::UUID::nil() and Poco::UUID::isNil() have been renamed to
Poco::UUID::null() and Poco::UUID::isNill(), respectively, to avoid Poco::UUID::null() and Poco::UUID::isNull(), respectively, to avoid
issues with Objective-C++ projects on Mac OS X and iOS where nil is issues with Objective-C++ projects on Mac OS X and iOS where nil is
a system-provided macro. a system-provided macro.

View File

@@ -3,7 +3,7 @@ AAAIntroduction
!!!Introduction !!!Introduction
Starting with release 1.3.7 the POCO C++ Libraries can be used on Starting with release 1.4.0 the POCO C++ Libraries can be used on
Windows CE 6. Project files for Visual Studio 2008 are provided that Windows CE 6. Project files for Visual Studio 2008 are provided that
support static and shared debug and release builds. support static and shared debug and release builds.