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 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 91 __EXPORT SfxHTMLParser::~SfxHTMLParser() 92 { 93 DBG_ASSERT( !pDLMedium, "Da ist ein File-Download stehengeblieben" ); 94 delete pDLMedium; 95 } 96 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 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 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 286 sal_Bool SfxHTMLParser::GetFileDownloadMIME( String& rMIME ) 287 { 288 return pDLMedium && pDLMedium->GetErrorCode()==0 && 289 pDLMedium->GetMIMEAndRedirect(rMIME)==0; 290 } 291 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( S2U(pBuffer) ); 329 } 330 331 delete pDLMedium; 332 pDLMedium = 0; 333 334 return bOK; 335 } 336 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 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 396 ScriptType SfxHTMLParser::GetScriptType( SvKeyValueIterator *pHTTPHeader ) const 397 { 398 if( !aScriptType.Len() ) 399 ((SfxHTMLParser *)this)->GetScriptType_Impl( pHTTPHeader ); 400 401 return eScriptType; 402 } 403 404 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 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