You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by ar...@apache.org on 2013/03/24 14:20:59 UTC

svn commit: r1460354 - in /openoffice/trunk/main/ucb/source/ucp/webdav: DAVResourceAccess.cxx DAVResourceAccess.hxx webdavcontent.cxx

Author: arielch
Date: Sun Mar 24 13:20:58 2013
New Revision: 1460354

URL: http://svn.apache.org/r1460354
Log:
i121201 - Handle servers not supporting HEAD requests

Modified:
    openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.cxx
    openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.hxx
    openoffice/trunk/main/ucb/source/ucp/webdav/webdavcontent.cxx

Modified: openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.cxx
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.cxx?rev=1460354&r1=1460353&r2=1460354&view=diff
==============================================================================
--- openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.cxx (original)
+++ openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.cxx Sun Mar 24 13:20:58 2013
@@ -466,6 +466,51 @@ uno::Reference< io::XInputStream > DAVRe
 }
 
 //=========================================================================
+uno::Reference< io::XInputStream > DAVResourceAccess::GET(
+    DAVRequestHeaders &rRequestHeaders,
+    const std::vector< rtl::OUString > & rHeaderNames,
+    DAVResource & rResource,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+  throw( DAVException )
+{
+    initialize();
+
+    uno::Reference< io::XInputStream > xStream;
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   rtl::OUString::createFromAscii( "GET" ),
+                                   rRequestHeaders );
+
+            xStream = m_xSession->GET( getRequestURI(),
+                                       rHeaderNames,
+                                       rResource,
+                                       DAVRequestEnvironment(
+                                           getRequestURI(),
+                                           new DAVAuthListener_Impl(
+                                               xEnv, m_aURL ),
+                                           rRequestHeaders, xEnv ) );
+        }
+        catch ( DAVException & e )
+        {
+            errorCount++;
+            bRetry = handleException( e, errorCount );
+            if ( !bRetry )
+                throw;
+        }
+    }
+    while ( bRetry );
+
+    return xStream;
+}
+
+//=========================================================================
 void DAVResourceAccess::GET(
     uno::Reference< io::XOutputStream > & rStream,
     const std::vector< rtl::OUString > & rHeaderNames,

Modified: openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.hxx
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.hxx?rev=1460354&r1=1460353&r2=1460354&view=diff
==============================================================================
--- openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.hxx (original)
+++ openoffice/trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.hxx Sun Mar 24 13:20:58 2013
@@ -128,6 +128,14 @@ public:
              com::sun::star::ucb::XCommandEnvironment > & xEnv )
         throw ( DAVException );
 
