xref: /AOO41X/main/sfx2/source/bastyp/sfxhtml.cxx (revision 24c56ab9f1bd1305754aa2f564704f38ff57627e)
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_sfx2.hxx"
26 
27 #include <tools/urlobj.hxx>
28 
29 #include <sfx2/objsh.hxx>
30 #include <sfx2/docfile.hxx>
31 #include "openflag.hxx"
32 
33 #include <svtools/htmlkywd.hxx>
34 #include <svtools/htmltokn.h>
35 #include <svtools/imap.hxx>
36 #include <svtools/imapcirc.hxx>
37 #include <svtools/imapobj.hxx>
38 #include <svtools/imappoly.hxx>
39 #include <svtools/imaprect.hxx>
40 #ifndef _SVSTDARR_ULONGS_DECL
41 #define _SVSTDARR_ULONGS
42 #include <svl/svstdarr.hxx>
43 #endif
44 #include <svl/zforlist.hxx>
45 #include <rtl/tencinfo.h>
46 #include <tools/tenccvt.hxx>
47 
48 #include <sfx2/sfxhtml.hxx>
49 
50 #include <com/sun/star/beans/XPropertyContainer.hpp>
51 
52 
53 using namespace ::com::sun::star;
54 
55 
56 sal_Char __FAR_DATA sHTML_MIME_text[] = "text/";
57 sal_Char __FAR_DATA sHTML_MIME_application[] = "application/";
58 sal_Char __FAR_DATA sHTML_MIME_experimental[] = "x-";
59 
60 // <INPUT TYPE=xxx>
61 static HTMLOptionEnum __READONLY_DATA aAreaShapeOptEnums[] =
62 {
63     { OOO_STRING_SVTOOLS_HTML_SH_rect,      IMAP_OBJ_RECTANGLE  },
64     { OOO_STRING_SVTOOLS_HTML_SH_rectangle, IMAP_OBJ_RECTANGLE  },
65     { OOO_STRING_SVTOOLS_HTML_SH_circ,      IMAP_OBJ_CIRCLE     },
66     { OOO_STRING_SVTOOLS_HTML_SH_circle,    IMAP_OBJ_CIRCLE     },
67     { OOO_STRING_SVTOOLS_HTML_SH_poly,          IMAP_OBJ_POLYGON    },
68     { OOO_STRING_SVTOOLS_HTML_SH_polygon,       IMAP_OBJ_POLYGON    },
69     { 0,                    0                   }
70 };
71 
SfxHTMLParser(SvStream & rStream,sal_Bool bIsNewDoc,SfxMedium * pMed)72 SfxHTMLParser::SfxHTMLParser( SvStream& rStream, sal_Bool bIsNewDoc,
73                               SfxMedium *pMed ) :
74     HTMLParser( rStream, bIsNewDoc ),
75     pMedium( pMed ), pDLMedium( 0 ),
76     nMetaTags( 0 )
77 {
78     DBG_ASSERT( RTL_TEXTENCODING_DONTKNOW == GetSrcEncoding( ),
79                 "SfxHTMLParser::SfxHTMLParser: Wo kommt der ZS her?" );
80     DBG_ASSERT( !IsSwitchToUCS2(),
81                 "SfxHTMLParser::SfxHTMLParser: Switch to UCS2?" );
82 
83     // Altough the real default encoding is ISO8859-1, we use MS-1252
84     // als default encoding.
85     SetSrcEncoding( GetExtendedCompatibilityTextEncoding(  RTL_TEXTENCODING_ISO_8859_1 ) );
86 
87     // If the file starts with a BOM, switch to UCS2.
88     SetSwitchToUCS2( sal_True );
89 }
90 
~SfxHTMLParser()91 __EXPORT SfxHTMLParser::~SfxHTMLParser()
92 {
93     DBG_ASSERT( !pDLMedium, "Da ist ein File-Download stehengeblieben" );
94     delete pDLMedium;
95 }
96 
ParseMapOptions(ImageMap * pImageMap,const HTMLOptions * pOptions)97 sal_Bool SfxHTMLParser::ParseMapOptions(ImageMap * pImageMap,
98                                     const HTMLOptions * pOptions)
99 {
100     DBG_ASSERT( pImageMap, "ParseMapOptions: keine Image-Map" );
101     DBG_ASSERT( pOptions, "ParseMapOptions: keine Optionen" );
102 
103     String aName;
104 
105     for( sal_uInt16 i=pOptions->Count(); i; )
106     {
107         const HTMLOption *pOption = (*pOptions)[--i];
108         switch( pOption->GetToken() )
109         {
110         case HTML_O_NAME:
111             aName = pOption->GetString();
112             break;
113         }
114     }
115 
116     if( aName.Len() )
117         pImageMap->SetName( aName );
118 
119     return aName.Len() > 0;
120 }
121 
ParseAreaOptions(ImageMap * pImageMap,const String & rBaseURL,const HTMLOptions * pOptions,sal_uInt16 nEventMouseOver,sal_uInt16 nEventMouseOut)122 sal_Bool SfxHTMLParser::ParseAreaOptions(ImageMap * pImageMap, const String& rBaseURL,
123                                      const HTMLOptions * pOptions,
124                                      sal_uInt16 nEventMouseOver,
125                                      sal_uInt16 nEventMouseOut )
126 {
127     DBG_ASSERT( pImageMap, "ParseAreaOptions: keine Image-Map" );
128     DBG_ASSERT( pOptions, "ParseAreaOptions: keine Optionen" );
129 
130     sal_uInt16 nShape = IMAP_OBJ_RECTANGLE;
131     SvULongs aCoords;
132     String aName, aHRef, aAlt, aTarget, sEmpty;
133     sal_Bool bNoHRef = sal_False;
134     SvxMacroTableDtor aMacroTbl;
135 
136     for( sal_uInt16 i=pOptions->Count(); i; )
137     {
138         sal_uInt16 nEvent = 0;
139         ScriptType eScrpType = STARBASIC;
140         const HTMLOption *pOption = (*pOptions)[--i];
141         switch( pOption->GetToken() )
142         {
143         case HTML_O_NAME:
144             aName = pOption->GetString();
145             break;
146         case HTML_O_SHAPE:
147             pOption->GetEnum( nShape, aAreaShapeOptEnums );
148             break;
149         case HTML_O_COORDS:
150             pOption->GetNumbers( aCoords, sal_True );
151             break;
152         case HTML_O_HREF:
153             aHRef = INetURLObject::GetAbsURL( rBaseURL, pOption->GetString() );
154             break;
155         case HTML_O_NOHREF:
156             bNoHRef = sal_True;
157             break;
158         case HTML_O_ALT:
159             aAlt = pOption->GetString();
160             break;
161         case HTML_O_TARGET:
162             aTarget = pOption->GetString();
163             break;
164 
165         case HTML_O_ONMOUSEOVER:
166             eScrpType = JAVASCRIPT;
167         case HTML_O_SDONMOUSEOVER:
168             nEvent = nEventMouseOver;
169             goto IMAPOBJ_SETEVENT;
170 
171         case HTML_O_ONMOUSEOUT:
172             eScrpType = JAVASCRIPT;
173         case HTML_O_SDONMOUSEOUT:
174             nEvent = nEventMouseOut;
175             goto IMAPOBJ_SETEVENT;
176 IMAPOBJ_SETEVENT:
177             if( nEvent )
178             {
179                 String sTmp( pOption->GetString() );
180                 if( sTmp.Len() )
181                 {
182                     sTmp.ConvertLineEnd();
183                     aMacroTbl.Insert( nEvent,
184                         new SvxMacro( sTmp, sEmpty, eScrpType ));
185                 }
186             }
187             break;
188         }
189     }
190 
191     if( bNoHRef )
192         aHRef.Erase();
193 
194     sal_Bool bNewArea = sal_True;
195     switch( nShape )
196     {
197     case IMAP_OBJ_RECTANGLE:
198         if( aCoords.Count() >=4 )
199         {
200             Rectangle aRec( aCoords[0], aCoords[1],
201                             aCoords[2], aCoords[3] );
202             IMapRectangleObject aMapRObj( aRec, aHRef, aAlt, String(), aTarget, aName,
203                                           !bNoHRef );
204             if( aMacroTbl.Count() )
205                 aMapRObj.SetMacroTable( aMacroTbl );
206             pImageMap->InsertIMapObject( aMapRObj );
207         }
208         break;
209     case IMAP_OBJ_CIRCLE:
210         if( aCoords.Count() >=3 )
211         {
212             Point aPoint( aCoords[0], aCoords[1] );
213             IMapCircleObject aMapCObj( aPoint, aCoords[2],aHRef, aAlt, String(),
214                                        aTarget, aName, !bNoHRef );
215             if( aMacroTbl.Count() )
216                 aMapCObj.SetMacroTable( aMacroTbl );
217             pImageMap->InsertIMapObject( aMapCObj );
218         }
219         break;
220     case IMAP_OBJ_POLYGON:
221         if( aCoords.Count() >=6 )
222         {
223             sal_uInt16 nCount = aCoords.Count() / 2;
224             Polygon aPoly( nCount );
225             for( sal_uInt16 i=0; i<nCount; i++ )
226                 aPoly[i] = Point( aCoords[2*i], aCoords[2*i+1] );
227             IMapPolygonObject aMapPObj( aPoly, aHRef, aAlt, String(), aTarget, aName,
228                                         !bNoHRef );
229             if( aMacroTbl.Count() )
230                 aMapPObj.SetMacroTable( aMacroTbl );
231             pImageMap->InsertIMapObject( aMapPObj );
232         }
233         break;
234     default:
235         bNewArea = sal_False;
236     }
237 
238     return bNewArea;
239 }
240 
241 
StartFileDownload(const String & rURL,int nToken,SfxObjectShell * pSh)242 void SfxHTMLParser::StartFileDownload( const String& rURL, int nToken,
243                                        SfxObjectShell *pSh )
244 {
245     DBG_ASSERT( !pDLMedium, "StartFileDwonload bei aktivem Download" );
246     if( pDLMedium )
247         return;
248 
249     pDLMedium = new SfxMedium( rURL, SFX_STREAM_READONLY, sal_False );
250     if( pSh )
251     {
252         // Medium registrieren, damit abgebrochen werden kann
253         pSh->RegisterTransfer( *pDLMedium );
254 
255         // Target-Frame uebertragen, damit auch javascript:-URLs
256         // "geladen" werden koennen.
257         //const SfxMedium *pShMedium = pSh->GetMedium();
258         //if( pShMedium )
259         //  pDLMedium->SetLoadTargetFrame( pShMedium->GetLoadTargetFrame() );
260     }
261 
262     // Download anstossen (Achtung: Kann auch synchron sein).
263     if ( sal_True /*pMedium->GetDoneLink() == Link()*/ )
264         pDLMedium->DownLoad();
265     else
266     {
267         // Downloading-Flag auf sal_True setzen. Es werden dann auch
268         // Data-Available-Links, wenn wir in den Pending-Staus gelangen.
269         SetDownloadingFile( sal_True );
270         pDLMedium->DownLoad( STATIC_LINK( this, SfxHTMLParser, FileDownloadDone ) );
271 
272         // Wenn das Dowsnloading-Flag noch gesetzt ist erfolgt der Download
273         // asynchron. Wir gehen dann in den Pedning-Staus und warten dort.
274         // Solange sind alle Aufrufe des Data-Avaialble-Link gesperrt.
275         if( IsDownloadingFile() )
276         {
277             // Den aktuellen Zustand einfrieren und in den Pending-Status gehen.
278             // Wenn der Download beendet oder abgebrochen wurde, wird ueber
279             // NewDataRead ein Continue mit dem uebergeben Token angesteossen.
280             SaveState( nToken );
281             eState = SVPAR_PENDING;
282         }
283     }
284 }
285 
GetFileDownloadMIME(String & rMIME)286 sal_Bool SfxHTMLParser::GetFileDownloadMIME( String& rMIME )
287 {
288     return pDLMedium && pDLMedium->GetErrorCode()==0 &&
289            pDLMedium->GetMIMEAndRedirect(rMIME)==0;
290 }
291 
FinishFileDownload(String & rStr)292 sal_Bool SfxHTMLParser::FinishFileDownload( String& rStr )
293 {
294     String aStr;
295 
296     sal_Bool bOK = pDLMedium && pDLMedium->GetErrorCode()==0;
297     if( bOK )
298     {
299         SvStream* pStream = pDLMedium->GetInStream();
300         DBG_ASSERT( pStream, "Kein In-Stream vom Medium erhalten" );
301 
302         SvMemoryStream aStream;
303         if( pStream )   // HACK wegen #65563#
304             aStream << *pStream;
305 
306         aStream.Seek( STREAM_SEEK_TO_END );
307         DBG_ASSERT( aStream.Tell() < STRING_MAXLEN,
308                     "File zu lang fuer einen String, Ende abgeschnitten" );
309         xub_StrLen nLen = aStream.Tell() < STRING_MAXLEN
310                         ? (xub_StrLen)aStream.Tell()
311                         : STRING_MAXLEN;
312 
313         // TODO: untested!!!
314         rtl_TextEncoding eEnc =
315             GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 );
316         String sMime;
317         if( pDLMedium->GetMIMEAndRedirect( sMime ) == 0 )
318         {
319             rtl_TextEncoding eMimeEnc = GetEncodingByMIME( sMime );
320             if( RTL_TEXTENCODING_DONTKNOW != eMimeEnc )
321                 eEnc = eMimeEnc;
322         }
323 
324         ByteString sBuffer;
325         sal_Char* pBuffer = sBuffer.AllocBuffer(nLen);
326         aStream.Seek( 0 );
327         aStream.Read((void*)pBuffer, nLen);
328         rStr = String( pBuffer, RTL_TEXTENCODING_UTF8);
329     }
330 
331     delete pDLMedium;
332     pDLMedium = 0;
333 
334     return bOK;
335 }
336 
IMPL_STATIC_LINK(SfxHTMLParser,FileDownloadDone,void *,EMPTYARG)337 IMPL_STATIC_LINK( SfxHTMLParser, FileDownloadDone, void*, EMPTYARG )
338 {
339     // Der Download ist jetzt abgeschlossen. Ausserdem muss/darf der
340     // Data-Available-Link wieder durchgelassen werden.
341     pThis->SetDownloadingFile( sal_False );
342 
343     // ... und einmal aufrufen, damit weitergelesen wird.
344     pThis->CallAsyncCallLink();
345 
346     return 0;
347 }
348 
GetScriptType_Impl(SvKeyValueIterator * pHTTPHeader)349 void SfxHTMLParser::GetScriptType_Impl( SvKeyValueIterator *pHTTPHeader )
350 {
351     aScriptType = DEFINE_CONST_UNICODE(SVX_MACRO_LANGUAGE_JAVASCRIPT);
352     eScriptType = JAVASCRIPT;
353     if( pHTTPHeader )
354     {
355         SvKeyValue aKV;
356         for( sal_Bool bCont = pHTTPHeader->GetFirst( aKV ); bCont;
357              bCont = pHTTPHeader->GetNext( aKV ) )
358         {
359             if( aKV.GetKey().EqualsIgnoreCaseAscii(
360                                     OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
361             {
362                 if( aKV.GetValue().Len() )
363                 {
364                     String aTmp( aKV.GetValue() );
365                     if( aTmp.EqualsIgnoreCaseAscii( sHTML_MIME_text, 0, 5 ) )
366                         aTmp.Erase( 0, 5 );
367                     else if( aTmp.EqualsIgnoreCaseAscii( sHTML_MIME_application,
368                                                          0, 12 ) )
369                         aTmp.Erase( 0, 12 );
370                     else
371                         break;
372 
373                     if( aTmp.EqualsIgnoreCaseAscii( sHTML_MIME_experimental, 0,
374                                                     2 ) )
375                     {
376                         aTmp.Erase( 0, 2 );
377                     }
378 
379                     if( aTmp.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_LG_starbasic ) )
380                     {
381                         eScriptType = STARBASIC;
382                         aScriptType = DEFINE_CONST_UNICODE(SVX_MACRO_LANGUAGE_STARBASIC);
383                     }
384                     if( !aTmp.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_LG_javascript ) )
385                     {
386                         eScriptType = EXTENDED_STYPE;
387                         aScriptType = aTmp;
388                     }
389                 }
390                 break;
391             }
392         }
393     }
394 }
395 
GetScriptType(SvKeyValueIterator * pHTTPHeader) const396 ScriptType SfxHTMLParser::GetScriptType( SvKeyValueIterator *pHTTPHeader ) const
397 {
398     if( !aScriptType.Len() )
399         ((SfxHTMLParser *)this)->GetScriptType_Impl( pHTTPHeader );
400 
401     return eScriptType;
402 }
403 
GetScriptTypeString(SvKeyValueIterator * pHTTPHeader) const404 const String& SfxHTMLParser::GetScriptTypeString(
405                                     SvKeyValueIterator *pHTTPHeader ) const
406 {
407     if( !aScriptType.Len() )
408         ((SfxHTMLParser *)this)->GetScriptType_Impl( pHTTPHeader );
409 
410     return aScriptType;
411 }
412 
GetTableDataOptionsValNum(sal_uInt32 & nNumForm,LanguageType & eNumLang,const String & aValStr,const String & aNumStr,SvNumberFormatter & rFormatter)413 double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32& nNumForm,
414         LanguageType& eNumLang, const String& aValStr, const String& aNumStr,
415         SvNumberFormatter& rFormatter )
416 {
417     LanguageType eParseLang = (LanguageType )aNumStr.ToInt32();
418     sal_uInt32 nParseForm =
419         rFormatter.GetFormatForLanguageIfBuiltIn( 0, eParseLang );
420     double fVal;
421     rFormatter.IsNumberFormat( aValStr, nParseForm, fVal );
422     if ( aNumStr.GetTokenCount( ';' ) > 2 )
423     {
424         eNumLang = (LanguageType)aNumStr.GetToken( 1, ';' ).ToInt32();
425         xub_StrLen nPos = aNumStr.Search( ';' );
426         nPos = aNumStr.Search( ';', nPos + 1 );
427         String aFormat( aNumStr.Copy( nPos + 1 ) );
428         xub_StrLen nCheckPos;
429         short nType;
430         if ( eNumLang != LANGUAGE_SYSTEM )
431             rFormatter.PutEntry( aFormat, nCheckPos, nType, nNumForm, eNumLang );
432         else
433             rFormatter.PutandConvertEntry( aFormat, nCheckPos, nType, nNumForm,
434                 eParseLang, eNumLang );
435     }
436     else
437     {
438         eNumLang = LANGUAGE_SYSTEM;
439         nNumForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eNumLang );
440     }
441     return fVal;
442 }
443 
444