/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #include #include "openflag.hxx" #include #include #include #include #include #include #include #ifndef _SVSTDARR_ULONGS_DECL #define _SVSTDARR_ULONGS #include #endif #include #include #include #include #include using namespace ::com::sun::star; sal_Char __FAR_DATA sHTML_MIME_text[] = "text/"; sal_Char __FAR_DATA sHTML_MIME_application[] = "application/"; sal_Char __FAR_DATA sHTML_MIME_experimental[] = "x-"; // static HTMLOptionEnum __READONLY_DATA aAreaShapeOptEnums[] = { { OOO_STRING_SVTOOLS_HTML_SH_rect, IMAP_OBJ_RECTANGLE }, { OOO_STRING_SVTOOLS_HTML_SH_rectangle, IMAP_OBJ_RECTANGLE }, { OOO_STRING_SVTOOLS_HTML_SH_circ, IMAP_OBJ_CIRCLE }, { OOO_STRING_SVTOOLS_HTML_SH_circle, IMAP_OBJ_CIRCLE }, { OOO_STRING_SVTOOLS_HTML_SH_poly, IMAP_OBJ_POLYGON }, { OOO_STRING_SVTOOLS_HTML_SH_polygon, IMAP_OBJ_POLYGON }, { 0, 0 } }; SfxHTMLParser::SfxHTMLParser( SvStream& rStream, sal_Bool bIsNewDoc, SfxMedium *pMed ) : HTMLParser( rStream, bIsNewDoc ), pMedium( pMed ), pDLMedium( 0 ), nMetaTags( 0 ) { DBG_ASSERT( RTL_TEXTENCODING_DONTKNOW == GetSrcEncoding( ), "SfxHTMLParser::SfxHTMLParser: Wo kommt der ZS her?" ); DBG_ASSERT( !IsSwitchToUCS2(), "SfxHTMLParser::SfxHTMLParser: Switch to UCS2?" ); // Altough the real default encoding is ISO8859-1, we use MS-1252 // als default encoding. SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) ); // If the file starts with a BOM, switch to UCS2. SetSwitchToUCS2( sal_True ); } __EXPORT SfxHTMLParser::~SfxHTMLParser() { DBG_ASSERT( !pDLMedium, "Da ist ein File-Download stehengeblieben" ); delete pDLMedium; } sal_Bool SfxHTMLParser::ParseMapOptions(ImageMap * pImageMap, const HTMLOptions * pOptions) { DBG_ASSERT( pImageMap, "ParseMapOptions: keine Image-Map" ); DBG_ASSERT( pOptions, "ParseMapOptions: keine Optionen" ); String aName; for( sal_uInt16 i=pOptions->Count(); i; ) { const HTMLOption *pOption = (*pOptions)[--i]; switch( pOption->GetToken() ) { case HTML_O_NAME: aName = pOption->GetString(); break; } } if( aName.Len() ) pImageMap->SetName( aName ); return aName.Len() > 0; } sal_Bool SfxHTMLParser::ParseAreaOptions(ImageMap * pImageMap, const String& rBaseURL, const HTMLOptions * pOptions, sal_uInt16 nEventMouseOver, sal_uInt16 nEventMouseOut ) { DBG_ASSERT( pImageMap, "ParseAreaOptions: keine Image-Map" ); DBG_ASSERT( pOptions, "ParseAreaOptions: keine Optionen" ); sal_uInt16 nShape = IMAP_OBJ_RECTANGLE; SvULongs aCoords; String aName, aHRef, aAlt, aTarget, sEmpty; sal_Bool bNoHRef = sal_False; SvxMacroTableDtor aMacroTbl; for( sal_uInt16 i=pOptions->Count(); i; ) { sal_uInt16 nEvent = 0; ScriptType eScrpType = STARBASIC; const HTMLOption *pOption = (*pOptions)[--i]; switch( pOption->GetToken() ) { case HTML_O_NAME: aName = pOption->GetString(); break; case HTML_O_SHAPE: pOption->GetEnum( nShape, aAreaShapeOptEnums ); break; case HTML_O_COORDS: pOption->GetNumbers( aCoords, sal_True ); break; case HTML_O_HREF: aHRef = INetURLObject::GetAbsURL( rBaseURL, pOption->GetString() ); break; case HTML_O_NOHREF: bNoHRef = sal_True; break; case HTML_O_ALT: aAlt = pOption->GetString(); break; case HTML_O_TARGET: aTarget = pOption->GetString(); break; case HTML_O_ONMOUSEOVER: eScrpType = JAVASCRIPT; case HTML_O_SDONMOUSEOVER: nEvent = nEventMouseOver; goto IMAPOBJ_SETEVENT; case HTML_O_ONMOUSEOUT: eScrpType = JAVASCRIPT; case HTML_O_SDONMOUSEOUT: nEvent = nEventMouseOut; goto IMAPOBJ_SETEVENT; IMAPOBJ_SETEVENT: if( nEvent ) { String sTmp( pOption->GetString() ); if( sTmp.Len() ) { sTmp.ConvertLineEnd(); aMacroTbl.Insert( nEvent, new SvxMacro( sTmp, sEmpty, eScrpType )); } } break; } } if( bNoHRef ) aHRef.Erase(); sal_Bool bNewArea = sal_True; switch( nShape ) { case IMAP_OBJ_RECTANGLE: if( aCoords.Count() >=4 ) { Rectangle aRec( aCoords[0], aCoords[1], aCoords[2], aCoords[3] ); IMapRectangleObject aMapRObj( aRec, aHRef, aAlt, String(), aTarget, aName, !bNoHRef ); if( aMacroTbl.Count() ) aMapRObj.SetMacroTable( aMacroTbl ); pImageMap->InsertIMapObject( aMapRObj ); } break; case IMAP_OBJ_CIRCLE: if( aCoords.Count() >=3 ) { Point aPoint( aCoords[0], aCoords[1] ); IMapCircleObject aMapCObj( aPoint, aCoords[2],aHRef, aAlt, String(), aTarget, aName, !bNoHRef ); if( aMacroTbl.Count() ) aMapCObj.SetMacroTable( aMacroTbl ); pImageMap->InsertIMapObject( aMapCObj ); } break; case IMAP_OBJ_POLYGON: if( aCoords.Count() >=6 ) { sal_uInt16 nCount = aCoords.Count() / 2; Polygon aPoly( nCount ); for( sal_uInt16 i=0; iInsertIMapObject( aMapPObj ); } break; default: bNewArea = sal_False; } return bNewArea; } void SfxHTMLParser::StartFileDownload( const String& rURL, int nToken, SfxObjectShell *pSh ) { DBG_ASSERT( !pDLMedium, "StartFileDwonload bei aktivem Download" ); if( pDLMedium ) return; pDLMedium = new SfxMedium( rURL, SFX_STREAM_READONLY, sal_False ); if( pSh ) { // Medium registrieren, damit abgebrochen werden kann pSh->RegisterTransfer( *pDLMedium ); // Target-Frame uebertragen, damit auch javascript:-URLs // "geladen" werden koennen. //const SfxMedium *pShMedium = pSh->GetMedium(); //if( pShMedium ) // pDLMedium->SetLoadTargetFrame( pShMedium->GetLoadTargetFrame() ); } // Download anstossen (Achtung: Kann auch synchron sein). if ( sal_True /*pMedium->GetDoneLink() == Link()*/ ) pDLMedium->DownLoad(); else { // Downloading-Flag auf sal_True setzen. Es werden dann auch // Data-Available-Links, wenn wir in den Pending-Staus gelangen. SetDownloadingFile( sal_True ); pDLMedium->DownLoad( STATIC_LINK( this, SfxHTMLParser, FileDownloadDone ) ); // Wenn das Dowsnloading-Flag noch gesetzt ist erfolgt der Download // asynchron. Wir gehen dann in den Pedning-Staus und warten dort. // Solange sind alle Aufrufe des Data-Avaialble-Link gesperrt. if( IsDownloadingFile() ) { // Den aktuellen Zustand einfrieren und in den Pending-Status gehen. // Wenn der Download beendet oder abgebrochen wurde, wird ueber // NewDataRead ein Continue mit dem uebergeben Token angesteossen. SaveState( nToken ); eState = SVPAR_PENDING; } } } sal_Bool SfxHTMLParser::GetFileDownloadMIME( String& rMIME ) { return pDLMedium && pDLMedium->GetErrorCode()==0 && pDLMedium->GetMIMEAndRedirect(rMIME)==0; } sal_Bool SfxHTMLParser::FinishFileDownload( String& rStr ) { String aStr; sal_Bool bOK = pDLMedium && pDLMedium->GetErrorCode()==0; if( bOK ) { SvStream* pStream = pDLMedium->GetInStream(); DBG_ASSERT( pStream, "Kein In-Stream vom Medium erhalten" ); SvMemoryStream aStream; if( pStream ) // HACK wegen #65563# aStream << *pStream; aStream.Seek( STREAM_SEEK_TO_END ); DBG_ASSERT( aStream.Tell() < STRING_MAXLEN, "File zu lang fuer einen String, Ende abgeschnitten" ); xub_StrLen nLen = aStream.Tell() < STRING_MAXLEN ? (xub_StrLen)aStream.Tell() : STRING_MAXLEN; // TODO: untested!!! rtl_TextEncoding eEnc = GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ); String sMime; if( pDLMedium->GetMIMEAndRedirect( sMime ) == 0 ) { rtl_TextEncoding eMimeEnc = GetEncodingByMIME( sMime ); if( RTL_TEXTENCODING_DONTKNOW != eMimeEnc ) eEnc = eMimeEnc; } ByteString sBuffer; sal_Char* pBuffer = sBuffer.AllocBuffer(nLen); aStream.Seek( 0 ); aStream.Read((void*)pBuffer, nLen); rStr = String( pBuffer, RTL_TEXTENCODING_UTF8); } delete pDLMedium; pDLMedium = 0; return bOK; } IMPL_STATIC_LINK( SfxHTMLParser, FileDownloadDone, void*, EMPTYARG ) { // Der Download ist jetzt abgeschlossen. Ausserdem muss/darf der // Data-Available-Link wieder durchgelassen werden. pThis->SetDownloadingFile( sal_False ); // ... und einmal aufrufen, damit weitergelesen wird. pThis->CallAsyncCallLink(); return 0; } void SfxHTMLParser::GetScriptType_Impl( SvKeyValueIterator *pHTTPHeader ) { aScriptType = DEFINE_CONST_UNICODE(SVX_MACRO_LANGUAGE_JAVASCRIPT); eScriptType = JAVASCRIPT; if( pHTTPHeader ) { SvKeyValue aKV; for( sal_Bool bCont = pHTTPHeader->GetFirst( aKV ); bCont; bCont = pHTTPHeader->GetNext( aKV ) ) { if( aKV.GetKey().EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_script_type ) ) { if( aKV.GetValue().Len() ) { String aTmp( aKV.GetValue() ); if( aTmp.EqualsIgnoreCaseAscii( sHTML_MIME_text, 0, 5 ) ) aTmp.Erase( 0, 5 ); else if( aTmp.EqualsIgnoreCaseAscii( sHTML_MIME_application, 0, 12 ) ) aTmp.Erase( 0, 12 ); else break; if( aTmp.EqualsIgnoreCaseAscii( sHTML_MIME_experimental, 0, 2 ) ) { aTmp.Erase( 0, 2 ); } if( aTmp.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_LG_starbasic ) ) { eScriptType = STARBASIC; aScriptType = DEFINE_CONST_UNICODE(SVX_MACRO_LANGUAGE_STARBASIC); } if( !aTmp.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_LG_javascript ) ) { eScriptType = EXTENDED_STYPE; aScriptType = aTmp; } } break; } } } } ScriptType SfxHTMLParser::GetScriptType( SvKeyValueIterator *pHTTPHeader ) const { if( !aScriptType.Len() ) ((SfxHTMLParser *)this)->GetScriptType_Impl( pHTTPHeader ); return eScriptType; } const String& SfxHTMLParser::GetScriptTypeString( SvKeyValueIterator *pHTTPHeader ) const { if( !aScriptType.Len() ) ((SfxHTMLParser *)this)->GetScriptType_Impl( pHTTPHeader ); return aScriptType; } double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32& nNumForm, LanguageType& eNumLang, const String& aValStr, const String& aNumStr, SvNumberFormatter& rFormatter ) { LanguageType eParseLang = (LanguageType )aNumStr.ToInt32(); sal_uInt32 nParseForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eParseLang ); double fVal; rFormatter.IsNumberFormat( aValStr, nParseForm, fVal ); if ( aNumStr.GetTokenCount( ';' ) > 2 ) { eNumLang = (LanguageType)aNumStr.GetToken( 1, ';' ).ToInt32(); xub_StrLen nPos = aNumStr.Search( ';' ); nPos = aNumStr.Search( ';', nPos + 1 ); String aFormat( aNumStr.Copy( nPos + 1 ) ); xub_StrLen nCheckPos; short nType; if ( eNumLang != LANGUAGE_SYSTEM ) rFormatter.PutEntry( aFormat, nCheckPos, nType, nNumForm, eNumLang ); else rFormatter.PutandConvertEntry( aFormat, nCheckPos, nType, nNumForm, eParseLang, eNumLang ); } else { eNumLang = LANGUAGE_SYSTEM; nNumForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eNumLang ); } return fVal; }