1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sfxhtml.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include <tools/urlobj.hxx>
36 #include <sfx2/objsh.hxx>
37 #include <sfx2/docfile.hxx>
38 #include "openflag.hxx"
40 #include <svtools/htmlkywd.hxx>
41 #include <svtools/htmltokn.h>
42 #include <svtools/imap.hxx>
43 #include <svtools/imapcirc.hxx>
44 #include <svtools/imapobj.hxx>
45 #include <svtools/imappoly.hxx>
46 #include <svtools/imaprect.hxx>
47 #ifndef _SVSTDARR_ULONGS_DECL
48 #define _SVSTDARR_ULONGS
49 #include <svtools/svstdarr.hxx>
51 #include <svtools/zforlist.hxx>
52 #include <rtl/tencinfo.h>
53 #include <tools/tenccvt.hxx>
55 #include <sfx2/sfxhtml.hxx>
57 #include <com/sun/star/beans/XPropertyContainer.hpp>
60 using namespace ::com::sun::star
;
63 sal_Char __FAR_DATA sHTML_MIME_text
[] = "text/";
64 sal_Char __FAR_DATA sHTML_MIME_application
[] = "application/";
65 sal_Char __FAR_DATA sHTML_MIME_experimental
[] = "x-";
68 #ifdef __MINGW32__ // for runtime pseudo reloc
69 static HTMLOptionEnum aAreaShapeOptEnums
[] =
71 static HTMLOptionEnum __READONLY_DATA aAreaShapeOptEnums
[] =
74 { OOO_STRING_SVTOOLS_HTML_SH_rect
, IMAP_OBJ_RECTANGLE
},
75 { OOO_STRING_SVTOOLS_HTML_SH_rectangle
, IMAP_OBJ_RECTANGLE
},
76 { OOO_STRING_SVTOOLS_HTML_SH_circ
, IMAP_OBJ_CIRCLE
},
77 { OOO_STRING_SVTOOLS_HTML_SH_circle
, IMAP_OBJ_CIRCLE
},
78 { OOO_STRING_SVTOOLS_HTML_SH_poly
, IMAP_OBJ_POLYGON
},
79 { OOO_STRING_SVTOOLS_HTML_SH_polygon
, IMAP_OBJ_POLYGON
},
83 SfxHTMLParser::SfxHTMLParser( SvStream
& rStream
, BOOL bIsNewDoc
,
85 HTMLParser( rStream
, bIsNewDoc
),
86 pMedium( pMed
), pDLMedium( 0 ),
89 DBG_ASSERT( RTL_TEXTENCODING_DONTKNOW
== GetSrcEncoding( ),
90 "SfxHTMLParser::SfxHTMLParser: Wo kommt der ZS her?" );
91 DBG_ASSERT( !IsSwitchToUCS2(),
92 "SfxHTMLParser::SfxHTMLParser: Switch to UCS2?" );
94 // Altough the real default encoding is ISO8859-1, we use MS-1252
95 // als default encoding.
96 SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1
) );
98 // If the file starts with a BOM, switch to UCS2.
99 SetSwitchToUCS2( TRUE
);
102 __EXPORT
SfxHTMLParser::~SfxHTMLParser()
104 DBG_ASSERT( !pDLMedium
, "Da ist ein File-Download stehengeblieben" );
108 BOOL
SfxHTMLParser::ParseMapOptions(ImageMap
* pImageMap
,
109 const HTMLOptions
* pOptions
)
111 DBG_ASSERT( pImageMap
, "ParseMapOptions: keine Image-Map" );
112 DBG_ASSERT( pOptions
, "ParseMapOptions: keine Optionen" );
116 for( USHORT i
=pOptions
->Count(); i
; )
118 const HTMLOption
*pOption
= (*pOptions
)[--i
];
119 switch( pOption
->GetToken() )
122 aName
= pOption
->GetString();
128 pImageMap
->SetName( aName
);
130 return aName
.Len() > 0;
133 BOOL
SfxHTMLParser::ParseAreaOptions(ImageMap
* pImageMap
, const String
& rBaseURL
,
134 const HTMLOptions
* pOptions
,
135 USHORT nEventMouseOver
,
136 USHORT nEventMouseOut
)
138 DBG_ASSERT( pImageMap
, "ParseAreaOptions: keine Image-Map" );
139 DBG_ASSERT( pOptions
, "ParseAreaOptions: keine Optionen" );
141 USHORT nShape
= IMAP_OBJ_RECTANGLE
;
143 String aName
, aHRef
, aAlt
, aTarget
, sEmpty
;
144 BOOL bNoHRef
= FALSE
;
145 SvxMacroTableDtor aMacroTbl
;
147 for( USHORT i
=pOptions
->Count(); i
; )
150 ScriptType eScrpType
= STARBASIC
;
151 const HTMLOption
*pOption
= (*pOptions
)[--i
];
152 switch( pOption
->GetToken() )
155 aName
= pOption
->GetString();
158 pOption
->GetEnum( nShape
, aAreaShapeOptEnums
);
161 pOption
->GetNumbers( aCoords
, TRUE
);
164 aHRef
= INetURLObject::GetAbsURL( rBaseURL
, pOption
->GetString() );
170 aAlt
= pOption
->GetString();
173 aTarget
= pOption
->GetString();
176 case HTML_O_ONMOUSEOVER
:
177 eScrpType
= JAVASCRIPT
;
178 case HTML_O_SDONMOUSEOVER
:
179 nEvent
= nEventMouseOver
;
180 goto IMAPOBJ_SETEVENT
;
182 case HTML_O_ONMOUSEOUT
:
183 eScrpType
= JAVASCRIPT
;
184 case HTML_O_SDONMOUSEOUT
:
185 nEvent
= nEventMouseOut
;
186 goto IMAPOBJ_SETEVENT
;
190 String
sTmp( pOption
->GetString() );
193 sTmp
.ConvertLineEnd();
194 aMacroTbl
.Insert( nEvent
,
195 new SvxMacro( sTmp
, sEmpty
, eScrpType
));
205 BOOL bNewArea
= TRUE
;
208 case IMAP_OBJ_RECTANGLE
:
209 if( aCoords
.Count() >=4 )
211 Rectangle
aRec( aCoords
[0], aCoords
[1],
212 aCoords
[2], aCoords
[3] );
213 IMapRectangleObject
aMapRObj( aRec
, aHRef
, aAlt
, String(), aTarget
, aName
,
215 if( aMacroTbl
.Count() )
216 aMapRObj
.SetMacroTable( aMacroTbl
);
217 pImageMap
->InsertIMapObject( aMapRObj
);
220 case IMAP_OBJ_CIRCLE
:
221 if( aCoords
.Count() >=3 )
223 Point
aPoint( aCoords
[0], aCoords
[1] );
224 IMapCircleObject
aMapCObj( aPoint
, aCoords
[2],aHRef
, aAlt
, String(),
225 aTarget
, aName
, !bNoHRef
);
226 if( aMacroTbl
.Count() )
227 aMapCObj
.SetMacroTable( aMacroTbl
);
228 pImageMap
->InsertIMapObject( aMapCObj
);
231 case IMAP_OBJ_POLYGON
:
232 if( aCoords
.Count() >=6 )
234 USHORT nCount
= aCoords
.Count() / 2;
235 Polygon
aPoly( nCount
);
236 for( USHORT i
=0; i
<nCount
; i
++ )
237 aPoly
[i
] = Point( aCoords
[2*i
], aCoords
[2*i
+1] );
238 IMapPolygonObject
aMapPObj( aPoly
, aHRef
, aAlt
, String(), aTarget
, aName
,
240 if( aMacroTbl
.Count() )
241 aMapPObj
.SetMacroTable( aMacroTbl
);
242 pImageMap
->InsertIMapObject( aMapPObj
);
253 void SfxHTMLParser::StartFileDownload( const String
& rURL
, int nToken
,
254 SfxObjectShell
*pSh
)
256 DBG_ASSERT( !pDLMedium
, "StartFileDwonload bei aktivem Download" );
260 pDLMedium
= new SfxMedium( rURL
, SFX_STREAM_READONLY
, FALSE
);
263 // Medium registrieren, damit abgebrochen werden kann
264 pSh
->RegisterTransfer( *pDLMedium
);
266 // Target-Frame uebertragen, damit auch javascript:-URLs
267 // "geladen" werden koennen.
268 //const SfxMedium *pShMedium = pSh->GetMedium();
270 // pDLMedium->SetLoadTargetFrame( pShMedium->GetLoadTargetFrame() );
273 // Download anstossen (Achtung: Kann auch synchron sein).
274 if ( TRUE
/*pMedium->GetDoneLink() == Link()*/ )
275 pDLMedium
->DownLoad();
278 // Downloading-Flag auf TRUE setzen. Es werden dann auch
279 // Data-Available-Links, wenn wir in den Pending-Staus gelangen.
280 SetDownloadingFile( TRUE
);
281 pDLMedium
->DownLoad( STATIC_LINK( this, SfxHTMLParser
, FileDownloadDone
) );
283 // Wenn das Dowsnloading-Flag noch gesetzt ist erfolgt der Download
284 // asynchron. Wir gehen dann in den Pedning-Staus und warten dort.
285 // Solange sind alle Aufrufe des Data-Avaialble-Link gesperrt.
286 if( IsDownloadingFile() )
288 // Den aktuellen Zustand einfrieren und in den Pending-Status gehen.
289 // Wenn der Download beendet oder abgebrochen wurde, wird ueber
290 // NewDataRead ein Continue mit dem uebergeben Token angesteossen.
292 eState
= SVPAR_PENDING
;
297 BOOL
SfxHTMLParser::GetFileDownloadMIME( String
& rMIME
)
299 return pDLMedium
&& pDLMedium
->GetErrorCode()==0 &&
300 pDLMedium
->GetMIMEAndRedirect(rMIME
)==0;
303 BOOL
SfxHTMLParser::FinishFileDownload( String
& rStr
)
307 BOOL bOK
= pDLMedium
&& pDLMedium
->GetErrorCode()==0;
310 SvStream
* pStream
= pDLMedium
->GetInStream();
311 DBG_ASSERT( pStream
, "Kein In-Stream vom Medium erhalten" );
313 SvMemoryStream aStream
;
314 if( pStream
) // HACK wegen #65563#
317 aStream
.Seek( STREAM_SEEK_TO_END
);
318 DBG_ASSERT( aStream
.Tell() < STRING_MAXLEN
,
319 "File zu lang fuer einen String, Ende abgeschnitten" );
320 xub_StrLen nLen
= aStream
.Tell() < STRING_MAXLEN
321 ? (xub_StrLen
)aStream
.Tell()
325 rtl_TextEncoding eEnc
=
326 GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1
);
328 if( pDLMedium
->GetMIMEAndRedirect( sMime
) == 0 )
330 rtl_TextEncoding eMimeEnc
= GetEncodingByMIME( sMime
);
331 if( RTL_TEXTENCODING_DONTKNOW
!= eMimeEnc
)
336 sal_Char
* pBuffer
= sBuffer
.AllocBuffer(nLen
);
338 aStream
.Read((void*)pBuffer
, nLen
);
339 rStr
= String( S2U(pBuffer
) );
348 IMPL_STATIC_LINK( SfxHTMLParser
, FileDownloadDone
, void*, EMPTYARG
)
350 // Der Download ist jetzt abgeschlossen. Ausserdem muss/darf der
351 // Data-Available-Link wieder durchgelassen werden.
352 pThis
->SetDownloadingFile( FALSE
);
354 // ... und einmal aufrufen, damit weitergelesen wird.
355 pThis
->CallAsyncCallLink();
360 rtl_TextEncoding
SfxHTMLParser::GetEncodingByHttpHeader( SvKeyValueIterator
*pHTTPHeader
)
362 rtl_TextEncoding eRet
= RTL_TEXTENCODING_DONTKNOW
;
366 for( BOOL bCont
= pHTTPHeader
->GetFirst( aKV
); bCont
;
367 bCont
= pHTTPHeader
->GetNext( aKV
) )
369 if( aKV
.GetKey().EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type
) )
371 if( aKV
.GetValue().Len() )
373 eRet
= SfxHTMLParser::GetEncodingByMIME( aKV
.GetValue() );
381 BOOL
SfxHTMLParser::SetEncodingByHTTPHeader(
382 SvKeyValueIterator
*pHTTPHeader
)
385 rtl_TextEncoding eEnc
= SfxHTMLParser::GetEncodingByHttpHeader( pHTTPHeader
);
386 if(RTL_TEXTENCODING_DONTKNOW
!= eEnc
)
388 SetSrcEncoding( eEnc
);
394 void SfxHTMLParser::GetScriptType_Impl( SvKeyValueIterator
*pHTTPHeader
)
396 aScriptType
= DEFINE_CONST_UNICODE(SVX_MACRO_LANGUAGE_JAVASCRIPT
);
397 eScriptType
= JAVASCRIPT
;
401 for( BOOL bCont
= pHTTPHeader
->GetFirst( aKV
); bCont
;
402 bCont
= pHTTPHeader
->GetNext( aKV
) )
404 if( aKV
.GetKey().EqualsIgnoreCaseAscii(
405 OOO_STRING_SVTOOLS_HTML_META_content_script_type
) )
407 if( aKV
.GetValue().Len() )
409 String
aTmp( aKV
.GetValue() );
410 if( aTmp
.EqualsIgnoreCaseAscii( sHTML_MIME_text
, 0, 5 ) )
412 else if( aTmp
.EqualsIgnoreCaseAscii( sHTML_MIME_application
,
418 if( aTmp
.EqualsIgnoreCaseAscii( sHTML_MIME_experimental
, 0,
424 if( aTmp
.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_LG_starbasic
) )
426 eScriptType
= STARBASIC
;
427 aScriptType
= DEFINE_CONST_UNICODE(SVX_MACRO_LANGUAGE_STARBASIC
);
429 if( !aTmp
.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_LG_javascript
) )
431 eScriptType
= EXTENDED_STYPE
;
441 ScriptType
SfxHTMLParser::GetScriptType( SvKeyValueIterator
*pHTTPHeader
) const
443 if( !aScriptType
.Len() )
444 ((SfxHTMLParser
*)this)->GetScriptType_Impl( pHTTPHeader
);
449 const String
& SfxHTMLParser::GetScriptTypeString(
450 SvKeyValueIterator
*pHTTPHeader
) const
452 if( !aScriptType
.Len() )
453 ((SfxHTMLParser
*)this)->GetScriptType_Impl( pHTTPHeader
);
458 double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32
& nNumForm
,
459 LanguageType
& eNumLang
, const String
& aValStr
, const String
& aNumStr
,
460 SvNumberFormatter
& rFormatter
)
462 LanguageType eParseLang
= (LanguageType
)aNumStr
.ToInt32();
463 sal_uInt32 nParseForm
=
464 rFormatter
.GetFormatForLanguageIfBuiltIn( 0, eParseLang
);
466 rFormatter
.IsNumberFormat( aValStr
, nParseForm
, fVal
);
467 if ( aNumStr
.GetTokenCount( ';' ) > 2 )
469 eNumLang
= (LanguageType
)aNumStr
.GetToken( 1, ';' ).ToInt32();
470 xub_StrLen nPos
= aNumStr
.Search( ';' );
471 nPos
= aNumStr
.Search( ';', nPos
+ 1 );
472 String
aFormat( aNumStr
.Copy( nPos
+ 1 ) );
473 xub_StrLen nCheckPos
;
475 if ( eNumLang
!= LANGUAGE_SYSTEM
)
476 rFormatter
.PutEntry( aFormat
, nCheckPos
, nType
, nNumForm
, eNumLang
);
478 rFormatter
.PutandConvertEntry( aFormat
, nCheckPos
, nType
, nNumForm
,
479 eParseLang
, eNumLang
);
483 eNumLang
= LANGUAGE_SYSTEM
;
484 nNumForm
= rFormatter
.GetFormatForLanguageIfBuiltIn( 0, eNumLang
);