xref: /trunk/main/sw/source/filter/basflt/iodetect.cxx (revision b63233d8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include <iodetect.hxx>
28 
29 #include <errhdl.hxx>
30 #include <osl/endian.h>
31 #include <sot/storage.hxx>
32 #include <svtools/parhtml.hxx>
33 #include <tools/urlobj.hxx>
34 
35 bool IsDocShellRegistered();
36 
37 SwIoDetect aFilterDetect[] =
38 {
39     SwIoDetect( FILTER_RTF,      STRING_LEN ),
40     SwIoDetect( FILTER_BAS,      STRING_LEN ),
41     SwIoDetect( sWW6,            STRING_LEN ),
42     SwIoDetect( FILTER_WW8,      STRING_LEN ),
43     SwIoDetect( sRtfWH,          STRING_LEN ),
44     SwIoDetect( sHTML,           4 ),
45     SwIoDetect( sWW1,            STRING_LEN ),
46     SwIoDetect( sWW5,            STRING_LEN ),
47     SwIoDetect( FILTER_XML,      4 ),
48     SwIoDetect( FILTER_TEXT_DLG, 8 ),
49     SwIoDetect( FILTER_TEXT,     4 )
50 };
51 
IsReader(const sal_Char * pHeader,sal_uLong nLen_,const String &,const String &) const52 const sal_Char* SwIoDetect::IsReader(const sal_Char* pHeader, sal_uLong nLen_,
53     const String & /*rFileName*/, const String& /*rUserData*/) const
54 {
55     // Filter erkennung
56     struct W1_FIB
57     {
58         SVBT16 wIdent;      // 0x0 int magic number
59         SVBT16 nFib;        // 0x2 FIB version written
60         SVBT16 nProduct;    // 0x4 product version written by
61         SVBT16 nlocale;     // 0x6 language stamp---localized version;
62         SVBT16 pnNext;      // 0x8
63         SVBT16 fFlags;
64 
65         sal_uInt16 nFibGet()    { return SVBT16ToShort(nFib); }
66         sal_uInt16 wIdentGet()  { return SVBT16ToShort(wIdent); }
67         sal_uInt16 fFlagsGet()  { return SVBT16ToShort(fFlags); }
68         // SVBT16 fComplex :1;// 0004 when 1, file is in complex, fast-saved format.
69         sal_Bool fComplexGet()  { return static_cast< sal_Bool >((fFlagsGet() >> 2) & 1); }
70     };
71 
72     int bRet = sal_False;
73     rtl::OString aName( pName );
74     if ( sHTML == aName )
75         bRet = HTMLParser::IsHTMLFormat( pHeader, sal_True, RTL_TEXTENCODING_DONTKNOW );
76     else if ( FILTER_RTF == aName )
77         bRet = 0 == strncmp( "{\\rtf", pHeader, 5 );
78     else if ( sWW5 == aName )
79     {
80         W1_FIB *pW1Header = (W1_FIB*)pHeader;
81         if (pW1Header->wIdentGet() == 0xA5DC && pW1Header->nFibGet() == 0x65)
82             bRet = true; /*WW5*/
83         else if (pW1Header->wIdentGet() == 0xA5DB && pW1Header->nFibGet() == 0x2D)
84             bRet = true; /*WW2*/
85     }
86     else if ( sWW1 == aName )
87     {
88         bRet = (( ((W1_FIB*)pHeader)->wIdentGet() == 0xA59C
89                     && ((W1_FIB*)pHeader)->nFibGet() == 0x21)
90                 && ((W1_FIB*)pHeader)->fComplexGet() == 0);
91     }
92     else if ( FILTER_TEXT == aName )
93         bRet = SwIoSystem::IsDetectableText(pHeader, nLen_);
94     else if ( FILTER_TEXT_DLG == aName)
95         bRet = SwIoSystem::IsDetectableText( pHeader, nLen_, 0, 0, 0, true);
96     return bRet ? pName : 0;
97 }
98 
GetSubStorageName(const SfxFilter & rFltr)99 const String SwIoSystem::GetSubStorageName( const SfxFilter& rFltr )
100 {
101     /* bei den StorageFiltern noch den SubStorageNamen setzen */
102     const String& rUserData = rFltr.GetUserData();
103     if( rUserData.EqualsAscii(FILTER_XML) ||
104         rUserData.EqualsAscii(FILTER_XMLV) ||
105         rUserData.EqualsAscii(FILTER_XMLVW) )
106         return String::CreateFromAscii(
107                 RTL_CONSTASCII_STRINGPARAM( "content.xml" ));
108     if( rUserData.EqualsAscii(sWW6) || rUserData.EqualsAscii(FILTER_WW8) )
109         return String::CreateFromAscii(
110                 RTL_CONSTASCII_STRINGPARAM( "WordDocument" ));
111     return String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "" ));
112 }
113 
GetFilterOfFormat(const String & rFmtNm,const SfxFilterContainer * pCnt)114 const SfxFilter* SwIoSystem::GetFilterOfFormat(const String& rFmtNm,
115     const SfxFilterContainer* pCnt)
116 {
117     SfxFilterContainer aCntSw( String::CreateFromAscii( sSWRITER ) );
118     SfxFilterContainer aCntSwWeb( String::CreateFromAscii( sSWRITERWEB ) );
119     const SfxFilterContainer* pFltCnt = pCnt ? pCnt : ( IsDocShellRegistered() ? &aCntSw : &aCntSwWeb );
120 
121     do {
122         if( pFltCnt )
123         {
124             SfxFilterMatcher aMatcher( pFltCnt->GetName() );
125             SfxFilterMatcherIter aIter( &aMatcher );
126             const SfxFilter* pFilter = aIter.First();
127             while ( pFilter )
128             {
129                 if( pFilter->GetUserData() == rFmtNm )
130                     return pFilter;
131                 pFilter = aIter.Next();
132             }
133         }
134         if( pCnt || pFltCnt == &aCntSwWeb )
135             break;
136         pFltCnt = &aCntSwWeb;
137     } while( sal_True );
138     return 0;
139 }
140 
IsValidStgFilter(const com::sun::star::uno::Reference<com::sun::star::embed::XStorage> & rStg,const SfxFilter & rFilter)141 sal_Bool SwIoSystem::IsValidStgFilter( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rStg, const SfxFilter& rFilter)
142 {
143     sal_Bool bRet = sal_False;
144     try
145     {
146         sal_uLong nStgFmtId = SotStorage::GetFormatID( rStg );
147         bRet = rStg->isStreamElement( ::rtl::OUString::createFromAscii("content.xml") );
148         if ( bRet )
149             bRet = ( nStgFmtId && ( rFilter.GetFormat() == nStgFmtId ) );
150     }
151     catch ( com::sun::star::uno::Exception& )
152     {
153     }
154 
155     return bRet;
156 }
157 
IsValidStgFilter(SotStorage & rStg,const SfxFilter & rFilter)158 sal_Bool SwIoSystem::IsValidStgFilter(SotStorage& rStg, const SfxFilter& rFilter)
159 {
160     sal_uLong nStgFmtId = rStg.GetFormat();
161     /*#i8409# We cannot trust the clipboard id anymore :-(*/
162     if( rFilter.GetUserData().EqualsAscii(FILTER_WW8) ||
163             rFilter.GetUserData().EqualsAscii(sWW6) )
164     {
165         nStgFmtId = 0;
166     }
167 
168     sal_Bool bRet = SVSTREAM_OK == rStg.GetError() &&
169         ( !nStgFmtId || rFilter.GetFormat() == nStgFmtId ) &&
170         ( rStg.IsContained( SwIoSystem::GetSubStorageName( rFilter )) );
171     if( bRet )
172     {
173         /* Bug 53445 - es gibt Excel Docs ohne ClipBoardId! */
174         /* Bug 62703 - und auch WinWord Docs ohne ClipBoardId! */
175         if( rFilter.GetUserData().EqualsAscii(FILTER_WW8) ||
176                 rFilter.GetUserData().EqualsAscii(sWW6) )
177         {
178             bRet = !((rStg.IsContained( String::CreateFromAscii("0Table" )) ||
179                         rStg.IsContained( String::CreateFromAscii("1Table" ))) ^
180                     rFilter.GetUserData().EqualsAscii(FILTER_WW8));
181             if (bRet && !rFilter.IsAllowedAsTemplate())
182             {
183                 SotStorageStreamRef xRef =
184                     rStg.OpenSotStream(String::CreateFromAscii("WordDocument"),
185                             STREAM_STD_READ | STREAM_NOCREATE );
186                 xRef->Seek(10);
187                 sal_uInt8 nByte;
188                 *xRef >> nByte;
189                 bRet = !(nByte & 1);
190             }
191         }
192         //      else if( !rFilter.GetUserData().EqualsAscii(sCExcel) )
193         //          bRet = rFilter.GetFormat() == nStgFmtId;
194     }
195     return bRet;
196 }
197 
TerminateBuffer(sal_Char * pBuffer,sal_uLong nBytesRead,sal_uLong nBufferLen)198 void TerminateBuffer(sal_Char *pBuffer, sal_uLong nBytesRead, sal_uLong nBufferLen)
199 {
200     OSL_ENSURE(nBytesRead <= nBufferLen - 2,
201             "what you read must be less than the max + null termination");
202     OSL_ENSURE(!(nBufferLen & 0x00000001),"nMaxReadBuf must be an even number");
203     if (nBytesRead <= nBufferLen - 2)
204     {
205         pBuffer[nBytesRead] = '\0';
206         pBuffer[nBytesRead+1] = '\0';
207         if (nBytesRead & 0x00000001)
208             pBuffer[nBytesRead+2] = '\0';
209     }
210 }
211 
212 /* Feststellen ob das File in dem entsprechenden Format vorliegt. */
213 /* Z.z werden nur unsere eigene Filter unterstuetzt               */
IsFileFilter(SfxMedium & rMedium,const String & rFmtName,const SfxFilter ** ppFilter)214 sal_Bool SwIoSystem::IsFileFilter( SfxMedium& rMedium, const String& rFmtName,
215         const SfxFilter** ppFilter )
216 {
217     sal_Bool bRet = sal_False;
218 
219     SfxFilterContainer aCntSw( String::CreateFromAscii( sSWRITER ) );
220     SfxFilterContainer aCntSwWeb( String::CreateFromAscii( sSWRITERWEB ) );
221     const SfxFilterContainer& rFltContainer = IsDocShellRegistered() ? aCntSw : aCntSwWeb;
222 
223     com::sun::star::uno::Reference < com::sun::star::embed::XStorage > xStor;
224     SotStorageRef xStg;
225     if (rMedium.IsStorage())
226         xStor = rMedium.GetStorage();
227     else
228     {
229         SvStream* pStream = rMedium.GetInStream();
230         if ( pStream && SotStorage::IsStorageFile(pStream) )
231             xStg = new SotStorage( pStream, sal_False );
232     }
233 
234     SfxFilterMatcher aMatcher( rFltContainer.GetName() );
235     SfxFilterMatcherIter aIter( &aMatcher );
236     const SfxFilter* pFltr = aIter.First();
237     while ( pFltr )
238     {
239         if( pFltr->GetUserData() == rFmtName )
240         {
241             const String& rUserData = pFltr->GetUserData();
242             if( 'C' == *rUserData.GetBuffer() )
243             {
244                 if ( xStor.is() )
245                     bRet = IsValidStgFilter( xStor, *pFltr );
246                 else if ( xStg.Is() )
247                     bRet = xStg.Is() && IsValidStgFilter( *xStg, *pFltr );
248                 bRet = bRet && (pFltr->GetUserData() == rFmtName);
249             }
250             else if( !xStg.Is() && !xStor.is() )
251             {
252                 SvStream* pStrm = rMedium.GetInStream();
253                 if( pStrm && !pStrm->GetError() )
254                 {
255                     sal_Char aBuffer[4098];
256                     const sal_uLong nMaxRead = sizeof(aBuffer) - 2;
257                     sal_uLong nBytesRead = pStrm->Read(aBuffer, nMaxRead);
258                     pStrm->Seek(STREAM_SEEK_TO_BEGIN);
259                     TerminateBuffer(aBuffer, nBytesRead, sizeof(aBuffer));
260                     for (sal_uInt16 i = 0; i < MAXFILTER; ++i)
261                     {
262                         if (aFilterDetect[i].IsFilter(rFmtName))
263                         {
264                             bRet = 0 != aFilterDetect[i].IsReader( aBuffer, nBytesRead,
265                                     rMedium.GetPhysicalName(), rUserData );
266                             break;
267                         }
268                     }
269                 }
270             }
271 
272             if( bRet && ppFilter  )
273                 *ppFilter = pFltr;
274         }
275 
276         pFltr = aIter.Next();
277     }
278 
279     return bRet;
280 }
281 
282 /* die Methode stellt fest, von welchem Typ der stream (File) ist.        */
283 /* Es wird versucht, eine dem Filter entsprechende Byte-Folge zu finden.  */
284 /* Wird kein entsprechender gefunden, wird zur Zeit der ASCII-Reader      */
285 /* returnt !! Der Returnwert ist der interne Filtername!                  */
286 /* rPrefFltName ist der interne Name des Filters, den der Benutzer im     */
287 /* Open-Dialog eingestellt hat.                                           */
GetFileFilter(const String & rFileName,const String & rPrefFltName,SfxMedium * pMedium)288 const SfxFilter* SwIoSystem::GetFileFilter(const String& rFileName,
289     const String& rPrefFltName, SfxMedium* pMedium)
290 {
291     SfxFilterContainer aCntSw( String::CreateFromAscii( sSWRITER ) );
292     SfxFilterContainer aCntSwWeb( String::CreateFromAscii( sSWRITERWEB ) );
293     const SfxFilterContainer* pFCntnr = IsDocShellRegistered() ? &aCntSw : &aCntSwWeb;
294 
295     if( !pFCntnr )
296         return 0;
297 
298     SfxFilterMatcher aMatcher( pFCntnr->GetName() );
299     SfxFilterMatcherIter aIter( &aMatcher );
300     const SfxFilter* pFilter = aIter.First();
301     if ( !pFilter )
302         return 0;
303 
304     if( pMedium ? ( pMedium->IsStorage() || SotStorage::IsStorageFile( pMedium->GetInStream() ) ) : SotStorage::IsStorageFile( rFileName ) )
305     {
306         // package storage or OLEStorage based format
307         SotStorageRef xStg;
308         sal_Bool bDeleteMedium = sal_False;
309         if (!pMedium )
310         {
311             INetURLObject aObj;
312             aObj.SetSmartProtocol( INET_PROT_FILE );
313             aObj.SetSmartURL( rFileName );
314             pMedium = new SfxMedium( aObj.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READ, sal_False );
315             bDeleteMedium = sal_True;
316         }
317 
318         // templates should not get precedence over "normal" filters (#i35508, #i33168)
319         const SfxFilter* pTemplateFilter = 0;
320         const SfxFilter* pOldFilter = pFCntnr->GetFilter4FilterName( rPrefFltName );
321         sal_Bool bLookForTemplate = pOldFilter && pOldFilter->IsOwnTemplateFormat();
322         if ( pMedium->IsStorage() )
323         {
324             com::sun::star::uno::Reference < com::sun::star::embed::XStorage > xStor = pMedium->GetStorage();
325             if ( xStor.is() )
326             {
327                 while ( pFilter )
328                 {
329                     if( 'C' == *pFilter->GetUserData().GetBuffer() && IsValidStgFilter( xStor, *pFilter ) )
330                     {
331                         if ( pFilter->IsOwnTemplateFormat() && !bLookForTemplate )
332                             // found template filter; maybe there's a "normal" one also
333                             pTemplateFilter = pFilter;
334                         else
335                             return pFilter;
336                     }
337 
338                     pFilter = aIter.Next();
339                 }
340 
341                 // there's only a template filter that could be found
342                 if ( pTemplateFilter )
343                     pFilter = pTemplateFilter;
344             }
345         }
346         else
347         {
348             SvStream* pStream = pMedium->GetInStream();
349             if ( pStream && SotStorage::IsStorageFile(pStream) )
350                 xStg = new SotStorage( pStream, sal_False );
351 
352             if( xStg.Is() && ( xStg->GetError() == SVSTREAM_OK ) )
353             {
354                 while ( pFilter )
355                 {
356                     if( 'C' == *pFilter->GetUserData().GetBuffer() && IsValidStgFilter( *xStg, *pFilter ) )
357                     {
358                         if ( pFilter->IsOwnTemplateFormat() && !bLookForTemplate )
359                             // found template filter; maybe there's a "normal" one also
360                             pTemplateFilter = pFilter;
361                         else
362                             return pFilter;
363                     }
364 
365                     pFilter = aIter.Next();
366                 }
367 
368                 // there's only a template filter that could be found
369                 if ( pTemplateFilter )
370                     pFilter = pTemplateFilter;
371 
372             }
373         }
374 
375         return pFilter;
376     }
377 
378     sal_Char aBuffer[4098];
379     const sal_uLong nMaxRead = sizeof(aBuffer) - 2;
380     sal_uLong nBytesRead = 0;
381     if (pMedium)
382     {
383         SvStream* pIStrm = pMedium->GetInStream();
384         if( !pIStrm || SVSTREAM_OK != pIStrm->GetError() )
385             return 0;
386         sal_uLong nCurrPos = pIStrm->Tell();
387         nBytesRead = pIStrm->Read(aBuffer, nMaxRead);
388         pIStrm->Seek( nCurrPos );
389     }
390     /*
391        else
392        {
393        SvFileStream aStrm( rFileName, STREAM_READ );
394 
395     // ohne FileName oder ohne Stream gibts nur den ANSI-Filter
396     if( !rFileName.Len() || SVSTREAM_OK != aStrm.GetError() )
397     return 0;
398 
399     nBytesRead = aStrm.Read(aBuffer, nMaxRead);
400     aStrm.Close();
401     }*/
402 
403     TerminateBuffer(aBuffer, nBytesRead, sizeof(aBuffer));
404 
405 
406     /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
407     /* suche nach dem bestimmten Filter, falls kein entsprechender        */
408     /* gefunden wird, so wird der ASCII-Filter returnt.                   */
409     /* Gibt es Filter ohne einen Identifizierungs-String, so werden diese */
410     /* nie erkannt und es wird auch der ASCII-Filter returnt.             */
411     /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
412     {
413         const SfxFilter* pFilterTmp = 0;
414         const sal_Char* pNm;
415         for( sal_uInt16 n = 0; n < MAXFILTER; ++n )
416         {
417             String sEmptyUserData;
418             pNm = aFilterDetect[n].IsReader(aBuffer, nBytesRead, rFileName, sEmptyUserData);
419             pFilterTmp = pNm ? SwIoSystem::GetFilterOfFormat(String::CreateFromAscii(pNm), pFCntnr) : 0;
420             if (pNm && pFilterTmp)
421             {
422                 return pFilterTmp;
423             }
424         }
425     }
426 
427     /* Ok, bis jetzt kein Filter gefunden, also befrage mal die */
428     /* "WORD 4 WORD" Filter                                     */
429     if( rFileName.Len() )
430     {
431         if( pMedium )
432             pMedium->CloseInStream();
433 
434     }
435     return SwIoSystem::GetTextFilter( aBuffer, nBytesRead);
436 }
437 
IsDetectableText(const sal_Char * pBuf,sal_uLong & rLen,CharSet * pCharSet,bool * pSwap,LineEnd * pLineEnd,bool bEncodedFilter)438 bool SwIoSystem::IsDetectableText(const sal_Char* pBuf, sal_uLong &rLen,
439     CharSet *pCharSet, bool *pSwap, LineEnd *pLineEnd, bool bEncodedFilter)
440 {
441     bool bSwap = false;
442     CharSet eCharSet = RTL_TEXTENCODING_DONTKNOW;
443     bool bLE = true;
444     sal_uLong nHead=0;
445     /*See if its a known unicode type*/
446     if (rLen >= 2)
447     {
448         if (rLen > 2 && sal_uInt8(pBuf[0]) == 0xEF && sal_uInt8(pBuf[1]) == 0xBB &&
449             sal_uInt8(pBuf[2]) == 0xBF)
450         {
451             eCharSet = RTL_TEXTENCODING_UTF8;
452             nHead = 3;
453         }
454         else if (sal_uInt8(pBuf[0]) == 0xFE && sal_uInt8(pBuf[1]) == 0xFF)
455         {
456             eCharSet = RTL_TEXTENCODING_UCS2;
457             bLE = false;
458             nHead = 2;
459         }
460         else if (sal_uInt8(pBuf[1]) == 0xFE && sal_uInt8(pBuf[0]) == 0xFF)
461         {
462             eCharSet = RTL_TEXTENCODING_UCS2;
463             nHead = 2;
464         }
465         pBuf+=nHead;
466         rLen-=nHead;
467     }
468 
469     bool bCR = false, bLF = false, bNoNormalChar = false,
470         bIsBareUnicode = false;
471 
472     if (eCharSet != RTL_TEXTENCODING_DONTKNOW)
473     {
474         String sWork;
475         sal_Unicode *pNewBuf = sWork.AllocBuffer( static_cast< xub_StrLen >(rLen));
476         sal_Size nNewLen;
477         if (eCharSet != RTL_TEXTENCODING_UCS2)
478         {
479             nNewLen = rLen;
480             rtl_TextToUnicodeConverter hConverter =
481                 rtl_createTextToUnicodeConverter(eCharSet);
482             rtl_TextToUnicodeContext hContext =
483                 rtl_createTextToUnicodeContext(hConverter);
484 
485             sal_Size nCntBytes;
486             sal_uInt32 nInfo;
487             nNewLen = rtl_convertTextToUnicode( hConverter, hContext, pBuf,
488                 rLen, pNewBuf, nNewLen,
489                 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
490                   RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
491                   RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT), &nInfo, &nCntBytes);
492 
493             rtl_destroyTextToUnicodeContext(hConverter, hContext);
494             rtl_destroyTextToUnicodeConverter(hConverter);
495         }
496         else
497         {
498             nNewLen = rLen/2;
499             memcpy(pNewBuf, pBuf, rLen);
500 #ifdef OSL_LITENDIAN
501             bool bNativeLE = true;
502 #else
503             bool bNativeLE = false;
504 #endif
505             if (bLE != bNativeLE)
506             {
507                 bSwap = true;
508                 sal_Char* pF = (sal_Char*)pNewBuf;
509                 sal_Char* pN = pF+1;
510                 for(xub_StrLen n = 0; n < nNewLen; ++n, pF+=2, pN+=2)
511                 {
512                     sal_Char c = *pF;
513                     *pF = *pN;
514                     *pN = c;
515                 }
516             }
517         }
518 
519         sWork.ReleaseBufferAccess( static_cast< xub_StrLen >(nNewLen) );
520         pNewBuf = sWork.GetBufferAccess();
521 
522         for (sal_uLong nCnt = 0; nCnt < nNewLen; ++nCnt, ++pNewBuf)
523         {
524             switch (*pNewBuf)
525             {
526                 case 0xA:
527                     bLF = true;
528                     break;
529                 case 0xD:
530                     bCR = true;
531                     break;
532                 default:
533                     break;
534             }
535         }
536     }
537     else
538     {
539         for( sal_uLong nCnt = 0; nCnt < rLen; ++nCnt, ++pBuf )
540         {
541             switch (*pBuf)
542             {
543                 case 0x0:
544                     if( nCnt + 1 < rLen && !*(pBuf+1) )
545                         return 0;
546                     bIsBareUnicode = true;
547                     break;
548                 case 0xA:
549                     bLF = true;
550                     break;
551                 case 0xD:
552                     bCR = true;
553                     break;
554                 case 0xC:
555                 case 0x1A:
556                 case 0x9:
557                     break;
558                 default:
559                     if (0x20 > (sal_uInt8)*pBuf)
560                         bNoNormalChar = true;
561                     break;
562             }
563         }
564     }
565 
566     LineEnd eSysLE = GetSystemLineEnd();
567     LineEnd eLineEnd;
568     if (!bCR && !bLF)
569         eLineEnd = eSysLE;
570     else
571         eLineEnd = bCR ? ( bLF ? LINEEND_CRLF : LINEEND_CR ) : LINEEND_LF;
572 
573     if (pCharSet)
574         *pCharSet = eCharSet;
575     if (pSwap)
576         *pSwap = bSwap;
577     if (pLineEnd)
578         *pLineEnd = eLineEnd;
579 
580     return bEncodedFilter || (!bIsBareUnicode && eSysLE == eLineEnd);
581 }
582 
GetTextFilter(const sal_Char * pBuf,sal_uLong nLen)583 const SfxFilter* SwIoSystem::GetTextFilter( const sal_Char* pBuf, sal_uLong nLen)
584 {
585     bool bAuto = IsDetectableText(pBuf, nLen);
586     const sal_Char* pNm = bAuto ? FILTER_TEXT : FILTER_TEXT_DLG;
587     return SwIoSystem::GetFilterOfFormat( String::CreateFromAscii(pNm), 0 );
588 }
589