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