+    com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+    GET( DAVRequestHeaders & rRequestHeaders,
+         const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
+         DAVResource & rResource,
+         const com::sun::star::uno::Reference<
+             com::sun::star::ucb::XCommandEnvironment > & xEnv )
+        throw ( DAVException );
+
     void
     GET( com::sun::star::uno::Reference<
              com::sun::star::io::XOutputStream > & rStream,

Modified: openoffice/trunk/main/ucb/source/ucp/webdav/webdavcontent.cxx
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/ucb/source/ucp/webdav/webdavcontent.cxx?rev=1460354&r1=1460353&r2=1460354&view=diff
==============================================================================
--- openoffice/trunk/main/ucb/source/ucp/webdav/webdavcontent.cxx (original)
+++ openoffice/trunk/main/ucb/source/ucp/webdav/webdavcontent.cxx Sun Mar 24 13:20:58 2013
@@ -87,6 +87,118 @@
 using namespace com::sun::star;
 using namespace http_dav_ucp;
 
+namespace
+{
+static void lcl_sendPartialGETRequest( bool &bError,
+                                       DAVException &aLastException,
+                                       const std::vector< rtl::OUString > aProps,
+                                       std::vector< rtl::OUString > &aHeaderNames,
+                                       const std::auto_ptr< DAVResourceAccess > &xResAccess,
+                                       std::auto_ptr< ContentProperties > &xProps,
+                                       const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+{
+    bool bIsRequestSize = false;
+    DAVResource aResource;
+    DAVRequestHeaders aPartialGet;
+    aPartialGet.push_back(
+        DAVRequestHeader(
+            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Range" ) ),
+            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "bytes=0-0" ))));
+
+    for ( std::vector< rtl::OUString >::const_iterator it = aHeaderNames.begin();
+            it != aHeaderNames.end(); it++ )
+    {
+        if ( it->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) )
+        {
+            bIsRequestSize = true;
+            break;
+        }
+    }
+
+    if ( bIsRequestSize )
+    {
+        // we need to know if the server accepts range requests for a resource
+        // and the range unit it uses
+        aHeaderNames.push_back( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Accept-Ranges" ) ) );
+        aHeaderNames.push_back( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Content-Range" ) ) );
+    }
+    try
+    {
+        uno::Reference< io::XInputStream > xIn = xResAccess->GET( aPartialGet,
+                                                                  aHeaderNames,
+                                                                  aResource,
+                                                                  xEnv );
+        bError = false;
+
+        if ( bIsRequestSize )
+        {
+            // the ContentProperties maps "Content-Length" to the UCB "Size" property
+            // This would have an unrealistic value of 1 byte because we did only a partial GET
+            // Solution: if "Content-Range" is present, map it with UCB "Size" property
+            rtl::OUString aAcceptRanges, aContentRange, aContentLength;
+            std::vector< DAVPropertyValue > &aResponseProps = aResource.properties;
+            for ( std::vector< DAVPropertyValue >::const_iterator it = aResponseProps.begin();
+                    it != aResponseProps.end(); it++ )
+            {
+                if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Accept-Ranges" ) ) )
+                    it->Value >>= aAcceptRanges;
+                else if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Range" ) ) )
+                    it->Value >>= aContentRange;
+                else if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) )
+                    it->Value >>= aContentLength;
+            }
+
+            sal_Int64 nSize = 1;
+            if ( aContentLength.getLength() )
+            {
+                nSize = aContentLength.toInt64();
+            }
+
+            // according to http://tools.ietf.org/html/rfc2616#section-3.12
+            // the only range unit defined is "bytes" and implementations
+            // MAY ignore ranges specified using other units.
+            if ( nSize == 1 &&
+                    aContentRange.getLength() &&
+                    aAcceptRanges.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "bytes" ) ) )
+            {
+                // Parse the Content-Range to get the size
+                // vid. http://tools.ietf.org/html/rfc2616#section-14.16
+                // Content-Range: <range unit> <bytes range>/<size>
+                sal_Int32 nSlash = aContentRange.lastIndexOf( sal_Unicode('/'));
+                if ( nSlash != -1 )
+                {
+                    rtl::OUString aSize = aContentRange.copy( nSlash + 1 );
+                    // "*" means that the instance-length is unknown at the time when the response was generated
+                    if ( !aSize.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "*" )))
+                    {
+                        for ( std::vector< DAVPropertyValue >::iterator it = aResponseProps.begin();
+                                it != aResponseProps.end(); it++ )
+                        {
+                            if ( it->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) )
+                            {
+                                it->Value <<= aSize;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if ( xProps.get() )
+            xProps->addProperties(
+                aProps,
+                ContentProperties( aResource ) );
+        else
+            xProps.reset ( new ContentProperties( aResource ) );
+    }
+    catch ( DAVException const & ex )
+    {
+        aLastException = ex;
+    }
+}
+}
+
 //=========================================================================
 //=========================================================================
 //
@@ -1364,13 +1476,43 @@ uno::Reference< sdbc::XRow > Content::ge
                     }
                     catch ( DAVException const & e )
                     {
-                        bNetworkAccessAllowed
-                            = shouldAccessNetworkAfterException( e );
+                        // non "general-purpose servers" may not support HEAD requests
+                        // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1
+                        // In this case, perform a partial GET only to get the header info
+                        // vid. http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
+                        // WARNING if the server does not support partial GETs,
+                        // the GET will transfer the whole content
+                        bool bError = true;
+                        DAVException aLastException = e;
+
+                        // According to the spec. the origin server SHOULD return
+                        // * 405 (Method Not Allowed):
+                        //      the method is known but not allowed for the requested resource
+                        // * 501 (Not Implemented):
+                        //      the method is unrecognized or not implemented
+                        // TODO SC_NOT_FOUND is only for google-code server
+                        if ( aLastException.getStatus() == SC_NOT_IMPLEMENTED ||
+                                aLastException.getStatus() == SC_METHOD_NOT_ALLOWED ||
+                                aLastException.getStatus() == SC_NOT_FOUND )
+                        {
+                            lcl_sendPartialGETRequest( bError,
+                                                       aLastException,
+                                                       aMissingProps,
+                                                       aHeaderNames,
+                                                       xResAccess,
+                                                       xProps,
+                                                       xEnv );
+                            m_bDidGetOrHead = !bError;
+                        }
 
-                        if ( !bNetworkAccessAllowed )
+                        if ( bError )
                         {
-                            cancelCommandExecution( e, xEnv );
-                            // unreachable
+                            if ( !(bNetworkAccessAllowed
+                                    = shouldAccessNetworkAfterException( aLastException )) )
+                            {
+                                cancelCommandExecution( aLastException, xEnv );
+                                // unreachable
+                            }
                         }
                     }
                 }