Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/other-licenses/nsis/Contrib/WebBrowser/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 20 kB image not shown  

Quelle  WebBrowser.cpp   Sprache: C

 
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "WebBrowser.h"
#include <mshtmdid.h>

WebBrowser::WebBrowser(HWND _hWndParent) : mHwndParent(_hWndParent) {
  // Whatever executed this constructor owns our first reference.
  AddRef();

  HRESULT hr = ::OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0,
                           thisthis, (void**)&mOleObject);
  if (FAILED(hr)) {
    return;
  }

  RECT posRect;
  ::GetClientRect(mHwndParent, &posRect);

  hr = mOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, nullptr, this, 0,
                          mHwndParent, &posRect);
  if (FAILED(hr)) {
    mOleObject->Release();
    mOleObject = nullptr;
    return;
  }

  SetRect(posRect);

  hr = mOleObject->QueryInterface(&mWebBrowser2);
  if (FAILED(hr)) {
    mOleObject->Release();
    mOleObject = nullptr;
    return;
  }

  mWebBrowser2->put_Silent(VARIANT_TRUE);
}

WebBrowser::~WebBrowser() {
  if (mWebBrowser2) {
    mWebBrowser2->Release();
    mWebBrowser2 = nullptr;
  }
  if (mOleInPlaceActiveObject) {
    mOleInPlaceActiveObject->Release();
    mOleInPlaceActiveObject = nullptr;
  }
  if (mOleInPlaceObject) {
    mOleInPlaceObject->Release();
    mOleInPlaceObject = nullptr;
  }
  if (mOleObject) {
    mOleObject->Release();
    mOleObject = nullptr;
  }
}

void WebBrowser::Shutdown() {
  if (mOleObject) {
    mOleObject->Close(OLECLOSE_NOSAVE);
    mOleObject->SetClientSite(nullptr);
  }
}

bool WebBrowser::IsInitialized() { return mOleObject != nullptr; }

HRESULT WebBrowser::ActiveObjectTranslateAccelerator(bool tab, LPMSG lpmsg) {
  if (IsInitialized() && mOleInPlaceActiveObject) {
    HRESULT hr = mOleInPlaceActiveObject->TranslateAcceleratorW(lpmsg);
    if (hr == S_FALSE && tab) {
      // The browser control will give up focus, but it is the only control so
      // it would get focus again via IsDialogMessage. This does not result in
      // the focus returning to the web page, though, so instead let the
      // control process the tab again.
      hr = mOleInPlaceActiveObject->TranslateAcceleratorW(lpmsg);
    }
    return hr;
  } else {
    return S_FALSE;
  }
}

void WebBrowser::SetRect(const RECT& _rc) {
  mRect = _rc;

  if (mOleInPlaceObject) {
    mOleInPlaceObject->SetObjectRects(&mRect, &mRect);
  }
}

void WebBrowser::Resize(DWORD width, DWORD height) {
  RECT r = mRect;
  r.bottom = r.top + height;
  r.right = r.left + width;
  SetRect(r);
}

void WebBrowser::Navigate(wchar_t* url) {
  if (!IsInitialized()) {
    return;
  }

  VARIANT flags;
  VariantInit(&flags);
  flags.vt = VT_I4;
  flags.intVal = navNoHistory | navEnforceRestricted | navUntrustedForDownload |
                 navBlockRedirectsXDomain;

  mWebBrowser2->Navigate(url, &flags, nullptr, nullptr, nullptr);
}

void WebBrowser::AddCustomFunction(wchar_t* name, CustomFunction function,
                                   void* arg) {
  CustomFunctionRecord record = {name, function, arg};

// We've disabled exceptions but push_back can throw on an allocation
// failure, so we need to suppress a warning trying to tell us that
// that combination doesn't make any sense.
#pragma warning(suppress : 4530)
  mCustomFunctions.push_back(record);
}

//////////////////////////////////////////////////////////////////////////////
// IUnknown
//////////////////////////////////////////////////////////////////////////////
// This is a standard IUnknown implementation, we don't need anything special.

