/src/libreoffice/sfx2/source/bastyp/sfxhtml.cxx
Line | Count | Source |
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 | | |
46 | | using namespace ::com::sun::star; |
47 | | |
48 | | |
49 | | // <INPUT TYPE=xxx> |
50 | | HTMLOptionEnum<IMapObjectType> const aAreaShapeOptEnums[] = |
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 | | |
61 | | SfxHTMLParser::SfxHTMLParser( SvStream& rStream, bool bIsNewDoc, |
62 | | SfxMedium *pMed ) |
63 | 13.8k | : HTMLParser(rStream, bIsNewDoc) |
64 | 13.8k | , pMedium(pMed) |
65 | 13.8k | , eScriptType(STARBASIC) |
66 | 13.8k | { |
67 | 13.8k | DBG_ASSERT( RTL_TEXTENCODING_UTF8 == GetSrcEncoding( ), |
68 | 13.8k | "SfxHTMLParser::SfxHTMLParser: From where comes ZS?" ); |
69 | | |
70 | 13.8k | DBG_ASSERT( !IsSwitchToUCS2(), |
71 | 13.8k | "SfxHTMLParser::SfxHTMLParser: Switch to UCS2?" ); |
72 | | |
73 | | // If the file starts with a BOM, switch to UCS2. |
74 | 13.8k | SetSwitchToUCS2( true ); |
75 | 13.8k | } |
76 | | |
77 | | SfxHTMLParser::~SfxHTMLParser() |
78 | 13.8k | { |
79 | 13.8k | DBG_ASSERT( !pDLMedium, "Here is a File Download that has got stuck" ); |
80 | 13.8k | } |
81 | | |
82 | | bool SfxHTMLParser::ParseMapOptions( |
83 | | ImageMap* pImageMap, const HTMLOptions& rOptions) |
84 | 1.85k | { |
85 | 1.85k | DBG_ASSERT( pImageMap, "ParseMapOptions: No Image-Map" ); |
86 | | |
87 | 1.85k | OUString aName; |
88 | | |
89 | 3.77k | for (size_t i = rOptions.size(); i; ) |
90 | 1.92k | { |
91 | 1.92k | const HTMLOption& aOption = rOptions[--i]; |
92 | 1.92k | if ( aOption.GetToken() == HtmlOptionId::NAME ) |
93 | 1.45k | aName = aOption.GetString(); |
94 | 1.92k | } |
95 | | |
96 | 1.85k | if( !aName.isEmpty() ) |
97 | 1.20k | pImageMap->SetName( aName ); |
98 | | |
99 | 1.85k | return !aName.isEmpty(); |
100 | 1.85k | } |
101 | | |
102 | | bool SfxHTMLParser::ParseAreaOptions(ImageMap * pImageMap, std::u16string_view rBaseURL, |
103 | | const HTMLOptions& rOptions, |
104 | | SvMacroItemId nEventMouseOver, |
105 | | SvMacroItemId nEventMouseOut ) |
106 | 2.54k | { |
107 | 2.54k | DBG_ASSERT( pImageMap, "ParseAreaOptions: no Image-Map" ); |
108 | | |
109 | 2.54k | IMapObjectType nShape = IMapObjectType::Rectangle; |
110 | 2.54k | std::vector<sal_uInt32> aCoords; |
111 | 2.54k | OUString aName, aHRef, aAlt, aTarget; |
112 | 2.54k | bool bNoHRef = false; |
113 | 2.54k | SvxMacroTableDtor aMacroTbl; |
114 | | |
115 | 11.4k | for (size_t i = rOptions.size(); i; ) |
116 | 8.92k | { |
117 | 8.92k | SvMacroItemId nEvent = SvMacroItemId::NONE; |
118 | 8.92k | ScriptType eScrpType = STARBASIC; |
119 | 8.92k | const HTMLOption& rOption = rOptions[--i]; |
120 | 8.92k | switch( rOption.GetToken() ) |
121 | 8.92k | { |
122 | 38 | case HtmlOptionId::NAME: |
123 | 38 | aName = rOption.GetString(); |
124 | 38 | break; |
125 | 1.93k | case HtmlOptionId::SHAPE: |
126 | 1.93k | rOption.GetEnum( nShape, aAreaShapeOptEnums ); |
127 | 1.93k | break; |
128 | 2.14k | case HtmlOptionId::COORDS: |
129 | 2.14k | rOption.GetNumbers( aCoords ); |
130 | 2.14k | break; |
131 | 942 | case HtmlOptionId::HREF: |
132 | 942 | aHRef = INetURLObject::GetAbsURL( rBaseURL, rOption.GetString() ); |
133 | 942 | break; |
134 | 2 | case HtmlOptionId::NOHREF: |
135 | 2 | bNoHRef = true; |
136 | 2 | break; |
137 | 991 | case HtmlOptionId::ALT: |
138 | 991 | aAlt = rOption.GetString(); |
139 | 991 | break; |
140 | 78 | case HtmlOptionId::TARGET: |
141 | 78 | aTarget = rOption.GetString(); |
142 | 78 | break; |
143 | | |
144 | 18 | case HtmlOptionId::ONMOUSEOVER: |
145 | 18 | eScrpType = JAVASCRIPT; |
146 | 18 | [[fallthrough]]; |
147 | 18 | case HtmlOptionId::SDONMOUSEOVER: |
148 | 18 | nEvent = nEventMouseOver; |
149 | 18 | goto IMAPOBJ_SETEVENT; |
150 | | |
151 | 44 | case HtmlOptionId::ONMOUSEOUT: |
152 | 44 | eScrpType = JAVASCRIPT; |
153 | 44 | [[fallthrough]]; |
154 | 44 | case HtmlOptionId::SDONMOUSEOUT: |
155 | 44 | nEvent = nEventMouseOut; |
156 | 44 | goto IMAPOBJ_SETEVENT; |
157 | 62 | IMAPOBJ_SETEVENT: |
158 | 62 | if( nEvent != SvMacroItemId::NONE) |
159 | 62 | { |
160 | 62 | OUString sTmp( rOption.GetString() ); |
161 | 62 | if( !sTmp.isEmpty() ) |
162 | 62 | { |
163 | 62 | sTmp = convertLineEnd(sTmp, GetSystemLineEnd()); |
164 | 62 | aMacroTbl.Insert( nEvent, SvxMacro( sTmp, u""_ustr, eScrpType )); |
165 | 62 | } |
166 | 62 | } |
167 | 62 | break; |
168 | 2.72k | default: break; |
169 | 8.92k | } |
170 | 8.92k | } |
171 | | |
172 | 2.54k | if( bNoHRef ) |
173 | 2 | aHRef.clear(); |
174 | | |
175 | 2.54k | bool bNewArea = true; |
176 | 2.54k | switch( nShape ) |
177 | 2.54k | { |
178 | 2.41k | case IMapObjectType::Rectangle: |
179 | 2.41k | if( aCoords.size() >=4 ) |
180 | 1.63k | { |
181 | 1.63k | tools::Rectangle aRect( aCoords[0], aCoords[1], |
182 | 1.63k | aCoords[2], aCoords[3] ); |
183 | 1.63k | std::unique_ptr<IMapRectangleObject> pMapRObj( new IMapRectangleObject(aRect, aHRef, aAlt, OUString(), aTarget, aName, |
184 | 1.63k | !bNoHRef )); |
185 | 1.63k | if( !aMacroTbl.empty() ) |
186 | 3 | pMapRObj->SetMacroTable( aMacroTbl ); |
187 | 1.63k | pImageMap->InsertIMapObject( std::move(pMapRObj) ); |
188 | 1.63k | } |
189 | 2.41k | break; |
190 | 53 | case IMapObjectType::Circle: |
191 | 53 | if( aCoords.size() >=3 ) |
192 | 52 | { |
193 | 52 | Point aPoint( aCoords[0], aCoords[1] ); |
194 | 52 | std::unique_ptr<IMapCircleObject> pMapCObj(new IMapCircleObject(aPoint, aCoords[2],aHRef, aAlt, OUString(), |
195 | 52 | aTarget, aName, !bNoHRef )); |
196 | 52 | if( !aMacroTbl.empty() ) |
197 | 0 | pMapCObj->SetMacroTable( aMacroTbl ); |
198 | 52 | pImageMap->InsertIMapObject( std::move(pMapCObj) ); |
199 | 52 | } |
200 | 53 | break; |
201 | 79 | case IMapObjectType::Polygon: |
202 | 79 | if( aCoords.size() >=6 ) |
203 | 66 | { |
204 | 66 | sal_uInt16 nCount = aCoords.size() / 2; |
205 | 66 | tools::Polygon aPoly( nCount ); |
206 | 393 | for( sal_uInt16 i=0; i<nCount; i++ ) |
207 | 327 | aPoly[i] = Point( aCoords[2*i], aCoords[2*i+1] ); |
208 | 66 | std::unique_ptr<IMapPolygonObject> pMapPObj(new IMapPolygonObject( aPoly, aHRef, aAlt, OUString(), aTarget, aName, |
209 | 66 | !bNoHRef )); |
210 | 66 | if( !aMacroTbl.empty() ) |
211 | 1 | pMapPObj->SetMacroTable( aMacroTbl ); |
212 | 66 | pImageMap->InsertIMapObject( std::move(pMapPObj) ); |
213 | 66 | } |
214 | 79 | break; |
215 | 0 | default: |
216 | 0 | bNewArea = false; |
217 | 2.54k | } |
218 | | |
219 | 2.54k | return bNewArea; |
220 | 2.54k | } |
221 | | |
222 | | void SfxHTMLParser::StartFileDownload(const OUString& rURL) |
223 | 0 | { |
224 | 0 | DBG_ASSERT( !pDLMedium, "StartFileDownload when active Download" ); |
225 | 0 | if( pDLMedium ) |
226 | 0 | return; |
227 | | |
228 | 0 | pDLMedium.reset( new SfxMedium( rURL, SFX_STREAM_READONLY ) ); |
229 | 0 | pDLMedium->Download(); |
230 | 0 | } |
231 | | |
232 | | bool SfxHTMLParser::FinishFileDownload( OUString& rStr ) |
233 | 0 | { |
234 | 0 | bool bOK = pDLMedium && pDLMedium->GetErrorCode() == ERRCODE_NONE; |
235 | 0 | if( bOK ) |
236 | 0 | { |
237 | 0 | SvStream* pStream = pDLMedium->GetInStream(); |
238 | 0 | DBG_ASSERT( pStream, "No In-Stream received from Medium" ); |
239 | |
|
240 | 0 | SvMemoryStream aStream; |
241 | 0 | if( pStream ) |
242 | 0 | aStream.WriteStream( *pStream ); |
243 | |
|
244 | 0 | sal_uInt64 const nLen = aStream.TellEnd(); |
245 | 0 | aStream.Seek( 0 ); |
246 | 0 | rStr = read_uInt8s_ToOUString(aStream, nLen, RTL_TEXTENCODING_UTF8); |
247 | 0 | } |
248 | |
|
249 | 0 | pDLMedium.reset(); |
250 | |
|
251 | 0 | return bOK; |
252 | 0 | } |
253 | | |
254 | | void SfxHTMLParser::GetScriptType_Impl( SvKeyValueIterator *pHTTPHeader ) |
255 | 6.77k | { |
256 | 6.77k | aScriptType = SVX_MACRO_LANGUAGE_JAVASCRIPT; |
257 | 6.77k | eScriptType = JAVASCRIPT; |
258 | 6.77k | if( !pHTTPHeader ) |
259 | 0 | return; |
260 | | |
261 | 6.77k | SvKeyValue aKV; |
262 | 8.68k | for( bool bCont = pHTTPHeader->GetFirst( aKV ); bCont; |
263 | 6.77k | bCont = pHTTPHeader->GetNext( aKV ) ) |
264 | 1.90k | { |
265 | 1.90k | if( aKV.GetKey().equalsIgnoreAsciiCase( |
266 | 1.90k | OOO_STRING_SVTOOLS_HTML_META_content_script_type ) ) |
267 | 5 | { |
268 | 5 | if( !aKV.GetValue().isEmpty() ) |
269 | 4 | { |
270 | 4 | OUString aTmp( aKV.GetValue() ); |
271 | 4 | if( aTmp.startsWithIgnoreAsciiCase( "text/" ) ) |
272 | 3 | aTmp = aTmp.copy( 5 ); |
273 | 1 | else if( aTmp.startsWithIgnoreAsciiCase( "application/" ) ) |
274 | 0 | aTmp = aTmp.copy( 12 ); |
275 | 1 | else |
276 | 1 | break; |
277 | | |
278 | 3 | if( aTmp.startsWithIgnoreAsciiCase( "x-" ) ) // MIME-experimental |
279 | 0 | { |
280 | 0 | aTmp = aTmp.copy( 2 ); |
281 | 0 | } |
282 | | |
283 | 3 | if( aTmp.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_LG_starbasic ) ) |
284 | 0 | { |
285 | 0 | eScriptType = STARBASIC; |
286 | 0 | aScriptType = SVX_MACRO_LANGUAGE_STARBASIC; |
287 | 0 | } |
288 | 3 | if( !aTmp.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_LG_javascript ) ) |
289 | 0 | { |
290 | 0 | eScriptType = EXTENDED_STYPE; |
291 | 0 | aScriptType = aTmp; |
292 | 0 | } |
293 | 3 | } |
294 | 4 | break; |
295 | 5 | } |
296 | 1.90k | } |
297 | 6.77k | } |
298 | | |
299 | | ScriptType SfxHTMLParser::GetScriptType( SvKeyValueIterator *pHTTPHeader ) const |
300 | 91.5k | { |
301 | 91.5k | if( aScriptType.isEmpty() ) |
302 | 6.77k | const_cast<SfxHTMLParser *>(this)->GetScriptType_Impl( pHTTPHeader ); |
303 | | |
304 | 91.5k | return eScriptType; |
305 | 91.5k | } |
306 | | |
307 | | const OUString& SfxHTMLParser::GetScriptTypeString( |
308 | | SvKeyValueIterator *pHTTPHeader ) const |
309 | 91.5k | { |
310 | 91.5k | if( aScriptType.isEmpty() ) |
311 | 0 | const_cast<SfxHTMLParser *>(this)->GetScriptType_Impl( pHTTPHeader ); |
312 | | |
313 | 91.5k | return aScriptType; |
314 | 91.5k | } |
315 | | |
316 | | double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32& nNumForm, |
317 | | LanguageType& eNumLang, const OUString& aValStr, std::u16string_view aNumStr, |
318 | | SvNumberFormatter& rFormatter ) |
319 | 148k | { |
320 | 148k | LanguageType eParseLang(o3tl::toInt32(aNumStr)); |
321 | 148k | sal_uInt32 nParseForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eParseLang ); |
322 | 148k | double fVal; |
323 | 148k | (void)rFormatter.IsNumberFormat(aValStr, nParseForm, fVal); |
324 | 148k | if ( comphelper::string::getTokenCount(aNumStr, ';') > 2 ) |
325 | 131k | { |
326 | 131k | sal_Int32 nIdx {0}; |
327 | 131k | eNumLang = LanguageType(o3tl::toInt32(o3tl::getToken(aNumStr, 1, ';', nIdx ))); |
328 | 131k | OUString aFormat( aNumStr.substr( nIdx ) ); |
329 | 131k | sal_Int32 nCheckPos; |
330 | 131k | SvNumFormatType nType; |
331 | 131k | if ( eNumLang != LANGUAGE_SYSTEM ) |
332 | 64.2k | rFormatter.PutEntry( aFormat, nCheckPos, nType, nNumForm, eNumLang ); |
333 | 66.8k | else |
334 | 66.8k | rFormatter.PutandConvertEntry( aFormat, nCheckPos, nType, nNumForm, |
335 | 66.8k | eParseLang, eNumLang, true); |
336 | 131k | } |
337 | 17.1k | else |
338 | 17.1k | { |
339 | 17.1k | eNumLang = LANGUAGE_SYSTEM; |
340 | 17.1k | nNumForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eNumLang ); |
341 | 17.1k | } |
342 | 148k | return fVal; |
343 | 148k | } |
344 | | |
345 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |