1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_webdav.hxx"
26 
27 /**************************************************************************
28 								TODO
29  **************************************************************************
30 
31  *************************************************************************/
32 #include <ucbhelper/contentidentifier.hxx>
33 #include "webdavprovider.hxx"
34 #include "webdavcontent.hxx"
35 #include "webdavuseragent.hxx"
36 
37 #include <osl/mutex.hxx>
38 #include <rtl/ustrbuf.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <com/sun/star/beans/NamedValue.hpp>
41 #include <com/sun/star/container/XNameAccess.hpp>
42 #include <apr_version.h>
43 #include <apu_version.h>
44 #include <serf.h>
45 
46 using namespace com::sun::star;
47 using namespace http_dav_ucp;
48 
49 
50 rtl::OUString &WebDAVUserAgent::operator()() const
51 {
52     rtl::OUStringBuffer aBuffer;
53     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Apache " ));
54     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "$ooName/$ooSetupVersion" ));
55 #if OSL_DEBUG_LEVEL > 0
56     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " apr/" ) );
57     aBuffer.appendAscii(apr_version_string());
58 
59     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " apr-util/" ) );
60     aBuffer.appendAscii(apu_version_string());
61 
62     int major, minor, patch;
63     serf_lib_version(&major, &minor, &patch);
64     aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " serf/" ) );
65     aBuffer.append(major);
66     aBuffer.append( L'.' );
67     aBuffer.append(minor);
68     aBuffer.append( L'.' );
69     aBuffer.append(patch);
70 #endif
71     static rtl::OUString aUserAgent( aBuffer.makeStringAndClear() );
72     return aUserAgent;
73 }
74 
75 //=========================================================================
76 //=========================================================================
77 //
78 // ContentProvider Implementation.
79 //
80 //=========================================================================
81 //=========================================================================
82 
83 ContentProvider::ContentProvider(
84                 const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
85 : ::ucbhelper::ContentProviderImplHelper( rSMgr ),
86   m_xDAVSessionFactory( new DAVSessionFactory() ),
87   m_pProps( 0 )
88 {
89     static bool bInit = false;
90     if ( bInit )
91         return;
92     bInit = true;
93     try
94     {
95         uno::Reference< uno::XComponentContext > xContext(
96             ::comphelper::getProcessComponentContext() );
97         uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
98             xContext->getServiceManager()->createInstanceWithContext(
99                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
100                                   "com.sun.star.configuration.ConfigurationProvider")), xContext),
101             uno::UNO_QUERY_THROW );
102 
103         beans::NamedValue aNodePath;
104         aNodePath.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
105         aNodePath.Value <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Setup/Product"));
106 
107         uno::Sequence< uno::Any > aArgs( 1 );
108         aArgs[0] <<= aNodePath;
109 
110         uno::Reference< container::XNameAccess > xConfigAccess(
111             xConfigProvider->createInstanceWithArguments(
112                 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
113                     "com.sun.star.configuration.ConfigurationAccess")), aArgs),
114             uno::UNO_QUERY_THROW );
115 
116         rtl::OUString aVal;
117         xConfigAccess->getByName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooName"))) >>= aVal;
118 
119         rtl::OUString &aUserAgent = WebDAVUserAgent::get();
120         sal_Int32 nIndex = aUserAgent.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "$ooName" ) );
121         if ( !aVal.getLength() || nIndex == -1 )
122             return;
123         aUserAgent = aUserAgent.replaceAt( nIndex, RTL_CONSTASCII_LENGTH( "$ooName" ), aVal );
124 
125         xConfigAccess->getByName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupVersion"))) >>= aVal;
126         nIndex = aUserAgent.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "$ooSetupVersion" ) );
127         if ( !aVal.getLength() || nIndex == -1 )
128             return;
129         aUserAgent = aUserAgent.replaceAt( nIndex, RTL_CONSTASCII_LENGTH( "$ooSetupVersion" ), aVal );
130 
131     }
132     catch ( const uno::Exception &e )
133     {
134         OSL_TRACE( "ContentProvider -caught exception! %s",
135                    rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
136         (void) e;
137     }
138 }
139 
140 //=========================================================================
141 // virtual
142 ContentProvider::~ContentProvider()
143 {
144 	delete m_pProps;
145 }
146 
147 //=========================================================================
148 //
149 // XInterface methods.
150 //
151 //=========================================================================
152 
153 XINTERFACE_IMPL_3( ContentProvider,
154                    lang::XTypeProvider,
155                    lang::XServiceInfo,
156                    ucb::XContentProvider );
157 
158 //=========================================================================
159 //
160 // XTypeProvider methods.
161 //
162 //=========================================================================
163 
164 XTYPEPROVIDER_IMPL_3( ContentProvider,
165                       lang::XTypeProvider,
166                       lang::XServiceInfo,
167                       ucb::XContentProvider );
168 
169 //=========================================================================
170 //
171 // XServiceInfo methods.
172 //
173 //=========================================================================
174 
175 XSERVICEINFO_IMPL_1( ContentProvider,
176                      rtl::OUString::createFromAscii(
177 			 			"com.sun.star.comp.WebDAVContentProvider" ),
178                      rtl::OUString::createFromAscii(
179 				 		WEBDAV_CONTENT_PROVIDER_SERVICE_NAME ) );
180 
181 //=========================================================================
182 //
183 // Service factory implementation.
184 //
185 //=========================================================================
186 
187 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
188 
189 //=========================================================================
190 //
191 // XContentProvider methods.
192 //
193 //=========================================================================
194 
195 // virtual
196 uno::Reference< ucb::XContent > SAL_CALL
197 ContentProvider::queryContent(
198             const uno::Reference<
199                     ucb::XContentIdentifier >& Identifier )
200     throw( ucb::IllegalIdentifierException,
201            uno::RuntimeException )
202 {
203 	// Check URL scheme...
204 
205     const rtl::OUString aScheme
206         = Identifier->getContentProviderScheme().toAsciiLowerCase();
207     if ( !aScheme.equalsAsciiL(
208             RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME ) ) &&
209          !aScheme.equalsAsciiL(
210             RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) &&
211          !aScheme.equalsAsciiL(
212             RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) &&
213          !aScheme.equalsAsciiL(
214             RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) &&
215          !aScheme.equalsAsciiL(
216             RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
217         throw ucb::IllegalIdentifierException();
218 
219 	// Normalize URL and create new Id, if nessacary.
220     rtl::OUString aURL = Identifier->getContentIdentifier();
221 
222     // At least: <scheme> + "://"
223     if ( aURL.getLength() < ( aScheme.getLength() + 3 ) )
224         throw ucb::IllegalIdentifierException();
225 
226     if ( ( aURL.getStr()[ aScheme.getLength() ]     != sal_Unicode( ':' ) ) ||
227          ( aURL.getStr()[ aScheme.getLength() + 1 ] != sal_Unicode( '/' ) ) ||
228          ( aURL.getStr()[ aScheme.getLength() + 2 ] != sal_Unicode( '/' ) ) )
229         throw ucb::IllegalIdentifierException();
230 
231     uno::Reference< ucb::XContentIdentifier > xCanonicId;
232 
233     bool bNewId = false;
234     if ( aScheme.equalsAsciiL(
235             RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) )
236     {
237         aURL = aURL.replaceAt( 0,
238                                WEBDAV_URL_SCHEME_LENGTH,
239                                rtl::OUString::createFromAscii(
240                                                     HTTP_URL_SCHEME ) );
241         bNewId = true;
242     }
243     else if ( aScheme.equalsAsciiL(
244             RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) )
245     {
246         aURL = aURL.replaceAt( 0,
247                                DAV_URL_SCHEME_LENGTH,
248                                rtl::OUString::createFromAscii(
249                                                     HTTP_URL_SCHEME ) );
250         bNewId = true;
251     }
252     else if ( aScheme.equalsAsciiL(
253             RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
254     {
255         aURL = aURL.replaceAt( 0,
256                                DAVS_URL_SCHEME_LENGTH,
257                                rtl::OUString::createFromAscii(
258                                                     HTTPS_URL_SCHEME ) );
259         bNewId = true;
260     }
261 
262     sal_Int32 nPos = aURL.lastIndexOf( '/' );
263 	if ( nPos != aURL.getLength() - 1 )
264 	{
265 		// Find second slash in URL.
266 		nPos = aURL.indexOf( '/', aURL.indexOf( '/' ) + 1 );
267 		if ( nPos == -1 )
268             throw ucb::IllegalIdentifierException();
269 
270 		nPos = aURL.indexOf( '/', nPos + 1 );
271 		if ( nPos == -1 )
272 		{
273             aURL += rtl::OUString::createFromAscii( "/" );
274             bNewId = true;
275 		}
276 	}
277 
278     if ( bNewId )
279         xCanonicId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
280     else
281         xCanonicId = Identifier;
282 
283 	osl::MutexGuard aGuard( m_aMutex );
284 
285 	// Check, if a content with given id already exists...
286     uno::Reference< ucb::XContent > xContent
287 		= queryExistingContent( xCanonicId ).get();
288 	if ( xContent.is() )
289 		return xContent;
290 
291 	// Create a new content.
292 
293 	try
294 	{
295         xContent = new ::http_dav_ucp::Content(
296                         m_xSMgr, this, xCanonicId, m_xDAVSessionFactory );
297         registerNewContent( xContent );
298 	}
299     catch ( ucb::ContentCreationException const & )
300 	{
301         throw ucb::IllegalIdentifierException();
302 	}
303 
304 	if ( !xContent->getIdentifier().is() )
305         throw ucb::IllegalIdentifierException();
306 
307 	return xContent;
308 }
309 
310