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