LibreOffice Module sfx2 (master) 1
sfxhtml.cxx
Go to the documentation of this file.
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
21#include <tools/urlobj.hxx>
22#include <tools/debug.hxx>
23
24#include <sfx2/docfile.hxx>
25#include <sfx2/event.hxx>
26#include <openflag.hxx>
27
28#include <svl/numformat.hxx>
29#include <svtools/htmlkywd.hxx>
30#include <svtools/htmltokn.h>
31#include <vcl/imap.hxx>
32#include <vcl/imapcirc.hxx>
33#include <vcl/imapobj.hxx>
34#include <vcl/imappoly.hxx>
35#include <vcl/imaprect.hxx>
36#include <svl/zforlist.hxx>
37
38#include <sfx2/sfxhtml.hxx>
39
40#include <comphelper/string.hxx>
41#include <o3tl/string_view.hxx>
42
43#include <vector>
44
45
46using namespace ::com::sun::star;
47
48
49// <INPUT TYPE=xxx>
51{
52 { OOO_STRING_SVTOOLS_HTML_SH_rect, IMapObjectType::Rectangle },
53 { OOO_STRING_SVTOOLS_HTML_SH_rectangle, IMapObjectType::Rectangle },
54 { OOO_STRING_SVTOOLS_HTML_SH_circ, IMapObjectType::Circle },
55 { OOO_STRING_SVTOOLS_HTML_SH_circle, IMapObjectType::Circle },
56 { OOO_STRING_SVTOOLS_HTML_SH_poly, IMapObjectType::Polygon },
57 { OOO_STRING_SVTOOLS_HTML_SH_polygon, IMapObjectType::Polygon },
58 { nullptr, IMapObjectType::Rectangle }
59};
60
61SfxHTMLParser::SfxHTMLParser( SvStream& rStream, bool bIsNewDoc,
62 SfxMedium *pMed )
63 : HTMLParser(rStream, bIsNewDoc)
64 , pMedium(pMed)
65 , eScriptType(STARBASIC)
66{
67 DBG_ASSERT( RTL_TEXTENCODING_UTF8 == GetSrcEncoding( ),
68 "SfxHTMLParser::SfxHTMLParser: From where comes ZS?" );
69
71 "SfxHTMLParser::SfxHTMLParser: Switch to UCS2?" );
72
73 // If the file starts with a BOM, switch to UCS2.
74 SetSwitchToUCS2( true );
75}
76
78{
79 DBG_ASSERT( !pDLMedium, "Here is a File Download that has got stuck" );
80}
81
83 ImageMap* pImageMap, const HTMLOptions& rOptions)
84{
85 DBG_ASSERT( pImageMap, "ParseMapOptions: No Image-Map" );
86
87 OUString aName;
88
89 for (size_t i = rOptions.size(); i; )
90 {
91 const HTMLOption& aOption = rOptions[--i];
92 if ( aOption.GetToken() == HtmlOptionId::NAME )
93 aName = aOption.GetString();
94 }
95
96 if( !aName.isEmpty() )
97 pImageMap->SetName( aName );
98
99 return !aName.isEmpty();
100}
101
102bool SfxHTMLParser::ParseAreaOptions(ImageMap * pImageMap, std::u16string_view rBaseURL,
103 const HTMLOptions& rOptions,
104 SvMacroItemId nEventMouseOver,
105 SvMacroItemId nEventMouseOut )
106{
107 DBG_ASSERT( pImageMap, "ParseAreaOptions: no Image-Map" );
108
109 IMapObjectType nShape = IMapObjectType::Rectangle;
110 std::vector<sal_uInt32> aCoords;
111 OUString aName, aHRef, aAlt, aTarget;
112 bool bNoHRef = false;
113 SvxMacroTableDtor aMacroTbl;
114
115 for (size_t i = rOptions.size(); i; )
116 {
118 ScriptType eScrpType = STARBASIC;
119 const HTMLOption& rOption = rOptions[--i];
120 switch( rOption.GetToken() )
121 {
122 case HtmlOptionId::NAME:
123 aName = rOption.GetString();
124 break;
125 case HtmlOptionId::SHAPE:
126 rOption.GetEnum( nShape, aAreaShapeOptEnums );
127 break;
128 case HtmlOptionId::COORDS:
129 rOption.GetNumbers( aCoords );
130 break;
131 case HtmlOptionId::HREF:
132 aHRef = INetURLObject::GetAbsURL( rBaseURL, rOption.GetString() );
133 break;
134 case HtmlOptionId::NOHREF:
135 bNoHRef = true;
136 break;
137 case HtmlOptionId::ALT:
138 aAlt = rOption.GetString();
139 break;
140 case HtmlOptionId::TARGET:
141 aTarget = rOption.GetString();
142 break;
143
144 case HtmlOptionId::ONMOUSEOVER:
145 eScrpType = JAVASCRIPT;
146 [[fallthrough]];
147 case HtmlOptionId::SDONMOUSEOVER:
148 nEvent = nEventMouseOver;
149 goto IMAPOBJ_SETEVENT;
150
151 case HtmlOptionId::ONMOUSEOUT:
152 eScrpType = JAVASCRIPT;
153 [[fallthrough]];
154 case HtmlOptionId::SDONMOUSEOUT:
155 nEvent = nEventMouseOut;
156 goto IMAPOBJ_SETEVENT;
157IMAPOBJ_SETEVENT:
158 if( nEvent != SvMacroItemId::NONE)
159 {
160 OUString sTmp( rOption.GetString() );
161 if( !sTmp.isEmpty() )
162 {
163 sTmp = convertLineEnd(sTmp, GetSystemLineEnd());
164 aMacroTbl.Insert( nEvent, SvxMacro( sTmp, "", eScrpType ));
165 }
166 }
167 break;
168 default: break;
169 }
170 }
171
172 if( bNoHRef )
173 aHRef.clear();
174
175 bool bNewArea = true;
176 switch( nShape )
177 {
178 case IMapObjectType::Rectangle:
179 if( aCoords.size() >=4 )
180 {
181 tools::Rectangle aRect( aCoords[0], aCoords[1],
182 aCoords[2], aCoords[3] );
183 std::unique_ptr<IMapRectangleObject> pMapRObj( new IMapRectangleObject(aRect, aHRef, aAlt, OUString(), aTarget, aName,
184 !bNoHRef ));
185 if( !aMacroTbl.empty() )
186 pMapRObj->SetMacroTable( aMacroTbl );
187 pImageMap->InsertIMapObject( std::move(pMapRObj) );
188 }
189 break;
190 case IMapObjectType::Circle:
191 if( aCoords.size() >=3 )
192 {
193 Point aPoint( aCoords[0], aCoords[1] );
194 std::unique_ptr<IMapCircleObject> pMapCObj(new IMapCircleObject(aPoint, aCoords[2],aHRef, aAlt, OUString(),
195 aTarget, aName, !bNoHRef ));
196 if( !aMacroTbl.empty() )
197 pMapCObj->SetMacroTable( aMacroTbl );
198 pImageMap->InsertIMapObject( std::move(pMapCObj) );
199 }
200 break;
201 case IMapObjectType::Polygon:
202 if( aCoords.size() >=6 )
203 {
204 sal_uInt16 nCount = aCoords.size() / 2;
205 tools::Polygon aPoly( nCount );
206 for( sal_uInt16 i=0; i<nCount; i++ )
207 aPoly[i] = Point( aCoords[2*i], aCoords[2*i+1] );
208 std::unique_ptr<IMapPolygonObject> pMapPObj(new IMapPolygonObject( aPoly, aHRef, aAlt, OUString(), aTarget, aName,
209 !bNoHRef ));
210 if( !aMacroTbl.empty() )
211 pMapPObj->SetMacroTable( aMacroTbl );
212 pImageMap->InsertIMapObject( std::move(pMapPObj) );
213 }
214 break;
215 default:
216 bNewArea = false;
217 }
218
219 return bNewArea;
220}
221
222void SfxHTMLParser::StartFileDownload(const OUString& rURL)
223{
224 DBG_ASSERT( !pDLMedium, "StartFileDownload when active Download" );
225 if( pDLMedium )
226 return;
227
228 pDLMedium.reset( new SfxMedium( rURL, SFX_STREAM_READONLY ) );
229 pDLMedium->Download();
230}
231
233{
234 bool bOK = pDLMedium && pDLMedium->GetErrorCode() == ERRCODE_NONE;
235 if( bOK )
236 {
237 SvStream* pStream = pDLMedium->GetInStream();
238 DBG_ASSERT( pStream, "No In-Stream received from Medium" );
239
240 SvMemoryStream aStream;
241 if( pStream )
242 aStream.WriteStream( *pStream );
243
244 sal_uInt64 const nLen = aStream.TellEnd();
245 aStream.Seek( 0 );
246 rStr = read_uInt8s_ToOUString(aStream, nLen, RTL_TEXTENCODING_UTF8);
247 }
248
249 pDLMedium.reset();
250
251 return bOK;
252}
253
255{
258 if( !pHTTPHeader )
259 return;
260
261 SvKeyValue aKV;
262 for( bool bCont = pHTTPHeader->GetFirst( aKV ); bCont;
263 bCont = pHTTPHeader->GetNext( aKV ) )
264 {
265 if( aKV.GetKey().equalsIgnoreAsciiCase(
267 {
268 if( !aKV.GetValue().isEmpty() )
269 {
270 OUString aTmp( aKV.GetValue() );
271 if( aTmp.startsWithIgnoreAsciiCase( "text/" ) )
272 aTmp = aTmp.copy( 5 );
273 else if( aTmp.startsWithIgnoreAsciiCase( "application/" ) )
274 aTmp = aTmp.copy( 12 );
275 else
276 break;
277
278 if( aTmp.startsWithIgnoreAsciiCase( "x-" ) ) // MIME-experimental
279 {
280 aTmp = aTmp.copy( 2 );
281 }
282
283 if( aTmp.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_LG_starbasic ) )
284 {
287 }
288 if( !aTmp.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_LG_javascript ) )
289 {
291 aScriptType = aTmp;
292 }
293 }
294 break;
295 }
296 }
297}
298
300{
301 if( aScriptType.isEmpty() )
302 const_cast<SfxHTMLParser *>(this)->GetScriptType_Impl( pHTTPHeader );
303
304 return eScriptType;
305}
306
308 SvKeyValueIterator *pHTTPHeader ) const
309{
310 if( aScriptType.isEmpty() )
311 const_cast<SfxHTMLParser *>(this)->GetScriptType_Impl( pHTTPHeader );
312
313 return aScriptType;
314}
315
316double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32& nNumForm,
317 LanguageType& eNumLang, const OUString& aValStr, std::u16string_view aNumStr,
318 SvNumberFormatter& rFormatter )
319{
320 LanguageType eParseLang(o3tl::toInt32(aNumStr));
321 sal_uInt32 nParseForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eParseLang );
322 double fVal;
323 (void)rFormatter.IsNumberFormat(aValStr, nParseForm, fVal);
324 if ( comphelper::string::getTokenCount(aNumStr, ';') > 2 )
325 {
326 sal_Int32 nIdx {0};
327 eNumLang = LanguageType(o3tl::toInt32(o3tl::getToken(aNumStr, 1, ';', nIdx )));
328 OUString aFormat( aNumStr.substr( nIdx ) );
329 sal_Int32 nCheckPos;
331 if ( eNumLang != LANGUAGE_SYSTEM )
332 rFormatter.PutEntry( aFormat, nCheckPos, nType, nNumForm, eNumLang );
333 else
334 rFormatter.PutandConvertEntry( aFormat, nCheckPos, nType, nNumForm,
335 eParseLang, eNumLang, true);
336 }
337 else
338 {
339 eNumLang = LANGUAGE_SYSTEM;
340 nNumForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eNumLang );
341 }
342 return fVal;
343}
344
345/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
HtmlOptionId GetToken() const
void GetNumbers(std::vector< sal_uInt32 > &rNumbers) const
const OUString & GetString() const
EnumT GetEnum(const HTMLOptionEnum< EnumT > *pOptEnums, EnumT nDflt=static_cast< EnumT >(0)) const
static OUString GetAbsURL(std::u16string_view rTheBaseURIRef, OUString const &rTheRelURIRef, EncodeMechanism eEncodeMechanism=EncodeMechanism::WasEncoded, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
void SetName(const OUString &rName)
void InsertIMapObject(const IMapObject &rIMapObject)
ScriptType GetScriptType(SvKeyValueIterator *) const
Definition: sfxhtml.cxx:299
static bool ParseAreaOptions(ImageMap *pImageMap, std::u16string_view rBaseURL, const HTMLOptions &rOptions, SvMacroItemId nEventMouseOver, SvMacroItemId nEventMouseOut)
Definition: sfxhtml.cxx:102
const OUString & GetScriptTypeString(SvKeyValueIterator *) const
Definition: sfxhtml.cxx:307
std::unique_ptr< SfxMedium > pDLMedium
Definition: sfxhtml.hxx:41
void StartFileDownload(const OUString &rURL)
Definition: sfxhtml.cxx:222
static double GetTableDataOptionsValNum(sal_uInt32 &nNumForm, LanguageType &eNumLang, const OUString &aValStr, std::u16string_view aNumStr, SvNumberFormatter &rFormatter)
Definition: sfxhtml.cxx:316
SAL_DLLPRIVATE void GetScriptType_Impl(SvKeyValueIterator *)
Definition: sfxhtml.cxx:254
virtual ~SfxHTMLParser() override
Definition: sfxhtml.cxx:77
static bool ParseMapOptions(ImageMap *pImageMap, const HTMLOptions &rOptions)
Definition: sfxhtml.cxx:82
bool FinishFileDownload(OUString &rStr)
Definition: sfxhtml.cxx:232
SfxHTMLParser(SvStream &rStream, bool bNewDoc, SfxMedium *pMedium)
Definition: sfxhtml.cxx:61
OUString aScriptType
Definition: sfxhtml.hxx:38
ScriptType eScriptType
Definition: sfxhtml.hxx:43
virtual bool GetFirst(SvKeyValue &rKeyVal)
virtual bool GetNext(SvKeyValue &rKeyVal)
const OUString & GetKey() const
const OUString & GetValue() const
virtual sal_uInt64 TellEnd() override
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
bool PutandConvertEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge, LanguageType eNewLnge, bool bConvertDateOrder, bool bReplaceBooleanEquivalent=true)
sal_uInt32 GetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat, LanguageType eLnge=LANGUAGE_DONTKNOW)
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
rtl_TextEncoding GetSrcEncoding() const
bool IsSwitchToUCS2() const
void SetSwitchToUCS2(bool bSet)
sal_uInt64 Seek(sal_uInt64 nPos)
SvStream & WriteStream(SvStream &rStream)
SvxMacro & Insert(SvMacroItemId nEvent, const SvxMacro &rMacro)
bool empty() const
int nCount
#define DBG_ASSERT(sCon, aError)
#define ERRCODE_NONE
SvMacroItemId
these values get stored in streams in a 16-bit value
Definition: event.hxx:41
#define OOO_STRING_SVTOOLS_HTML_LG_javascript
#define OOO_STRING_SVTOOLS_HTML_SH_circle
#define OOO_STRING_SVTOOLS_HTML_SH_circ
#define OOO_STRING_SVTOOLS_HTML_SH_rect
#define OOO_STRING_SVTOOLS_HTML_META_content_script_type
#define OOO_STRING_SVTOOLS_HTML_LG_starbasic
#define OOO_STRING_SVTOOLS_HTML_SH_rectangle
#define OOO_STRING_SVTOOLS_HTML_SH_polygon
#define OOO_STRING_SVTOOLS_HTML_SH_poly
IMapObjectType
OUString aName
#define LANGUAGE_SYSTEM
LineEnd GetSystemLineEnd()
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
ScriptType
EXTENDED_STYPE
JAVASCRIPT
STARBASIC
constexpr OUStringLiteral SVX_MACRO_LANGUAGE_JAVASCRIPT
constexpr OUStringLiteral SVX_MACRO_LANGUAGE_STARBASIC
sal_Int32 getTokenCount(std::string_view rIn, char cTok)
int i
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
#define SFX_STREAM_READONLY
Definition: openflag.hxx:26
::std::vector< HTMLOption > HTMLOptions
QPRO_FUNC_TYPE nType
HTMLOptionEnum< IMapObjectType > const aAreaShapeOptEnums[]
Definition: sfxhtml.cxx:50
OUString read_uInt8s_ToOUString(SvStream &rStrm, std::size_t nUnits, rtl_TextEncoding eEnc)
SvNumFormatType