HRESULT STDMETHODCALLTYPE WebBrowser::QueryInterface(REFIID riid,
                                                     void** ppvObject) {
  if (riid == __uuidof(IUnknown)) {
    *ppvObject = static_cast<IOleClientSite*>(this);
  } else if (riid == __uuidof(IOleClientSite)) {
    *ppvObject = static_cast<IOleClientSite*>(this);
  } else if (riid == __uuidof(IOleInPlaceSite)) {
    *ppvObject = static_cast<IOleInPlaceSite*>(this);
  } else if (riid == __uuidof(IDropTarget)) {
    *ppvObject = static_cast<IDropTarget*>(this);
  } else if (riid == __uuidof(IStorage)) {
    *ppvObject = static_cast<IStorage*>(this);
  } else if (riid == __uuidof(IDocHostUIHandler)) {
    *ppvObject = static_cast<IDocHostUIHandler*>(this);
  } else if (riid == __uuidof(IDocHostShowUI)) {
    *ppvObject = static_cast<IDocHostShowUI*>(this);
  } else if (riid == __uuidof(IDispatch)) {
    *ppvObject = static_cast<IDispatch*>(this);
  } else {
    *ppvObject = nullptr;
    return E_NOINTERFACE;
  }

  AddRef();
  return S_OK;
}

ULONG STDMETHODCALLTYPE WebBrowser::AddRef() {
  return InterlockedIncrement(&mComRefCount);
}

ULONG STDMETHODCALLTYPE WebBrowser::Release() {
  ULONG refCount = InterlockedDecrement(&mComRefCount);
  if (refCount == 0) {
    delete this;
  }
  return refCount;
}

//////////////////////////////////////////////////////////////////////////////
// IOleWindow
//////////////////////////////////////////////////////////////////////////////

