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 : #include "scdetect.hxx"
21 :
22 : #include <sal/macros.h>
23 :
24 : #include <framework/interaction.hxx>
25 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 : #include <com/sun/star/beans/PropertyValue.hpp>
27 : #include <com/sun/star/frame/XFrame.hpp>
28 : #include <com/sun/star/frame/XModel.hpp>
29 : #include <com/sun/star/awt/XWindow.hpp>
30 : #include <com/sun/star/lang/XUnoTunnel.hpp>
31 : #include <comphelper/processfactory.hxx>
32 : #include <comphelper/string.hxx>
33 : #include <cppuhelper/supportsservice.hxx>
34 : #include <com/sun/star/container/XNameAccess.hpp>
35 : #include <com/sun/star/io/XInputStream.hpp>
36 : #include <com/sun/star/task/XInteractionHandler.hpp>
37 : #include <com/sun/star/ucb/CommandAbortedException.hpp>
38 : #include <com/sun/star/ucb/InteractiveAppException.hpp>
39 : #include <com/sun/star/ucb/XContent.hpp>
40 : #include <com/sun/star/packages/zip/ZipIOException.hpp>
41 :
42 : #include <toolkit/helper/vclunohelper.hxx>
43 : #include <ucbhelper/simpleinteractionrequest.hxx>
44 :
45 : #include <svtools/parhtml.hxx>
46 : #include <rtl/ustring.h>
47 : #include <svl/itemset.hxx>
48 : #include <vcl/window.hxx>
49 : #include <svl/eitem.hxx>
50 : #include <svl/stritem.hxx>
51 : #include <tools/urlobj.hxx>
52 : #include <osl/mutex.hxx>
53 : #include <svtools/sfxecode.hxx>
54 : #include <svtools/ehdl.hxx>
55 : #include <sot/storinfo.hxx>
56 : #include <vcl/svapp.hxx>
57 : #include <sfx2/sfxsids.hrc>
58 : #include <sfx2/request.hxx>
59 : #include <sfx2/docfile.hxx>
60 : #include <sfx2/docfilt.hxx>
61 : #include <sfx2/fcontnr.hxx>
62 : #include <sfx2/app.hxx>
63 : #include <sfx2/brokenpackageint.hxx>
64 :
65 : using namespace ::com::sun::star;
66 : using namespace ::com::sun::star::uno;
67 : using namespace ::com::sun::star::io;
68 : using namespace ::com::sun::star::frame;
69 : using namespace ::com::sun::star::task;
70 : using namespace ::com::sun::star::beans;
71 : using namespace ::com::sun::star::lang;
72 : using namespace ::com::sun::star::ucb;
73 :
74 : namespace {
75 :
76 : const sal_Char pFilterLotus[] = "Lotus";
77 : const sal_Char pFilterQPro6[] = "Quattro Pro 6.0";
78 : const sal_Char pFilterDBase[] = "dBase";
79 : const sal_Char pFilterDif[] = "DIF";
80 : const sal_Char pFilterSylk[] = "SYLK";
81 :
82 : // Tabelle mit Suchmustern
83 : // Bedeutung der Sequenzen
84 : // 0x00??: genau Byte 0x?? muss an dieser Stelle stehen
85 : // 0x0100: ein Byte ueberlesen (don't care)
86 : // 0x02nn: ein Byte aus 0xnn Alternativen folgt
87 : // 0x8000: Erkennung abgeschlossen
88 :
89 :
90 : #define M_DC 0x0100
91 : #define M_ALT(ANZ) (0x0200+(ANZ))
92 : #define M_ENDE 0x8000
93 :
94 : const sal_uInt16 pLotus[] = // Lotus 1/1A/2
95 : { 0x0000, 0x0000, 0x0002, 0x0000,
96 : M_ALT(2), 0x0004, 0x0006,
97 : 0x0004, M_ENDE };
98 :
99 : const sal_uInt16 pLotusNew[] = // Lotus >= 9.7
100 : { 0x0000, 0x0000, M_DC, 0x0000, // Rec# + Len (0x1a)
101 : M_ALT(3), 0x0003, 0x0004, 0x0005, // File Revision Code 97->ME
102 : 0x0010, 0x0004, 0x0000, 0x0000,
103 : M_ENDE };
104 :
105 : const sal_uInt16 pLotus2[] = // Lotus >3
106 : { 0x0000, 0x0000, 0x001A, 0x0000, // Rec# + Len (26)
107 : M_ALT(2), 0x0000, 0x0002, // File Revision Code
108 : 0x0010,
109 : 0x0004, 0x0000, // File Revision Subcode
110 : M_ENDE };
111 :
112 : const sal_uInt16 pQPro[] =
113 : { 0x0000, 0x0000, 0x0002, 0x0000,
114 : M_ALT(4), 0x0001, 0x0002, // WB1, WB2
115 : 0x0006, 0x0007, // QPro 6/7 (?)
116 : 0x0010,
117 : M_ENDE };
118 :
119 : const sal_uInt16 pDIF1[] = // DIF mit CR-LF
120 : {
121 : 'T', 'A', 'B', 'L', 'E',
122 : M_DC, M_DC,
123 : '0', ',', '1',
124 : M_DC, M_DC,
125 : '\"',
126 : M_ENDE };
127 :
128 : const sal_uInt16 pDIF2[] = // DIF mit CR oder LF
129 : {
130 : 'T', 'A', 'B', 'L', 'E',
131 : M_DC,
132 : '0', ',', '1',
133 : M_DC,
134 : '\"',
135 : M_ENDE };
136 :
137 : const sal_uInt16 pSylk[] = // Sylk
138 : {
139 : 'I', 'D', ';',
140 : M_ALT(3), 'P', 'N', 'E', // 'P' plus undocumented Excel extensions 'N' and 'E'
141 : M_ENDE };
142 :
143 0 : bool detectThisFormat(SvStream& rStr, const sal_uInt16* pSearch)
144 : {
145 : sal_uInt8 nByte;
146 0 : rStr.Seek( 0 ); // am Anfang war alles Uebel...
147 0 : rStr.ReadUChar( nByte );
148 0 : bool bSync = true;
149 0 : while( !rStr.IsEof() && bSync )
150 : {
151 0 : sal_uInt16 nMuster = *pSearch;
152 :
153 0 : if( nMuster < 0x0100 )
154 : { // direkter Byte-Vergleich
155 0 : if( ( sal_uInt8 ) nMuster != nByte )
156 0 : bSync = false;
157 : }
158 0 : else if( nMuster & M_DC )
159 : { // don't care
160 : }
161 0 : else if( nMuster & M_ALT(0) )
162 : { // alternative Bytes
163 0 : sal_uInt8 nAnzAlt = ( sal_uInt8 ) nMuster;
164 0 : bSync = false; // zunaechst unsynchron
165 0 : while( nAnzAlt > 0 )
166 : {
167 0 : pSearch++;
168 0 : if( ( sal_uInt8 ) *pSearch == nByte )
169 0 : bSync = true; // jetzt erst Synchronisierung
170 0 : nAnzAlt--;
171 : }
172 : }
173 0 : else if( nMuster & M_ENDE )
174 : { // Format detected
175 0 : return true;
176 : }
177 :
178 0 : pSearch++;
179 0 : rStr.ReadUChar( nByte );
180 : }
181 :
182 0 : return false;
183 : }
184 :
185 : }
186 :
187 0 : ScFilterDetect::ScFilterDetect( const uno::Reference<uno::XComponentContext>& /*xContext*/ )
188 : {
189 0 : }
190 :
191 0 : ScFilterDetect::~ScFilterDetect()
192 : {
193 0 : }
194 :
195 : #if 0
196 : // This method is no longer used, but I do want to keep this for now to see
197 : // if we could transfer this check to the now centralized ascii detection
198 : // code in the filter module.
199 : static sal_Bool lcl_MayBeAscii( SvStream& rStream )
200 : {
201 : // ASCII/CSV is considered possible if there are no null bytes, or a Byte
202 : // Order Mark is present, or if, for Unicode UCS2/UTF-16, all null bytes
203 : // are on either even or uneven byte positions.
204 :
205 : rStream.Seek(STREAM_SEEK_TO_BEGIN);
206 :
207 : const size_t nBufSize = 2048;
208 : sal_uInt16 aBuffer[ nBufSize ];
209 : sal_uInt8* pByte = reinterpret_cast<sal_uInt8*>(aBuffer);
210 : sal_uLong nBytesRead = rStream.Read( pByte, nBufSize*2);
211 :
212 : if ( nBytesRead >= 2 && (aBuffer[0] == 0xfffe || aBuffer[0] == 0xfeff) )
213 : {
214 : // Unicode BOM file may contain null bytes.
215 : return sal_True;
216 : }
217 :
218 : const sal_uInt16* p = aBuffer;
219 : sal_uInt16 nMask = 0xffff;
220 : nBytesRead /= 2;
221 : while( nBytesRead-- && nMask )
222 : {
223 : sal_uInt16 nVal = *p++ & nMask;
224 : if (!(nVal & 0x00ff))
225 : nMask &= 0xff00;
226 : if (!(nVal & 0xff00))
227 : nMask &= 0x00ff;
228 : }
229 :
230 : return nMask != 0;
231 : }
232 : #endif
233 :
234 0 : static sal_Bool lcl_MayBeDBase( SvStream& rStream )
235 : {
236 : // Look for dbf marker, see connectivity/source/inc/dbase/DTable.hxx
237 : // DBFType for values.
238 : const sal_uInt8 nValidMarks[] = {
239 0 : 0x03, 0x04, 0x05, 0x30, 0x43, 0xB3, 0x83, 0x8b, 0x8e, 0xf5 };
240 : sal_uInt8 nMark;
241 0 : rStream.Seek(STREAM_SEEK_TO_BEGIN);
242 0 : rStream.ReadUChar( nMark );
243 0 : bool bValidMark = false;
244 0 : for (size_t i=0; i < sizeof(nValidMarks)/sizeof(nValidMarks[0]) && !bValidMark; ++i)
245 : {
246 0 : if (nValidMarks[i] == nMark)
247 0 : bValidMark = true;
248 : }
249 0 : if ( !bValidMark )
250 0 : return false;
251 :
252 0 : const size_t nHeaderBlockSize = 32;
253 : // Empty dbf is >= 32*2+1 bytes in size.
254 0 : const size_t nEmptyDbf = nHeaderBlockSize * 2 + 1;
255 :
256 0 : rStream.Seek(STREAM_SEEK_TO_END);
257 0 : sal_uLong nSize = rStream.Tell();
258 0 : if ( nSize < nEmptyDbf )
259 0 : return false;
260 :
261 : // length of header starts at 8
262 0 : rStream.Seek(8);
263 : sal_uInt16 nHeaderLen;
264 0 : rStream.ReadUInt16( nHeaderLen );
265 :
266 0 : if ( nHeaderLen < nEmptyDbf || nSize < nHeaderLen )
267 0 : return false;
268 :
269 : // Last byte of header must be 0x0d, this is how it's specified.
270 : // #i9581#,#i26407# but some applications don't follow the specification
271 : // and pad the header with one byte 0x00 to reach an
272 : // even boundary. Some (#i88577# ) even pad more or pad using a 0x1a ^Z
273 : // control character (#i8857#). This results in:
274 : // Last byte of header must be 0x0d on 32 bytes boundary.
275 0 : sal_uInt16 nBlocks = (nHeaderLen - 1) / nHeaderBlockSize;
276 0 : sal_uInt8 nEndFlag = 0;
277 0 : while ( nBlocks > 1 && nEndFlag != 0x0d ) {
278 0 : rStream.Seek( nBlocks-- * nHeaderBlockSize );
279 0 : rStream.ReadUChar( nEndFlag );
280 : }
281 :
282 0 : return ( 0x0d == nEndFlag );
283 : }
284 :
285 0 : OUString SAL_CALL ScFilterDetect::detect( uno::Sequence<beans::PropertyValue>& lDescriptor )
286 : throw( uno::RuntimeException, std::exception )
287 : {
288 0 : uno::Reference< XInputStream > xStream;
289 0 : uno::Reference< XContent > xContent;
290 0 : uno::Reference< XInteractionHandler > xInteraction;
291 0 : OUString aURL;
292 0 : OUString sTemp;
293 0 : OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
294 0 : OUString aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
295 :
296 0 : OUString aDocumentTitle; // interesting only if set in this method
297 :
298 : // opening as template is done when a parameter tells to do so and a template filter can be detected
299 : // (otherwise no valid filter would be found) or if the detected filter is a template filter and
300 : // there is no parameter that forbids to open as template
301 0 : sal_Bool bOpenAsTemplate = false;
302 0 : sal_Bool bWasReadOnly = false, bReadOnly = false;
303 :
304 0 : sal_Bool bRepairPackage = false;
305 0 : sal_Bool bRepairAllowed = false;
306 0 : bool bDeepDetection = false;
307 :
308 : // now some parameters that can already be in the array, but may be overwritten or new inserted here
309 : // remember their indices in the case new values must be added to the array
310 0 : sal_Int32 nPropertyCount = lDescriptor.getLength();
311 0 : sal_Int32 nIndexOfFilterName = -1;
312 0 : sal_Int32 nIndexOfInputStream = -1;
313 0 : sal_Int32 nIndexOfContent = -1;
314 0 : sal_Int32 nIndexOfReadOnlyFlag = -1;
315 0 : sal_Int32 nIndexOfTemplateFlag = -1;
316 0 : sal_Int32 nIndexOfDocumentTitle = -1;
317 :
318 0 : for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
319 : {
320 : // extract properties
321 0 : if ( lDescriptor[nProperty].Name == "URL" )
322 : {
323 0 : lDescriptor[nProperty].Value >>= sTemp;
324 0 : aURL = sTemp;
325 : }
326 0 : else if( aURL.isEmpty() && lDescriptor[nProperty].Name == "FileName" )
327 : {
328 0 : lDescriptor[nProperty].Value >>= sTemp;
329 0 : aURL = sTemp;
330 : }
331 0 : else if ( lDescriptor[nProperty].Name == "TypeName" )
332 : {
333 0 : lDescriptor[nProperty].Value >>= sTemp;
334 0 : aTypeName = sTemp;
335 : }
336 0 : else if ( lDescriptor[nProperty].Name == "FilterName" )
337 : {
338 0 : lDescriptor[nProperty].Value >>= sTemp;
339 0 : aPreselectedFilterName = sTemp;
340 :
341 : // if the preselected filter name is not correct, it must be erased after detection
342 : // remember index of property to get access to it later
343 0 : nIndexOfFilterName = nProperty;
344 : }
345 0 : else if ( lDescriptor[nProperty].Name == "InputStream" )
346 0 : nIndexOfInputStream = nProperty;
347 0 : else if ( lDescriptor[nProperty].Name == "ReadOnly" )
348 0 : nIndexOfReadOnlyFlag = nProperty;
349 0 : else if ( lDescriptor[nProperty].Name == "UCBContent" )
350 0 : nIndexOfContent = nProperty;
351 0 : else if ( lDescriptor[nProperty].Name == "AsTemplate" )
352 : {
353 0 : lDescriptor[nProperty].Value >>= bOpenAsTemplate;
354 0 : nIndexOfTemplateFlag = nProperty;
355 : }
356 0 : else if ( lDescriptor[nProperty].Name == "InteractionHandler" )
357 0 : lDescriptor[nProperty].Value >>= xInteraction;
358 0 : else if ( lDescriptor[nProperty].Name == "RepairPackage" )
359 0 : lDescriptor[nProperty].Value >>= bRepairPackage;
360 0 : else if ( lDescriptor[nProperty].Name == "DocumentTitle" )
361 0 : nIndexOfDocumentTitle = nProperty;
362 0 : else if (lDescriptor[nProperty].Name == "DeepDetection")
363 0 : bDeepDetection = lDescriptor[nProperty].Value.get<sal_Bool>();
364 : }
365 :
366 : // can't check the type for external filters, so set the "dont" flag accordingly
367 0 : SolarMutexGuard aGuard;
368 : //SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED;
369 :
370 0 : SfxAllItemSet *pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
371 0 : TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
372 0 : SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
373 :
374 0 : bWasReadOnly = pItem && pItem->GetValue();
375 :
376 0 : const SfxFilter* pFilter = 0;
377 0 : OUString aPrefix = "private:factory/";
378 0 : if( aURL.startsWith( aPrefix ) )
379 : {
380 0 : OUString aPattern = aPrefix + "scalc";
381 0 : if ( aURL.startsWith( aPattern ) )
382 0 : pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
383 : }
384 : else
385 : {
386 : // container for Calc filters
387 0 : SfxFilterMatcher aMatcher("scalc");
388 0 : if ( !aPreselectedFilterName.isEmpty() )
389 0 : pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
390 0 : else if( !aTypeName.isEmpty() )
391 0 : pFilter = aMatcher.GetFilter4EA( aTypeName );
392 :
393 : // ctor of SfxMedium uses owner transition of ItemSet
394 0 : SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
395 0 : aMedium.UseInteractionHandler( true );
396 :
397 0 : sal_Bool bIsStorage = aMedium.IsStorage();
398 0 : if ( aMedium.GetErrorCode() == ERRCODE_NONE )
399 : {
400 : // remember input stream and content and put them into the descriptor later
401 : // should be done here since later the medium can switch to a version
402 0 : xStream.set(aMedium.GetInputStream());
403 0 : xContent.set(aMedium.GetContent());
404 0 : bReadOnly = aMedium.IsReadOnly();
405 :
406 : // maybe that IsStorage() already created an error!
407 0 : if ( bIsStorage )
408 : {
409 0 : uno::Reference < embed::XStorage > xStorage(aMedium.GetStorage( false ));
410 0 : if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
411 : {
412 : // error during storage creation means _here_ that the medium
413 : // is broken, but we can not handle it in medium since unpossibility
414 : // to create a storage does not _always_ means that the medium is broken
415 0 : aMedium.SetError(aMedium.GetLastStorageCreationState(), OUString(OSL_LOG_PREFIX));
416 0 : if ( xInteraction.is() )
417 : {
418 0 : OUString empty;
419 : try
420 : {
421 : InteractiveAppException xException( empty,
422 : uno::Reference< XInterface >(),
423 : InteractionClassification_ERROR,
424 0 : aMedium.GetError() );
425 :
426 : uno::Reference< XInteractionRequest > xRequest(
427 : new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
428 0 : ucbhelper::CONTINUATION_APPROVE ) );
429 0 : xInteraction->handle( xRequest );
430 : }
431 0 : catch ( Exception & ) {};
432 : }
433 : }
434 0 : else if ( xStorage.is() )
435 : {
436 : try
437 : {
438 0 : OUString aFilterName;
439 0 : if ( pFilter )
440 0 : aFilterName = pFilter->GetName();
441 0 : aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : false, &aFilterName );
442 : }
443 0 : catch( const lang::WrappedTargetException& aWrap )
444 : {
445 0 : if (!bDeepDetection)
446 : // Bail out early unless it's a deep detection.
447 0 : return OUString();
448 :
449 0 : packages::zip::ZipIOException aZipException;
450 :
451 : // repairing is done only if this type is requested from outside
452 0 : if ( ( aWrap.TargetException >>= aZipException ) && !aTypeName.isEmpty() )
453 : {
454 0 : if ( xInteraction.is() )
455 : {
456 : // the package is broken one
457 0 : aDocumentTitle = aMedium.GetURLObject().getName(
458 : INetURLObject::LAST_SEGMENT,
459 : true,
460 0 : INetURLObject::DECODE_WITH_CHARSET );
461 :
462 0 : if ( !bRepairPackage )
463 : {
464 : // ask the user whether he wants to try to repair
465 0 : RequestPackageReparation aRequest( aDocumentTitle );
466 0 : xInteraction->handle( aRequest.GetRequest() );
467 0 : bRepairAllowed = aRequest.isApproved();
468 : }
469 :
470 0 : if ( !bRepairAllowed )
471 : {
472 : // repair either not allowed or not successful
473 0 : NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
474 0 : xInteraction->handle( aNotifyRequest.GetRequest() );
475 : }
476 : }
477 :
478 0 : if ( !bRepairAllowed )
479 0 : aTypeName = "";
480 0 : }
481 0 : }
482 0 : catch( uno::RuntimeException& )
483 : {
484 0 : throw;
485 : }
486 0 : catch( uno::Exception& )
487 : {
488 0 : aTypeName = "";
489 : }
490 :
491 0 : if ( !aTypeName.isEmpty() )
492 0 : pFilter = SfxFilterMatcher("scalc").GetFilter4EA( aTypeName );
493 0 : }
494 : }
495 : else
496 : {
497 : // Non-storage format.
498 :
499 0 : if (aTypeName == "calc8_template" ||
500 0 : aTypeName == "calc8" ||
501 0 : aTypeName == "calc_StarOffice_XML_Calc" ||
502 0 : aTypeName == "calc_StarOffice_XML_Calc_Template")
503 : // These types require storage. Bail out.
504 0 : return OUString();
505 :
506 0 : SvStream* pStream = aMedium.GetInStream();
507 0 : if (!pStream)
508 : // No stream, no detection.
509 0 : return OUString();
510 :
511 0 : pFilter = NULL;
512 :
513 0 : const char* pSearchFilterName = NULL;
514 0 : if (aTypeName == "calc_Lotus")
515 : {
516 0 : if (!detectThisFormat(*pStream, pLotus) && !detectThisFormat(*pStream, pLotusNew) && !detectThisFormat(*pStream, pLotus2))
517 0 : return OUString();
518 :
519 0 : pSearchFilterName = pFilterLotus;
520 : }
521 0 : else if (aTypeName == "calc_QPro")
522 : {
523 0 : if (!detectThisFormat(*pStream, pQPro))
524 0 : return OUString();
525 :
526 0 : pSearchFilterName = pFilterQPro6;
527 : }
528 0 : else if (aTypeName == "calc_SYLK")
529 : {
530 0 : if (!detectThisFormat(*pStream, pSylk))
531 0 : return OUString();
532 :
533 0 : pSearchFilterName = pFilterSylk;
534 : }
535 0 : else if (aTypeName == "calc_DIF")
536 : {
537 0 : if (!detectThisFormat(*pStream, pDIF1) && !detectThisFormat(*pStream, pDIF2))
538 0 : return OUString();
539 :
540 0 : pSearchFilterName = pFilterDif;
541 : }
542 0 : else if (aTypeName == "calc_dBase")
543 : {
544 0 : if (!lcl_MayBeDBase(*pStream))
545 0 : return OUString();
546 :
547 0 : pSearchFilterName = pFilterDBase;
548 : }
549 :
550 0 : if (!pSearchFilterName)
551 0 : return OUString();
552 :
553 0 : pFilter = aMatcher.GetFilter4FilterName(OUString::createFromAscii(pSearchFilterName));
554 : }
555 0 : }
556 : }
557 :
558 0 : if ( nIndexOfInputStream == -1 && xStream.is() )
559 : {
560 : // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
561 0 : lDescriptor.realloc( nPropertyCount + 1 );
562 0 : lDescriptor[nPropertyCount].Name = "InputStream";
563 0 : lDescriptor[nPropertyCount].Value <<= xStream;
564 0 : nPropertyCount++;
565 : }
566 :
567 0 : if ( nIndexOfContent == -1 && xContent.is() )
568 : {
569 : // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opened twice
570 0 : lDescriptor.realloc( nPropertyCount + 1 );
571 0 : lDescriptor[nPropertyCount].Name = "UCBContent";
572 0 : lDescriptor[nPropertyCount].Value <<= xContent;
573 0 : nPropertyCount++;
574 : }
575 :
576 0 : if ( bReadOnly != bWasReadOnly )
577 : {
578 0 : if ( nIndexOfReadOnlyFlag == -1 )
579 : {
580 0 : lDescriptor.realloc( nPropertyCount + 1 );
581 0 : lDescriptor[nPropertyCount].Name = "ReadOnly";
582 0 : lDescriptor[nPropertyCount].Value <<= bReadOnly;
583 0 : nPropertyCount++;
584 : }
585 : else
586 0 : lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
587 : }
588 :
589 0 : if ( !bRepairPackage && bRepairAllowed )
590 : {
591 0 : lDescriptor.realloc( nPropertyCount + 1 );
592 0 : lDescriptor[nPropertyCount].Name = "RepairPackage";
593 0 : lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
594 0 : nPropertyCount++;
595 :
596 0 : bOpenAsTemplate = sal_True;
597 :
598 : // TODO/LATER: set progress bar that should be used
599 : }
600 :
601 0 : if ( bOpenAsTemplate )
602 : {
603 0 : if ( nIndexOfTemplateFlag == -1 )
604 : {
605 0 : lDescriptor.realloc( nPropertyCount + 1 );
606 0 : lDescriptor[nPropertyCount].Name = "AsTemplate";
607 0 : lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
608 0 : nPropertyCount++;
609 : }
610 : else
611 0 : lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
612 : }
613 :
614 0 : if ( !aDocumentTitle.isEmpty() )
615 : {
616 : // the title was set here
617 0 : if ( nIndexOfDocumentTitle == -1 )
618 : {
619 0 : lDescriptor.realloc( nPropertyCount + 1 );
620 0 : lDescriptor[nPropertyCount].Name = "DocumentTitle";
621 0 : lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
622 0 : nPropertyCount++;
623 : }
624 : else
625 0 : lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
626 : }
627 :
628 0 : if (!pFilter)
629 0 : return OUString();
630 :
631 0 : if (nIndexOfFilterName == -1)
632 : {
633 0 : lDescriptor.realloc(nPropertyCount + 1);
634 0 : lDescriptor[nPropertyCount].Name = "FilterName";
635 0 : lDescriptor[nPropertyCount].Value <<= pFilter->GetName();
636 0 : ++nPropertyCount;
637 : }
638 : else
639 0 : lDescriptor[nIndexOfFilterName].Value <<= pFilter->GetName();
640 :
641 0 : return aTypeName;
642 : }
643 :
644 0 : OUString SAL_CALL ScFilterDetect::getImplementationName() throw (uno::RuntimeException, std::exception)
645 : {
646 0 : return impl_getStaticImplementationName();
647 : }
648 :
649 0 : sal_Bool ScFilterDetect::supportsService( const OUString& sServiceName )
650 : throw (uno::RuntimeException, std::exception)
651 : {
652 0 : return cppu::supportsService(this, sServiceName);
653 : }
654 :
655 0 : com::sun::star::uno::Sequence<OUString> ScFilterDetect::getSupportedServiceNames()
656 : throw (uno::RuntimeException, std::exception)
657 : {
658 0 : return impl_getStaticSupportedServiceNames();
659 : }
660 :
661 0 : uno::Sequence<OUString> ScFilterDetect::impl_getStaticSupportedServiceNames()
662 : {
663 0 : uno::Sequence<OUString> seqServiceNames(1);
664 0 : seqServiceNames.getArray()[0] = "com.sun.star.frame.ExtendedTypeDetection";
665 0 : return seqServiceNames;
666 : }
667 :
668 0 : OUString ScFilterDetect::impl_getStaticImplementationName()
669 : {
670 0 : return OUString("com.sun.star.comp.calc.FormatDetector");
671 : }
672 :
673 0 : uno::Reference<uno::XInterface> ScFilterDetect::impl_createInstance(
674 : const uno::Reference<uno::XComponentContext>& xContext ) throw (uno::Exception)
675 : {
676 0 : return static_cast<cppu::OWeakObject*>(new ScFilterDetect(xContext));
677 : }
678 :
679 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|