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