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
SvtURLBox_Impl()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
GetMutex()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 //-------------------------------------------------------------------------
SvtMatchContext_Impl(SvtURLBox * pBoxP,const String & rText)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 //-------------------------------------------------------------------------
~SvtMatchContext_Impl()168 SvtMatchContext_Impl::~SvtMatchContext_Impl()
169 {
170 aLink.ClearPendingCall();
171 delete pURLs;
172 delete pCompletions;
173 }
174
175 //-------------------------------------------------------------------------
FillPicklist(SvStringsDtor & rPickList)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 //-------------------------------------------------------------------------
Cancel()206 void SAL_CALL SvtMatchContext_Impl::Cancel()
207 {
208 // Cancel button pressed
209 terminate();
210 }
211
212 //-------------------------------------------------------------------------
Stop()213 void SvtMatchContext_Impl::Stop()
214 {
215 bStop = sal_True;
216
217 if( isRunning() )
218 terminate();
219 }
220
221 //-------------------------------------------------------------------------
onTerminated()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 //-------------------------------------------------------------------------
Insert(const String & rCompletion,const String & rURL,sal_Bool bForce)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 //-------------------------------------------------------------------------
ReadFolder(const String & rURL,const String & rMatch,sal_Bool bSmart)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 //-------------------------------------------------------------------------
ParseSmart(String aText,String aBaseURL,String aWorkDir)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 //-------------------------------------------------------------------------
run()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 //-------------------------------------------------------------------------
TryAutoComplete(sal_Bool bForce)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 //-------------------------------------------------------------------------
SvtURLBox(Window * pParent,INetProtocol eSmart)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 //-------------------------------------------------------------------------
SvtURLBox(Window * pParent,WinBits _nStyle,INetProtocol eSmart)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 //-------------------------------------------------------------------------
SvtURLBox(Window * pParent,const ResId & _rResId,INetProtocol eSmart)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 //-------------------------------------------------------------------------
ImplInit()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 //-------------------------------------------------------------------------
~SvtURLBox()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 //-------------------------------------------------------------------------
UpdatePickList()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 //-------------------------------------------------------------------------
SetSmartProtocol(INetProtocol eProt)885 void SvtURLBox::SetSmartProtocol( INetProtocol eProt )
886 {
887 if ( eSmartProtocol != eProt )
888 {
889 eSmartProtocol = eProt;
890 UpdatePicklistForSmartProtocol_Impl();
891 }
892 }
893
894 //-------------------------------------------------------------------------
UpdatePicklistForSmartProtocol_Impl()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 //-------------------------------------------------------------------------
ProcessKey(const KeyCode & rKey)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 //-------------------------------------------------------------------------
Modify()1040 void SvtURLBox::Modify()
1041 {
1042 ComboBox::Modify();
1043 }
1044
1045 //-------------------------------------------------------------------------
PreNotify(NotifyEvent & rNEvt)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 //-------------------------------------------------------------------------
IMPL_LINK(SvtURLBox,AutoCompleteHdl_Impl,void *,EMPTYARG)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 //-------------------------------------------------------------------------
Notify(NotifyEvent & rEvt)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 //-------------------------------------------------------------------------
Select()1115 void SvtURLBox::Select()
1116 {
1117 ComboBox::Select();
1118 ClearModifyFlag();
1119 }
1120
1121 //-------------------------------------------------------------------------
SetOnlyDirectories(sal_Bool bDir)1122 void SvtURLBox::SetOnlyDirectories( sal_Bool bDir )
1123 {
1124 bOnlyDirectories = bDir;
1125 if ( bOnlyDirectories )
1126 Clear();
1127 }
1128
1129 //-------------------------------------------------------------------------
SetNoURLSelection(sal_Bool bSet)1130 void SvtURLBox::SetNoURLSelection( sal_Bool bSet )
1131 {
1132 bNoSelection = bSet;
1133 }
1134
1135 //-------------------------------------------------------------------------
GetURL()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 //-------------------------------------------------------------------------
DisableHistory()1226 void SvtURLBox::DisableHistory()
1227 {
1228 bHistoryDisabled = sal_True;
1229 UpdatePicklistForSmartProtocol_Impl();
1230 }
1231
1232 //-------------------------------------------------------------------------
SetBaseURL(const String & rURL)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 */
TildeParsing(String & aText,String & aBaseURL)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 //-------------------------------------------------------------------------
SetUrlFilter(const IUrlFilter * _pFilter)1345 void SvtURLBox::SetUrlFilter( const IUrlFilter* _pFilter )
1346 {
1347 pImp->pUrlFilter = _pFilter;
1348 }
1349
1350 //-------------------------------------------------------------------------
GetUrlFilter() const1351 const IUrlFilter* SvtURLBox::GetUrlFilter( ) const
1352 {
1353 return pImp->pUrlFilter;
1354 }
1355 // -----------------------------------------------------------------------------
SetFilter(const String & _sFilter)1356 void SvtURLBox::SetFilter(const String& _sFilter)
1357 {
1358 pImp->m_aFilters.clear();
1359 FilterMatch::createWildCardFilterList(_sFilter,pImp->m_aFilters);
1360 }
1361
1362