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