HRESULT STDMETHODCALLTYPE
WebBrowser::GetWindow(__RPC__deref_out_opt HWND* phwnd) {
  *phwnd = mHwndParent;
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::ContextSensitiveHelp(BOOL fEnterMode) {
  // We don't provide context-sensitive help.
  return E_NOTIMPL;
}

//////////////////////////////////////////////////////////////////////////////
// IOleInPlaceSite
//////////////////////////////////////////////////////////////////////////////

HRESULT STDMETHODCALLTYPE WebBrowser::CanInPlaceActivate() {
  // We always support in-place activation.
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceActivate() {
  OleLockRunning(mOleObject, TRUEFALSE);
  mOleObject->QueryInterface(&mOleInPlaceObject);
  mOleInPlaceObject->QueryInterface(&mOleInPlaceActiveObject);
  mOleInPlaceObject->SetObjectRects(&mRect, &mRect);

  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::OnUIActivate() {
  // Nothing to do before activating the control's UI.
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::GetWindowContext(
    __RPC__deref_out_opt IOleInPlaceFrame** ppFrame,
    __RPC__deref_out_opt IOleInPlaceUIWindow** ppDoc,
    __RPC__out LPRECT lprcPosRect, __RPC__out LPRECT lprcClipRect,
    __RPC__inout LPOLEINPLACEFRAMEINFO lpFrameInfo) {
  *ppFrame = nullptr;
  *ppDoc = nullptr;
  *lprcPosRect = mRect;
  *lprcClipRect = mRect;

  lpFrameInfo->fMDIApp = false;
  lpFrameInfo->hwndFrame = mHwndParent;
  lpFrameInfo->haccel = nullptr;
  lpFrameInfo->cAccelEntries = 0;

  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::Scroll(SIZE scrollExtant) {
  // We should have disabled all scrollbars.
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::OnUIDeactivate(BOOL fUndoable) {
  // Nothing to do after deactivating the control's UI.
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::OnInPlaceDeactivate() {
  if (mOleInPlaceObject) {
    mOleInPlaceObject->Release();
    mOleInPlaceObject = nullptr;
  }

  return S_OK;
}

// We don't support the concept of undo.
HRESULT STDMETHODCALLTYPE WebBrowser::DiscardUndoState() { return E_NOTIMPL; }

HRESULT STDMETHODCALLTYPE WebBrowser::DeactivateAndUndo() { return E_NOTIMPL; }

// We don't support moving or resizing the control.
HRESULT STDMETHODCALLTYPE
WebBrowser::OnPosRectChange(__RPC__in LPCRECT lprcPosRect) {
  return E_NOTIMPL;
}

//////////////////////////////////////////////////////////////////////////////
// IOleClientSite
//////////////////////////////////////////////////////////////////////////////
// We don't need anything that IOleClientSite does, because we're doing OLE
// only in the most basic sense and we don't support linking (or, indeed,
// embedding), but some implementation of this interface is required for
// OleCreate to work, so we have to have a stub version.

HRESULT STDMETHODCALLTYPE WebBrowser::SaveObject() { return E_NOTIMPL; }

HRESULT STDMETHODCALLTYPE
WebBrowser::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,
                       __RPC__deref_out_opt IMoniker** ppmk) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE
WebBrowser::GetContainer(__RPC__deref_out_opt IOleContainer** ppContainer) {
  *ppContainer = nullptr;
  return E_NOINTERFACE;
}

HRESULT STDMETHODCALLTYPE WebBrowser::ShowObject() { return S_OK; }

HRESULT STDMETHODCALLTYPE WebBrowser::OnShowWindow(BOOL fShow) { return S_OK; }

HRESULT STDMETHODCALLTYPE WebBrowser::RequestNewObjectLayout() {
  return E_NOTIMPL;
}

//////////////////////////////////////////////////////////////////////////////
// IDropTarget
//////////////////////////////////////////////////////////////////////////////
// This is a stub implementation which blocks all dropping. The main reason we
// want to do that is prevent accidentally dropping something on the control
// and having it navigate, because there's no recovering from that except to
// restart the app, and also it would look ridiculous. There could also be
// security implications though, which we'd rather just avoid engaging with
// altogether if we can.

HRESULT STDMETHODCALLTYPE
WebBrowser::DragEnter(__RPC__in_opt IDataObject* pDataObj, DWORD grfKeyState,
                      POINTL pt, __RPC__inout DWORD* pdwEffect) {
  *pdwEffect = DROPEFFECT_NONE;
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::DragOver(DWORD grfKeyState, POINTL pt,
                                               __RPC__inout DWORD* pdwEffect) {
  *pdwEffect = DROPEFFECT_NONE;
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::DragLeave() { return S_OK; }

HRESULT STDMETHODCALLTYPE WebBrowser::Drop(__RPC__in_opt IDataObject* pDataObj,
                                           DWORD grfKeyState, POINTL pt,
                                           __RPC__inout DWORD* pdwEffect) {
  *pdwEffect = DROPEFFECT_NONE;
  return S_OK;
}

//////////////////////////////////////////////////////////////////////////////
// IStorage
//////////////////////////////////////////////////////////////////////////////
// We don't need anything that IStorage does, but we have to pass some
// implementation of it to OleCreate, so we need to have a stub version.

HRESULT STDMETHODCALLTYPE WebBrowser::CreateStream(
    __RPC__in_string const OLECHAR* pwcsName, DWORD grfMode, DWORD reserved1,
    DWORD reserved2, __RPC__deref_out_opt IStream** ppstm) {
  *ppstm = nullptr;
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::OpenStream(const OLECHAR* pwcsName,
                                                 void* reserved1, DWORD grfMode,
                                                 DWORD reserved2,
                                                 IStream** ppstm) {
  *ppstm = nullptr;
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::CreateStorage(
    __RPC__in_string const OLECHAR* pwcsName, DWORD grfMode, DWORD reserved1,
    DWORD reserved2, __RPC__deref_out_opt IStorage** ppstg) {
  *ppstg = nullptr;
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE
WebBrowser::OpenStorage(__RPC__in_opt_string const OLECHAR* pwcsName,
                        __RPC__in_opt IStorage* pstgPriority, DWORD grfMode,
                        __RPC__deref_opt_in_opt SNB snbExclude, DWORD reserved,
                        __RPC__deref_out_opt IStorage** ppstg) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::CopyTo(DWORD ciidExclude,
                                             const IID* rgiidExclude,
                                             __RPC__in_opt SNB snbExclude,
                                             IStorage* pstgDest) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::MoveElementTo(
    __RPC__in_string const OLECHAR* pwcsName, __RPC__in_opt IStorage* pstgDest,
    __RPC__in_string const OLECHAR* pwcsNewName, DWORD grfFlags) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::Commit(DWORD grfCommitFlags) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::Revert() { return E_NOTIMPL; }

HRESULT STDMETHODCALLTYPE WebBrowser::EnumElements(DWORD reserved1,
                                                   void* reserved2,
                                                   DWORD reserved3,
                                                   IEnumSTATSTG** ppenum) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE
WebBrowser::DestroyElement(__RPC__in_string const OLECHAR* pwcsName) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE
WebBrowser::RenameElement(__RPC__in_string const OLECHAR* pwcsOldName,
                          __RPC__in_string const OLECHAR* pwcsNewName) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::SetElementTimes(
    __RPC__in_opt_string const OLECHAR* pwcsName,
    __RPC__in_opt const FILETIME* pctime, __RPC__in_opt const FILETIME* patime,
    __RPC__in_opt const FILETIME* pmtime) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::SetClass(__RPC__in REFCLSID clsid) {
  return S_OK;
}

HRESULT STDMETHODCALLTYPE WebBrowser::SetStateBits(DWORD grfStateBits,
                                                   DWORD grfMask) {
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE WebBrowser::Stat(__RPC__out STATSTG* pstatstg,
                                           DWORD grfStatFlag) {
  return E_NOTIMPL;
}

//////////////////////////////////////////////////////////////////////////////
// IDocHostUIHandler
//////////////////////////////////////////////////////////////////////////////
// Our implementation for this interface is basically all about disabling
// things that we don't want/need.

HRESULT __stdcall WebBrowser::ShowContextMenu(DWORD dwID, POINT* ppt,
                                              IUnknown* pcmdtReserved,
                                              IDispatch* pdispReserved) {
  // Returning S_OK signals that we've handled the request for a context menu
  // (which we did, by doing nothing), so the control won't try to open one.
  return S_OK;
}

HRESULT __stdcall WebBrowser::GetHostInfo(DOCHOSTUIINFO* pInfo) {
  pInfo->cbSize = sizeof(DOCHOSTUIINFO);
  pInfo->dwFlags =
      DOCHOSTUIFLAG_DIALOG | DOCHOSTUIFLAG_DISABLE_HELP_MENU |
      DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_SCROLL_NO |
      DOCHOSTUIFLAG_OPENNEWWIN | DOCHOSTUIFLAG_OVERRIDEBEHAVIORFACTORY |
      DOCHOSTUIFLAG_THEME | DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK |
      DOCHOSTUIFLAG_DISABLE_UNTRUSTEDPROTOCOL | DOCHOSTUIFLAG_DPI_AWARE;
  pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
  pInfo->pchHostCss = nullptr;
  pInfo->pchHostNS = nullptr;
  return S_OK;
}

HRESULT __stdcall WebBrowser::ShowUI(DWORD dwID,
                                     IOleInPlaceActiveObject* pActiveObject,
                                     IOleCommandTarget* pCommandTarget,
                                     IOleInPlaceFrame* pFrame,
                                     IOleInPlaceUIWindow* pDoc) {
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::HideUI() { return E_NOTIMPL; }

HRESULT __stdcall WebBrowser::UpdateUI() { return E_NOTIMPL; }

HRESULT __stdcall WebBrowser::EnableModeless(BOOL fEnable) { return E_NOTIMPL; }

HRESULT __stdcall WebBrowser::OnDocWindowActivate(BOOL fActivate) {
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::OnFrameWindowActivate(BOOL fActivate) {
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::ResizeBorder(LPCRECT prcBorder,
                                           IOleInPlaceUIWindow* pUIWindow,
                                           BOOL fRameWindow) {
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::TranslateAccelerator(LPMSG lpMsg,
                                                   const GUID* pguidCmdGroup,
                                                   DWORD nCmdID) {
  return S_FALSE;
}

HRESULT __stdcall WebBrowser::GetOptionKeyPath(LPOLESTR* pchKey, DWORD dw) {
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::GetDropTarget(IDropTarget* pDropTarget,
                                            IDropTarget** ppDropTarget) {
  // The IDropTarget implementation that we need is an empty stub, so we'll do
  // the easy and convenient thing and just use this object.
  return QueryInterface(IID_PPV_ARGS(ppDropTarget));
}

HRESULT __stdcall WebBrowser::GetExternal(IDispatch** ppDispatch) {
  // This object has to implement IDispatch anyway so that we can use
  // DISPID_AMBIENT_DLCONTROL, so we'll make this the external handler also.
  return QueryInterface(IID_PPV_ARGS(ppDispatch));
}

HRESULT __stdcall WebBrowser::TranslateUrl(DWORD dwTranslate, LPWSTR pchURLIn,
                                           LPWSTR* ppchURLOut) {
  *ppchURLOut = nullptr;
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::FilterDataObject(IDataObject* pDO,
                                               IDataObject** ppDORet) {
  *ppDORet = nullptr;
  return E_NOTIMPL;
}

//////////////////////////////////////////////////////////////////////////////
// IDocHostShowUI
//////////////////////////////////////////////////////////////////////////////

HRESULT __stdcall WebBrowser::ShowMessage(HWND hwnd, LPOLESTR lpstrText,
                                          LPOLESTR lpstrCaption, DWORD dwType,
                                          LPOLESTR lpstrHelpFile,
                                          DWORD dwHelpContext,
                                          LRESULT* plResult) {
  // Don't allow MSHTML to generate message boxes.
  return S_OK;
}

HRESULT __stdcall WebBrowser::ShowHelp(HWND hwnd, LPOLESTR pszHelpFile,
                                       UINT uCommand, DWORD dwData,
                                       POINT ptMouse,
                                       IDispatch* pDispatchObjectHit) {
  // Don't allow MSHTML to show any help.
  return S_OK;
}

//////////////////////////////////////////////////////////////////////////////
// IDispatch
//////////////////////////////////////////////////////////////////////////////

// We're not using a type library.
HRESULT __stdcall WebBrowser::GetTypeInfoCount(UINT* pctinfo) {
  if (pctinfo) {
    *pctinfo = 0;
  }
  return S_OK;
}

HRESULT __stdcall WebBrowser::GetTypeInfo(UINT iTInfo, LCID lcid,
                                          ITypeInfo** ppTInfo) {
  return E_NOTIMPL;
}

HRESULT __stdcall WebBrowser::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
                                            UINT cNames, LCID lcid,
                                            DISPID* rgDispId) {
  if (cNames != 1) {
    return E_NOTIMPL;
  }

  for (size_t i = 0; i < mCustomFunctions.size(); ++i) {
    if (mCustomFunctions[i].mName == rgszNames[0]) {
      // DISPID values need to be 1-indexed because 0 is reserved
      // (DISPID_VALUE).
      *rgDispId = i + 1;
      return S_OK;
    }
  }

  *rgDispId = DISPID_UNKNOWN;
  return DISP_E_UNKNOWNNAME;
}

HRESULT __stdcall WebBrowser::Invoke(DISPID dispIdMember, REFIID riid,
                                     LCID lcid, WORD wFlags,
                                     DISPPARAMS* pDispParams,
                                     VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
                                     UINT* puArgErr) {
  if (dispIdMember == DISPID_AMBIENT_DLCONTROL && pVarResult) {
    VariantClear(pVarResult);
    pVarResult->vt = VT_I4;
    // As a light security measure, disable a bunch of stuff we don't want
    // to be able to run in the web control.
    pVarResult->intVal = DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS |
                         DLCTL_NO_RUNACTIVEXCTLS | DLCTL_NO_FRAMEDOWNLOAD |
                         DLCTL_NO_BEHAVIORS | DLCTL_NO_CLIENTPULL |
                         DLCTL_NOFRAMES | DLCTL_FORCEOFFLINE | DLCTL_SILENT |
                         DLCTL_OFFLINE | DLCTL_DLIMAGES;
    return S_OK;
  }

  // Otherwise this should be one of our custom functions.
  // We only support invoking these as methods, not property access.
  if ((wFlags & DISPATCH_METHOD) == 0) {
    return DISP_E_TYPEMISMATCH;
  }

  // Make sure this DISPID is valid in our custom functions list.
  // DISPID values are 1-indexed because 0 is reserved (DISPID_VALUE).
  DISPID customFunctionIndex = dispIdMember - 1;
  if (customFunctionIndex < 0 ||
      customFunctionIndex >= (DISPID)mCustomFunctions.size()) {
    return DISP_E_MEMBERNOTFOUND;
  }

  // If the caller passed an argument to this custom function, use it.
  // If not, make an empty VARIANT we can pass to it instead.
  VARIANT argument;
  VariantInit(&argument);
  if (pDispParams->cArgs > 0) {
    argument = pDispParams->rgvarg[0];
  }

  CustomFunctionRecord foundFunction = mCustomFunctions[customFunctionIndex];
  foundFunction.mFunction(foundFunction.mArg, argument, pVarResult);

  return S_OK;
}

Messung V0.5
C=87 H=99 G=93

¤ Dauer der Verarbeitung: 0.37 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.