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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sfx2.hxx"
24
25 #include <sfx2/linkmgr.hxx>
26 #include <com/sun/star/document/UpdateDocMode.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/util/XURLTransformer.hpp>
29
30 #include <sfx2/objsh.hxx>
31 #include <svl/urihelper.hxx>
32 #include <sot/formats.hxx>
33 #include <tools/urlobj.hxx>
34 #include <sot/exchange.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <sfx2/lnkbase.hxx>
38 #include <sfx2/app.hxx>
39 #include <vcl/graph.hxx>
40 #include <svl/stritem.hxx>
41 #include <svl/eitem.hxx>
42 #include <svl/intitem.hxx>
43 #include <unotools/localfilehelper.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <i18npool/mslangid.hxx>
46 #include <sfx2/request.hxx>
47 #include <vcl/dibtools.hxx>
48
49 #include "fileobj.hxx"
50 #include "impldde.hxx"
51 #include "app.hrc"
52 #include "sfx2/sfxresid.hxx"
53
54 #define _SVSTDARR_STRINGSDTOR
55 #include <svl/svstdarr.hxx>
56
57 namespace sfx2
58 {
59
60 class SvxInternalLink : public sfx2::SvLinkSource
61 {
62 public:
SvxInternalLink()63 SvxInternalLink() {}
64
65 virtual sal_Bool Connect( sfx2::SvBaseLink* );
66 };
67
68
SV_IMPL_PTRARR(SvBaseLinks,SvBaseLinkRefPtr)69 SV_IMPL_PTRARR( SvBaseLinks, SvBaseLinkRefPtr )
70
71 LinkManager::LinkManager(SfxObjectShell* p)
72 : pPersist(p),
73 mAutoAskUpdateAllLinks(sal_False),
74 mUpdateAsked(sal_False)
75 {
76 }
77
~LinkManager()78 LinkManager::~LinkManager()
79 {
80 SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData();
81 for( sal_uInt16 n = aLinkTbl.Count(); n; --n, ++ppRef )
82 {
83 if( (*ppRef)->Is() )
84 {
85 (*(*ppRef))->Disconnect();
86 (*(*ppRef))->SetLinkManager( NULL );
87 }
88 delete *ppRef;
89 }
90 }
91
92
93 /************************************************************************
94 |* LinkManager::Remove()
95 |*
96 |* Description
97 *************************************************************************/
98
Remove(SvBaseLink * pLink)99 void LinkManager::Remove( SvBaseLink *pLink )
100 {
101 // do not insert links double
102 int bFound = sal_False;
103 SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData();
104 for( sal_uInt16 n = aLinkTbl.Count(); n; --n, ++ppRef )
105 {
106 if( pLink == *(*ppRef) )
107 {
108 (*(*ppRef))->Disconnect();
109 (*(*ppRef))->SetLinkManager( NULL );
110 (*(*ppRef)).Clear();
111 bFound = sal_True;
112 }
113
114 // if there are still some empty ones, get rid of them
115 if( !(*ppRef)->Is() )
116 {
117 delete *ppRef;
118 aLinkTbl.Remove( aLinkTbl.Count() - n, 1 );
119 if( bFound )
120 return ;
121 --ppRef;
122 }
123 }
124 }
125
126
Remove(sal_uInt16 nPos,sal_uInt16 nCnt)127 void LinkManager::Remove( sal_uInt16 nPos, sal_uInt16 nCnt )
128 {
129 if( nCnt && nPos < aLinkTbl.Count() )
130 {
131 if( nPos + nCnt > aLinkTbl.Count() )
132 nCnt = aLinkTbl.Count() - nPos;
133
134 SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData() + nPos;
135 for( sal_uInt16 n = nCnt; n; --n, ++ppRef )
136 {
137 if( (*ppRef)->Is() )
138 {
139 (*(*ppRef))->Disconnect();
140 (*(*ppRef))->SetLinkManager( NULL );
141 }
142 delete *ppRef;
143 }
144 aLinkTbl.Remove( nPos, nCnt );
145 }
146 }
147
148
Insert(SvBaseLink * pLink)149 sal_Bool LinkManager::Insert( SvBaseLink* pLink )
150 {
151
152 // do not insert links double
153 for( sal_uInt16 n = 0; n < aLinkTbl.Count(); ++n )
154 {
155 SvBaseLinkRef* pTmp = aLinkTbl[ n ];
156 if( !pTmp->Is() )
157 aLinkTbl.DeleteAndDestroy( n-- );
158
159 if( pLink == *pTmp )
160 return sal_False;
161 }
162
163 SvBaseLinkRef* pTmp = new SvBaseLinkRef( pLink );
164 pLink->SetLinkManager( this );
165 aLinkTbl.Insert( pTmp, aLinkTbl.Count() );
166 if (mAutoAskUpdateAllLinks)
167 {
168 Window *parent = NULL;
169 SfxObjectShell* persist = GetPersist();
170 if (persist != NULL)
171 parent = GetPersist()->GetDialogParent();
172
173 SetUserAllowsLinkUpdate(pLink, GetUserAllowsLinkUpdate(parent));
174 }
175
176 return sal_True;
177 }
178
179
InsertLink(SvBaseLink * pLink,sal_uInt16 nObjType,sal_uInt16 nUpdateMode,const String * pName)180 sal_Bool LinkManager::InsertLink( SvBaseLink * pLink,
181 sal_uInt16 nObjType,
182 sal_uInt16 nUpdateMode,
183 const String* pName )
184 {
185 // in any case: do this first
186 pLink->SetObjType( nObjType );
187 if( pName )
188 pLink->SetName( *pName );
189 pLink->SetUpdateMode( nUpdateMode );
190 return Insert( pLink );
191 }
192
193
InsertDDELink(SvBaseLink * pLink,const String & rServer,const String & rTopic,const String & rItem)194 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink,
195 const String& rServer,
196 const String& rTopic,
197 const String& rItem )
198 {
199 if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
200 return sal_False;
201
202 String sCmd;
203 ::sfx2::MakeLnkName( sCmd, &rServer, rTopic, rItem );
204
205 pLink->SetObjType( OBJECT_CLIENT_DDE );
206 pLink->SetName( sCmd );
207 return Insert( pLink );
208 }
209
210
InsertDDELink(SvBaseLink * pLink)211 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink )
212 {
213 DBG_ASSERT( OBJECT_CLIENT_SO & pLink->GetObjType(), "no OBJECT_CLIENT_SO" );
214 if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
215 return sal_False;
216
217 if( pLink->GetObjType() == OBJECT_CLIENT_SO )
218 pLink->SetObjType( OBJECT_CLIENT_DDE );
219
220 return Insert( pLink );
221 }
222
223
224 // ask for the strings to be used in the dialog
GetDisplayNames(const SvBaseLink * pLink,String * pType,String * pFile,String * pLinkStr,String * pFilter) const225 sal_Bool LinkManager::GetDisplayNames( const SvBaseLink * pLink,
226 String* pType,
227 String* pFile,
228 String* pLinkStr,
229 String* pFilter ) const
230 {
231 sal_Bool bRet = sal_False;
232 const String sLNm( pLink->GetLinkSourceName() );
233 if( sLNm.Len() )
234 {
235 switch( pLink->GetObjType() )
236 {
237 case OBJECT_CLIENT_FILE:
238 case OBJECT_CLIENT_GRF:
239 case OBJECT_CLIENT_OLE:
240 {
241 sal_uInt16 nPos = 0;
242 String sFile( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
243 String sRange( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
244
245 if( pFile )
246 *pFile = sFile;
247 if( pLinkStr )
248 *pLinkStr = sRange;
249 if( pFilter )
250 *pFilter = sLNm.Copy( nPos );
251
252 if( pType )
253 {
254 sal_uInt16 nObjType = pLink->GetObjType();
255 *pType = String( SfxResId(
256 ( OBJECT_CLIENT_FILE == nObjType || OBJECT_CLIENT_OLE == nObjType )
257 ? RID_SVXSTR_FILELINK
258 : RID_SVXSTR_GRAFIKLINK ));
259 }
260 bRet = sal_True;
261 }
262 break;
263 case OBJECT_CLIENT_DDE:
264 {
265 sal_uInt16 nTmp = 0;
266 String sCmd( sLNm );
267 String sServer( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
268 String sTopic( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
269
270 if( pType )
271 *pType = sServer;
272 if( pFile )
273 *pFile = sTopic;
274 if( pLinkStr )
275 *pLinkStr = sCmd.Copy( nTmp );
276 bRet = sal_True;
277 }
278 break;
279 default:
280 break;
281 }
282 }
283
284 return bRet;
285 }
286
SetAutoAskUpdateAllLinks()287 void LinkManager::SetAutoAskUpdateAllLinks()
288 {
289 mAutoAskUpdateAllLinks = sal_True;
290 mUpdateAsked = sal_False;
291 }
292
SetNeverAskUpdateAllLinks()293 void LinkManager::SetNeverAskUpdateAllLinks()
294 {
295 mAutoAskUpdateAllLinks = sal_False;
296 mAllowUpdate = sal_True;
297 mUpdateAsked = sal_True;
298 }
299
GetUserAllowsLinkUpdate(Window * pParentWin)300 sal_Bool LinkManager::GetUserAllowsLinkUpdate(Window *pParentWin)
301 {
302 if (!mUpdateAsked)
303 {
304 if (QueryBox(pParentWin, WB_YES_NO | WB_DEF_NO, SfxResId(STR_QUERY_UPDATE_LINKS)).Execute() == RET_YES)
305 mAllowUpdate = sal_True;
306 else
307 mAllowUpdate = sal_False;
308 mUpdateAsked = sal_True;
309 }
310 return mAllowUpdate;
311 }
312
SetUserAllowsLinkUpdate(SvBaseLink * pLink,sal_Bool allows)313 void LinkManager::SetUserAllowsLinkUpdate(SvBaseLink *pLink, sal_Bool allows)
314 {
315 SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
316
317 if (pShell)
318 {
319 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pShell->getEmbeddedObjectContainer();
320 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(allows);
321 }
322 }
323
324
UpdateAllLinks(sal_Bool bAskUpdate,sal_Bool,sal_Bool bUpdateGrfLinks,Window * pParentWin)325 void LinkManager::UpdateAllLinks(
326 sal_Bool bAskUpdate,
327 sal_Bool /*bCallErrHdl*/,
328 sal_Bool bUpdateGrfLinks,
329 Window* pParentWin )
330 {
331 SvStringsDtor aApps, aTopics, aItems;
332 String sApp, sTopic, sItem;
333
334 // first create a copy of the array, so that updated links to not interfere with ... in between!!
335 SvPtrarr aTmpArr( 255, 50 );
336 sal_uInt16 n;
337 for( n = 0; n < aLinkTbl.Count(); ++n )
338 {
339 SvBaseLink* pLink = *aLinkTbl[ n ];
340 if( !pLink )
341 {
342 Remove( n-- );
343 continue;
344 }
345 aTmpArr.Insert( pLink, aTmpArr.Count() );
346 }
347
348 for( n = 0; n < aTmpArr.Count(); ++n )
349 {
350 SvBaseLink* pLink = (SvBaseLink*)aTmpArr[ n ];
351
352 // first search the entry in the array
353 sal_uInt16 nFndPos = USHRT_MAX;
354 for( sal_uInt16 i = 0; i < aLinkTbl.Count(); ++i )
355 if( pLink == *aLinkTbl[ i ] )
356 {
357 nFndPos = i;
358 break;
359 }
360
361 if( USHRT_MAX == nFndPos )
362 continue; // was not already existing!
363
364 // do not update graphic links yet
365 if( !pLink->IsVisible() ||
366 ( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
367 continue;
368
369 sal_Bool allows = sal_True;
370
371 if (bAskUpdate)
372 {
373 allows = GetUserAllowsLinkUpdate(pParentWin);
374 }
375
376 SetUserAllowsLinkUpdate(pLink, allows);
377 bAskUpdate = sal_False; // one time is OK
378
379 if (allows)
380 pLink->Update();
381 }
382 }
383
384 /************************************************************************
385 |* SvBaseLink::CreateObject()
386 |*
387 |* Description
388 *************************************************************************/
389
CreateObj(SvBaseLink * pLink)390 SvLinkSourceRef LinkManager::CreateObj( SvBaseLink * pLink )
391 {
392 switch( pLink->GetObjType() )
393 {
394 case OBJECT_CLIENT_FILE:
395 case OBJECT_CLIENT_GRF:
396 case OBJECT_CLIENT_OLE:
397 return new SvFileObject;
398 case OBJECT_INTERN:
399 return new SvxInternalLink;
400 case OBJECT_CLIENT_DDE:
401 return new SvDDEObject;
402 default:
403 return SvLinkSourceRef();
404 }
405 }
406
InsertServer(SvLinkSource * pObj)407 sal_Bool LinkManager::InsertServer( SvLinkSource* pObj )
408 {
409 // do not insert double
410 if( !pObj || USHRT_MAX != aServerTbl.GetPos( pObj ) )
411 return sal_False;
412
413 aServerTbl.Insert( pObj, aServerTbl.Count() );
414 return sal_True;
415 }
416
417
RemoveServer(SvLinkSource * pObj)418 void LinkManager::RemoveServer( SvLinkSource* pObj )
419 {
420 sal_uInt16 nPos = aServerTbl.GetPos( pObj );
421 if( USHRT_MAX != nPos )
422 aServerTbl.Remove( nPos, 1 );
423 }
424
425
MakeLnkName(String & rName,const String * pType,const String & rFile,const String & rLink,const String * pFilter)426 void MakeLnkName( String& rName, const String* pType, const String& rFile,
427 const String& rLink, const String* pFilter )
428 {
429 if( pType )
430 (rName = *pType).EraseLeadingChars().EraseTrailingChars() += cTokenSeperator;
431 else if( rName.Len() )
432 rName.Erase();
433
434 ((rName += rFile).EraseLeadingChars().EraseTrailingChars() +=
435 cTokenSeperator ).EraseLeadingChars().EraseTrailingChars() += rLink;
436 if( pFilter )
437 ((rName += cTokenSeperator ) += *pFilter).EraseLeadingChars().EraseTrailingChars();
438 }
439
InsertFileLink(sfx2::SvBaseLink & rLink,sal_uInt16 nFileType,const String & rFileNm,const String * pFilterNm,const String * pRange)440 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink,
441 sal_uInt16 nFileType,
442 const String& rFileNm,
443 const String* pFilterNm,
444 const String* pRange )
445 {
446 if( !( OBJECT_CLIENT_SO & rLink.GetObjType() ))
447 return sal_False;
448
449 String sCmd( rFileNm );
450 sCmd += ::sfx2::cTokenSeperator;
451 if( pRange )
452 sCmd += *pRange;
453 if( pFilterNm )
454 ( sCmd += ::sfx2::cTokenSeperator ) += *pFilterNm;
455
456 return InsertLink( &rLink, nFileType, sfx2::LINKUPDATE_ONCALL, &sCmd );
457 }
458
InsertFileLink(sfx2::SvBaseLink & rLink)459 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink )
460 {
461 if( OBJECT_CLIENT_FILE == ( OBJECT_CLIENT_FILE & rLink.GetObjType() ))
462 return InsertLink( &rLink, rLink.GetObjType(), sfx2::LINKUPDATE_ONCALL );
463 return sal_False;
464 }
465
466 // a transfer will be discontinued, therefore cancel all DownloadMedia
467 // (at the moment only interesting for the FileLinks!)
CancelTransfers()468 void LinkManager::CancelTransfers()
469 {
470 SvFileObject* pFileObj;
471 sfx2::SvBaseLink* pLnk;
472
473 const sfx2::SvBaseLinks& rLnks = GetLinks();
474 for( sal_uInt16 n = rLnks.Count(); n; )
475 if( 0 != ( pLnk = &(*rLnks[ --n ])) &&
476 OBJECT_CLIENT_FILE == (OBJECT_CLIENT_FILE & pLnk->GetObjType()) &&
477 0 != ( pFileObj = (SvFileObject*)pLnk->GetObj() ) )
478 // 0 != ( pFileObj = (SvFileObject*)SvFileObject::ClassFactory()->
479 // CastAndAddRef( pLnk->GetObj() )) )
480 pFileObj->CancelTransfers();
481 }
482
483 // to send status information from the FileObject to the BaseLink, there is an own ClipboardId.
484 // The SvData object has then the respective information as string.
485 // Currently this will be used for FileObject in connection with JavaScript
486 // - that needs information about Load/Abort/Error
RegisterStatusInfoId()487 sal_uIntPtr LinkManager::RegisterStatusInfoId()
488 {
489 static sal_uIntPtr nFormat = 0;
490
491 if( !nFormat )
492 {
493 // how does the new interface look like?
494 // nFormat = Exchange::RegisterFormatName( "StatusInfo vom SvxInternalLink" );
495 nFormat = SotExchange::RegisterFormatName(
496 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM(
497 "StatusInfo vom SvxInternalLink" )));
498 }
499 return nFormat;
500 }
501
502 // ----------------------------------------------------------------------
503
GetGraphicFromAny(const String & rMimeType,const::com::sun::star::uno::Any & rValue,Graphic & rGrf)504 sal_Bool LinkManager::GetGraphicFromAny( const String& rMimeType,
505 const ::com::sun::star::uno::Any & rValue,
506 Graphic& rGrf )
507 {
508 sal_Bool bRet = sal_False;
509 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
510 if( rValue.hasValue() && ( rValue >>= aSeq ) )
511 {
512 SvMemoryStream aMemStm( (void*)aSeq.getConstArray(), aSeq.getLength(),
513 STREAM_READ );
514 aMemStm.Seek( 0 );
515
516 switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
517 {
518 case SOT_FORMATSTR_ID_SVXB:
519 {
520 aMemStm >> rGrf;
521 bRet = sal_True;
522 }
523 break;
524 case FORMAT_GDIMETAFILE:
525 {
526 GDIMetaFile aMtf;
527 aMtf.Read( aMemStm );
528 rGrf = aMtf;
529 bRet = sal_True;
530 }
531 break;
532 case FORMAT_BITMAP:
533 {
534 Bitmap aBmp;
535 ReadDIB(aBmp, aMemStm, true);
536 rGrf = aBmp;
537 bRet = sal_True;
538 }
539 break;
540 }
541 }
542 return bRet;
543 }
544
urlIsSafe(const::rtl::OUString & url)545 sal_Bool LinkManager::urlIsSafe( const ::rtl::OUString &url )
546 {
547 if ( url.getLength() == 0 ) {
548 return sal_False;
549 }
550 if ( !xURLTransformer.is() ) {
551 const com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext ( ::comphelper::getProcessComponentContext() );
552 com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiComponentFactory > xFactory ( xContext->getServiceManager(), ::com::sun::star::uno::UNO_QUERY );
553 if ( !xFactory.is() ) {
554 return sal_False;
555 }
556 xURLTransformer.set( xFactory->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.util.URLTransformer" ), xContext), com::sun::star::uno::UNO_QUERY );
557 if ( !xURLTransformer.is() ) {
558 return sal_False;
559 }
560 }
561 com::sun::star::util::URL aURL;
562 aURL.Complete = url;
563 sal_Bool b = xURLTransformer->parseSmart( aURL, ::rtl::OUString() );
564 if ( !b ) {
565 return sal_False;
566 }
567 return urlIsSafe( aURL );
568 }
569
urlIsSafe(const::com::sun::star::util::URL & url)570 sal_Bool LinkManager::urlIsSafe( const ::com::sun::star::util::URL &url )
571 {
572 sal_Bool result = ( url.Path.getLength() == 0 ) &&
573 ( url.Server.getLength() == 0);
574 return result;
575 }
576
577
urlIsVendor(const::rtl::OUString & url)578 sal_Bool LinkManager::urlIsVendor( const ::rtl::OUString &url )
579 {
580 if ( url.matchIgnoreAsciiCaseAsciiL( "vnd.sun.star.", 13, 0 ) ) {
581 return url.matchIgnoreAsciiCaseAsciiL ( "expand", 6, 13 ) ||
582 url.matchIgnoreAsciiCaseAsciiL ( "script", 6, 13 ) ||
583 url.matchIgnoreAsciiCaseAsciiL ( "tdoc", 4, 13 ) ||
584 url.matchIgnoreAsciiCaseAsciiL ( "uno", 3, 13 );
585 }
586 return sal_False;
587 }
588
589
590 // ----------------------------------------------------------------------
lcl_DDE_RelToAbs(const String & rTopic,const String & rBaseURL)591 String lcl_DDE_RelToAbs( const String& rTopic, const String& rBaseURL )
592 {
593 String sRet;
594 INetURLObject aURL( rTopic );
595 if( INET_PROT_NOT_VALID == aURL.GetProtocol() )
596 utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
597 if( !sRet.Len() )
598 sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
599 return sRet;
600 }
601
Connect(sfx2::SvBaseLink * pLink)602 sal_Bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
603 {
604 SfxObjectShell* pFndShell = 0;
605 sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
606 String sTopic, sItem, sReferer;
607 if( pLink->GetLinkManager() &&
608 pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sTopic, &sItem )
609 && sTopic.Len() )
610 {
611 // for the moment run through the DocumentShells and search for the ones with names:
612
613 com::sun::star::lang::Locale aLocale;
614 MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aLocale );
615 CharClass aCC( aLocale );
616
617 String sNm( sTopic ), sTmp;
618 aCC.toLower( sNm );
619
620 TypeId aType( TYPE(SfxObjectShell) );
621
622 sal_Bool bFirst = sal_True;
623 SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
624 if( pShell && pShell->GetMedium() )
625 {
626 sReferer = pShell->GetMedium()->GetBaseURL();
627 SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False );
628 if ( pItem )
629 nUpdateMode = pItem->GetValue();
630 }
631
632 String sNmURL( lcl_DDE_RelToAbs( sTopic, sReferer ) );
633 aCC.toLower( sNmURL );
634
635 if ( !pShell )
636 {
637 bFirst = sal_False;
638 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
639 }
640
641 while( pShell )
642 {
643 if( !sTmp.Len() )
644 {
645 sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
646 sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
647 }
648
649
650 aCC.toLower( sTmp );
651 if( sTmp == sNmURL ) // these we want to have
652 {
653 pFndShell = pShell;
654 break;
655 }
656
657 if( bFirst )
658 {
659 bFirst = sal_False;
660 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
661 }
662 else
663 pShell = SfxObjectShell::GetNext( *pShell, &aType, sal_False );
664
665 sTmp.Erase();
666 }
667 }
668
669 // empty topics are not allowed - which document is it
670 if( !sTopic.Len() )
671 return sal_False;
672
673 if( !pFndShell )
674 {
675 // try to load the file:
676 INetURLObject aURL( sTopic );
677 INetProtocol eOld = aURL.GetProtocol();
678 aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
679 if( INET_PROT_NOT_VALID != eOld ||
680 INET_PROT_HTTP != aURL.GetProtocol() )
681 {
682 SfxStringItem aName( SID_FILE_NAME, sTopic );
683 SfxBoolItem aMinimized(SID_MINIMIZED, sal_True);
684 SfxBoolItem aHidden(SID_HIDDEN, sal_True);
685 SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
686 SfxStringItem aReferer( SID_REFERER, sReferer );
687 SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
688 SfxBoolItem aReadOnly(SID_DOC_READONLY, sal_True);
689
690 // #i14200# (DDE-link crashes wordprocessor)
691 SfxAllItemSet aArgs( SFX_APP()->GetPool() );
692 aArgs.Put(aReferer);
693 aArgs.Put(aTarget);
694 aArgs.Put(aHidden);
695 aArgs.Put(aMinimized);
696 aArgs.Put(aName);
697 aArgs.Put(aUpdate);
698 aArgs.Put(aReadOnly);
699 pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
700 }
701 }
702
703 sal_Bool bRet = sal_False;
704 if( pFndShell )
705 {
706 sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
707 if( pNewSrc )
708 {
709 bRet = sal_True;
710
711 ::com::sun::star::datatransfer::DataFlavor aFl;
712 SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
713
714 pLink->SetObj( pNewSrc );
715 pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
716 sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
717 ? ADVISEMODE_ONLYONCE
718 : 0 );
719 }
720 }
721 return bRet;
722 }
723
724
725 }
726