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