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_ucb.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32 #include <ucbhelper/contentidentifier.hxx>
33 #include "odma_provider.hxx"
34 #include "odma_content.hxx"
35 #include "odma_contentprops.hxx"
36 #include <com/sun/star/util/Date.hpp>
37 #include <com/sun/star/util/Time.hpp>
38 #include <rtl/uri.hxx>
39 #include <algorithm>
40 #include <osl/file.hxx>
41
42 using namespace com::sun::star;
43 using namespace odma;
44
45 //=========================================================================
46 //=========================================================================
47 //
48 // ContentProvider Implementation.
49 //
50 //=========================================================================
51 //=========================================================================
52 ODMHANDLE ContentProvider::m_aOdmHandle = NULL;
53
ContentProvider(const uno::Reference<lang::XMultiServiceFactory> & rSMgr)54 ContentProvider::ContentProvider(
55 const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
56 : ::ucbhelper::ContentProviderImplHelper( rSMgr )
57 {
58
59 }
60
61 //=========================================================================
62 // virtual
~ContentProvider()63 ContentProvider::~ContentProvider()
64 {
65 ContentsMap::iterator aIter = m_aContents.begin();
66 for (;aIter != m_aContents.end() ;++aIter )
67 {
68 if(aIter->second->m_bIsOpen)
69 closeDocument(aIter->first);
70 }
71 if(m_aOdmHandle)
72 {
73 NODMUnRegisterApp(m_aOdmHandle);
74 m_aOdmHandle = NULL;
75 }
76 }
77 // -----------------------------------------------------------------------------
getHandle()78 ODMHANDLE ContentProvider::getHandle()
79 {
80 if(!m_aOdmHandle)
81 {
82 ODMSTATUS odm = NODMRegisterApp(&m_aOdmHandle,ODM_API_VERSION,ODMA_ODMA_REGNAME,NULL,NULL);
83 switch(odm)
84 {
85 case ODM_SUCCESS:
86 break;
87 case ODM_E_NODMS:
88 break;
89 case ODM_E_CANTINIT:
90 break;
91 case ODM_E_VERSION:
92 break;
93 default:
94 break;
95 }
96 }
97 return m_aOdmHandle;
98 }
99 // -----------------------------------------------------------------------------
100
101 //=========================================================================
102 //
103 // XInterface methods.
104 //
105 //=========================================================================
106
107 // @@@ Add own interfaces.
108 XINTERFACE_IMPL_3( ContentProvider,
109 lang::XTypeProvider,
110 lang::XServiceInfo,
111 ucb::XContentProvider );
112
113 //=========================================================================
114 //
115 // XTypeProvider methods.
116 //
117 //=========================================================================
118
119 // @@@ Add own interfaces.
120 XTYPEPROVIDER_IMPL_3( ContentProvider,
121 lang::XTypeProvider,
122 lang::XServiceInfo,
123 ucb::XContentProvider );
124
125 //=========================================================================
126 //
127 // XServiceInfo methods.
128 //
129 //=========================================================================
130
131 // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."!
132 // @@@ Adjust service name.
133 XSERVICEINFO_IMPL_1( ContentProvider,
134 rtl::OUString::createFromAscii(
135 "com.sun.star.comp.odma.ContentProvider" ),
136 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_PROVIDER_SERVICE_NAME) ) );
137
138 //=========================================================================
139 //
140 // Service factory implementation.
141 //
142 //=========================================================================
143
144 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
145
146 //=========================================================================
147 //
148 // XContentProvider methods.
149 //
150 //=========================================================================
151
152 // virtual
queryContent(const uno::Reference<ucb::XContentIdentifier> & Identifier)153 uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent(
154 const uno::Reference< ucb::XContentIdentifier >& Identifier )
155 {
156 // Check URL scheme...
157 if(!getHandle())
158 throw ucb::IllegalIdentifierException();
159
160 rtl::OUString aScheme( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME) ) );
161 sal_Int32 nIndex = 0;
162 rtl::OUString sOdma = aScheme.getToken(3,'.',nIndex);
163 rtl::OUString sCanonicURL = Identifier->getContentIdentifier();
164 // check if url starts with odma
165 if ( !(Identifier->getContentProviderScheme().equalsIgnoreAsciiCase( aScheme ) ||
166 Identifier->getContentProviderScheme().equalsIgnoreAsciiCase( sOdma )) )
167 throw ucb::IllegalIdentifierException();
168
169 if(!( sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME_SHORT ODMA_URL_SHORT)) ||
170 sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT))))
171 throw ucb::IllegalIdentifierException();
172
173 // @@@ Further id checks may go here...
174 #if 0
175 if ( id-check-failes )
176 throw ucb::IllegalIdentifierException();
177 #endif
178
179 // @@@ Id normalization may go here...
180 #if 0
181 // Normalize URL and create new Id.
182 rtl::OUString aCanonicURL = ( Identifier->getContentIdentifier() );
183 uno::Reference< ucb::XContentIdentifier > xCanonicId
184 = new ::ucb::ContentIdentifier( m_xSMgr, aCanonicURL );
185 #else
186 uno::Reference< ucb::XContentIdentifier > xCanonicId = Identifier;
187 #endif
188
189 osl::MutexGuard aGuard( m_aMutex );
190
191 // Check, if a content with given id already exists...
192 uno::Reference< ucb::XContent > xContent
193 = queryExistingContent( xCanonicId ).get();
194 if ( xContent.is() )
195 return xContent;
196
197 // @@@ Decision, which content implementation to instantiate may be
198 // made here ( in case you have different content classes ).
199
200 // Create a new content.
201
202 sCanonicURL = convertURL(sCanonicURL);
203
204 ::rtl::Reference<ContentProperties> aProp;
205 // first check if we got an ODMA ID from outside
206 if( sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_ODMAID)))
207 {// we get an original ODMA id so we have to look for the name
208 ::rtl::OString sDocId = ::rtl::OUStringToOString(sCanonicURL,RTL_TEXTENCODING_MS_1252);
209 sal_Char* lpszDocName = new sal_Char[ODM_NAME_MAX];
210
211 ODMSTATUS odm = NODMGetDocInfo( getHandle(),
212 const_cast<sal_Char*>(sDocId.getStr()),
213 ODM_NAME,
214 lpszDocName,
215 ODM_NAME_MAX
216 );
217 if(odm == ODM_SUCCESS)
218 {
219 aProp = new ContentProperties();
220 aProp->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(lpszDocName),RTL_TEXTENCODING_ASCII_US);
221 aProp->m_sDocumentId = sDocId;
222 aProp->m_sContentType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE));
223 append(aProp);
224 }
225 delete [] lpszDocName;
226 }
227 else // we got an already fetched name here so look for it
228 {
229 // we have a valid document name
230 aProp = getContentPropertyWithTitle(sCanonicURL);
231 if(!aProp.is())
232 aProp = getContentPropertyWithSavedAsName(sCanonicURL);
233 if(!aProp.is())
234 {
235 if(sCanonicURL.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("/")))
236 { // found only the scheme
237 aProp = new ContentProperties();
238 aProp->m_sDocumentId = "/";
239 aProp->m_sTitle = sCanonicURL;
240 aProp->m_bIsFolder = sal_True;
241 aProp->m_bIsDocument = !aProp->m_bIsFolder;
242 m_aContents.insert(ContentsMap::value_type(aProp->m_sDocumentId,aProp));
243 }
244 else
245 aProp = queryContentProperty(sCanonicURL);
246 }
247 }
248 if(!aProp.is())
249 throw ucb::IllegalIdentifierException();
250
251 xContent = new Content( m_xSMgr, this, xCanonicId ,aProp);
252 registerNewContent( xContent );
253
254 if ( !xContent->getIdentifier().is() )
255 throw ucb::IllegalIdentifierException();
256
257 return xContent;
258 }
259 // -----------------------------------------------------------------------------
closeDocument(const::rtl::OString & _sDocumentId)260 void ContentProvider::closeDocument(const ::rtl::OString& _sDocumentId)
261 {
262 ContentsMap::iterator aIter = m_aContents.find(_sDocumentId);
263 if(aIter != m_aContents.end())
264 {
265 DWORD dwFlags = ODM_SILENT;
266 ODMSTATUS odm = NODMCloseDocEx( ContentProvider::getHandle(),
267 const_cast<sal_Char*>(_sDocumentId.getStr()),
268 &dwFlags,
269 0xFFFFFFFF,
270 0xFFFFFFFF,
271 NULL,
272 0);
273 OSL_ENSURE(odm == ODM_SUCCESS,"Error while closing a document!");
274 if(odm == ODM_SUCCESS)
275 aIter->second->m_bIsOpen = sal_False;
276 }
277 }
278 // -----------------------------------------------------------------------------
saveDocument(const::rtl::OString & _sDocumentId)279 void ContentProvider::saveDocument(const ::rtl::OString& _sDocumentId)
280 {
281 ContentsMap::iterator aIter = m_aContents.find(_sDocumentId);
282 if(aIter != m_aContents.end())
283 {
284 sal_Char* lpszDocId = new sal_Char[ODM_DOCID_MAX];
285 DWORD dwFlags = ODM_SILENT;
286 ODMSTATUS odm = NODMSaveDocEx(getHandle(),
287 const_cast<sal_Char*>(_sDocumentId.getStr()),
288 lpszDocId,
289 &dwFlags);
290 OSL_ENSURE(odm == ODM_SUCCESS,"Could not save document!");
291 if(odm != ODM_SUCCESS)
292 {
293 delete [] lpszDocId;
294 throw uno::Exception();
295 }
296 aIter->second->m_sDocumentId = rtl::OString(lpszDocId);
297 delete [] lpszDocId;
298 }
299 }
300 // -----------------------------------------------------------------------------
toDate(const::rtl::OString & _sSQLString)301 util::Date toDate(const ::rtl::OString& _sSQLString)
302 {
303 sal_uInt16 nYear = 0,
304 nMonth = 0,
305 nDay = 0;
306 nYear = (sal_uInt16)_sSQLString.copy(0,4).toInt32();
307 nMonth = (sal_uInt16)_sSQLString.copy(4,2).toInt32();
308 nDay = (sal_uInt16)_sSQLString.copy(6,2).toInt32();
309
310 return util::Date(nDay,nMonth,nYear);
311 }
312 //-----------------------------------------------------------------------------
toTime(const::rtl::OString & _sSQLString)313 util::Time toTime(const ::rtl::OString& _sSQLString)
314 {
315 sal_uInt16 nHour = 0,
316 nMinute = 0,
317 nSecond = 0;
318 nHour = (sal_uInt16)_sSQLString.copy(8,2).toInt32();
319 nMinute = (sal_uInt16)_sSQLString.copy(10,2).toInt32();
320 nSecond = (sal_uInt16)_sSQLString.copy(12,2).toInt32();
321
322 return util::Time(0,nHour,nMinute,nSecond);
323 }
324 //-----------------------------------------------------------------------------
toDateTime(const::rtl::OString & _sSQLString)325 util::DateTime toDateTime(const ::rtl::OString& _sSQLString)
326 {
327 util::Date aDate = toDate(_sSQLString);
328 util::Time aTime = toTime(_sSQLString);
329
330 return util::DateTime(0,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year);
331 }
332 // -----------------------------------------------------------------------------
fillDocumentProperties(const::rtl::Reference<ContentProperties> & _rProp)333 void ContentProvider::fillDocumentProperties(const ::rtl::Reference<ContentProperties>& _rProp)
334 {
335 // read some properties from the DMS
336 sal_Char* lpszDocInfo = new sal_Char[ODM_DOCID_MAX];
337 sal_Char* pDocId = const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr());
338
339 // read the create date of the document
340 ODMSTATUS odm = NODMGetDocInfo( getHandle(),
341 pDocId,
342 ODM_CREATEDDATE,
343 lpszDocInfo,
344 ODM_DOCID_MAX);
345 if(odm == ODM_SUCCESS)
346 _rProp->m_aDateCreated = toDateTime(::rtl::OString(lpszDocInfo));
347
348 // read the modified date of the document
349 odm = NODMGetDocInfo( getHandle(),
350 pDocId,
351 ODM_MODIFYDATE,
352 lpszDocInfo,
353 ODM_DOCID_MAX);
354 if(odm == ODM_SUCCESS)
355 _rProp->m_aDateModified = toDateTime(::rtl::OString(lpszDocInfo));
356
357 // read the title of the document
358 odm = NODMGetDocInfo( getHandle(),
359 pDocId,
360 ODM_TITLETEXT,
361 lpszDocInfo,
362 ODM_DOCID_MAX);
363 if(odm == ODM_SUCCESS)
364 _rProp->m_sTitle = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
365
366 // read the name of the document
367 odm = NODMGetDocInfo( getHandle(),
368 pDocId,
369 ODM_NAME,
370 lpszDocInfo,
371 ODM_DOCID_MAX);
372 if(odm == ODM_SUCCESS)
373 _rProp->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
374
375 // read the author of the document
376 odm = NODMGetDocInfo( getHandle(),
377 pDocId,
378 ODM_AUTHOR,
379 lpszDocInfo,
380 ODM_DOCID_MAX);
381 if(odm == ODM_SUCCESS)
382 _rProp->m_sAuthor = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
383
384 // read the subject of the document
385 odm = NODMGetDocInfo( getHandle(),
386 pDocId,
387 ODM_SUBJECT,
388 lpszDocInfo,
389 ODM_DOCID_MAX);
390 if(odm == ODM_SUCCESS)
391 _rProp->m_sSubject = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
392
393 // read the keywords of the document
394 odm = NODMGetDocInfo( getHandle(),
395 pDocId,
396 ODM_KEYWORDS,
397 lpszDocInfo,
398 ODM_DOCID_MAX);
399 if(odm == ODM_SUCCESS)
400 _rProp->m_sKeywords = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
401
402 /*
403 odm = NODMGetDocInfo( getHandle(),
404 const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()),
405 ODM_URL,
406 lpszDocInfo,
407 ODM_DOCID_MAX);
408 */
409 delete [] lpszDocInfo;
410 }
411 // -----------------------------------------------------------------------------
append(const::rtl::Reference<ContentProperties> & _rProp)412 void ContentProvider::append(const ::rtl::Reference<ContentProperties>& _rProp)
413 {
414 // now fill some more properties
415 fillDocumentProperties(_rProp);
416 // and append them
417 m_aContents.insert(ContentsMap::value_type(_rProp->m_sDocumentId,_rProp));
418 }
419 // -----------------------------------------------------------------------------
queryContentProperty(const::rtl::OUString & _sDocumentName)420 ::rtl::Reference<ContentProperties> ContentProvider::queryContentProperty(const ::rtl::OUString& _sDocumentName)
421 {
422 ::rtl::Reference<ContentProperties> aReturn;
423 sal_Char* lpszDMSList = new sal_Char[ODM_DMSID_MAX];
424
425 ODMSTATUS odm = NODMGetDMS(ODMA_ODMA_REGNAME, lpszDMSList);
426 if(odm == ODM_SUCCESS)
427 {
428 sal_Char* pQueryId = new sal_Char[ODM_QUERYID_MAX];
429 lpszDMSList[strlen(lpszDMSList)+1] = '\0';
430
431 ::rtl::OString sTitleText(::rtl::OUStringToOString(_sDocumentName,RTL_TEXTENCODING_ASCII_US));
432 ::rtl::OString sQuery("SELECT ODM_DOCID, ODM_NAME WHERE ODM_TITLETEXT = '");
433 sQuery += sTitleText;
434 sQuery += "'";
435
436 DWORD dwFlags = ODM_SPECIFIC;
437 odm = NODMQueryExecute(getHandle(), sQuery,dwFlags, lpszDMSList, pQueryId );
438 if(odm == ODM_SUCCESS)
439 {
440 sal_uInt16 nCount = 10;
441 sal_uInt16 nMaxCount = 10;
442 sal_Char* lpszDocId = new sal_Char[ODM_DOCID_MAX * nMaxCount];
443 sal_Char* lpszDocName = new sal_Char[ODM_NAME_MAX * nMaxCount];
444 sal_Char* lpszDocInfo = new sal_Char[ODM_DOCID_MAX];
445
446 ::rtl::OUString sContentType(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE));
447 do
448 {
449 if(nCount >= nMaxCount)
450 {
451 // get the result
452 nCount = nMaxCount;
453 odm = NODMQueryGetResults(getHandle(), pQueryId,lpszDocId, lpszDocName, ODM_NAME_MAX, (WORD*)&nCount);
454 }
455 if(odm == ODM_SUCCESS)
456 for(sal_uInt16 i = 0; i < nCount; ++i)
457 {
458 odm = NODMGetDocInfo( getHandle(),
459 &lpszDocId[ODM_DOCID_MAX*i],
460 ODM_TITLETEXT,
461 lpszDocInfo,
462 ODM_DOCID_MAX);
463 if( odm == ODM_SUCCESS && sTitleText == ::rtl::OString(lpszDocInfo))
464 {
465 aReturn = new ContentProperties();
466 aReturn->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(&lpszDocName[ODM_NAME_MAX*i]),RTL_TEXTENCODING_ASCII_US);
467 aReturn->m_sDocumentId = ::rtl::OString(&lpszDocId[ODM_DOCID_MAX*i]);
468 aReturn->m_sContentType = sContentType;
469 append(aReturn);
470 nCount = 0; // break condition from outer loop
471 break;
472 }
473 }
474 }
475 while(nCount > nMaxCount);
476
477 delete [] lpszDocInfo;
478 delete [] lpszDocId;
479 delete [] lpszDocName;
480 }
481
482 // now close the query
483 odm = NODMQueryClose(ContentProvider::getHandle(), pQueryId);
484 delete [] pQueryId;
485 }
486 delete [] lpszDMSList;
487
488
489 return aReturn;
490 }
491 // -----------------------------------------------------------------------------
getContentProperty(const::rtl::OUString & _sName,const ContentPropertiesMemberFunctor & _aFunctor) const492 ::rtl::Reference<ContentProperties> ContentProvider::getContentProperty(const ::rtl::OUString& _sName,
493 const ContentPropertiesMemberFunctor& _aFunctor) const
494 {
495 ::rtl::Reference<ContentProperties> aReturn;
496 ContentsMap::const_iterator aFind = ::std::find_if( m_aContents.begin(),
497 m_aContents.end(),
498 ::std::compose1(
499 ::std::bind2nd(_aFunctor,_sName),
500 ::std::select2nd<ContentsMap::value_type>()
501 )
502 );
503 if(aFind != m_aContents.end())
504 aReturn = aFind->second;
505 return aReturn;
506 }
507 // -----------------------------------------------------------------------------
getContentPropertyWithSavedAsName(const::rtl::OUString & _sSaveAsName) const508 ::rtl::Reference<ContentProperties> ContentProvider::getContentPropertyWithSavedAsName(const ::rtl::OUString& _sSaveAsName) const
509 {
510 ContentPropertiesMemberFunctor aFunc(::std::mem_fun(&ContentProperties::getSavedAsName));
511 return getContentProperty(_sSaveAsName,aFunc);
512 }
513 // -----------------------------------------------------------------------------
getContentPropertyWithTitle(const::rtl::OUString & _sTitle) const514 ::rtl::Reference<ContentProperties> ContentProvider::getContentPropertyWithTitle(const ::rtl::OUString& _sTitle) const
515 {
516 ContentPropertiesMemberFunctor aFunc(::std::mem_fun(&ContentProperties::getTitle));
517 return getContentProperty(_sTitle,aFunc);
518 }
519 // -----------------------------------------------------------------------------
openDoc(const::rtl::Reference<ContentProperties> & _rProp)520 ::rtl::OUString ContentProvider::openDoc(const ::rtl::Reference<ContentProperties>& _rProp)
521 {
522 OSL_ENSURE(_rProp.is(),"No valid content properties!");
523 if(!_rProp->m_bIsOpen)
524 {
525 sal_Char *pFileName = new sal_Char[ODM_FILENAME_MAX];
526
527 DWORD dwFlag = ODM_MODIFYMODE | ODM_SILENT;
528 ODMSTATUS odm = NODMOpenDoc(getHandle(), dwFlag, const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), pFileName);
529 switch(odm)
530 {
531 case ODM_E_INUSE:
532 dwFlag = ODM_VIEWMODE;
533 if( NODMOpenDoc(getHandle(), dwFlag, const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), pFileName) != ODM_SUCCESS)
534 break;
535 // else run through
536 case ODM_SUCCESS:
537 ::osl::FileBase::getFileURLFromSystemPath(::rtl::OStringToOUString(rtl::OString(pFileName),RTL_TEXTENCODING_ASCII_US)
538 ,_rProp->m_sFileURL);
539 _rProp->m_bIsOpen = sal_True;
540 break;
541 default:
542 delete [] pFileName;
543 throw uno::Exception(); // TODO give a more precise error message here
544 }
545
546 delete [] pFileName;
547 }
548 return _rProp->m_sFileURL;
549 }
550 // -----------------------------------------------------------------------------
convertURL(const::rtl::OUString & _sCanonicURL)551 ::rtl::OUString ContentProvider::convertURL(const ::rtl::OUString& _sCanonicURL)
552 {
553 sal_Int32 nPos = 0;
554 // check if url starts with odma
555 if(_sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME_SHORT ODMA_URL_SHORT)))
556 { // URL starts with odma:// so we have to remove this
557 nPos = ODMA_URL_SHORT_LGTH;
558 }
559 else if(_sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT)))
560 { // URL starts with vnd.sun.star.odma:/// so we have to remove this
561 nPos = ODMA_URL_LGTH;
562 }
563
564 ::rtl::OUString sCanonicURL = _sCanonicURL;
565 // now check what formats we allow
566 if(nPos == _sCanonicURL.getLength()) // only ask for root entry
567 sCanonicURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
568
569 if(nPos < sCanonicURL.getLength())
570 {
571 sCanonicURL = sCanonicURL.copy(nPos);
572 sCanonicURL = rtl::Uri::decode(sCanonicURL,rtl_UriDecodeWithCharset,RTL_TEXTENCODING_UTF8);
573 }
574 if(sCanonicURL.getLength() > 1 && sCanonicURL.getStr()[0] == sal_Unicode('/'))
575 {
576 sCanonicURL = sCanonicURL.copy(1);
577 if(sCanonicURL.getLength() == 1 && sCanonicURL.getStr()[0] == sal_Unicode('.'))
578 sCanonicURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
579 }
580 return sCanonicURL;
581 }
582 // -----------------------------------------------------------------------------
deleteDocument(const::rtl::Reference<ContentProperties> & _rProp)583 sal_Bool ContentProvider::deleteDocument(const ::rtl::Reference<ContentProperties>& _rProp)
584 {
585 closeDocument(_rProp->m_sDocumentId);
586 ODMSTATUS odm = NODMActivate(ContentProvider::getHandle(),
587 ODM_DELETE,
588 const_cast< sal_Char*>(_rProp->m_sDocumentId.getStr()));
589 if(odm == ODM_SUCCESS)
590 m_aContents.erase(_rProp->m_sDocumentId);
591
592 return odm == ODM_SUCCESS;
593 }
594 // -----------------------------------------------------------------------------
595