1 --- officecfg/registry/data/org/openoffice/ucb/Configuration.xcu
2 +++ officecfg/registry/data/org/openoffice/ucb/Configuration.xcu
7 + <node oor:name="Provider14" oor:op="replace">
8 + <prop oor:name="ServiceName">
9 + <value>com.sun.star.ucb.WebDAVContentProvider</value>
11 + <prop oor:name="URLTemplate">
12 + <value>webdav</value>
14 + <prop oor:name="Arguments">
18 + <node oor:name="Provider15" oor:op="replace">
19 + <prop oor:name="ServiceName">
20 + <value>com.sun.star.ucb.WebDAVContentProvider</value>
22 + <prop oor:name="URLTemplate">
23 + <value>webdavs</value>
25 + <prop oor:name="Arguments">
29 <!-- We want the Provider to be the final fallback provider -->
30 <node oor:name="Provider999" oor:op="replace" install:module="gio">
31 <prop oor:name="ServiceName">
32 --- tools/inc/tools/urlobj.hxx
33 +++ tools/inc/tools/urlobj.hxx
34 @@ -141,9 +141,14 @@ enum INetProtocol
35 INET_PROT_TELNET = 28,
36 INET_PROT_VND_SUN_STAR_EXPAND = 29,
37 INET_PROT_VND_SUN_STAR_TDOC = 30,
38 - INET_PROT_GENERIC = 31,
43 + INET_PROT_DAVS = 33,
44 + INET_PROT_WEBDAV = 34,
45 + INET_PROT_WEBDAVS = 35,
46 + INET_PROT_GENERIC = 36,
47 + INET_PROT_GENERIC_HIERARCHICAL = 37,
51 //============================================================================
52 --- tools/source/fsys/urlobj.cxx
53 +++ tools/source/fsys/urlobj.cxx
54 @@ -374,21 +374,21 @@ static INetURLObject::SchemeInfo const a
56 { "ftp", "ftp://", 21, true, true, false, true, true, true, true,
58 - { "http", "http://", 80, true, false, false, false, true, true,
59 + { "http", "http://", 80, true, true, false, true, true, true,
61 { "file", "file://", 0, true, false, false, false, true, false,
63 { "mailto", "mailto:", 0, false, false, false, false, false,
65 - { "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, false,
66 - false, false, true, true, true, true },
67 + { "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, true,
68 + false, true, true, true, true, true },
69 { "news", "news:", 0, false, false, false, false, false, false, false,
71 { "private", "private:", 0, false, false, false, false, false,
73 { "vnd.sun.star.help", "vnd.sun.star.help://", 0, true, false, false,
74 false, false, false, true, true },
75 - { "https", "https://", 443, true, false, false, false, true, true,
76 + { "https", "https://", 443, true, true, false, true, true, true,
78 { "slot", "slot:", 0, false, false, false, false, false, false,
80 @@ -432,9 +432,19 @@ static INetURLObject::SchemeInfo const a
81 false, false, false, false, false },
82 { "vnd.sun.star.tdoc", "vnd.sun.star.tdoc:", 0, false, false, false,
83 false, false, false, true, false },
84 - { "", "", 0, false, false, false, false, false, false, false, false },
85 { "smb", "smb://", 139, true, true, false, true, true, true, true,
88 + { "dav", "dav://", 80, true, true, false, true, true, true, true,
90 + { "davs", "davs://", 443, true, true, false, true, true, true,
92 + { "webdav", "webdav://", 80, true, true, false, true, true, true, true,
94 + { "webdavs", "webdavs://", 443, true, true, false, true, true, true,
96 + { "", "", 0, false, false, false, false, false, false, false, false },
97 + { "", "", 0, false, false, false, false, false, false, true, false }
101 inline INetURLObject::SchemeInfo const &
102 @@ -849,7 +859,10 @@ bool INetURLObject::setAbsURIRef(rtl::OU
103 aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter);
104 if (aSynScheme.getLength() > 0)
106 - m_eScheme = INET_PROT_GENERIC;
107 + if (p1 != pEnd && *p1 == '/')
108 + m_eScheme = INET_PROT_GENERIC_HIERARCHICAL;
110 + m_eScheme = INET_PROT_GENERIC;
114 @@ -866,8 +879,9 @@ bool INetURLObject::setAbsURIRef(rtl::OU
118 - if (m_eScheme != INET_PROT_GENERIC) {
119 - aSynScheme = rtl::OUString::createFromAscii(getSchemeInfo().m_pScheme);
120 + const char *pSchemeName = getSchemeInfo().m_pScheme;
121 + if (pSchemeName[0] != '\0') {
122 + aSynScheme = rtl::OUString::createFromAscii(pSchemeName);
124 m_aScheme.set(aSynAbsURIRef, aSynScheme, aSynAbsURIRef.getLength());
125 aSynAbsURIRef.append(sal_Unicode(':'));
126 @@ -2120,6 +2134,8 @@ INetURLObject::getPrefix(sal_Unicode con
127 PrefixInfo::INTERNAL },
128 { "cid:", 0, INET_PROT_CID, PrefixInfo::OFFICIAL },
129 { "data:", 0, INET_PROT_DATA, PrefixInfo::OFFICIAL },
130 + { "dav:", 0, INET_PROT_DAV, PrefixInfo::OFFICIAL },
131 + { "davs:", 0, INET_PROT_DAVS, PrefixInfo::OFFICIAL },
132 { "db:", "staroffice.db:", INET_PROT_DB, PrefixInfo::INTERNAL },
133 { "file:", 0, INET_PROT_FILE, PrefixInfo::OFFICIAL },
134 { "ftp:", 0, INET_PROT_FTP, PrefixInfo::OFFICIAL },
135 @@ -2201,6 +2217,8 @@ INetURLObject::getPrefix(sal_Unicode con
136 PrefixInfo::OFFICIAL },
137 { "vnd.sun.star.wfs:", 0, INET_PROT_VND_SUN_STAR_WFS,
138 PrefixInfo::OFFICIAL },
139 + { "webdav:", 0, INET_PROT_WEBDAV, PrefixInfo::OFFICIAL },
140 + { "webdavs:", 0, INET_PROT_WEBDAVS, PrefixInfo::OFFICIAL },
141 { "wfs:", "vnd.sun.star.wfs:", INET_PROT_VND_SUN_STAR_WFS,
142 PrefixInfo::ALIAS } };
143 PrefixInfo const * pFirst = aMap + 1;
144 @@ -3004,6 +3022,10 @@ bool INetURLObject::parsePath(INetProtoc
145 case INET_PROT_VND_SUN_STAR_WEBDAV:
146 case INET_PROT_HTTPS:
148 + case INET_PROT_DAV:
149 + case INET_PROT_DAVS:
150 + case INET_PROT_WEBDAV:
151 + case INET_PROT_WEBDAVS:
152 if (pPos < pEnd && *pPos != '/')
154 while (pPos < pEnd && *pPos != nQueryDelimiter
155 @@ -3422,6 +3444,7 @@ bool INetURLObject::parsePath(INetProtoc
158 case INET_PROT_GENERIC:
159 + case INET_PROT_GENERIC_HIERARCHICAL:
160 while (pPos < pEnd && *pPos != nFragmentDelimiter)
162 EscapeType eEscapeType;
163 @@ -4133,10 +4156,13 @@ bool INetURLObject::ConcatData(INetProto
166 m_eScheme = eTheScheme;
167 - if (HasError() || m_eScheme == INET_PROT_GENERIC)
168 + const char *pSchemeName = getSchemeInfo().m_pScheme;
170 + if (HasError() || pSchemeName[0] == '\0')
173 m_aAbsURIRef.setLength(0);
174 - m_aAbsURIRef.appendAscii(getSchemeInfo().m_pScheme);
175 + m_aAbsURIRef.appendAscii(pSchemeName);
176 m_aAbsURIRef.append(sal_Unicode(':'));
177 if (getSchemeInfo().m_bAuthority)
179 --- tools/workben/urltest.cxx
180 +++ tools/workben/urltest.cxx
181 @@ -1476,7 +1476,7 @@ main()
183 url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("A-b.3:/%2f?x#y"));
184 urlobj = INetURLObject(url);
185 - bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
186 + bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
187 bSuccess &= assertEqual(
188 url, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a-b.3:/%2F?x#y")),
189 rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
190 @@ -1504,7 +1504,7 @@ main()
192 url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("foo:/"));
193 urlobj = INetURLObject(url);
194 - bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
195 + bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
196 bSuccess &= assertEqual(
198 rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
199 @@ -1542,7 +1542,7 @@ main()
201 url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("A-b.3:/%2f?x#y"));
202 urlobj = INetURLObject(url, INET_PROT_CID);
203 - bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
204 + bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
205 bSuccess &= assertEqual(
206 url, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a-b.3:/%2F?x#y")),
207 rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
208 @@ -1563,7 +1563,7 @@ main()
210 url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("foo:/"));
211 urlobj = INetURLObject(url, INET_PROT_CID);
212 - bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
213 + bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
214 bSuccess &= assertEqual(
216 rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
217 --- ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
218 +++ ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
220 #include <rtl/ref.hxx>
221 #include "DAVAuthListener.hxx"
223 +#include <com/sun/star/ucb/XCommandEnvironment.hpp>
227 typedef std::pair< rtl::OUString, rtl::OUString > DAVRequestHeader;
228 @@ -46,12 +50,12 @@ struct DAVRequestEnvironment
229 // rtl::Reference< DAVStatusListener > m_xStatusListener;
230 // rtl::Reference< DAVProgressListener > m_xStatusListener;
231 DAVRequestHeaders m_aRequestHeaders;
232 - uno::Reference< ucb::XCommandEnvironment > m_xEnv;
233 + com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > m_xEnv;
235 -DAVRequestEnvironment( const rtl::OUString & rRequestURI,
236 + DAVRequestEnvironment( const rtl::OUString & rRequestURI,
237 const rtl::Reference< DAVAuthListener > & xListener,
238 const DAVRequestHeaders & rRequestHeaders,
239 - const uno::Reference< ucb::XCommandEnvironment > & xEnv)
240 + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv)
241 : m_aRequestURI( rRequestURI ),
242 m_xAuthListener( xListener ),
243 m_aRequestHeaders( rRequestHeaders ),
244 --- ucb/source/ucp/webdav/DAVResourceAccess.cxx
245 +++ ucb/source/ucp/webdav/DAVResourceAccess.cxx
247 #include "DAVAuthListenerImpl.hxx"
248 #include "DAVResourceAccess.hxx"
250 +#include <comphelper/processfactory.hxx>
251 +#include <ucbhelper/commandenvironment.hxx>
253 using namespace webdav_ucp;
254 using namespace com::sun::star;
256 @@ -61,11 +64,18 @@ int DAVAuthListener_Impl::authenticate(
257 sal_Bool bAllowPersistentStoring,
258 sal_Bool bCanUseSystemCredentials )
260 + uno::Reference< task::XInteractionHandler > xIH;
264 - uno::Reference< task::XInteractionHandler > xIH
265 - = m_xEnv->getInteractionHandler();
266 + xIH = m_xEnv->getInteractionHandler();
270 + xIH = DAVResourceAccess::createCommandEnvironment()->getInteractionHandler();
276 // #102871# - Supply username and password from previous try.
277 // Password container service depends on this!
278 @@ -444,15 +446,16 @@ void DAVResourceAccess::GET(
281 //=========================================================================
282 -uno::Reference< io::XInputStream > DAVResourceAccess::GET(
283 +uno::Reference< io::XStream > DAVResourceAccess::GET(
284 const std::vector< rtl::OUString > & rHeaderNames,
285 DAVResource & rResource,
286 - const uno::Reference< ucb::XCommandEnvironment > & xEnv )
287 + const uno::Reference< ucb::XCommandEnvironment > & xEnv,
288 + sal_Bool bAllowEmpty )
289 throw( DAVException )
293 - uno::Reference< io::XInputStream > xStream;
294 + uno::Reference< io::XStream > xStream;
298 @@ -472,7 +475,8 @@ uno::Reference< io::XInputStream > DAVRe
299 DAVRequestEnvironment(
301 new DAVAuthListener_Impl( xEnv, m_aURL ),
302 - aHeaders, xEnv ) );
306 catch ( DAVException & e )
308 @@ -606,6 +610,45 @@ void DAVResourceAccess::PUT(
311 //=========================================================================
312 +void DAVResourceAccess::PUT(
313 + const char * buffer, size_t size,
314 + const uno::Reference< ucb::XCommandEnvironment > & xEnv )
315 +throw( DAVException )
319 + bool bRetry = false;
320 + int errorCount = 0;
326 + DAVRequestHeaders aHeaders;
327 + getUserRequestHeaders( xEnv,
329 + rtl::OUString::createFromAscii( "PUT" ),
332 + m_xSession->PUT( getRequestURI(),
334 + DAVRequestEnvironment(
336 + new DAVAuthListener_Impl( xEnv, m_aURL ),
337 + aHeaders, xEnv ) );
339 + catch ( DAVException & e )
342 + bRetry = handleException( e, errorCount );
350 +//=========================================================================
351 uno::Reference< io::XInputStream > DAVResourceAccess::POST(
352 const rtl::OUString & rContentType,
353 const rtl::OUString & rReferer,
354 @@ -888,22 +931,44 @@ void DAVResourceAccess::DESTROY(
356 //=========================================================================
357 void DAVResourceAccess::LOCK (
358 - const ucb::Lock & /*rLock*/,
359 - const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
361 + const uno::Reference< ucb::XCommandEnvironment > & xEnv )
362 throw( DAVException )
365 - OSL_ENSURE( sal_False, "DAVResourceAccess::LOCK - NYI" );
368 + DAVRequestHeaders aHeaders;
369 + getUserRequestHeaders( xEnv,
371 + rtl::OUString::createFromAscii( "LOCK" ),
374 + m_xSession->LOCK( rLock,
375 + DAVRequestEnvironment(
377 + new DAVAuthListener_Impl( xEnv, m_aURL ),
378 + aHeaders, xEnv ) );
381 //=========================================================================
382 void DAVResourceAccess::UNLOCK (
383 - const ucb::Lock & /*rLock*/,
384 - const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
386 + const uno::Reference< ucb::XCommandEnvironment > & xEnv )
387 throw( DAVException )
390 - OSL_ENSURE( sal_False, "DAVResourceAccess::UNLOCK - NYI" );
393 + DAVRequestHeaders aHeaders;
394 + getUserRequestHeaders( xEnv,
396 + rtl::OUString::createFromAscii( "UNLOCK" ),
399 + m_xSession->UNLOCK( rLock,
400 + DAVRequestEnvironment(
402 + new DAVAuthListener_Impl( xEnv, m_aURL ),
403 + aHeaders, xEnv ) );
406 //=========================================================================
407 @@ -1008,6 +1073,18 @@ void DAVResourceAccess::getUserRequestHe
412 +com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > DAVResourceAccess::createCommandEnvironment( void )
414 + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
415 + uno::Reference< task::XInteractionHandler > xInteractionHandler = uno::Reference< task::XInteractionHandler > (
416 + xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), uno::UNO_QUERY );
417 + ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, uno::Reference< ucb::XProgressHandler >() );
419 + return uno::Reference< ucb::XCommandEnvironment >( static_cast< ucb::XCommandEnvironment* >( pCommandEnv ), uno::UNO_QUERY );
423 //=========================================================================
424 sal_Bool DAVResourceAccess::detectRedirectCycle(
425 const rtl::OUString& rRedirectURL )
426 --- ucb/source/ucp/webdav/DAVResourceAccess.hxx
427 +++ ucb/source/ucp/webdav/DAVResourceAccess.hxx
428 @@ -134,11 +134,12 @@ public:
429 com::sun::star::ucb::XCommandEnvironment > & xEnv )
430 throw( DAVException );
432 - com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
433 + com::sun::star::uno::Reference< com::sun::star::io::XStream >
434 GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
435 DAVResource & rResource,
436 const com::sun::star::uno::Reference<
437 - com::sun::star::ucb::XCommandEnvironment > & xEnv )
438 + com::sun::star::ucb::XCommandEnvironment > & xEnv,
439 + sal_Bool bAllowEmpty = sal_False )
440 throw( DAVException );
443 @@ -157,6 +158,11 @@ public:
444 com::sun::star::ucb::XCommandEnvironment > & xEnv )
445 throw( DAVException );
448 + PUT( const char * buffer, size_t size,
449 + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv )
450 + throw( DAVException );
452 com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
453 POST( const rtl::OUString & rContentType,
454 const rtl::OUString & rReferer,
455 @@ -204,13 +210,13 @@ public:
456 throw( DAVException );
459 - LOCK( const com::sun::star::ucb::Lock & rLock,
460 + LOCK( com::sun::star::ucb::Lock & rLock,
461 const com::sun::star::uno::Reference<
462 com::sun::star::ucb::XCommandEnvironment > & xEnv )
463 throw( DAVException );
466 - UNLOCK( const com::sun::star::ucb::Lock & rLock,
467 + UNLOCK( com::sun::star::ucb::Lock & rLock,
468 const com::sun::star::uno::Reference<
469 com::sun::star::ucb::XCommandEnvironment > & xEnv )
470 throw( DAVException );
471 @@ -223,6 +229,8 @@ public:
472 const rtl::OUString & rMethod,
473 DAVRequestHeaders & rRequestHeaders );
475 + static com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > createCommandEnvironment( void );
478 const rtl::OUString & getRequestURI() const;
479 sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL )
480 --- ucb/source/ucp/webdav/DAVSession.hxx
481 +++ ucb/source/ucp/webdav/DAVSession.hxx
485 #include <rtl/ustring.hxx>
486 +#include <com/sun/star/io/XStream.hpp>
487 #include <com/sun/star/io/XInputStream.hpp>
488 #include <com/sun/star/io/XOutputStream.hpp>
489 +#include <com/sun/star/ucb/Lock.hpp>
491 #include "DAVException.hxx"
492 #include "DAVProperties.hxx"
493 #include "DAVResource.hxx"
495 #include "DAVTypes.hxx"
496 #include "DAVRequestEnvironment.hxx"
503 @@ -114,11 +115,12 @@ public:
504 const DAVRequestEnvironment & rEnv )
505 throw( DAVException ) = 0;
507 - virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
508 + virtual com::sun::star::uno::Reference< com::sun::star::io::XStream >
509 GET( const ::rtl::OUString & inPath,
510 const std::vector< ::rtl::OUString > & inHeaderNames,
511 DAVResource & ioResource,
512 - const DAVRequestEnvironment & rEnv )
513 + const DAVRequestEnvironment & rEnv,
514 + sal_Bool bAllowEmpty )
515 throw( DAVException ) = 0;
517 virtual void GET( const ::rtl::OUString & inPath,
518 @@ -134,6 +136,12 @@ public:
520 throw( DAVException ) = 0;
522 + virtual void PUT( const ::rtl::OUString & inPath,
523 + const char * buffer,
525 + const DAVRequestEnvironment & rEnv )
526 + throw ( DAVException ) = 0;
528 virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
529 POST( const rtl::OUString & inPath,
530 const rtl::OUString & rContentType,
531 @@ -173,16 +181,14 @@ public:
532 const DAVRequestEnvironment & rEnv )
533 throw( DAVException ) = 0;
535 - // Note: Uncomment the following if locking support is required
537 - virtual void LOCK ( const Lock & inLock,
538 + virtual void LOCK ( com::sun::star::ucb::Lock & rLock,
539 const DAVRequestEnvironment & rEnv )
540 throw( DAVException ) = 0;
542 - virtual void UNLOCK ( const Lock & inLock,
543 + virtual void UNLOCK ( com::sun::star::ucb::Lock & rLock,
544 const DAVRequestEnvironment & rEnv )
545 throw( DAVException ) = 0;
549 rtl::Reference< DAVSessionFactory > m_xFactory;
551 --- ucb/source/ucp/webdav/NeonInputStream.cxx
552 +++ ucb/source/ucp/webdav/NeonInputStream.cxx
554 // MARKER(update_precomp.py): autogen include statement, do not remove
555 #include "precompiled_ucb.hxx"
556 #include "NeonInputStream.hxx"
557 +#include "DAVResourceAccess.hxx"
559 #include <rtl/memory.h>
560 +#include <com/sun/star/ucb/CommandFailedException.hpp>
562 +#include <comphelper/processfactory.hxx>
563 +#include <com/sun/star/lang/XMultiServiceFactory.hpp>
567 using namespace cppu;
568 -using namespace rtl;
569 using namespace com::sun::star::io;
570 -using namespace com::sun::star::uno;
571 +using namespace com::sun::star;
572 using namespace webdav_ucp;
575 // -------------------------------------------------------------------
577 // -------------------------------------------------------------------
578 -NeonInputStream::NeonInputStream( void )
581 +NeonInputStream::NeonInputStream()
584 + m_bDirty( sal_False )
588 @@ -62,24 +69,59 @@ NeonInputStream::~NeonInputStream( void
589 // -------------------------------------------------------------------
590 void NeonInputStream::AddToStream( const char * inBuf, sal_Int32 inLen )
592 - mInputBuffer.realloc( sal::static_int_cast<sal_Int32>(mLen) + inLen );
593 - rtl_copyMemory( mInputBuffer.getArray() + mLen, inBuf, inLen );
595 + OSL_ENSURE( !m_bDirty, "Cannot AddToStream() when it was already written to it." );
597 + m_aInputBuffer.realloc( sal::static_int_cast<sal_Int32>(m_nLen) + inLen );
598 + rtl_copyMemory( m_aInputBuffer.getArray() + m_nLen, inBuf, inLen );
602 +// -------------------------------------------------------------------
603 +// Associate a URL with this stream
604 +// -------------------------------------------------------------------
605 +void NeonInputStream::SetURL( const rtl::OUString &rURL )
607 + osl::MutexGuard aGuard( m_aLock );
612 // -------------------------------------------------------------------
614 // -------------------------------------------------------------------
615 -Any NeonInputStream::queryInterface( const Type &type )
616 - throw( RuntimeException )
617 +uno::Any NeonInputStream::queryInterface( const uno::Type &type )
618 + throw( uno::RuntimeException )
620 - Any aRet = ::cppu::queryInterface( type,
621 - static_cast< XInputStream * >( this ),
622 - static_cast< XSeekable * >( this ) );
623 + uno::Any aRet = ::cppu::queryInterface( type,
624 + static_cast< XStream * >( this ),
625 + static_cast< XInputStream * >( this ),
626 + static_cast< XOutputStream * >( this ),
627 + static_cast< XSeekable * >( this ),
628 + static_cast< XTruncate * >( this ) );
629 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type );
632 // -------------------------------------------------------------------
634 +// -------------------------------------------------------------------
635 +com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL
636 +NeonInputStream::getInputStream( void )
637 + throw( com::sun::star::uno::RuntimeException )
639 + return uno::Reference< XInputStream >( this );
642 +// -------------------------------------------------------------------
644 +// -------------------------------------------------------------------
645 +com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL
646 +NeonInputStream::getOutputStream( void )
647 + throw( com::sun::star::uno::RuntimeException )
649 + return uno::Reference< XOutputStream >( this );
652 +// -------------------------------------------------------------------
654 // "Reads" the specified number of bytes from the stream
655 // -------------------------------------------------------------------
656 @@ -92,7 +134,7 @@ sal_Int32 SAL_CALL NeonInputStream::read
658 // Work out how much we're actually going to write
659 sal_Int32 theBytes2Read = nBytesToRead;
660 - sal_Int32 theBytesLeft = sal::static_int_cast<sal_Int32>(mLen - mPos);
661 + sal_Int32 theBytesLeft = sal::static_int_cast<sal_Int32>(m_nLen - m_nPos);
662 if ( theBytes2Read > theBytesLeft )
663 theBytes2Read = theBytesLeft;
665 @@ -101,10 +143,10 @@ sal_Int32 SAL_CALL NeonInputStream::read
669 - aData.getArray(), mInputBuffer.getConstArray() + mPos, theBytes2Read );
670 + aData.getArray(), m_aInputBuffer.getConstArray() + m_nPos, theBytes2Read );
672 // Update our stream position for next time
673 - mPos += theBytes2Read;
674 + m_nPos += theBytes2Read;
676 return theBytes2Read;
678 @@ -133,9 +175,9 @@ void SAL_CALL NeonInputStream::skipBytes
679 ::com::sun::star::io::IOException,
680 ::com::sun::star::uno::RuntimeException )
682 - mPos += nBytesToSkip;
683 - if ( mPos >= mLen )
685 + m_nPos += nBytesToSkip;
686 + if ( m_nPos >= m_nLen )
690 // -------------------------------------------------------------------
691 @@ -147,7 +189,7 @@ sal_Int32 SAL_CALL NeonInputStream::avai
692 ::com::sun::star::io::IOException,
693 ::com::sun::star::uno::RuntimeException )
695 - return sal::static_int_cast<sal_Int32>(mLen - mPos);
696 + return sal::static_int_cast<sal_Int32>(m_nLen - m_nPos);
699 // -------------------------------------------------------------------
700 @@ -168,12 +210,12 @@ void SAL_CALL NeonInputStream::seek( sal
701 ::com::sun::star::io::IOException,
702 ::com::sun::star::uno::RuntimeException )
704 - if ( location < 0 )
705 - throw ::com::sun::star::lang::IllegalArgumentException();
706 + if ( location < 0 )
707 + throw ::com::sun::star::lang::IllegalArgumentException();
709 - if ( location <= mLen )
712 + if ( location <= m_nLen )
715 throw ::com::sun::star::lang::IllegalArgumentException();
718 @@ -184,7 +226,7 @@ sal_Int64 SAL_CALL NeonInputStream::getP
719 throw( ::com::sun::star::io::IOException,
720 ::com::sun::star::uno::RuntimeException )
726 // -------------------------------------------------------------------
727 @@ -194,5 +236,108 @@ sal_Int64 SAL_CALL NeonInputStream::getL
728 throw( ::com::sun::star::io::IOException,
729 ::com::sun::star::uno::RuntimeException )
735 +// -------------------------------------------------------------------
737 +// -------------------------------------------------------------------
738 +void SAL_CALL NeonInputStream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
739 + throw( com::sun::star::io::NotConnectedException,
740 + com::sun::star::io::BufferSizeExceededException,
741 + com::sun::star::io::IOException,
742 + com::sun::star::uno::RuntimeException)
744 +#if OSL_DEBUG_LEVEL > 0
745 + fprintf( stderr, "WebDAV: writeBytes()\n" );
748 + sal_Int32 nDataLen = aData.getLength();
749 + OSL_ASSERT( nDataLen >= 0 );
752 + if ( nDataLen == 0 )
755 + // Update the length of the stream & size of the buffer
756 + if ( m_nLen < m_nPos + nDataLen )
758 + m_nLen = m_nPos + nDataLen;
759 + if ( m_aInputBuffer.getLength() < m_nLen )
760 + m_aInputBuffer.realloc( sal::static_int_cast<sal_Int32>( m_nLen ) );
763 + rtl_copyMemory( m_aInputBuffer.getArray() + m_nPos, aData.getConstArray(), nDataLen );
764 + m_nPos += nDataLen;
766 + m_bDirty = sal_True;
769 +// -------------------------------------------------------------------
771 +// -------------------------------------------------------------------
772 +void SAL_CALL NeonInputStream::flush( void )
773 + throw( NotConnectedException, BufferSizeExceededException,
774 + IOException, uno::RuntimeException )
778 +#if OSL_DEBUG_LEVEL > 0
779 + fprintf( stderr, "WebDAV: flush(), saving the changed file.\n" );
781 + // FIXME It's really hacky to create the new session
782 + // But so far it seems I have no other chance...
783 + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
784 + rtl::Reference< DAVSessionFactory > rDAVFactory( new DAVSessionFactory() );
786 + DAVResourceAccess aResourceAccess( xFactory, rDAVFactory, m_aURL );
789 + aResourceAccess.PUT( reinterpret_cast<const char*>( m_aInputBuffer.getConstArray() ), m_nLen,
790 + DAVResourceAccess::createCommandEnvironment() );
792 + catch ( DAVException & e )
794 + throw ucb::CommandFailedException(
796 + uno::Reference< uno::XInterface >(),
797 + uno::makeAny( e.getData() ) );
800 + m_bDirty = sal_False;
804 +// -------------------------------------------------------------------
806 +// -------------------------------------------------------------------
807 +void SAL_CALL NeonInputStream::closeOutput( void )
808 + throw( com::sun::star::io::NotConnectedException,
809 + com::sun::star::io::IOException,
810 + com::sun::star::uno::RuntimeException )
814 +#if OSL_DEBUG_LEVEL > 0
815 + fprintf( stderr, "WebDAV: TODO write on closeOutput(), the stream is dirty!\n" );
820 +// -------------------------------------------------------------------
822 +// -------------------------------------------------------------------
823 +void SAL_CALL NeonInputStream::truncate( void )
824 + throw( com::sun::star::io::IOException,
825 + com::sun::star::uno::RuntimeException )
827 +#if OSL_DEBUG_LEVEL > 0
828 + fprintf( stderr, "WebDAV: truncate()\n" );
833 + m_nLen = m_nPos = 0;
834 + m_bDirty = sal_True;
837 --- ucb/source/ucp/webdav/NeonInputStream.hxx
838 +++ ucb/source/ucp/webdav/NeonInputStream.hxx
840 #define _NEONINPUTSTREAM_HXX_
842 #include <sal/types.h>
843 +#include <osl/mutex.hxx>
844 +#include <osl/signal.h>
845 #include <rtl/ustring.hxx>
846 #include <cppuhelper/weak.hxx>
848 +#include <com/sun/star/io/XStream.hpp>
849 #include <com/sun/star/io/XInputStream.hpp>
850 +#include <com/sun/star/io/XOutputStream.hpp>
851 #include <com/sun/star/io/XSeekable.hpp>
852 +#include <com/sun/star/io/XTruncate.hpp>
853 +#include <com/sun/star/ucb/Lock.hpp>
855 +#include "DAVRequestEnvironment.hxx"
859 @@ -45,21 +53,33 @@ namespace webdav_ucp
860 // A simple XInputStream implementation provided specifically for use
861 // by the DAVSession::GET method.
862 // -------------------------------------------------------------------
863 -class NeonInputStream : public ::com::sun::star::io::XInputStream,
864 +class NeonInputStream : public ::com::sun::star::io::XStream,
865 + public ::com::sun::star::io::XInputStream,
866 + public ::com::sun::star::io::XOutputStream,
867 public ::com::sun::star::io::XSeekable,
868 + public ::com::sun::star::io::XTruncate,
869 public ::cppu::OWeakObject
872 - com::sun::star::uno::Sequence< sal_Int8 > mInputBuffer;
877 - NeonInputStream( void );
878 - virtual ~NeonInputStream();
880 + com::sun::star::uno::Sequence< sal_Int8 > m_aInputBuffer;
881 + sal_Int64 m_nLen; // cannot be just m_aInputBuffer.getLength() - the buffer can be bigger
886 + rtl::OUString m_aURL;
888 + osl::Mutex m_aLock;
890 - // Add some data to the end of the stream
891 - void AddToStream( const char * inBuf, sal_Int32 inLen );
893 + NeonInputStream( void );
894 + virtual ~NeonInputStream();
896 + // Add some data to the end of the stream
897 + void AddToStream( const char * inBuf, sal_Int32 inLen );
899 + // Associate a URL with this stream
900 + void SetURL( const rtl::OUString &rURL );
903 virtual com::sun::star::uno::Any SAL_CALL queryInterface(
904 @@ -74,6 +94,12 @@ class NeonInputStream : public ::com::su
906 { OWeakObject::release(); }
909 + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL getInputStream( void )
910 + throw( com::sun::star::uno::RuntimeException );
912 + virtual com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL getOutputStream( void )
913 + throw( com::sun::star::uno::RuntimeException );
916 virtual sal_Int32 SAL_CALL readBytes(
917 @@ -121,6 +147,30 @@ class NeonInputStream : public ::com::su
918 virtual sal_Int64 SAL_CALL getLength()
919 throw( ::com::sun::star::io::IOException,
920 ::com::sun::star::uno::RuntimeException );
923 + virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
924 + throw( com::sun::star::io::NotConnectedException,
925 + com::sun::star::io::BufferSizeExceededException,
926 + com::sun::star::io::IOException,
927 + com::sun::star::uno::RuntimeException);
929 + virtual void SAL_CALL flush( void )
930 + throw( com::sun::star::io::NotConnectedException,
931 + com::sun::star::io::BufferSizeExceededException,
932 + com::sun::star::io::IOException,
933 + com::sun::star::uno::RuntimeException);
936 + virtual void SAL_CALL closeOutput( void )
937 + throw( com::sun::star::io::NotConnectedException,
938 + com::sun::star::io::IOException,
939 + com::sun::star::uno::RuntimeException );
942 + virtual void SAL_CALL truncate( void )
943 + throw( com::sun::star::io::IOException,
944 + com::sun::star::uno::RuntimeException );
947 } // namespace webdav_ucp
948 --- ucb/source/ucp/webdav/NeonSession.cxx
949 +++ ucb/source/ucp/webdav/NeonSession.cxx
951 #ifndef _SIMPLECERTIFICATIONVALIDATIONREQUEST_HXX_
952 #include "ucbhelper/simplecertificatevalidationrequest.hxx"
954 +#include <ucbhelper/cancelcommandexecution.hxx>
956 #include <cppuhelper/bootstrap.hxx>
958 @@ -153,6 +154,12 @@ static sal_uInt16 makeStatusCode( const
959 return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() );
962 +static sal_uInt16 getStatusCode( HttpSession *pSession )
964 + rtl::OUString aText = rtl::OUString::createFromAscii( ne_get_error( pSession ) );
965 + return makeStatusCode( aText );
968 // -------------------------------------------------------------------
969 struct NeonRequestContext
971 @@ -196,12 +203,13 @@ struct NeonRequestContext
972 // -------------------------------------------------------------------
974 #if NEON_VERSION >= 0x0250
975 -extern "C" int NeonSession_ResponseBlockReader(void * inUserData,
978 -extern "C" void NeonSession_ResponseBlockReader(void * inUserData,
981 - const char * inBuf,
983 +NeonSession_ResponseBlockReader( void * inUserData,
984 + const char * inBuf,
987 // neon calls this function with (inLen == 0)...
989 @@ -226,12 +234,13 @@ extern "C" void NeonSession_ResponseBloc
990 // -------------------------------------------------------------------
992 #if NEON_VERSION >= 0x0250
993 -extern "C" int NeonSession_ResponseBlockWriter( void * inUserData,
996 -extern "C" void NeonSession_ResponseBlockWriter( void * inUserData,
999 - const char * inBuf,
1001 +NeonSession_ResponseBlockWriter( void * inUserData,
1002 + const char * inBuf,
1005 // neon calls this function with (inLen == 0)...
1007 @@ -299,11 +308,10 @@ extern "C" int NeonSession_NeonAuth( voi
1011 - NeonUri uri( theSession->getRequestEnvironment().m_aRequestURI );
1012 - rtl::OUString aUserInfo( uri.GetUserInfo() );
1013 + rtl::OUString aUserInfo( theSession->getUserInfo() );
1014 if ( aUserInfo.getLength() )
1016 - sal_Int32 nPos = aUserInfo.indexOf( '@' );
1017 + sal_Int32 nPos = aUserInfo.indexOf( ':' );
1020 theUserName = aUserInfo;
1021 @@ -564,6 +572,8 @@ extern "C" void NeonSession_PreSendReque
1025 +NeonLockStore * NeonSession::s_aNeonLockStore = NULL;
1027 // -------------------------------------------------------------------
1029 // -------------------------------------------------------------------
1030 @@ -581,6 +591,7 @@ NeonSession::NeonSession(
1031 m_aScheme = theUri.GetScheme();
1032 m_aHostName = theUri.GetHost();
1033 m_nPort = theUri.GetPort();
1034 + m_aUserInfo = theUri.GetUserInfo();
1038 @@ -594,14 +605,6 @@ NeonSession::~NeonSession( )
1040 ne_session_destroy( m_pHttpSession );
1042 - // Note: Uncomment the following if locking support is required
1044 - if ( mNeonLockSession != NULL )
1046 - ne_lock_unregister( mNeonLockSession );
1047 - mNeonLockSession = NULL;
1052 delete static_cast<RequestDataMap*>(m_pRequestData);
1053 @@ -629,6 +632,9 @@ void NeonSession::Init()
1054 throw DAVException( DAVException::DAV_SESSION_CREATE,
1055 NeonUri::makeConnectionEndPointString(
1056 m_aHostName, m_nPort ) );
1057 +#if OSL_DEBUG_LEVEL > 0
1058 + ne_debug_init( stderr, NE_DBG_LOCKS );
1060 // #122205# - libxml2 needs to be initialized once if used by
1061 // multithreaded programs like OOo.
1063 @@ -746,14 +752,15 @@ void NeonSession::Init()
1067 - // Note: Uncomment the following if locking support is required
1069 - mNeonLockSession = ne_lock_register( m_pHttpSession );
1070 + if ( !s_aNeonLockStore )
1071 + s_aNeonLockStore = ne_lockstore_create();
1073 - if ( mNeonLockSession == NULL )
1074 + if ( s_aNeonLockStore == NULL )
1075 throw DAVException( DAVException::DAV_SESSION_CREATE,
1076 - theUri::makeConnectionEndPointString() );
1078 + NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) );
1080 + // Register the lock store
1081 + ne_lockstore_register( s_aNeonLockStore, m_pHttpSession );
1083 // Register for redirects.
1084 ne_redirect_register( m_pHttpSession );
1085 @@ -1088,11 +1095,12 @@ void NeonSession::GET( const rtl::OUStri
1086 // -------------------------------------------------------------------
1088 // -------------------------------------------------------------------
1089 -uno::Reference< io::XInputStream >
1090 +uno::Reference< io::XStream >
1091 NeonSession::GET( const rtl::OUString & inPath,
1092 const std::vector< ::rtl::OUString > & inHeaderNames,
1093 DAVResource & ioResource,
1094 - const DAVRequestEnvironment & rEnv )
1095 + const DAVRequestEnvironment & rEnv,
1096 + sal_Bool bAllowEmpty )
1097 throw ( DAVException )
1099 osl::Guard< osl::Mutex > theGuard( m_aMutex );
1100 @@ -1104,16 +1112,23 @@ NeonSession::GET( const rtl::OUString &
1101 ioResource.uri = inPath;
1102 ioResource.properties.clear();
1104 - rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
1105 - NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
1106 + rtl::Reference< NeonInputStream > xStream( new NeonInputStream );
1107 + NeonRequestContext aCtx( xStream, inHeaderNames, ioResource );
1108 int theRetVal = GET( m_pHttpSession,
1109 rtl::OUStringToOString(
1110 inPath, RTL_TEXTENCODING_UTF8 ),
1111 NeonSession_ResponseBlockReader,
1114 - HandleError( theRetVal );
1115 - return uno::Reference< io::XInputStream >( xInputStream.get() );
1117 + HandleError( theRetVal );
1119 + catch ( DAVException const & e )
1121 + if ( !bAllowEmpty || ( e.getStatus() != SC_NOT_FOUND ) )
1124 + return uno::Reference< io::XStream >( xStream.get() );
1127 // -------------------------------------------------------------------
1128 @@ -1153,22 +1168,38 @@ void NeonSession::PUT( const rtl::OUStri
1129 const DAVRequestEnvironment & rEnv )
1130 throw ( DAVException )
1132 + // initialization etc. is performed in the other PUT
1134 + uno::Sequence< sal_Int8 > aDataToSend;
1135 + if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
1136 + throw DAVException( DAVException::DAV_INVALID_ARG );
1139 + reinterpret_cast< const char * >( aDataToSend.getConstArray() ),
1140 + aDataToSend.getLength(),
1144 +// -------------------------------------------------------------------
1146 +// -------------------------------------------------------------------
1147 +void NeonSession::PUT( const rtl::OUString &inPath,
1148 + const char * buffer,
1150 + const DAVRequestEnvironment & rEnv )
1151 + throw ( DAVException )
1153 osl::Guard< osl::Mutex > theGuard( m_aMutex );
1159 - uno::Sequence< sal_Int8 > aDataToSend;
1160 - if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
1161 - throw DAVException( DAVException::DAV_INVALID_ARG );
1163 int theRetVal = PUT( m_pHttpSession,
1164 rtl::OUStringToOString(
1165 inPath, RTL_TEXTENCODING_UTF8 ),
1166 - reinterpret_cast< const char * >(
1167 - aDataToSend.getConstArray() ),
1168 - aDataToSend.getLength() );
1172 HandleError( theRetVal );
1174 @@ -1344,9 +1375,7 @@ void NeonSession::DESTROY( const rtl::OU
1175 // -------------------------------------------------------------------
1177 // -------------------------------------------------------------------
1178 -// Note: Uncomment the following if locking support is required
1180 -void NeonSession::LOCK( const Lock & inLock,
1181 +void NeonSession::LOCK( ucb::Lock & rLock,
1182 const DAVRequestEnvironment & rEnv )
1183 throw ( DAVException )
1185 @@ -1356,16 +1385,13 @@ void NeonSession::LOCK( const Lock & inL
1189 - Lockit( inLock, true );
1190 + Lockit( rLock, true );
1194 // -------------------------------------------------------------------
1196 // -------------------------------------------------------------------
1197 -// Note: Uncomment the following if locking support is required
1199 -void NeonSession::UNLOCK( const Lock & inLock,
1200 +void NeonSession::UNLOCK( ucb::Lock & rLock,
1201 const DAVRequestEnvironment & rEnv )
1202 throw ( DAVException )
1204 @@ -1375,9 +1401,8 @@ void NeonSession::UNLOCK( const Lock & i
1208 - Lockit( inLock, false );
1209 + Lockit( rLock, false );
1213 // -------------------------------------------------------------------
1214 const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const
1215 @@ -1416,7 +1441,10 @@ void NeonSession::HandleError( int nErro
1216 case NE_ERROR: // Generic error
1218 rtl::OUString aText = rtl::OUString::createFromAscii(
1219 - ne_get_error( m_pHttpSession ) );
1220 + ne_get_error( m_pHttpSession ) );
1221 +#if OSL_DEBUG_LEVEL > 0
1222 + fprintf( stderr, "WebDAV: got error '%s'\n", rtl::OUStringToOString( aText, RTL_TEXTENCODING_UTF8 ).getStr() );
1224 throw DAVException( DAVException::DAV_HTTP_ERROR,
1226 makeStatusCode( aText ) );
1227 @@ -1473,77 +1501,156 @@ void NeonSession::HandleError( int nErro
1231 -// Note: Uncomment the following if locking support is required
1233 -void NeonSession::Lockit( const Lock & inLock, bool inLockit )
1234 +void NeonSession::Lockit( ucb::Lock & rLock, bool bLockit )
1235 throw ( DAVException )
1237 osl::Guard< osl::Mutex > theGuard( m_aMutex );
1239 - // Create the neon lock
1240 - NeonLock * theLock = new NeonLock;
1243 - // Set the lock uri
1244 - NeonUri theUri( inLock.uri );
1245 - theLock->uri = const_cast< char * >
1246 - ( rtl::OUStringToOString(
1247 - theUri.GetPath(), RTL_TEXTENCODING_UTF8 ).getStr() );
1248 + if ( !s_aNeonLockStore )
1249 + throw DAVException( DAVException::DAV_INVALID_ARG );
1253 - // Set the lock depth
1254 - switch( inLock.depth )
1258 - theLock->depth = int ( inLock.depth );
1261 - throw DAVException( DAVException::DAV_INVALID_ARG );
1265 + ne_uri_parse( rtl::OUStringToOString( m_aEnv.m_aRequestURI, RTL_TEXTENCODING_UTF8 ).getStr(),
1268 +#if NEON_VERSION < 0x0260
1269 +#define FILLIN( field, val ) aUri.field = aUri.field? aUri.field: strdup( rtl::OUStringToOString( val, RTL_TEXTENCODING_UTF8 ).getStr() )
1270 + FILLIN( scheme, m_aScheme );
1271 + FILLIN( host, m_aHostName );
1272 + aUri.port = aUri.port? aUri.port: m_nPort;
1276 - // Set the lock scope
1277 - switch ( inLock.scope )
1280 - theLock->scope = ne_lockscope_exclusive;
1283 - theLock->scope = ne_lockscope_shared;
1286 - throw DAVException( DAVException::DAV_INVALID_ARG );
1289 + // Create the neon lock
1290 + NeonLock * theLock = ne_lockstore_findbyuri( s_aNeonLockStore, &aUri );
1291 + bool bAlreadyExists = false;
1293 + bAlreadyExists = true;
1296 + theLock = ne_lock_create();
1298 - // Set the lock owner
1299 - const char * theOwner = rtl::OUStringToOString( inLock.owner,
1300 - RTL_TEXTENCODING_UTF8 );
1301 - theLock->owner = const_cast< char * > ( theOwner );
1303 - // Set the lock timeout
1304 - // Note: Neon ignores the timeout
1305 - //theLock->timeout = inLock.timeout;
1306 + // Set the lock uri
1307 + theLock->uri = aUri;
1309 - theRetVal = ne_lock( m_pHttpSession, theLock );
1313 + // Set the lock depth
1314 + switch( rLock.Depth )
1316 + case ucb::LockDepth_ZERO: theLock->depth = NE_DEPTH_ZERO; break;
1317 + case ucb::LockDepth_ONE: theLock->depth = NE_DEPTH_ONE; break;
1318 + case ucb::LockDepth_INFINITY: theLock->depth = NE_DEPTH_INFINITE; break;
1320 + throw DAVException( DAVException::DAV_INVALID_ARG );
1323 - // Set the lock token
1324 - rtl::OUString theToken = inLock.locktoken.getConstArray()[ 0 ];
1325 - theLock->token = const_cast< char * >
1326 - ( rtl::OUStringToOString(
1327 - theToken, RTL_TEXTENCODING_UTF8 ).getStr() );
1328 + // Set the lock scope
1329 + switch ( rLock.Scope )
1331 + case ucb::LockScope_EXCLUSIVE: theLock->scope = ne_lockscope_exclusive; break;
1332 + case ucb::LockScope_SHARED: theLock->scope = ne_lockscope_shared; break;
1334 + throw DAVException( DAVException::DAV_INVALID_ARG );
1338 - theRetVal = ne_unlock( m_pHttpSession, theLock );
1340 + // Set the lock owner
1341 + rtl::OUString aValue;
1342 + rLock.Owner >>= aValue;
1344 - HandleError( theRetVal );
1345 + theLock->owner = strdup( rtl::OUStringToOString( aValue, RTL_TEXTENCODING_UTF8 ).getStr() );
1347 + // Set the lock timeout
1348 + // We re-new the lock while the stream is open
1349 + theLock->timeout = rLock.Timeout;
1355 + if ( bAlreadyExists )
1357 +#if NEON_VERSION >= 0x0260
1358 + nRet = ne_lock_refresh( m_pHttpSession, theLock );
1360 + // workaround for a bug in neon 0.24
1361 + // we have to call with a bigger structure that is used internally
1362 + // and initialize parts of it
1366 + struct ne_lock active; /* activelock */
1367 + char *token; /* the token we're after. */
1372 + struct lock_ctx ctx;
1374 + memset( &ctx, 0, sizeof ctx );
1375 + ctx.cdata = ne_buffer_create();
1377 + memcpy( &ctx, theLock, sizeof( *theLock ) );
1378 + nRet = ne_lock_refresh( m_pHttpSession, reinterpret_cast<NeonLock*>( &ctx ) );
1380 + ne_buffer_destroy( ctx.cdata );
1382 + if ( ( nRet == NE_ERROR ) && strncmp (ne_get_error (m_pHttpSession), "No activelock ", strlen ("No activelock ")) == 0 )
1384 + bAlreadyExists = false;
1385 + ne_lockstore_remove( s_aNeonLockStore, theLock );
1388 + if ( !bAlreadyExists )
1390 + nRet = ne_lock( m_pHttpSession, theLock );
1392 + if ( nRet == NE_OK )
1394 + ne_lockstore_add( s_aNeonLockStore, theLock );
1396 + uno::Sequence< rtl::OUString > aTokens( 1 );
1397 + aTokens[0] = rtl::OUString::createFromAscii( theLock->token );
1398 + rLock.LockTokens = aTokens;
1400 +#if OSL_DEBUG_LEVEL > 0
1401 + fprintf( stderr, "WebDAV: locked the URL, the token is: %s\n", theLock->token );
1406 + if ( ( nRet == NE_ERROR ) && getStatusCode( m_pHttpSession ) == SC_LOCKED )
1408 + ucbhelper::cancelCommandExecution( ucb::IOErrorCode_LOCKING_VIOLATION,
1409 + uno::Sequence< uno::Any >( 0 ), // FIXME more info about the file?
1411 + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "a locking error occured" ) ),
1412 + uno::Reference< ucb::XCommandProcessor >() );
1414 +#if OSL_DEBUG_LEVEL > 0
1415 + else if ( nRet == NE_OK )
1416 + fprintf( stderr, "WebDAV: locked/refreshed lock OK\n" );
1418 + fprintf( stderr, "WebDAV: failed to lock the file: %s\n", ne_get_error( m_pHttpSession ) );
1423 + // Set the lock token
1424 + if ( rLock.LockTokens.getLength() > 0 )
1426 + rtl::OUString theToken = rLock.LockTokens.getConstArray()[ 0 ];
1427 + theLock->token = strdup( rtl::OUStringToOString( theToken, RTL_TEXTENCODING_UTF8 ).getStr() );
1429 +#if OSL_DEBUG_LEVEL > 0
1430 + fprintf( stderr, "WebDAV: going to unlock the URL, the token is: %s\n", theLock->token );
1433 + ne_unlock( m_pHttpSession, theLock );
1434 + ne_lockstore_remove( s_aNeonLockStore, theLock );
1435 + // FIXME even ne_lock_destroy( theLock )?
1441 // -------------------------------------------------------------------
1443 --- ucb/source/ucp/webdav/NeonSession.hxx
1444 +++ ucb/source/ucp/webdav/NeonSession.hxx
1445 @@ -57,6 +57,7 @@ class NeonSession : public DAVSession
1446 rtl::OUString m_aScheme;
1447 rtl::OUString m_aHostName;
1448 rtl::OUString m_aProxyName;
1449 + rtl::OUString m_aUserInfo;
1451 sal_Int32 m_nProxyPort;
1452 HttpSession * m_pHttpSession;
1453 @@ -70,8 +71,7 @@ class NeonSession : public DAVSession
1455 DAVRequestEnvironment m_aEnv;
1457 - // Note: Uncomment the following if locking support is required
1458 - // NeonLockSession * mNeonLockSession;
1459 + static NeonLockStore *s_aNeonLockStore;
1461 static bool m_bGlobalsInited;
1463 @@ -92,6 +92,8 @@ class NeonSession : public DAVSession
1464 const DAVRequestEnvironment & getRequestEnvironment() const
1467 + const rtl::OUString & getUserInfo() const { return m_aUserInfo; }
1470 OPTIONS( const ::rtl::OUString & inPath,
1471 DAVCapabilities & outCapabilities,
1472 @@ -142,11 +144,12 @@ class NeonSession : public DAVSession
1473 throw ( DAVException );
1475 virtual com::sun::star::uno::Reference<
1476 - com::sun::star::io::XInputStream >
1477 + com::sun::star::io::XStream >
1478 GET( const ::rtl::OUString & inPath,
1479 const std::vector< ::rtl::OUString > & inHeaderNames,
1480 DAVResource & ioResource,
1481 - const DAVRequestEnvironment & rEnv )
1482 + const DAVRequestEnvironment & rEnv,
1483 + sal_Bool bAllowEmpty = sal_False )
1484 throw ( DAVException );
1487 @@ -165,6 +168,13 @@ class NeonSession : public DAVSession
1488 const DAVRequestEnvironment & rEnv )
1489 throw ( DAVException );
1492 + PUT( const ::rtl::OUString & inPath,
1493 + const char * buffer,
1495 + const DAVRequestEnvironment & rEnv )
1496 + throw ( DAVException );
1498 virtual com::sun::star::uno::Reference<
1499 com::sun::star::io::XInputStream >
1500 POST( const rtl::OUString & inPath,
1501 @@ -209,16 +219,13 @@ class NeonSession : public DAVSession
1502 virtual void ABORT()
1503 throw ( DAVException );
1505 - // Note: Uncomment the following if locking support is required
1507 - virtual void LOCK (const Lock & inLock,
1508 - const DAVRequestEnvironment & rEnv )
1509 + virtual void LOCK ( com::sun::star::ucb::Lock & rLock,
1510 + const DAVRequestEnvironment & rEnv )
1511 throw ( DAVException );
1513 - virtual void UNLOCK (const Lock & inLock,
1514 - const DAVRequestEnvironment & rEnv )
1515 + virtual void UNLOCK ( com::sun::star::ucb::Lock & rLock,
1516 + const DAVRequestEnvironment & rEnv )
1517 throw ( DAVException );
1521 const rtl::OUString & getHostName() const { return m_aHostName; }
1522 @@ -239,9 +246,8 @@ class NeonSession : public DAVSession
1524 const ucbhelper::InternetProxyServer & getProxySettings() const;
1526 - // Note: Uncomment the following if locking support is required
1527 - // void Lockit( const Lock & inLock, bool inLockit )
1528 - // throw ( DAVException );
1529 + void Lockit( com::sun::star::ucb::Lock & rLock, bool bLockit )
1530 + throw ( DAVException );
1532 // low level GET implementation, used by public GET implementations
1533 static int GET( ne_session * sess,
1534 --- ucb/source/ucp/webdav/NeonTypes.hxx
1535 +++ ucb/source/ucp/webdav/NeonTypes.hxx
1537 #include <ne_utils.h>
1538 #include <ne_basic.h>
1539 #include <ne_props.h>
1540 +#include <ne_locks.h>
1542 typedef ne_session HttpSession;
1543 typedef ne_status HttpStatus;
1544 @@ -43,4 +44,7 @@ typedef ne_server_capabilities Http
1545 typedef ne_propname NeonPropName;
1546 typedef ne_prop_result_set NeonPropFindResultSet;
1548 +typedef ne_lock_store NeonLockStore;
1549 +typedef struct ne_lock NeonLock;
1551 #endif // _NEONTYPES_HXX_
1552 --- ucb/source/ucp/webdav/webdavcontent.cxx
1553 +++ ucb/source/ucp/webdav/webdavcontent.cxx
1556 *************************************************************************/
1557 #include <osl/diagnose.h>
1558 +#include <osl/thread.hxx>
1560 #include "osl/doublecheckedlocking.h"
1561 #include <rtl/uri.hxx>
1563 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
1564 #include <com/sun/star/beans/PropertyValue.hpp>
1565 #include <com/sun/star/io/XActiveDataSink.hpp>
1566 +#include <com/sun/star/io/XActiveDataStreamer.hpp>
1567 #include <com/sun/star/io/XOutputStream.hpp>
1568 #include <com/sun/star/lang/IllegalAccessException.hpp>
1569 #include "com/sun/star/ucb/AuthenticationRequest.hpp"
1570 #include <com/sun/star/ucb/CommandFailedException.hpp>
1571 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
1572 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
1573 -#ifndef _COM_SUN_STAR_UCB_INTERACTIVEBADTRANSFRERURLEXCEPTION_HPP_
1574 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
1576 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
1577 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
1578 -#ifndef _COM_SUN_STAR_UCB_INTERACTIVENETWORKGENBERALEXCEPTION_HPP_
1579 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
1581 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
1582 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
1583 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
1585 #include "NeonUri.hxx"
1586 #include "UCBDeadPropertyValue.hxx"
1588 +#include "NeonInputStream.hxx"
1590 using namespace com::sun::star;
1591 using namespace webdav_ucp;
1593 @@ -345,6 +345,123 @@ void SAL_CALL CommandEnvironment_Impl::h
1594 //=========================================================================
1595 //=========================================================================
1597 +// Our signal - 246 is just a random number ;-)
1598 +#define TICKER_THREAD_USER_SIGNAL ( OSL_SIGNAL_USER_RESERVED + 246 )
1600 +// -------------------------------------------------------------------
1601 +// A thread that 'ticks' - emits the user signal every second
1602 +// -------------------------------------------------------------------
1603 +class TickerThread : public osl::Thread
1609 + TickerThread() : osl::Thread(), m_bFinish( false ) {}
1611 + void finish() { m_bFinish = true; }
1615 + virtual void SAL_CALL run();
1618 +void TickerThread::run()
1620 + // we have to go through the loop more often to be able to finish ~quickly
1621 + const int nNth = 25;
1623 + int nCount = nNth;
1624 + while ( !m_bFinish )
1626 + if ( nCount-- <= 0 )
1628 + osl_raiseSignal( TICKER_THREAD_USER_SIGNAL, NULL );
1634 + aTV.Nanosec = 1000000000/nNth;
1639 +// -------------------------------------------------------------------
1640 +// A class that takes care of creating and destroying the ticker thread
1641 +// -------------------------------------------------------------------
1642 +class TickerThreadController
1644 + osl::Mutex m_aMutex;
1646 + TickerThread *m_pTickerThread;
1650 + TickerThreadController() : m_nCount( 0 ), m_pTickerThread( NULL ) {}
1656 +void TickerThreadController::start()
1658 + osl::MutexGuard aGuard( m_aMutex );
1660 + if ( ( m_nCount++ == 0 ) && !m_pTickerThread )
1662 + m_pTickerThread = new TickerThread();
1663 + m_pTickerThread->create();
1667 +void TickerThreadController::stop()
1669 + osl::MutexGuard aGuard( m_aMutex );
1671 + if ( ( --m_nCount == 0 ) && m_pTickerThread )
1673 + m_pTickerThread->finish();
1674 + m_pTickerThread->join();
1676 + delete m_pTickerThread;
1677 + m_pTickerThread = NULL;
1681 +// -------------------------------------------------------------------
1683 +// -------------------------------------------------------------------
1684 +oslSignalAction Content::HandleLockingSignal( void* pData, oslSignalInfo* pSignalInfo )
1686 + Content *pContent = static_cast< Content *>( pData );
1688 +#if OSL_DEBUG_LEVEL > 0
1689 + fprintf( stderr, "Content::HandleLockingSignal: pContent=%p pSignalInfo=%p\n", pContent, pSignalInfo );
1693 + return osl_Signal_ActCallNextHdl;
1695 + if ( pSignalInfo &&
1696 + pSignalInfo->Signal == osl_Signal_User &&
1697 + pSignalInfo->UserSignal == TICKER_THREAD_USER_SIGNAL )
1699 + pContent->RefreshLock();
1701 + else if ( !pSignalInfo || ( pSignalInfo->Signal != osl_Signal_User ) )
1703 + // terminating or something
1704 + pContent->m_xResAccess->UNLOCK( *pContent->m_pLock, pContent->m_xLockEnv );
1705 + delete pContent->m_pLock;
1706 + pContent->m_pLock = NULL;
1709 + return osl_Signal_ActCallNextHdl;
1712 +static TickerThreadController sTickerThreadController;
1714 //=========================================================================
1715 // ctr for content on an existing webdav resource
1717 @@ -358,7 +475,11 @@ Content::Content(
1718 m_pProvider( pProvider ),
1719 m_bTransient( false ),
1720 m_bCollection( false ),
1721 - m_bDidGetOrHead( false )
1722 + m_bDidGetOrHead( false ),
1723 + m_bForceReadOnly( false ),
1725 + m_nToExpire( -1 ),
1726 + m_pSignalHandler( NULL )
1730 @@ -369,6 +490,14 @@ Content::Content(
1732 NeonUri aURI( Identifier->getContentIdentifier() );
1733 m_aEscapedTitle = aURI.GetPathBaseName();
1735 + m_pSignalHandler = osl_addSignalHandler( HandleLockingSignal, this );
1737 +#if OSL_DEBUG_LEVEL > 0
1738 + fprintf( stderr, "Content::Content (existing resource): this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler );
1739 + fprintf( stderr, " identifier=%s\n", rtl::OUStringToOString( Identifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8 ).getStr() );
1741 + sTickerThreadController.start();
1743 catch ( DAVException const & )
1745 @@ -390,12 +518,24 @@ Content::Content(
1746 m_pProvider( pProvider ),
1747 m_bTransient( true ),
1748 m_bCollection( isCollection ),
1749 - m_bDidGetOrHead( false )
1750 + m_bDidGetOrHead( false ),
1751 + m_bForceReadOnly( false ),
1753 + m_nToExpire( -1 ),
1754 + m_pSignalHandler( NULL )
1758 m_xResAccess.reset( new DAVResourceAccess(
1759 rxSMgr, rSessionFactory, Identifier->getContentIdentifier() ) );
1761 + m_pSignalHandler = osl_addSignalHandler( HandleLockingSignal, this );
1763 +#if OSL_DEBUG_LEVEL > 0
1764 + fprintf( stderr, "Content::Content (nonexistent resource): this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler );
1765 + fprintf( stderr, " identifier=%s\n", rtl::OUStringToOString( Identifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8 ).getStr() );
1767 + sTickerThreadController.start();
1769 catch ( DAVException const & )
1771 @@ -409,6 +548,47 @@ Content::Content(
1775 +#if OSL_DEBUG_LEVEL > 0
1776 + fprintf( stderr, "Content::~Content: this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler );
1778 + sTickerThreadController.stop();
1780 + osl_removeSignalHandler( m_pSignalHandler );
1782 + if (m_pLock != NULL)
1785 + m_xResAccess->UNLOCK( *m_pLock, m_xLockEnv );
1789 + catch ( ucb::CommandFailedException const & )
1795 +// -------------------------------------------------------------------
1796 +// Lock the resource again
1797 +// -------------------------------------------------------------------
1798 +void Content::RefreshLock( void )
1800 + osl::MutexGuard aGuard( m_aLock );
1802 +#if OSL_DEBUG_LEVEL > 0
1803 + fprintf( stderr, "Content::RefreshLock(): m_nToExpire=%d m_pLock=%p\n", m_nToExpire, m_pLock);
1806 + if ( m_nToExpire > 0 )
1809 + // Refresh the lock if it expires in less than 30 s
1810 + if ( m_pLock && m_nToExpire >= 0 && m_nToExpire < 30 )
1812 + m_xResAccess->LOCK( *m_pLock, m_xLockEnv );
1814 + m_nToExpire = m_pLock->Timeout;
1818 //=========================================================================
1819 @@ -630,6 +811,11 @@ uno::Any SAL_CALL Content::execute(
1820 ucb::CommandAbortedException,
1821 uno::RuntimeException )
1823 +#if OSL_DEBUG_LEVEL > 0
1824 + fprintf( stderr, "WebDAV: Content::execute(): this=%p command=%s\n",
1825 + this, rtl::OUStringToOString( aCommand.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
1830 if ( aCommand.Name.equalsAsciiL(
1831 @@ -1000,6 +1000,11 @@
1832 if ( !Name.getLength() )
1833 throw lang::IllegalArgumentException();
1835 +#if OSL_DEBUG_LEVEL > 0
1836 + fprintf( stderr, "WebDAV: Content::addProperty(): this=%p property=%s\n",
1837 + this, rtl::OUStringToOString( Name, RTL_TEXTENCODING_UTF8 ).getStr() );
1840 // Check property type.
1841 if ( !UCBDeadPropertyValue::supportsType( DefaultValue.getValueType() ) )
1843 @@ -1100,6 +1100,11 @@
1844 // Try to remove property from server.
1845 //////////////////////////////////////////////////////////////////////
1847 +#if OSL_DEBUG_LEVEL > 0
1848 + fprintf( stderr, "WebDAV: Content::removeProperty(): this=%p property=%s\n",
1849 + this, rtl::OUStringToOString( Name, RTL_TEXTENCODING_UTF8 ).getStr() );
1854 std::vector< ProppatchValue > aProppatchValues;
1855 @@ -1349,6 +1535,31 @@ uno::Reference< sdbc::XRow > Content::ge
1856 uno::Reference< ucb::XContentIdentifier > xIdentifier;
1857 rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider;
1859 +#if OSL_DEBUG_LEVEL > 0
1860 + fprintf( stderr, "WebDAV: Content::getPropertyValues(): answering the following properties: " );
1861 + for ( int i = 0; i < rProperties.getLength(); ++i )
1862 + fprintf( stderr, " %s,",
1863 + rtl::OUStringToOString( rProperties[i].Name, RTL_TEXTENCODING_UTF8 ).getStr() );
1864 + fprintf( stderr, "\n" );
1867 + // WebDAV supports XActiveDataStreamer
1868 + // We have to return TRUE on
1869 + // - SupportsActiveStreaming - always
1870 + // - IsReadOnly - if we forced read only due to failed locking
1871 + if ( rProperties.getLength() == 1 )
1873 + if ( rProperties[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) ||
1874 + ( rProperties[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) && m_bForceReadOnly ) )
1876 + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
1877 + = new ::ucbhelper::PropertyValueSet( m_xSMgr );
1878 + xRow->appendBoolean( rProperties[0], sal_True );
1880 + return uno::Reference< sdbc::XRow >( xRow.get() );
1885 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1887 @@ -1475,8 +1686,13 @@ uno::Reference< sdbc::XRow > Content::ge
1889 if ( !bNetworkAccessAllowed )
1891 - cancelCommandExecution( e, xEnv );
1893 + if ( e.getStatus() == SC_NOT_FOUND )
1897 + cancelCommandExecution( e, xEnv );
1903 @@ -2000,6 +2000,10 @@
1907 +#if OSL_DEBUG_LEVEL > 0
1908 + fprintf( stderr, "WebDAV: Content::open() this=%p\n", this );
1911 sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) ||
1912 ( rArg.Mode == ucb::OpenMode::FOLDERS ) ||
1913 ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) );
1914 @@ -2092,13 +2308,17 @@ uno::Any Content::open(
1918 - if ( rArg.Sink.is() )
1921 + if ( !rArg.Sink.is() )
1926 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1927 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1929 +#if OSL_DEBUG_LEVEL > 0
1930 + fprintf( stderr, "WebDAV: rArg.Mode currently(?) unsupported\n" );
1932 // Currently(?) unsupported.
1933 ucbhelper::cancelCommandExecution(
1935 @@ -2115,6 +2332,9 @@ uno::Any Content::open(
1936 = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
1939 +#if OSL_DEBUG_LEVEL > 0
1940 + fprintf( stderr, "WebDAV: rArg.Sink is XOutputStream\n" );
1945 @@ -2159,6 +2379,60 @@ uno::Any Content::open(
1947 if ( xDataSink.is() )
1949 +#if OSL_DEBUG_LEVEL > 0
1950 + fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataSink\n" );
1952 + // PULL: wait for client read
1956 + osl::MutexGuard aGuard( m_aMutex );
1958 + // throw away previously cached headers.
1959 + m_xCachedProps.reset();
1961 + // fill inputsream sync; return if all data present
1962 + DAVResource aResource;
1963 + std::vector< rtl::OUString > aHeaders;
1964 + // // Obtain list containing all HTTP headers that can
1965 + // // be mapped to UCB properties.
1966 + // ContentProperties::getMappableHTTPHeaders( aHeaders );
1967 + uno::Reference< io::XInputStream > xIn
1968 + = m_xResAccess->GET( aHeaders, aResource, xEnv )->getInputStream();
1971 + osl::MutexGuard aGuard( m_aMutex );
1973 + m_xCachedProps.reset(
1974 + new ContentProperties( aResource ) );
1977 + xDataSink->setInputStream( xIn );
1979 + catch ( DAVException const & e )
1981 + cancelCommandExecution( e, xEnv );
1987 + uno::Reference< io::XActiveDataStreamer > xDataStreamer
1988 + = uno::Reference< io::XActiveDataStreamer >( rArg.Sink,
1990 + if ( xDataStreamer.is() && !m_bForceReadOnly )
1992 +#if OSL_DEBUG_LEVEL > 0
1993 + fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataStreamer\n" );
1995 + // prepare the lock
1996 + m_pLock = new ucb::Lock;
1997 + m_pLock->Depth = ucb::LockDepth_ZERO;
1998 + m_pLock->Scope = ucb::LockScope_EXCLUSIVE;
1999 + m_pLock->Timeout = 2*60; // 2 minutes
2001 + m_nToExpire = m_pLock->Timeout;
2003 // PULL: wait for client read
2006 @@ -2174,9 +2448,31 @@ uno::Any Content::open(
2007 DAVResource aResource;
2008 std::vector< rtl::OUString > aHeaders;
2010 - uno::Reference< io::XInputStream > xIn
2011 - = xResAccess->GET( aHeaders, aResource, xEnv );
2013 + m_xResAccess->LOCK( *m_pLock, xEnv );
2014 + m_xLockEnv = xEnv;
2016 + catch ( ucb::CommandFailedException const &e )
2019 + ucb::InteractiveIOException aIoException;
2020 + if ( ( e.Reason >>= aIoException ) && ( aIoException.Code == ucb::IOErrorCode_LOCKING_VIOLATION ) )
2024 + // yes => we must be read only at the next try
2025 + m_bForceReadOnly = sal_True;
2031 + uno::Reference< io::XStream > xStream
2032 + = xResAccess->GET( aHeaders, aResource, xEnv, sal_True );
2033 m_bDidGetOrHead = true;
2035 + // pass the URL to the stream
2036 + static_cast< NeonInputStream* >( xStream.get() )->SetURL( m_xResAccess->getURL() );
2039 osl::MutexGuard aGuard( m_aMutex );
2040 @@ -2191,16 +2487,24 @@ uno::Any Content::open(
2041 new DAVResourceAccess( *xResAccess.get() ) );
2044 - xDataSink->setInputStream( xIn );
2045 + xDataStreamer->setStream( xStream );
2047 catch ( DAVException const & e )
2049 + m_xResAccess->UNLOCK( *m_pLock, xEnv );
2052 + m_bForceReadOnly = sal_False;
2054 cancelCommandExecution( e, xEnv );
2060 +#if OSL_DEBUG_LEVEL > 0
2061 + fprintf( stderr, "WebDAV: unsupported rArg.Sink\n" );
2063 // Note: aOpenCommand.Sink may contain an XStream
2064 // implementation. Support for this type of
2065 // sink is optional...
2066 @@ -2228,9 +2532,16 @@ void Content::post(
2067 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2068 throw( uno::Exception )
2070 +#if OSL_DEBUG_LEVEL > 0
2071 + fprintf( stderr, "WebDAV: Content::post() this=%p\n", this );
2074 uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY );
2077 +#if OSL_DEBUG_LEVEL > 0
2078 + fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataSink\n" );
2082 std::auto_ptr< DAVResourceAccess > xResAccess;
2083 @@ -2262,6 +2569,9 @@ void Content::post(
2084 uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY );
2087 +#if OSL_DEBUG_LEVEL > 0
2088 + fprintf( stderr, "WebDAV: rArg.Sink is XOutputStream\n" );
2092 std::auto_ptr< DAVResourceAccess > xResAccess;
2093 @@ -2291,6 +2601,9 @@ void Content::post(
2097 +#if OSL_DEBUG_LEVEL > 0
2098 + fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataStreamer (or something)\n" );
2100 ucbhelper::cancelCommandExecution(
2102 ucb::UnsupportedDataSinkException(
2103 @@ -2600,6 +2600,10 @@
2104 rtl::OUString aEscapedTitle;
2105 std::auto_ptr< DAVResourceAccess > xResAccess;
2107 +#if OSL_DEBUG_LEVEL > 0
2108 + fprintf( stderr, "WebDAV: Content::insert() this=%p\n", this );
2112 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2114 @@ -2643,11 +2956,23 @@ void Content::transfer(
2115 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
2117 else if ( aScheme.equalsAsciiL(
2118 + RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME ) ) )
2120 + sourceURI.SetScheme(
2121 + rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
2123 + else if ( aScheme.equalsAsciiL(
2124 RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
2126 sourceURI.SetScheme(
2127 rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
2129 + else if ( aScheme.equalsAsciiL(
2130 + RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME ) ) )
2132 + sourceURI.SetScheme(
2133 + rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
2137 if ( !aScheme.equalsAsciiL(
2138 @@ -2674,6 +2999,18 @@ void Content::transfer(
2139 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) )
2140 targetURI.SetScheme(
2141 rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
2142 + else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
2143 + RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME ) ) )
2144 + targetURI.SetScheme(
2145 + rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
2146 + else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
2147 + RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
2148 + targetURI.SetScheme(
2149 + rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
2150 + else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
2151 + RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME ) ) )
2152 + targetURI.SetScheme(
2153 + rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
2155 // @@@ This implementation of 'transfer' only works
2156 // if the source and target are located at same host.
2157 --- ucb/source/ucp/webdav/webdavcontent.hxx
2158 +++ ucb/source/ucp/webdav/webdavcontent.hxx
2163 +#include <osl/signal.h>
2164 #include <rtl/ref.hxx>
2165 #include <com/sun/star/ucb/ContentCreationException.hpp>
2166 #include <com/sun/star/ucb/XContentCreator.hpp>
2167 +#include <com/sun/star/ucb/Lock.hpp>
2168 #include <ucbhelper/contenthelper.hxx>
2170 #include "DAVResourceAccess.hxx"
2171 #include "PropertyMap.hxx"
2173 @@ -91,6 +94,9 @@ class Content : public ::ucbhelper::Cont
2176 bool m_bDidGetOrHead;
2177 + bool m_bForceReadOnly;
2178 + com::sun::star::ucb::Lock *m_pLock;
2179 + uno::Reference< ucb::XCommandEnvironment > m_xLockEnv;
2180 std::vector< rtl::OUString > m_aFailedPropNames;
2183 @@ -184,6 +190,17 @@ private:
2185 static bool shouldAccessNetworkAfterException( const DAVException & e );
2187 + oslSignalHandler m_pSignalHandler;
2189 + osl::Mutex m_aLock;
2191 + // Refresh the lock of the resource
2192 + void RefreshLock( void );
2194 + // Refresh the lock if necessary, or unlock the resource when
2195 + // OOo crashes or is terminated
2196 + static oslSignalAction HandleLockingSignal( void* pData, oslSignalInfo* pInfo );
2199 Content( const ::com::sun::star::uno::Reference<
2200 ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr,
2201 --- ucb/source/ucp/webdav/webdavcontentcaps.cxx
2202 +++ ucb/source/ucp/webdav/webdavcontentcaps.cxx
2203 @@ -263,6 +263,24 @@ bool ContentProvider::getProperty(
2205 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
2206 beans::PropertyAttribute::BOUND ) );
2211 + RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" ) ),
2213 + getCppuBooleanType(),
2214 + beans::PropertyAttribute::BOUND
2215 + | beans::PropertyAttribute::READONLY ) );
2220 + RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
2222 + getCppuBooleanType(),
2223 + beans::PropertyAttribute::BOUND
2224 + | beans::PropertyAttribute::READONLY ) );
2228 --- ucb/source/ucp/webdav/webdavprovider.cxx
2229 +++ ucb/source/ucp/webdav/webdavprovider.cxx
2231 **************************************************************************
2233 *************************************************************************/
2235 +#include <string.h>
2237 #include <ucbhelper/contentidentifier.hxx>
2238 #include "webdavprovider.hxx"
2239 #include "webdavcontent.hxx"
2240 @@ -138,7 +141,11 @@ ContentProvider::queryContent(
2241 RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) &&
2242 !aScheme.equalsAsciiL(
2243 RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) &&
2244 - !aScheme.equalsAsciiL(
2245 + !aScheme.equalsAsciiL(
2246 + RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME ) ) &&
2247 + !aScheme.equalsAsciiL(
2248 + RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME ) ) &&
2249 + !aScheme.equalsAsciiL(
2250 RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME ) ) )
2251 throw ucb::IllegalIdentifierException();
2253 @@ -157,32 +164,27 @@ ContentProvider::queryContent(
2254 uno::Reference< ucb::XContentIdentifier > xCanonicId;
2256 bool bNewId = false;
2257 - if ( aScheme.equalsAsciiL(
2258 - RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) )
2262 + } const *pScheme, pReplace[] = {
2263 + { WEBDAV_URL_SCHEME, HTTP_URL_SCHEME },
2264 + { DAV_URL_SCHEME, HTTP_URL_SCHEME },
2265 + { DAVS_URL_SCHEME, HTTPS_URL_SCHEME },
2266 + { PLAIN_WEBDAV_URL_SCHEME, HTTP_URL_SCHEME },
2267 + { PLAIN_WEBDAVS_URL_SCHEME, HTTPS_URL_SCHEME },
2270 + for ( pScheme = pReplace; pScheme->from ; ++pScheme )
2272 - aURL = aURL.replaceAt( 0,
2273 - WEBDAV_URL_SCHEME_LENGTH,
2274 - rtl::OUString::createFromAscii(
2275 - HTTP_URL_SCHEME ) );
2278 - else if ( aScheme.equalsAsciiL(
2279 - RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) )
2281 - aURL = aURL.replaceAt( 0,
2282 - DAV_URL_SCHEME_LENGTH,
2283 - rtl::OUString::createFromAscii(
2284 - HTTP_URL_SCHEME ) );
2287 - else if ( aScheme.equalsAsciiL(
2288 - RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
2290 - aURL = aURL.replaceAt( 0,
2291 - DAVS_URL_SCHEME_LENGTH,
2292 - rtl::OUString::createFromAscii(
2293 - HTTPS_URL_SCHEME ) );
2295 + if ( aScheme.equalsAscii( pScheme->from ) )
2297 + aURL = aURL.replaceAt( 0,
2298 + strlen( pScheme->from ),
2299 + rtl::OUString::createFromAscii( pScheme->to ) );
2305 sal_Int32 nPos = aURL.lastIndexOf( '/' );
2306 @@ -208,6 +208,12 @@
2308 xCanonicId = Identifier;
2310 +#if OSL_DEBUG_LEVEL > 0
2311 + fprintf( stderr, "ContentProvider::queryContent(): bNewId=%s, xCanonicId=%s\n",
2312 + bNewId ? "YES" : "NO",
2313 + rtl::OUStringToOString( xCanonicId->getContentIdentifier(), RTL_TEXTENCODING_UTF8 ).getStr() );
2316 osl::MutexGuard aGuard( m_aMutex );
2318 // Check, if a content with given id already exists...
2319 @@ -232,4 +234,3 @@ ContentProvider::queryContent(
2324 --- ucb/source/ucp/webdav/webdavprovider.hxx
2325 +++ ucb/source/ucp/webdav/webdavprovider.hxx
2326 @@ -52,13 +52,10 @@ namespace webdav_ucp {
2327 // contents ) according to this scheme.
2328 #define WEBDAV_URL_SCHEME \
2329 "vnd.sun.star.webdav"
2330 -#define WEBDAV_URL_SCHEME_LENGTH 19
2332 #define HTTP_URL_SCHEME "http"
2333 -#define HTTP_URL_SCHEME_LENGTH 4
2335 #define HTTPS_URL_SCHEME "https"
2336 -#define HTTPS_URL_SCHEME_LENGTH 5
2338 #define DAV_URL_SCHEME "dav"
2339 #define DAV_URL_SCHEME_LENGTH 3
2340 @@ -70,6 +67,12 @@ namespace webdav_ucp {
2342 #define FTP_URL_SCHEME "ftp"
2344 +#define DAV_URL_SCHEME "dav"
2345 +#define DAVS_URL_SCHEME "davs"
2347 +#define PLAIN_WEBDAV_URL_SCHEME "webdav"
2348 +#define PLAIN_WEBDAVS_URL_SCHEME "webdavs"
2350 #define HTTP_CONTENT_TYPE \
2351 "application/" HTTP_URL_SCHEME "-content"
2353 --- unotools/source/ucbhelper/ucblockbytes.cxx
2354 +++ unotools/source/ucbhelper/ucblockbytes.cxx
2355 @@ -964,6 +964,10 @@ static sal_Bool UCBOpenContentSync(
2356 if( ! aScheme.equalsIgnoreAsciiCaseAscii("http") &&
2357 ! aScheme.equalsIgnoreAsciiCaseAscii("https") &&
2358 ! aScheme.equalsIgnoreAsciiCaseAscii("vnd.sun.star.webdav") &&
2359 + ! aScheme.equalsIgnoreAsciiCaseAscii("dav") &&
2360 + ! aScheme.equalsIgnoreAsciiCaseAscii("davs") &&
2361 + ! aScheme.equalsIgnoreAsciiCaseAscii("webdav") &&
2362 + ! aScheme.equalsIgnoreAsciiCaseAscii("webdavs") &&
2363 ! aScheme.equalsIgnoreAsciiCaseAscii("ftp"))
2364 return _UCBOpenContentSync(
2365 xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler);
2366 @@ -1541,7 +1545,13 @@ ErrCode UcbLockBytes::Flush() const
2367 Reference <XOutputStream > xOutputStream = getOutputStream_Impl();
2368 if ( !xOutputStream.is() )
2369 return ERRCODE_IO_CANTWRITE;
2370 - xOutputStream->flush();
2372 + xOutputStream->flush();
2376 + return ERRCODE_IO_CANTWRITE;
2378 return ERRCODE_NONE;