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_svtools.hxx" 26 27 #ifdef UNX 28 #include <pwd.h> 29 #include <sys/types.h> 30 #endif 31 32 #include <svtools/inettbc.hxx> 33 #include <com/sun/star/uno/Any.hxx> 34 #include <com/sun/star/uno/Reference.hxx> 35 #include <com/sun/star/beans/PropertyValue.hpp> 36 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 37 #include <com/sun/star/sdbc/XResultSet.hpp> 38 #include <com/sun/star/sdbc/XRow.hpp> 39 #include <com/sun/star/task/XInteractionHandler.hpp> 40 #include <com/sun/star/ucb/NumberedSortingInfo.hpp> 41 #include <com/sun/star/ucb/XAnyCompareFactory.hpp> 42 #include <com/sun/star/ucb/XProgressHandler.hpp> 43 #include <com/sun/star/ucb/XContentAccess.hpp> 44 #include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> 45 #include <comphelper/processfactory.hxx> 46 #include <vcl/toolbox.hxx> 47 #include <vos/thread.hxx> 48 #include <vos/mutex.hxx> 49 #include <vcl/svapp.hxx> 50 #include <unotools/historyoptions.hxx> 51 #include <svl/eitem.hxx> 52 #include <svl/stritem.hxx> 53 #include <svl/itemset.hxx> 54 #include "svl/urihelper.hxx" 55 #include <unotools/pathoptions.hxx> 56 57 #define _SVSTDARR_STRINGSDTOR 58 #include <svl/svstdarr.hxx> 59 #include <ucbhelper/commandenvironment.hxx> 60 #include <ucbhelper/content.hxx> 61 #include <unotools/localfilehelper.hxx> 62 #include <unotools/ucbhelper.hxx> 63 #include "iodlg.hrc" 64 #include <svtools/asynclink.hxx> 65 #include <svl/urlfilter.hxx> 66 67 #include <vector> 68 #include <algorithm> 69 70 // ----------------------------------------------------------------------- 71 72 using namespace ::rtl; 73 using namespace ::ucbhelper; 74 using namespace ::utl; 75 using namespace ::com::sun::star; 76 using namespace ::com::sun::star::beans; 77 using namespace ::com::sun::star::lang; 78 using namespace ::com::sun::star::sdbc; 79 using namespace ::com::sun::star::task; 80 using namespace ::com::sun::star::ucb; 81 using namespace ::com::sun::star::uno; 82 83 // ----------------------------------------------------------------------- 84 class SvtURLBox_Impl 85 { 86 public: 87 SvStringsDtor* pURLs; 88 SvStringsDtor* pCompletions; 89 const IUrlFilter* pUrlFilter; 90 ::std::vector< WildCard > m_aFilters; 91 92 static sal_Bool TildeParsing( String& aText, String& aBaseUrl ); 93 94 inline SvtURLBox_Impl( ) 95 :pURLs( NULL ) 96 ,pCompletions( NULL ) 97 ,pUrlFilter( NULL ) 98 { 99 FilterMatch::createWildCardFilterList(String(),m_aFilters); 100 } 101 }; 102 103 // ----------------------------------------------------------------------- 104 class SvtMatchContext_Impl : public ::vos::OThread 105 { 106 static ::vos::OMutex* pDirMutex; 107 108 SvStringsDtor aPickList; 109 SvStringsDtor* pCompletions; 110 SvStringsDtor* pURLs; 111 svtools::AsynchronLink aLink; 112 String aBaseURL; 113 String aText; 114 SvtURLBox* pBox; 115 sal_Bool bStop; 116 sal_Bool bOnlyDirectories; 117 sal_Bool bNoSelection; 118 119 DECL_STATIC_LINK( SvtMatchContext_Impl, Select_Impl, void* ); 120 121 virtual void SAL_CALL onTerminated( ); 122 virtual void SAL_CALL run(); 123 virtual void SAL_CALL Cancel(); 124 void Insert( const String& rCompletion, const String& rURL, sal_Bool bForce = sal_False); 125 void ReadFolder( const String& rURL, const String& rMatch, sal_Bool bSmart ); 126 void FillPicklist( SvStringsDtor& rPickList ); 127 128 public: 129 static ::vos::OMutex* GetMutex(); 130 131 SvtMatchContext_Impl( SvtURLBox* pBoxP, const String& rText ); 132 ~SvtMatchContext_Impl(); 133 void Stop(); 134 }; 135 136 ::vos::OMutex* SvtMatchContext_Impl::pDirMutex = 0; 137 138 ::vos::OMutex* SvtMatchContext_Impl::GetMutex() 139 { 140 ::vos::OGuard aGuard( ::vos::OMutex::getGlobalMutex() ); 141 if( !pDirMutex ) 142 pDirMutex = new ::vos::OMutex; 143 return pDirMutex; 144 } 145 146 //------------------------------------------------------------------------- 147 SvtMatchContext_Impl::SvtMatchContext_Impl( 148 SvtURLBox* pBoxP, const String& rText ) 149 : aLink( STATIC_LINK( this, SvtMatchContext_Impl, Select_Impl ) ) 150 , aBaseURL( pBoxP->aBaseURL ) 151 , aText( rText ) 152 , pBox( pBoxP ) 153 , bStop( sal_False ) 154 , bOnlyDirectories( pBoxP->bOnlyDirectories ) 155 , bNoSelection( pBoxP->bNoSelection ) 156 { 157 pURLs = new SvStringsDtor; 158 pCompletions = new SvStringsDtor; 159 160 aLink.CreateMutex(); 161 162 FillPicklist( aPickList ); 163 164 create(); 165 } 166 167 //------------------------------------------------------------------------- 168 SvtMatchContext_Impl::~SvtMatchContext_Impl() 169 { 170 aLink.ClearPendingCall(); 171 delete pURLs; 172 delete pCompletions; 173 } 174 175 //------------------------------------------------------------------------- 176 void SvtMatchContext_Impl::FillPicklist( SvStringsDtor& rPickList ) 177 { 178 // Einlesung der Historypickliste 179 Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( eHISTORY ); 180 sal_uInt32 nCount = seqPicklist.getLength(); 181 182 for( sal_uInt32 nItem=0; nItem < nCount; nItem++ ) 183 { 184 Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ]; 185 186 OUString sTitle; 187 INetURLObject aURL; 188 189 sal_uInt32 nPropertyCount = seqPropertySet.getLength(); 190 191 for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ ) 192 { 193 if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE ) 194 { 195 seqPropertySet[nProperty].Value >>= sTitle; 196 aURL.SetURL( sTitle ); 197 const StringPtr pStr = new String( aURL.GetMainURL( INetURLObject::DECODE_WITH_CHARSET ) ); 198 rPickList.Insert( pStr, (sal_uInt16) nItem ); 199 break; 200 } 201 } 202 } 203 } 204 205 //------------------------------------------------------------------------- 206 void SAL_CALL SvtMatchContext_Impl::Cancel() 207 { 208 // Cancel button pressed 209 terminate(); 210 } 211 212 //------------------------------------------------------------------------- 213 void SvtMatchContext_Impl::Stop() 214 { 215 bStop = sal_True; 216 217 if( isRunning() ) 218 terminate(); 219 } 220 221 //------------------------------------------------------------------------- 222 void SvtMatchContext_Impl::onTerminated( ) 223 { 224 aLink.Call( this ); 225 } 226 227 //------------------------------------------------------------------------- 228 // This method is called via AsynchronLink, so it has the SolarMutex and 229 // calling solar code ( VCL ... ) is safe. It is called when the thread is 230 // terminated ( finished work or stopped ). Cancelling the thread via 231 // Cancellable does not not discard the information gained so far, it 232 // inserts all collected completions into the listbox. 233 234 IMPL_STATIC_LINK( SvtMatchContext_Impl, Select_Impl, void*, ) 235 { 236 // avoid recursion through cancel button 237 if( pThis->bStop ) 238 { 239 // completions was stopped, no display 240 delete pThis; 241 return 0; 242 } 243 244 SvtURLBox* pBox = pThis->pBox; 245 pBox->bAutoCompleteMode = sal_True; 246 247 // did we filter completions which otherwise would have been valid? 248 // (to be filled below) 249 bool bValidCompletionsFiltered = false; 250 251 // insert all completed strings into the listbox 252 pBox->Clear(); 253 254 for( sal_uInt16 nPos = 0; nPos<pThis->pCompletions->Count(); nPos++ ) 255 { 256 String sCompletion( *(*pThis->pCompletions)[nPos] ); 257 258 // convert the file into an URL 259 String sURL( sCompletion ); 260 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCompletion, sURL ); 261 // note: if this doesn't work, we're not interested in: we're checking the 262 // untouched sCompletion then 263 264 if ( pBox->pImp->pUrlFilter ) 265 { 266 if ( !pBox->pImp->pUrlFilter->isUrlAllowed( sURL ) ) 267 { // this URL is not allowed 268 bValidCompletionsFiltered = true; 269 continue; 270 } 271 } 272 if (( sURL.Len() > 0 ) && ( sURL.GetChar(sURL.Len()-1) != '/' )) 273 { 274 String sUpperURL( sURL ); 275 sUpperURL.ToUpperAscii(); 276 277 ::std::vector< WildCard >::const_iterator aMatchingFilter = 278 ::std::find_if( 279 pBox->pImp->m_aFilters.begin(), 280 pBox->pImp->m_aFilters.end(), 281 FilterMatch( sUpperURL ) 282 ); 283 if ( aMatchingFilter == pBox->pImp->m_aFilters.end() ) 284 285 { // this URL is not allowed 286 bValidCompletionsFiltered = true; 287 continue; 288 } 289 } 290 291 pBox->InsertEntry( sCompletion ); 292 } 293 294 if( !pThis->bNoSelection && pThis->pCompletions->Count() && !bValidCompletionsFiltered ) 295 { 296 // select the first one 297 String aTmp( pBox->GetEntry(0) ); 298 pBox->SetText( aTmp ); 299 pBox->SetSelection( Selection( pThis->aText.Len(), aTmp.Len() ) ); 300 } 301 302 // transfer string lists to listbox and forget them 303 delete pBox->pImp->pURLs; 304 delete pBox->pImp->pCompletions; 305 pBox->pImp->pURLs = pThis->pURLs; 306 pBox->pImp->pCompletions = pThis->pCompletions; 307 pThis->pURLs = NULL; 308 pThis->pCompletions = NULL; 309 310 // force listbox to resize ( it may be open ) 311 pBox->Resize(); 312 313 // the box has this control as a member so we have to set that member 314 // to zero before deleting ourself. 315 pBox->pCtx = NULL; 316 delete pThis; 317 318 return 0; 319 } 320 321 //------------------------------------------------------------------------- 322 void SvtMatchContext_Impl::Insert( const String& rCompletion, 323 const String& rURL, 324 sal_Bool bForce ) 325 { 326 if( !bForce ) 327 { 328 // avoid doubles 329 for( sal_uInt16 nPos = pCompletions->Count(); nPos--; ) 330 if( *(*pCompletions)[ nPos ] == rCompletion ) 331 return; 332 } 333 334 const StringPtr pCompletion = new String( rCompletion ); 335 pCompletions->Insert( pCompletion, pCompletions->Count() ); 336 const StringPtr pURL = new String( rURL ); 337 pURLs->Insert( pURL, pURLs->Count() ); 338 } 339 340 //------------------------------------------------------------------------- 341 void SvtMatchContext_Impl::ReadFolder( const String& rURL, 342 const String& rMatch, 343 sal_Bool bSmart ) 344 { 345 // check folder to scan 346 if( !UCBContentHelper::IsFolder( rURL ) ) 347 return; 348 349 sal_Bool bPureHomePath = sal_False; 350 #ifdef UNX 351 bPureHomePath = aText.Search( '~' ) == 0 && aText.Search( '/' ) == STRING_NOTFOUND; 352 #endif 353 354 sal_Bool bExectMatch = bPureHomePath 355 || aText.CompareToAscii( "." ) == COMPARE_EQUAL 356 || (aText.Len() > 1 && aText.Copy( aText.Len() - 2, 2 ).CompareToAscii( "/." ) == COMPARE_EQUAL) 357 || (aText.Len() > 2 && aText.Copy( aText.Len() - 3, 3 ).CompareToAscii( "/.." ) == COMPARE_EQUAL); 358 359 // for pure home pathes ( ~username ) the '.' at the end of rMatch 360 // means that it poits to root catalog 361 // this is done only for file contents since home pathes parsing is usefull only for them 362 if ( bPureHomePath && rMatch.Equals( String::CreateFromAscii( "file:///." ) ) ) 363 { 364 // a home that refers to / 365 366 String aNewText( aText ); 367 aNewText += '/'; 368 Insert( aNewText, rURL, sal_True ); 369 370 return; 371 } 372 373 // string to match with 374 INetURLObject aMatchObj( rMatch ); 375 String aMatchName; 376 377 if ( rURL != String(aMatchObj.GetMainURL( INetURLObject::NO_DECODE ) )) 378 { 379 aMatchName = aMatchObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 380 381 // matching is always done case insensitive, but completion will be case sensitive and case preserving 382 aMatchName.ToLowerAscii(); 383 384 // if the matchstring ends with a slash, we must search for this also 385 if ( rMatch.GetChar(rMatch.Len()-1) == '/' ) 386 aMatchName += '/'; 387 } 388 389 xub_StrLen nMatchLen = aMatchName.Len(); 390 391 INetURLObject aFolderObj( rURL ); 392 DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" ); 393 394 try 395 { 396 uno::Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 397 398 Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), 399 new ::ucbhelper::CommandEnvironment( uno::Reference< XInteractionHandler >(), 400 uno::Reference< XProgressHandler >() ) ); 401 uno::Reference< XResultSet > xResultSet; 402 Sequence< OUString > aProps(2); 403 OUString* pProps = aProps.getArray(); 404 pProps[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); 405 pProps[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ); 406 407 try 408 { 409 uno::Reference< XDynamicResultSet > xDynResultSet; 410 ResultSetInclude eInclude = INCLUDE_FOLDERS_AND_DOCUMENTS; 411 if ( bOnlyDirectories ) 412 eInclude = INCLUDE_FOLDERS_ONLY; 413 414 xDynResultSet = aCnt.createDynamicCursor( aProps, eInclude ); 415 416 uno::Reference < XAnyCompareFactory > xCompare; 417 uno::Reference < XSortedDynamicResultSetFactory > xSRSFac( 418 xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SortedDynamicResultSetFactory") ) ), UNO_QUERY ); 419 420 Sequence< NumberedSortingInfo > aSortInfo( 2 ); 421 NumberedSortingInfo* pInfo = aSortInfo.getArray(); 422 pInfo[ 0 ].ColumnIndex = 2; 423 pInfo[ 0 ].Ascending = sal_False; 424 pInfo[ 1 ].ColumnIndex = 1; 425 pInfo[ 1 ].Ascending = sal_True; 426 427 uno::Reference< XDynamicResultSet > xDynamicResultSet; 428 xDynamicResultSet = 429 xSRSFac->createSortedDynamicResultSet( xDynResultSet, aSortInfo, xCompare ); 430 431 if ( xDynamicResultSet.is() ) 432 { 433 xResultSet = xDynamicResultSet->getStaticResultSet(); 434 } 435 } 436 catch( ::com::sun::star::uno::Exception& ) {} 437 438 if ( xResultSet.is() ) 439 { 440 uno::Reference< XRow > xRow( xResultSet, UNO_QUERY ); 441 uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); 442 443 try 444 { 445 while ( schedule() && xResultSet->next() ) 446 { 447 String aURL = xContentAccess->queryContentIdentifierString(); 448 String aTitle = xRow->getString(1); 449 sal_Bool bIsFolder = xRow->getBoolean(2); 450 451 // matching is always done case insensitive, but completion will be case sensitive and case preserving 452 aTitle.ToLowerAscii(); 453 454 if ( 455 !nMatchLen || 456 (bExectMatch && aMatchName.Equals(aTitle)) || 457 (!bExectMatch && aMatchName.CompareTo(aTitle, nMatchLen) == COMPARE_EQUAL) 458 ) 459 { 460 // all names fit if matchstring is empty 461 INetURLObject aObj( aURL ); 462 sal_Unicode aDelimiter = '/'; 463 if ( bSmart ) 464 // when parsing is done "smart", the delimiter must be "guessed" 465 aObj.getFSysPath( (INetURLObject::FSysStyle)(INetURLObject::FSYS_DETECT & ~INetURLObject::FSYS_VOS), &aDelimiter ); 466 467 if ( bIsFolder ) 468 aObj.setFinalSlash(); 469 470 // get the last name of the URL 471 String aMatch = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 472 String aInput( aText ); 473 if ( nMatchLen ) 474 { 475 if ((aText.Len() && aText.GetChar(aText.Len() - 1) == '.') || bPureHomePath) 476 { 477 // if a "special folder" URL was typed, don't touch the user input 478 aMatch.Erase( 0, nMatchLen ); 479 } 480 else 481 { 482 // make the user input case preserving 483 DBG_ASSERT( aInput.Len() >= nMatchLen, "Suspicious Matching!" ); 484 aInput.Erase( aInput.Len() - nMatchLen ); 485 } 486 } 487 488 aInput += aMatch; 489 490 // folders should get a final slash automatically 491 if ( bIsFolder ) 492 aInput += aDelimiter; 493 494 Insert( aInput, aObj.GetMainURL( INetURLObject::NO_DECODE ), sal_True ); 495 } 496 } 497 } 498 catch( ::com::sun::star::uno::Exception& ) 499 { 500 } 501 } 502 } 503 catch( ::com::sun::star::uno::Exception& ) 504 { 505 } 506 } 507 508 //------------------------------------------------------------------------- 509 String SvtURLBox::ParseSmart( String aText, String aBaseURL, String aWorkDir ) 510 { 511 String aMatch; 512 513 // parse ~ for Unix systems 514 // does nothing for Windows 515 if( !SvtURLBox_Impl::TildeParsing( aText, aBaseURL ) ) 516 return String(); 517 518 INetURLObject aURLObject; 519 if( aBaseURL.Len() ) 520 { 521 INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL ); 522 523 // if a base URL is set the string may be parsed relative 524 if( aText.Search( '/' ) == 0 ) 525 { 526 // text starting with slashes means absolute file URLs 527 String aTemp = INetURLObject::GetScheme( eBaseProt ); 528 529 // file URL must be correctly encoded! 530 String aTextURL = INetURLObject::encode( aText, INetURLObject::PART_FPATH, 531 '%', INetURLObject::ENCODE_ALL ); 532 aTemp += aTextURL; 533 534 INetURLObject aTmp( aTemp ); 535 if ( !aTmp.HasError() && aTmp.GetProtocol() != INET_PROT_NOT_VALID ) 536 aMatch = aTmp.GetMainURL( INetURLObject::NO_DECODE ); 537 } 538 else 539 { 540 String aSmart( aText ); 541 INetURLObject aObj( aBaseURL ); 542 543 // HRO: I suppose this hack should only be done for Windows !!!??? 544 #ifdef WNT 545 // HRO: INetURLObject::smatRel2Abs does not recognize '\\' as a relative path 546 // but in case of "\\\\" INetURLObject is right - this is an absolute path ! 547 548 if( aText.Search( '\\' ) == 0 && (aText.Len() < 2 || aText.GetChar( 1 ) != '\\') ) 549 { 550 // cut to first segment 551 String aTmp = INetURLObject::GetScheme( eBaseProt ); 552 aTmp += '/'; 553 aTmp += String(aObj.getName( 0, true, INetURLObject::DECODE_WITH_CHARSET )); 554 aObj.SetURL( aTmp ); 555 556 aSmart.Erase(0,1); 557 } 558 #endif 559 // base URL must be a directory ! 560 aObj.setFinalSlash(); 561 562 // take base URL and append current input 563 bool bWasAbsolute = sal_False; 564 #ifdef UNX 565 // don't support FSYS_MAC under Unix, because here ':' is a valid character for a filename 566 INetURLObject::FSysStyle eStyle = static_cast< INetURLObject::FSysStyle >( INetURLObject::FSYS_VOS | INetURLObject::FSYS_UNX | INetURLObject::FSYS_DOS ); 567 // encode file URL correctly 568 aSmart = INetURLObject::encode( aSmart, INetURLObject::PART_FPATH, '%', INetURLObject::ENCODE_ALL ); 569 INetURLObject aTmp( aObj.smartRel2Abs( 570 aSmart, bWasAbsolute, false, INetURLObject::WAS_ENCODED, RTL_TEXTENCODING_UTF8, false, eStyle ) ); 571 #else 572 INetURLObject aTmp( aObj.smartRel2Abs( aSmart, bWasAbsolute ) ); 573 #endif 574 575 if ( aText.GetChar( aText.Len() - 1 ) == '.' ) 576 // INetURLObject appends a final slash for the directories "." and "..", this is a bug! 577 // Remove it as a workaround 578 aTmp.removeFinalSlash(); 579 if ( !aTmp.HasError() && aTmp.GetProtocol() != INET_PROT_NOT_VALID ) 580 aMatch = aTmp.GetMainURL( INetURLObject::NO_DECODE ); 581 } 582 } 583 else 584 { 585 ::utl::LocalFileHelper::ConvertSystemPathToURL( aText, aWorkDir, aMatch ); 586 } 587 588 return aMatch; 589 } 590 591 //------------------------------------------------------------------------- 592 void SvtMatchContext_Impl::run() 593 { 594 ::vos::OGuard aGuard( GetMutex() ); 595 if( bStop ) 596 // have we been stopped while we were waiting for the mutex? 597 return; 598 599 // Reset match lists 600 pCompletions->Remove( 0, pCompletions->Count() ); 601 pURLs->Remove( 0, pURLs->Count() ); 602 603 // check for input 604 sal_uInt16 nTextLen = aText.Len(); 605 if ( !nTextLen ) 606 return; 607 608 if( aText.Search( '*' ) != STRING_NOTFOUND || aText.Search( '?' ) != STRING_NOTFOUND ) 609 // no autocompletion for wildcards 610 return; 611 612 String aMatch; 613 String aWorkDir( SvtPathOptions().GetWorkPath() ); 614 INetProtocol eProt = INetURLObject::CompareProtocolScheme( aText ); 615 INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL ); 616 if ( !aBaseURL.Len() ) 617 eBaseProt = INetURLObject::CompareProtocolScheme( aWorkDir ); 618 INetProtocol eSmartProt = pBox->GetSmartProtocol(); 619 620 // if the user input is a valid URL, go on with it 621 // otherwise it could be parsed smart with a predefined smart protocol 622 // ( or if this is not set with the protocol of a predefined base URL ) 623 if( eProt == INET_PROT_NOT_VALID || eProt == eSmartProt || (eSmartProt == INET_PROT_NOT_VALID && eProt == eBaseProt) ) 624 { 625 // not stopped yet ? 626 if( schedule() ) 627 { 628 if ( eProt == INET_PROT_NOT_VALID ) 629 aMatch = SvtURLBox::ParseSmart( aText, aBaseURL, aWorkDir ); 630 else 631 aMatch = aText; 632 if ( aMatch.Len() ) 633 { 634 INetURLObject aURLObject( aMatch ); 635 String aMainURL( aURLObject.GetMainURL( INetURLObject::NO_DECODE ) ); 636 if ( aMainURL.Len() ) 637 { 638 // if text input is a directory, it must be part of the match list! Until then it is scanned 639 if ( UCBContentHelper::IsFolder( aMainURL ) && aURLObject.hasFinalSlash() ) 640 Insert( aText, aMatch ); 641 else 642 // otherwise the parent folder will be taken 643 aURLObject.removeSegment(); 644 645 // scan directory and insert all matches 646 ReadFolder( aURLObject.GetMainURL( INetURLObject::NO_DECODE ), aMatch, eProt == INET_PROT_NOT_VALID ); 647 } 648 } 649 } 650 } 651 652 if ( bOnlyDirectories ) 653 // don't scan history picklist if only directories are allowed, picklist contains only files 654 return; 655 656 sal_Bool bFull = sal_False; 657 int nCount = aPickList.Count(); 658 659 INetURLObject aCurObj; 660 String aEmpty, aCurString, aCurMainURL; 661 INetURLObject aObj; 662 aObj.SetSmartProtocol( eSmartProt == INET_PROT_NOT_VALID ? INET_PROT_HTTP : eSmartProt ); 663 for( ;; ) 664 { 665 for( sal_uInt16 nPos = 0; schedule() && nPos < nCount; nPos++ ) 666 { 667 aCurObj.SetURL( *aPickList.GetObject( nPos ) ); 668 aCurObj.SetSmartURL( aCurObj.GetURLNoPass()); 669 aCurMainURL = aCurObj.GetMainURL( INetURLObject::NO_DECODE ); 670 671 if( eProt != INET_PROT_NOT_VALID && aCurObj.GetProtocol() != eProt ) 672 continue; 673 674 if( eSmartProt != INET_PROT_NOT_VALID && aCurObj.GetProtocol() != eSmartProt ) 675 continue; 676 677 switch( aCurObj.GetProtocol() ) 678 { 679 case INET_PROT_HTTP: 680 case INET_PROT_HTTPS: 681 case INET_PROT_FTP: 682 { 683 if( eProt == INET_PROT_NOT_VALID && !bFull ) 684 { 685 aObj.SetSmartURL( aText ); 686 if( aObj.GetURLPath().getLength() > 1 ) 687 continue; 688 } 689 690 aCurString = aCurMainURL; 691 if( eProt == INET_PROT_NOT_VALID ) 692 { 693 // try if text matches the scheme 694 String aScheme( INetURLObject::GetScheme( aCurObj.GetProtocol() ) ); 695 if ( aText.CompareIgnoreCaseToAscii( aScheme, aText.Len() ) == COMPARE_EQUAL && aText.Len() < aScheme.Len() ) 696 { 697 if( bFull ) 698 aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE ); 699 else 700 { 701 aCurObj.SetMark( aEmpty ); 702 aCurObj.SetParam( aEmpty ); 703 aCurObj.SetURLPath( aEmpty ); 704 aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE ); 705 } 706 707 Insert( aMatch, aMatch ); 708 } 709 710 // now try smart matching 711 aCurString.Erase( 0, aScheme.Len() ); 712 } 713 714 if( aText.CompareIgnoreCaseToAscii( aCurString, aText.Len() )== COMPARE_EQUAL ) 715 { 716 if( bFull ) 717 aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE ); 718 else 719 { 720 aCurObj.SetMark( aEmpty ); 721 aCurObj.SetParam( aEmpty ); 722 aCurObj.SetURLPath( aEmpty ); 723 aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE ); 724 } 725 726 String aURL( aMatch ); 727 if( eProt == INET_PROT_NOT_VALID ) 728 aMatch.Erase( 0, sal::static_int_cast< xub_StrLen >(INetURLObject::GetScheme( aCurObj.GetProtocol() ).getLength()) ); 729 730 if( aText.Len() < aMatch.Len() ) 731 Insert( aMatch, aURL ); 732 733 continue; 734 } 735 break; 736 } 737 default: 738 { 739 if( bFull ) 740 continue; 741 742 if( aText.CompareTo( aCurMainURL, aText.Len() ) == COMPARE_EQUAL ) 743 { 744 if( aText.Len() < aCurMainURL.Len() ) 745 Insert( aCurMainURL, aCurMainURL ); 746 747 continue; 748 } 749 break; 750 } 751 } 752 } 753 754 if( !bFull ) 755 bFull = sal_True; 756 else 757 break; 758 } 759 760 return; 761 } 762 763 //------------------------------------------------------------------------- 764 //------------------------------------------------------------------------- 765 //------------------------------------------------------------------------- 766 void SvtURLBox::TryAutoComplete( sal_Bool bForce ) 767 { 768 if( Application::AnyInput( INPUT_KEYBOARD ) ) return; 769 770 String aMatchString; 771 String aCurText = GetText(); 772 Selection aSelection( GetSelection() ); 773 if( aSelection.Max() != aCurText.Len() && !bForce ) 774 return; 775 sal_uInt16 nLen = (sal_uInt16)aSelection.Min(); 776 aCurText.Erase( nLen ); 777 if( aCurText.Len() && bIsAutoCompleteEnabled ) 778 { 779 if ( pCtx ) 780 { 781 pCtx->Stop(); 782 pCtx = NULL; 783 } 784 pCtx = new SvtMatchContext_Impl( this, aCurText ); 785 } 786 } 787 788 //------------------------------------------------------------------------- 789 SvtURLBox::SvtURLBox( Window* pParent, INetProtocol eSmart ) 790 : ComboBox( pParent , WB_DROPDOWN | WB_AUTOSIZE | WB_AUTOHSCROLL ), 791 pCtx( 0 ), 792 eSmartProtocol( eSmart ), 793 bAutoCompleteMode( sal_False ), 794 bOnlyDirectories( sal_False ), 795 bTryAutoComplete( sal_False ), 796 bCtrlClick( sal_False ), 797 bHistoryDisabled( sal_False ), 798 bNoSelection( sal_False ), 799 bIsAutoCompleteEnabled( sal_True ) 800 { 801 ImplInit(); 802 803 if ( GetDesktopRectPixel().GetWidth() > 800 ) 804 SetSizePixel( Size( 300, 240 ) ); 805 else 806 SetSizePixel( Size( 225, 240 ) ); 807 } 808 809 //------------------------------------------------------------------------- 810 SvtURLBox::SvtURLBox( Window* pParent, WinBits _nStyle, INetProtocol eSmart ) 811 : ComboBox( pParent, _nStyle ), 812 pCtx( 0 ), 813 eSmartProtocol( eSmart ), 814 bAutoCompleteMode( sal_False ), 815 bOnlyDirectories( sal_False ), 816 bTryAutoComplete( sal_False ), 817 bCtrlClick( sal_False ), 818 bHistoryDisabled( sal_False ), 819 bNoSelection( sal_False ), 820 bIsAutoCompleteEnabled( sal_True ) 821 { 822 ImplInit(); 823 } 824 825 //------------------------------------------------------------------------- 826 SvtURLBox::SvtURLBox( Window* pParent, const ResId& _rResId, INetProtocol eSmart ) 827 : ComboBox( pParent , _rResId ), 828 pCtx( 0 ), 829 eSmartProtocol( eSmart ), 830 bAutoCompleteMode( sal_False ), 831 bOnlyDirectories( sal_False ), 832 bTryAutoComplete( sal_False ), 833 bCtrlClick( sal_False ), 834 bHistoryDisabled( sal_False ), 835 bNoSelection( sal_False ), 836 bIsAutoCompleteEnabled( sal_True ) 837 { 838 ImplInit(); 839 } 840 841 //------------------------------------------------------------------------- 842 void SvtURLBox::ImplInit() 843 { 844 pImp = new SvtURLBox_Impl(); 845 846 if ( GetHelpId().getLength() == 0 ) 847 SetHelpId( ".uno:OpenURL" ); 848 EnableAutocomplete( sal_False ); 849 850 SetText( String() ); 851 852 GetSubEdit()->SetAutocompleteHdl( LINK( this, SvtURLBox, AutoCompleteHdl_Impl ) ); 853 UpdatePicklistForSmartProtocol_Impl(); 854 } 855 856 //------------------------------------------------------------------------- 857 SvtURLBox::~SvtURLBox() 858 { 859 if( pCtx ) 860 { 861 pCtx->Stop(); 862 pCtx = NULL; 863 } 864 865 delete pImp->pURLs; 866 delete pImp->pCompletions; 867 delete pImp; 868 } 869 870 //------------------------------------------------------------------------- 871 void SvtURLBox::UpdatePickList( ) 872 { 873 if( pCtx ) 874 { 875 pCtx->Stop(); 876 pCtx = NULL; 877 } 878 879 String sText = GetText(); 880 if ( sText.Len() && bIsAutoCompleteEnabled ) 881 pCtx = new SvtMatchContext_Impl( this, sText ); 882 } 883 884 //------------------------------------------------------------------------- 885 void SvtURLBox::SetSmartProtocol( INetProtocol eProt ) 886 { 887 if ( eSmartProtocol != eProt ) 888 { 889 eSmartProtocol = eProt; 890 UpdatePicklistForSmartProtocol_Impl(); 891 } 892 } 893 894 //------------------------------------------------------------------------- 895 void SvtURLBox::UpdatePicklistForSmartProtocol_Impl() 896 { 897 Clear(); 898 if ( !bHistoryDisabled ) 899 { 900 // read history pick list 901 Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( eHISTORY ); 902 sal_uInt32 nCount = seqPicklist.getLength(); 903 INetURLObject aCurObj; 904 905 for( sal_uInt32 nItem=0; nItem < nCount; nItem++ ) 906 { 907 Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ]; 908 909 OUString sURL; 910 911 sal_uInt32 nPropertyCount = seqPropertySet.getLength(); 912 913 for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ ) 914 { 915 if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL ) 916 { 917 seqPropertySet[nProperty].Value >>= sURL; 918 aCurObj.SetURL( sURL ); 919 920 if ( sURL.getLength() && ( eSmartProtocol != INET_PROT_NOT_VALID ) ) 921 { 922 if( aCurObj.GetProtocol() != eSmartProtocol ) 923 break; 924 } 925 926 String aURL( aCurObj.GetMainURL( INetURLObject::DECODE_WITH_CHARSET ) ); 927 928 if ( aURL.Len() && ( !pImp->pUrlFilter || pImp->pUrlFilter->isUrlAllowed( aURL ) ) ) 929 { 930 sal_Bool bFound = (aURL.GetChar(aURL.Len()-1) == '/' ); 931 if ( !bFound ) 932 { 933 String aUpperURL( aURL ); 934 aUpperURL.ToUpperAscii(); 935 936 bFound 937 = (::std::find_if( 938 pImp->m_aFilters.begin(), 939 pImp->m_aFilters.end(), 940 FilterMatch( aUpperURL ) ) 941 != pImp->m_aFilters.end()); 942 } 943 if ( bFound ) 944 { 945 String aFile; 946 if (::utl::LocalFileHelper::ConvertURLToSystemPath(aURL,aFile)) 947 InsertEntry(aFile); 948 else 949 InsertEntry(aURL); 950 } 951 } 952 break; 953 } 954 } 955 } 956 } 957 } 958 959 //------------------------------------------------------------------------- 960 sal_Bool SvtURLBox::ProcessKey( const KeyCode& rKey ) 961 { 962 // every key input stops the current matching thread 963 if( pCtx ) 964 { 965 pCtx->Stop(); 966 pCtx = NULL; 967 } 968 969 KeyCode aCode( rKey.GetCode() ); 970 if ( aCode == KEY_RETURN && GetText().Len() ) 971 { 972 // wait for completion of matching thread 973 ::vos::OGuard aGuard( SvtMatchContext_Impl::GetMutex() ); 974 975 if ( bAutoCompleteMode ) 976 { 977 // reset picklist 978 bAutoCompleteMode = sal_False; 979 Selection aSelection( GetSelection() ); 980 SetSelection( Selection( aSelection.Min(), aSelection.Min() ) ); 981 if ( bOnlyDirectories ) 982 Clear(); 983 else 984 UpdatePicklistForSmartProtocol_Impl(); 985 Resize(); 986 } 987 988 bCtrlClick = rKey.IsMod1(); 989 sal_Bool bHandled = sal_False; 990 if ( GetOpenHdl().IsSet() ) 991 { 992 bHandled = sal_True; 993 GetOpenHdl().Call(this); 994 } 995 else if ( GetSelectHdl().IsSet() ) 996 { 997 bHandled = sal_True; 998 GetSelectHdl().Call(this); 999 } 1000 1001 bCtrlClick = sal_False; 1002 1003 ClearModifyFlag(); 1004 return bHandled; 1005 } 1006 else if ( aCode == KEY_RETURN && !GetText().Len() && GetOpenHdl().IsSet() ) 1007 { 1008 // for file dialog 1009 bAutoCompleteMode = sal_False; 1010 GetOpenHdl().Call(this); 1011 return sal_True; 1012 } 1013 else if( aCode == KEY_ESCAPE ) 1014 { 1015 Selection aSelection( GetSelection() ); 1016 if ( bAutoCompleteMode || aSelection.Min() != aSelection.Max() ) 1017 { 1018 SetSelection( Selection( aSelection.Min(), aSelection.Min() ) ); 1019 if ( bOnlyDirectories ) 1020 Clear(); 1021 else 1022 UpdatePicklistForSmartProtocol_Impl(); 1023 Resize(); 1024 } 1025 else 1026 { 1027 return sal_False; 1028 } 1029 1030 bAutoCompleteMode = sal_False; 1031 return sal_True; 1032 } 1033 else 1034 { 1035 return sal_False; 1036 } 1037 } 1038 1039 //------------------------------------------------------------------------- 1040 void SvtURLBox::Modify() 1041 { 1042 ComboBox::Modify(); 1043 } 1044 1045 //------------------------------------------------------------------------- 1046 long SvtURLBox::PreNotify( NotifyEvent& rNEvt ) 1047 { 1048 if( rNEvt.GetWindow() == GetSubEdit() && rNEvt.GetType() == EVENT_KEYINPUT ) 1049 { 1050 1051 const KeyEvent& rEvent = *rNEvt.GetKeyEvent(); 1052 const KeyCode& rKey = rEvent.GetKeyCode(); 1053 KeyCode aCode( rKey.GetCode() ); 1054 if( ProcessKey( rKey ) ) 1055 { 1056 return sal_True; 1057 } 1058 else if( ( aCode == KEY_UP || aCode == KEY_DOWN ) && !rKey.IsMod2() ) 1059 { 1060 Selection aSelection( GetSelection() ); 1061 sal_uInt16 nLen = (sal_uInt16)aSelection.Min(); 1062 GetSubEdit()->KeyInput( rEvent ); 1063 SetSelection( Selection( nLen, GetText().Len() ) ); 1064 return sal_True; 1065 } 1066 1067 if ( MatchesPlaceHolder( GetText() ) ) 1068 { 1069 // set the selection so a key stroke will overwrite 1070 // the placeholder rather than edit it 1071 SetSelection( Selection( 0, GetText().Len() ) ); 1072 } 1073 } 1074 1075 return ComboBox::PreNotify( rNEvt ); 1076 } 1077 1078 //------------------------------------------------------------------------- 1079 IMPL_LINK( SvtURLBox, AutoCompleteHdl_Impl, void*, EMPTYARG ) 1080 { 1081 if ( GetSubEdit()->GetAutocompleteAction() == AUTOCOMPLETE_KEYINPUT ) 1082 { 1083 TryAutoComplete( sal_False ); 1084 return 1L; 1085 } 1086 1087 return 0L; 1088 } 1089 1090 //------------------------------------------------------------------------- 1091 long SvtURLBox::Notify( NotifyEvent &rEvt ) 1092 { 1093 if ( EVENT_GETFOCUS == rEvt.GetType() ) 1094 { 1095 #ifndef UNX 1096 // pb: don't select automatically on unix #93251# 1097 SetSelection( Selection( 0, GetText().Len() ) ); 1098 #endif 1099 } 1100 else if ( EVENT_LOSEFOCUS == rEvt.GetType() ) 1101 { 1102 if( !GetText().Len() ) 1103 ClearModifyFlag(); 1104 if ( pCtx ) 1105 { 1106 pCtx->Stop(); 1107 pCtx = NULL; 1108 } 1109 } 1110 1111 return ComboBox::Notify( rEvt ); 1112 } 1113 1114 //------------------------------------------------------------------------- 1115 void SvtURLBox::Select() 1116 { 1117 ComboBox::Select(); 1118 ClearModifyFlag(); 1119 } 1120 1121 //------------------------------------------------------------------------- 1122 void SvtURLBox::SetOnlyDirectories( sal_Bool bDir ) 1123 { 1124 bOnlyDirectories = bDir; 1125 if ( bOnlyDirectories ) 1126 Clear(); 1127 } 1128 1129 //------------------------------------------------------------------------- 1130 void SvtURLBox::SetNoURLSelection( sal_Bool bSet ) 1131 { 1132 bNoSelection = bSet; 1133 } 1134 1135 //------------------------------------------------------------------------- 1136 String SvtURLBox::GetURL() 1137 { 1138 // wait for end of autocompletion 1139 ::vos::OGuard aGuard( SvtMatchContext_Impl::GetMutex() ); 1140 1141 String aText( GetText() ); 1142 if ( MatchesPlaceHolder( aText ) ) 1143 return aPlaceHolder; 1144 // try to get the right case preserving URL from the list of URLs 1145 if ( pImp->pCompletions && pImp->pURLs ) 1146 { 1147 for( sal_uInt16 nPos=0; nPos<pImp->pCompletions->Count(); nPos++ ) 1148 { 1149 #ifdef DBG_UTIL 1150 String aTmp( *(*pImp->pCompletions)[ nPos ] ); 1151 #endif 1152 if( *(*pImp->pCompletions)[ nPos ] == aText ) 1153 return *(*pImp->pURLs)[nPos]; 1154 } 1155 } 1156 1157 #ifdef WNT 1158 // erase trailing spaces on Windows since thay are invalid on this OS and 1159 // most of the time they are inserted by accident via copy / paste 1160 aText.EraseTrailingChars(); 1161 if ( !aText.Len() ) 1162 return aText; 1163 // #i9739# - 2002-12-03 - fs@openoffice.org 1164 #endif 1165 1166 INetURLObject aObj( aText ); 1167 if( aText.Search( '*' ) != STRING_NOTFOUND || aText.Search( '?' ) != STRING_NOTFOUND ) 1168 { 1169 // no autocompletion for wildcards 1170 INetURLObject aTempObj; 1171 if ( eSmartProtocol != INET_PROT_NOT_VALID ) 1172 aTempObj.SetSmartProtocol( eSmartProtocol ); 1173 if ( aTempObj.SetSmartURL( aText ) ) 1174 return aTempObj.GetMainURL( INetURLObject::NO_DECODE ); 1175 else 1176 return aText; 1177 } 1178 1179 if ( aObj.GetProtocol() == INET_PROT_NOT_VALID ) 1180 { 1181 String aName = ParseSmart( aText, aBaseURL, SvtPathOptions().GetWorkPath() ); 1182 aObj.SetURL( aName ); 1183 ::rtl::OUString aURL( aObj.GetMainURL( INetURLObject::NO_DECODE ) ); 1184 if ( !aURL.getLength() ) 1185 // aText itself is invalid, and even together with aBaseURL, it could not 1186 // made valid -> no chance 1187 return aText; 1188 1189 bool bSlash = aObj.hasFinalSlash(); 1190 { 1191 static const rtl::OUString aPropName( 1192 rtl::OUString::createFromAscii("CasePreservingURL")); 1193 1194 rtl::OUString aFileURL; 1195 1196 Any aAny = 1197 UCBContentHelper::GetProperty(aURL,aPropName); 1198 sal_Bool success = (aAny >>= aFileURL); 1199 String aTitle; 1200 if(success) 1201 aTitle = String( 1202 INetURLObject(aFileURL).getName( 1203 INetURLObject::LAST_SEGMENT, 1204 true, 1205 INetURLObject::DECODE_WITH_CHARSET )); 1206 else 1207 success = 1208 UCBContentHelper::GetTitle(aURL,aTitle); 1209 1210 if( success && 1211 ( aTitle.Len() > 1 || 1212 (aTitle.CompareToAscii("/") != 0 && 1213 aTitle.CompareToAscii(".") != 0) ) ) 1214 { 1215 aObj.SetName( aTitle ); 1216 if ( bSlash ) 1217 aObj.setFinalSlash(); 1218 } 1219 } 1220 } 1221 1222 return aObj.GetMainURL( INetURLObject::NO_DECODE ); 1223 } 1224 1225 //------------------------------------------------------------------------- 1226 void SvtURLBox::DisableHistory() 1227 { 1228 bHistoryDisabled = sal_True; 1229 UpdatePicklistForSmartProtocol_Impl(); 1230 } 1231 1232 //------------------------------------------------------------------------- 1233 void SvtURLBox::SetBaseURL( const String& rURL ) 1234 { 1235 ::vos::OGuard aGuard( SvtMatchContext_Impl::GetMutex() ); 1236 1237 // Reset match lists 1238 if ( pImp->pCompletions ) 1239 pImp->pCompletions->Remove( 0, pImp->pCompletions->Count() ); 1240 1241 if ( pImp->pURLs ) 1242 pImp->pURLs->Remove( 0, pImp->pURLs->Count() ); 1243 1244 aBaseURL = rURL; 1245 } 1246 1247 //------------------------------------------------------------------------- 1248 /** Parse leading ~ for Unix systems, 1249 does nothing for Windows 1250 */ 1251 sal_Bool SvtURLBox_Impl::TildeParsing( 1252 String& 1253 #ifdef UNX 1254 aText 1255 #endif 1256 , String& 1257 #ifdef UNX 1258 aBaseURL 1259 #endif 1260 ) 1261 { 1262 #ifdef UNX 1263 if( aText.Search( '~' ) == 0 ) 1264 { 1265 String aParseTilde; 1266 sal_Bool bTrailingSlash = sal_True; // use trailing slash 1267 1268 if( aText.Len() == 1 || aText.GetChar( 1 ) == '/' ) 1269 { 1270 // covers "~" or "~/..." cases 1271 const char* aHomeLocation = getenv( "HOME" ); 1272 if( !aHomeLocation ) 1273 aHomeLocation = ""; 1274 1275 aParseTilde = String::CreateFromAscii( aHomeLocation ); 1276 1277 // in case the whole path is just "~" then there should 1278 // be no trailing slash at the end 1279 if( aText.Len() == 1 ) 1280 bTrailingSlash = sal_False; 1281 } 1282 else 1283 { 1284 // covers "~username" and "~username/..." cases 1285 xub_StrLen nNameEnd = aText.Search( '/' ); 1286 String aUserName = aText.Copy( 1, ( nNameEnd != STRING_NOTFOUND ) ? nNameEnd : ( aText.Len() - 1 ) ); 1287 1288 struct passwd* pPasswd = NULL; 1289 #ifdef SOLARIS 1290 Sequence< sal_Int8 > sBuf( 1024 ); 1291 struct passwd aTmp; 1292 sal_Int32 nRes = getpwnam_r( OUStringToOString( OUString( aUserName ), RTL_TEXTENCODING_ASCII_US ).getStr(), 1293 &aTmp, 1294 (char*)sBuf.getArray(), 1295 1024, 1296 &pPasswd ); 1297 if( !nRes && pPasswd ) 1298 aParseTilde = String::CreateFromAscii( pPasswd->pw_dir ); 1299 else 1300 return sal_False; // no such user 1301 #else 1302 pPasswd = getpwnam( OUStringToOString( OUString( aUserName ), RTL_TEXTENCODING_ASCII_US ).getStr() ); 1303 if( pPasswd ) 1304 aParseTilde = String::CreateFromAscii( pPasswd->pw_dir ); 1305 else 1306 return sal_False; // no such user 1307 #endif 1308 1309 // in case the path is "~username" then there should 1310 // be no trailing slash at the end 1311 if( nNameEnd == STRING_NOTFOUND ) 1312 bTrailingSlash = sal_False; 1313 } 1314 1315 if( !bTrailingSlash ) 1316 { 1317 if( !aParseTilde.Len() || aParseTilde.EqualsAscii( "/" ) ) 1318 { 1319 // "/" path should be converted to "/." 1320 aParseTilde = String::CreateFromAscii( "/." ); 1321 } 1322 else 1323 { 1324 // "blabla/" path should be converted to "blabla" 1325 aParseTilde.EraseTrailingChars( '/' ); 1326 } 1327 } 1328 else 1329 { 1330 if( aParseTilde.GetChar( aParseTilde.Len() - 1 ) != '/' ) 1331 aParseTilde += '/'; 1332 if( aText.Len() > 2 ) 1333 aParseTilde += aText.Copy( 2 ); 1334 } 1335 1336 aText = aParseTilde; 1337 aBaseURL = String(); // tilde provide absolute path 1338 } 1339 #endif 1340 1341 return sal_True; 1342 } 1343 1344 //------------------------------------------------------------------------- 1345 void SvtURLBox::SetUrlFilter( const IUrlFilter* _pFilter ) 1346 { 1347 pImp->pUrlFilter = _pFilter; 1348 } 1349 1350 //------------------------------------------------------------------------- 1351 const IUrlFilter* SvtURLBox::GetUrlFilter( ) const 1352 { 1353 return pImp->pUrlFilter; 1354 } 1355 // ----------------------------------------------------------------------------- 1356 void SvtURLBox::SetFilter(const String& _sFilter) 1357 { 1358 pImp->m_aFilters.clear(); 1359 FilterMatch::createWildCardFilterList(_sFilter,pImp->m_aFilters); 1360 } 1361 1362