| /************************************************************** |
| * |
| * 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 <tools/urlobj.hxx> |
| |
| #include <sfx2/objsh.hxx> |
| #include <sfx2/docfile.hxx> |
| #include "openflag.hxx" |
| |
| #include <svtools/htmlkywd.hxx> |
| #include <svtools/htmltokn.h> |
| #include <svtools/imap.hxx> |
| #include <svtools/imapcirc.hxx> |
| #include <svtools/imapobj.hxx> |
| #include <svtools/imappoly.hxx> |
| #include <svtools/imaprect.hxx> |
| #ifndef _SVSTDARR_ULONGS_DECL |
| #define _SVSTDARR_ULONGS |
| #include <svl/svstdarr.hxx> |
| #endif |
| #include <svl/zforlist.hxx> |
| #include <rtl/tencinfo.h> |
| #include <tools/tenccvt.hxx> |
| |
| #include <sfx2/sfxhtml.hxx> |
| |
| #include <com/sun/star/beans/XPropertyContainer.hpp> |
| |
| |
| 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-"; |
| |
| // <INPUT TYPE=xxx> |
| 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?" ); |
| |
| // Although 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; i<nCount; i++ ) |
| aPoly[i] = Point( aCoords[2*i], aCoords[2*i+1] ); |
| IMapPolygonObject aMapPObj( aPoly, aHRef, aAlt, String(), aTarget, aName, |
| !bNoHRef ); |
| if( aMacroTbl.Count() ) |
| aMapPObj.SetMacroTable( aMacroTbl ); |
| pImageMap->InsertIMapObject( 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; |
| } |
| |