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