<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/bho.h"

#include <shlguid.h>
#include <shobjidl.h>

#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/registry.h"
#include "base/scoped_bstr_win.h"
#include "base/scoped_comptr_win.h"
#include "base/scoped_variant_win.h"
#include "base/string_util.h"
#include "chrome_tab.h" // NOLINT
#include "chrome_frame/extra_system_apis.h"
#include "chrome_frame/http_negotiate.h"
#include "chrome_frame/protocol_sink_wrap.h"
#include "chrome_frame/utils.h"
#include "chrome_frame/vtable_patch_manager.h"
#include "net/http/http_util.h"

const wchar_t kPatchProtocols[] = L"PatchProtocols";
static const int kIBrowserServiceOnHttpEquivIndex = 30;

base::LazyInstance<base::ThreadLocalPointer<Bho> >
    Bho::bho_current_thread_instance_(base::LINKER_INITIALIZED);

PatchHelper g_patch_helper;

BEGIN_VTABLE_PATCHES(IBrowserService)
  VTABLE_PATCH_ENTRY(kIBrowserServiceOnHttpEquivIndex, Bho::OnHttpEquiv)
END_VTABLE_PATCHES()

_ATL_FUNC_INFO Bho::kBeforeNavigate2Info = {
  CC_STDCALL, VT_EMPTY, 7, {
    VT_DISPATCH,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_BOOL | VT_BYREF
  }
};

Bho::Bho() {
}

STDMETHODIMP Bho::SetSite(IUnknown* site) {
  HRESULT hr = S_OK;
  if (site) {
    ScopedComPtr<IWebBrowser2> web_browser2;
    web_browser2.QueryFrom(site);
    if (web_browser2) {
      hr = DispEventAdvise(web_browser2, &DIID_DWebBrowserEvents2);
      DCHECK(SUCCEEDED(hr)) << "DispEventAdvise failed. Error: " << hr;
    }

    if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) {
      ScopedComPtr<IBrowserService> browser_service;
      hr = DoQueryService(SID_SShellBrowser, site, browser_service.Receive());
      DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed."
          << " Site: " << site << " Error: " << hr;
      if (browser_service) {
        g_patch_helper.PatchBrowserService(browser_service);
        DCHECK(SUCCEEDED(hr)) << "vtable_patch::PatchInterfaceMethods failed."
            << " Site: " << site << " Error: " << hr;
      }
    }
    // Save away our BHO instance in TLS which enables it to be referenced by
    // our active document/activex instances to query referrer and other
    // information for a URL.
    AddRef();
    bho_current_thread_instance_.Pointer()->Set(this);
  } else {
    bho_current_thread_instance_.Pointer()->Set(NULL);
    Release();
  }

  return IObjectWithSiteImpl<Bho>::SetSite(site);
}

STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url,
    VARIANT* flags, VARIANT* target_frame_name, VARIANT* post_data,
    VARIANT* headers, VARIANT_BOOL* cancel) {
  ScopedComPtr<IWebBrowser2> web_browser2;
  if (dispatch)
    web_browser2.QueryFrom(dispatch);

  if (!web_browser2) {
    NOTREACHED() << "Can't find WebBrowser2 with given dispatch";
    return S_OK;  // Return success, we operate on best effort basis.
  }

  DLOG(INFO) << "BeforeNavigate2: " << url->bstrVal;

  if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) {
    VARIANT_BOOL is_top_level = VARIANT_FALSE;
    web_browser2->get_TopLevelContainer(&is_top_level);

    std::wstring current_url;
    bool is_chrome_protocol = false;
    if (is_top_level && IsValidUrlScheme(url->bstrVal, false)) {
      current_url.assign(url->bstrVal, SysStringLen(url->bstrVal));
      is_chrome_protocol = StartsWith(current_url, kChromeProtocolPrefix,
                                      false);

      if (!is_chrome_protocol && IsOptInUrl(current_url.c_str())) {
        DLOG(INFO) << "Opt-in URL. Switching to cf.";
        ScopedComPtr<IBrowserService> browser_service;
        DoQueryService(SID_SShellBrowser, web_browser2,
                       browser_service.Receive());
        DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed.";
        MarkBrowserOnThreadForCFNavigation(browser_service);
      }
    }
  }

  referrer_.clear();

  // Save away the referrer in case our active document needs it to initiate
  // navigation in chrome.
  if (headers && V_VT(headers) == VT_BSTR && headers->bstrVal != NULL) {
    std::string raw_headers_utf8 = WideToUTF8(headers->bstrVal);
    std::string http_headers =
        net::HttpUtil::AssembleRawHeaders(raw_headers_utf8.c_str(),
                                          raw_headers_utf8.length());
    net::HttpUtil::HeadersIterator it(http_headers.begin(), http_headers.end(),
                                      "\r\n");
    while (it.GetNext()) {
      if (LowerCaseEqualsASCII(it.name(), "referer")) {
        referrer_ = it.values();
        break;
      }
    }
  }
  url_ = url->bstrVal;
  return S_OK;
}

HRESULT Bho::FinalConstruct() {
  return S_OK;
}

void Bho::FinalRelease() {
}

namespace {

// See comments in Bho::OnHttpEquiv for details.
void ClearDocumentContents(IUnknown* browser) {
  ScopedComPtr<IWebBrowser2> web_browser2;
  if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser,
                               web_browser2.Receive()))) {
    ScopedComPtr<IDispatch> doc_disp;
    web_browser2->get_Document(doc_disp.Receive());
    ScopedComPtr<IHTMLDocument2> doc;
    if (doc_disp && SUCCEEDED(doc.QueryFrom(doc_disp))) {
      SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 0);
      doc->write(sa);
      ::SafeArrayDestroy(sa);
    }
  }
}

// Returns true if the currently loaded document in the browser has
// any embedded items such as a frame or an iframe.
bool DocumentHasEmbeddedItems(IUnknown* browser) {
  bool has_embedded_items = false;

  ScopedComPtr<IWebBrowser2> web_browser2;
  ScopedComPtr<IDispatch> document;
  if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser,
                               web_browser2.Receive())) &&
      SUCCEEDED(web_browser2->get_Document(document.Receive()))) {
    ScopedComPtr<IOleContainer> container;
    if (SUCCEEDED(container.QueryFrom(document))) {
      ScopedComPtr<IEnumUnknown> enumerator;
      container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive());
      if (enumerator) {
        ScopedComPtr<IUnknown> unk;
        DWORD fetched = 0;
        enumerator->Next(1, unk.Receive(), &fetched);
        has_embedded_items = (fetched != 0);
      }
    }
  }

  return has_embedded_items;
}

HRESULT DeletePreviousNavigationEntry(IBrowserService* browser) {
  DCHECK(browser);

  ScopedComPtr<ITravelLog> travel_log;
  HRESULT hr = browser->GetTravelLog(travel_log.Receive());
  DCHECK(travel_log);
  if (travel_log) {
    ScopedComPtr<ITravelLogEx> travel_log_ex;
    if (SUCCEEDED(hr = travel_log_ex.QueryFrom(travel_log)) ||
        SUCCEEDED(hr = travel_log.QueryInterface(__uuidof(IIEITravelLogEx),
            reinterpret_cast<void**>(travel_log_ex.Receive())))) {
      hr = travel_log_ex->DeleteIndexEntry(browser, -1);
    } else {
      NOTREACHED() << "ITravelLogEx";
    }
  }

  return hr;
}

}  // end namespace

HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv,
    IBrowserService* browser, IShellView* shell_view, BOOL done,
    VARIANT* in_arg, VARIANT* out_arg) {
  DLOG(INFO) << __FUNCTION__ << " done:" << done;

  // OnHttpEquiv with 'done' set to TRUE is called for all pages.
  // 0 or more calls with done set to FALSE are made.
  // When done is FALSE, the current moniker may not represent the page
  // being navigated to so we always have to wait for done to be TRUE
  // before re-initiating the navigation.

  if (done) {
    if (CheckForCFNavigation(browser, false)) {
      // TODO(tommi): See if we can't figure out a cleaner way to avoid this.
      // For small documents we can hit a problem here.  When we attempt to
      // navigate the document again in CF, mshtml can "complete" the current
      // navigation (if all data is available) and fire off script events such
      // as onload and even render the page.  This will happen inside
      // NavigateBrowserToMoniker below.
      // To work around this, we clear the contents of the document before
      // opening it up in CF.
      ClearDocumentContents(browser);

      ScopedComPtr<IOleObject> mshtml_ole_object;
      HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject,
          reinterpret_cast<void**>(mshtml_ole_object.Receive()));
      DCHECK(FAILED(hr) || mshtml_ole_object != NULL);
      if (mshtml_ole_object) {
        ScopedComPtr<IMoniker> moniker;
        hr = mshtml_ole_object->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
            OLEWHICHMK_OBJFULL, moniker.Receive());
        DCHECK(FAILED(hr) || moniker != NULL);
        if (moniker) {
          DLOG(INFO) << "Navigating in CF";

          ScopedComPtr<IBindCtx> bind_context;
          // This bind context will be discarded by IE and a new one
          // constructed, so it's OK to create a sync bind context.
          ::CreateBindCtx(0, bind_context.Receive());

          DCHECK(bind_context);

          // If there's a referrer, preserve it.
          std::wstring headers;
          // Pass in URL fragments if applicable.
          std::wstring fragment;

          Bho* chrome_frame_bho = Bho::GetCurrentThreadBhoInstance();
          if (chrome_frame_bho) {
            if (!chrome_frame_bho->referrer().empty()) {
              headers = StringPrintf(L"Referer: %ls\r\n\r\n",
                ASCIIToWide(chrome_frame_bho->referrer()).c_str());
            }
            // If the original URL contains an anchor, then the URL queried
            // from the moniker does not contain the anchor. To workaround
            // this we retrieve the URL from our BHO.
            std::wstring moniker_url = GetActualUrlFromMoniker(
                moniker, NULL, chrome_frame_bho->url());

            GURL parsed_moniker_url(moniker_url);
            if (parsed_moniker_url.has_ref()) {
              fragment = UTF8ToWide(parsed_moniker_url.ref());
            }
          }

          hr = NavigateBrowserToMoniker(browser, moniker, headers.c_str(),
                                        bind_context, fragment.c_str());

          if (SUCCEEDED(hr)) {
            // Now that we've reissued the request, we need to remove the
            // original one from the travel log.
            DeletePreviousNavigationEntry(browser);
          }
        } else {
          DLOG(ERROR) << "Couldn't get the current moniker";
        }
      }

      if (FAILED(hr)) {
        NOTREACHED();
        // Lower the flag.
        CheckForCFNavigation(browser, true);
      } else {
        // The navigate-in-gcf flag will be cleared in
        // HttpNegotiatePatch::ReportProgress when the mime type is reported.
      }
    }
  } else if (in_arg && VT_BSTR == V_VT(in_arg)) {
    if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) {
      // OnHttpEquiv is invoked for meta tags within sub frames as well.
      // We want to switch renderers only for the top level frame.
      // The theory here is that if there are any existing embedded items
      // (frames or iframes) in the current document, then the http-equiv
      // notification is coming from those and not the top level document.
      // The embedded items should only be created once the top level
      // doc has been created.
      if (!DocumentHasEmbeddedItems(browser))
        MarkBrowserOnThreadForCFNavigation(browser);
    }
  }

  return original_httpequiv(browser, shell_view, done, in_arg, out_arg);
}

Bho* Bho::GetCurrentThreadBhoInstance() {
  DCHECK(bho_current_thread_instance_.Pointer()->Get() != NULL);
  return bho_current_thread_instance_.Pointer()->Get();
}

namespace {
// Utility function that prevents the current module from ever being unloaded.
void PinModule() {
  FilePath module_path;
  if (PathService::Get(base::FILE_MODULE, &module_path)) {
    HMODULE unused;
    if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN,
                           module_path.value().c_str(), &unused)) {
      NOTREACHED() << "Failed to pin module " << module_path.value().c_str()
                   << " , last error: " << GetLastError();
    }
  } else {
    NOTREACHED() << "Could not get module path.";
  }
}
}  // namespace

bool PatchHelper::InitializeAndPatchProtocolsIfNeeded() {
  bool ret = false;

  _pAtlModule->m_csStaticDataInitAndTypeInfo.Lock();

  if (state_ == UNKNOWN) {
    // If we're going to start patching things, we'd better make sure that we
    // stick around for ever more:
    PinModule();

    HttpNegotiatePatch::Initialize();

    bool patch_protocol = GetConfigBool(false, kPatchProtocols);
    if (patch_protocol) {
      ProtocolSinkWrap::PatchProtocolHandlers();
      state_ = PATCH_PROTOCOL;
    } else {
      state_ = PATCH_IBROWSER;
    }
    ret = true;
  }

  _pAtlModule->m_csStaticDataInitAndTypeInfo.Unlock();

  return ret;
}

void PatchHelper::PatchBrowserService(IBrowserService* browser_service) {
  DCHECK(state_ == PATCH_IBROWSER);
  vtable_patch::PatchInterfaceMethods(browser_service,
                                      IBrowserService_PatchInfo);
}

void PatchHelper::UnpatchIfNeeded() {
  if (state_ == PATCH_PROTOCOL) {
    ProtocolSinkWrap::UnpatchProtocolHandlers();
  } else if (state_ == PATCH_IBROWSER) {
    vtable_patch::UnpatchInterfaceMethods(IBrowserService_PatchInfo);
  }

  HttpNegotiatePatch::Uninitialize();

  state_ = UNKNOWN;
}

<commit_msg>Avoid a DCHECK.  Check if the interface is already patched before patching.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/bho.h"

#include <shlguid.h>
#include <shobjidl.h>

#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/registry.h"
#include "base/scoped_bstr_win.h"
#include "base/scoped_comptr_win.h"
#include "base/scoped_variant_win.h"
#include "base/string_util.h"
#include "chrome_tab.h" // NOLINT
#include "chrome_frame/extra_system_apis.h"
#include "chrome_frame/http_negotiate.h"
#include "chrome_frame/protocol_sink_wrap.h"
#include "chrome_frame/utils.h"
#include "chrome_frame/vtable_patch_manager.h"
#include "net/http/http_util.h"

const wchar_t kPatchProtocols[] = L"PatchProtocols";
static const int kIBrowserServiceOnHttpEquivIndex = 30;

base::LazyInstance<base::ThreadLocalPointer<Bho> >
    Bho::bho_current_thread_instance_(base::LINKER_INITIALIZED);

PatchHelper g_patch_helper;

BEGIN_VTABLE_PATCHES(IBrowserService)
  VTABLE_PATCH_ENTRY(kIBrowserServiceOnHttpEquivIndex, Bho::OnHttpEquiv)
END_VTABLE_PATCHES()

_ATL_FUNC_INFO Bho::kBeforeNavigate2Info = {
  CC_STDCALL, VT_EMPTY, 7, {
    VT_DISPATCH,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_VARIANT | VT_BYREF,
    VT_BOOL | VT_BYREF
  }
};

Bho::Bho() {
}

STDMETHODIMP Bho::SetSite(IUnknown* site) {
  HRESULT hr = S_OK;
  if (site) {
    ScopedComPtr<IWebBrowser2> web_browser2;
    web_browser2.QueryFrom(site);
    if (web_browser2) {
      hr = DispEventAdvise(web_browser2, &DIID_DWebBrowserEvents2);
      DCHECK(SUCCEEDED(hr)) << "DispEventAdvise failed. Error: " << hr;
    }

    if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) {
      ScopedComPtr<IBrowserService> browser_service;
      hr = DoQueryService(SID_SShellBrowser, site, browser_service.Receive());
      DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed."
          << " Site: " << site << " Error: " << hr;
      if (browser_service) {
        g_patch_helper.PatchBrowserService(browser_service);
        DCHECK(SUCCEEDED(hr)) << "vtable_patch::PatchInterfaceMethods failed."
            << " Site: " << site << " Error: " << hr;
      }
    }
    // Save away our BHO instance in TLS which enables it to be referenced by
    // our active document/activex instances to query referrer and other
    // information for a URL.
    AddRef();
    bho_current_thread_instance_.Pointer()->Set(this);
  } else {
    bho_current_thread_instance_.Pointer()->Set(NULL);
    Release();
  }

  return IObjectWithSiteImpl<Bho>::SetSite(site);
}

STDMETHODIMP Bho::BeforeNavigate2(IDispatch* dispatch, VARIANT* url,
    VARIANT* flags, VARIANT* target_frame_name, VARIANT* post_data,
    VARIANT* headers, VARIANT_BOOL* cancel) {
  ScopedComPtr<IWebBrowser2> web_browser2;
  if (dispatch)
    web_browser2.QueryFrom(dispatch);

  if (!web_browser2) {
    NOTREACHED() << "Can't find WebBrowser2 with given dispatch";
    return S_OK;  // Return success, we operate on best effort basis.
  }

  DLOG(INFO) << "BeforeNavigate2: " << url->bstrVal;

  if (g_patch_helper.state() == PatchHelper::PATCH_IBROWSER) {
    VARIANT_BOOL is_top_level = VARIANT_FALSE;
    web_browser2->get_TopLevelContainer(&is_top_level);

    std::wstring current_url;
    bool is_chrome_protocol = false;
    if (is_top_level && IsValidUrlScheme(url->bstrVal, false)) {
      current_url.assign(url->bstrVal, SysStringLen(url->bstrVal));
      is_chrome_protocol = StartsWith(current_url, kChromeProtocolPrefix,
                                      false);

      if (!is_chrome_protocol && IsOptInUrl(current_url.c_str())) {
        DLOG(INFO) << "Opt-in URL. Switching to cf.";
        ScopedComPtr<IBrowserService> browser_service;
        DoQueryService(SID_SShellBrowser, web_browser2,
                       browser_service.Receive());
        DCHECK(browser_service) << "DoQueryService - SID_SShellBrowser failed.";
        MarkBrowserOnThreadForCFNavigation(browser_service);
      }
    }
  }

  referrer_.clear();

  // Save away the referrer in case our active document needs it to initiate
  // navigation in chrome.
  if (headers && V_VT(headers) == VT_BSTR && headers->bstrVal != NULL) {
    std::string raw_headers_utf8 = WideToUTF8(headers->bstrVal);
    std::string http_headers =
        net::HttpUtil::AssembleRawHeaders(raw_headers_utf8.c_str(),
                                          raw_headers_utf8.length());
    net::HttpUtil::HeadersIterator it(http_headers.begin(), http_headers.end(),
                                      "\r\n");
    while (it.GetNext()) {
      if (LowerCaseEqualsASCII(it.name(), "referer")) {
        referrer_ = it.values();
        break;
      }
    }
  }
  url_ = url->bstrVal;
  return S_OK;
}

HRESULT Bho::FinalConstruct() {
  return S_OK;
}

void Bho::FinalRelease() {
}

namespace {

// See comments in Bho::OnHttpEquiv for details.
void ClearDocumentContents(IUnknown* browser) {
  ScopedComPtr<IWebBrowser2> web_browser2;
  if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser,
                               web_browser2.Receive()))) {
    ScopedComPtr<IDispatch> doc_disp;
    web_browser2->get_Document(doc_disp.Receive());
    ScopedComPtr<IHTMLDocument2> doc;
    if (doc_disp && SUCCEEDED(doc.QueryFrom(doc_disp))) {
      SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 0);
      doc->write(sa);
      ::SafeArrayDestroy(sa);
    }
  }
}

// Returns true if the currently loaded document in the browser has
// any embedded items such as a frame or an iframe.
bool DocumentHasEmbeddedItems(IUnknown* browser) {
  bool has_embedded_items = false;

  ScopedComPtr<IWebBrowser2> web_browser2;
  ScopedComPtr<IDispatch> document;
  if (SUCCEEDED(DoQueryService(SID_SWebBrowserApp, browser,
                               web_browser2.Receive())) &&
      SUCCEEDED(web_browser2->get_Document(document.Receive()))) {
    ScopedComPtr<IOleContainer> container;
    if (SUCCEEDED(container.QueryFrom(document))) {
      ScopedComPtr<IEnumUnknown> enumerator;
      container->EnumObjects(OLECONTF_EMBEDDINGS, enumerator.Receive());
      if (enumerator) {
        ScopedComPtr<IUnknown> unk;
        DWORD fetched = 0;
        enumerator->Next(1, unk.Receive(), &fetched);
        has_embedded_items = (fetched != 0);
      }
    }
  }

  return has_embedded_items;
}

HRESULT DeletePreviousNavigationEntry(IBrowserService* browser) {
  DCHECK(browser);

  ScopedComPtr<ITravelLog> travel_log;
  HRESULT hr = browser->GetTravelLog(travel_log.Receive());
  DCHECK(travel_log);
  if (travel_log) {
    ScopedComPtr<ITravelLogEx> travel_log_ex;
    if (SUCCEEDED(hr = travel_log_ex.QueryFrom(travel_log)) ||
        SUCCEEDED(hr = travel_log.QueryInterface(__uuidof(IIEITravelLogEx),
            reinterpret_cast<void**>(travel_log_ex.Receive())))) {
      hr = travel_log_ex->DeleteIndexEntry(browser, -1);
    } else {
      NOTREACHED() << "ITravelLogEx";
    }
  }

  return hr;
}

}  // end namespace

HRESULT Bho::OnHttpEquiv(IBrowserService_OnHttpEquiv_Fn original_httpequiv,
    IBrowserService* browser, IShellView* shell_view, BOOL done,
    VARIANT* in_arg, VARIANT* out_arg) {
  DLOG(INFO) << __FUNCTION__ << " done:" << done;

  // OnHttpEquiv with 'done' set to TRUE is called for all pages.
  // 0 or more calls with done set to FALSE are made.
  // When done is FALSE, the current moniker may not represent the page
  // being navigated to so we always have to wait for done to be TRUE
  // before re-initiating the navigation.

  if (done) {
    if (CheckForCFNavigation(browser, false)) {
      // TODO(tommi): See if we can't figure out a cleaner way to avoid this.
      // For small documents we can hit a problem here.  When we attempt to
      // navigate the document again in CF, mshtml can "complete" the current
      // navigation (if all data is available) and fire off script events such
      // as onload and even render the page.  This will happen inside
      // NavigateBrowserToMoniker below.
      // To work around this, we clear the contents of the document before
      // opening it up in CF.
      ClearDocumentContents(browser);

      ScopedComPtr<IOleObject> mshtml_ole_object;
      HRESULT hr = shell_view->GetItemObject(SVGIO_BACKGROUND, IID_IOleObject,
          reinterpret_cast<void**>(mshtml_ole_object.Receive()));
      DCHECK(FAILED(hr) || mshtml_ole_object != NULL);
      if (mshtml_ole_object) {
        ScopedComPtr<IMoniker> moniker;
        hr = mshtml_ole_object->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
            OLEWHICHMK_OBJFULL, moniker.Receive());
        DCHECK(FAILED(hr) || moniker != NULL);
        if (moniker) {
          DLOG(INFO) << "Navigating in CF";

          ScopedComPtr<IBindCtx> bind_context;
          // This bind context will be discarded by IE and a new one
          // constructed, so it's OK to create a sync bind context.
          ::CreateBindCtx(0, bind_context.Receive());

          DCHECK(bind_context);

          // If there's a referrer, preserve it.
          std::wstring headers;
          // Pass in URL fragments if applicable.
          std::wstring fragment;

          Bho* chrome_frame_bho = Bho::GetCurrentThreadBhoInstance();
          if (chrome_frame_bho) {
            if (!chrome_frame_bho->referrer().empty()) {
              headers = StringPrintf(L"Referer: %ls\r\n\r\n",
                ASCIIToWide(chrome_frame_bho->referrer()).c_str());
            }
            // If the original URL contains an anchor, then the URL queried
            // from the moniker does not contain the anchor. To workaround
            // this we retrieve the URL from our BHO.
            std::wstring moniker_url = GetActualUrlFromMoniker(
                moniker, NULL, chrome_frame_bho->url());

            GURL parsed_moniker_url(moniker_url);
            if (parsed_moniker_url.has_ref()) {
              fragment = UTF8ToWide(parsed_moniker_url.ref());
            }
          }

          hr = NavigateBrowserToMoniker(browser, moniker, headers.c_str(),
                                        bind_context, fragment.c_str());

          if (SUCCEEDED(hr)) {
            // Now that we've reissued the request, we need to remove the
            // original one from the travel log.
            DeletePreviousNavigationEntry(browser);
          }
        } else {
          DLOG(ERROR) << "Couldn't get the current moniker";
        }
      }

      if (FAILED(hr)) {
        NOTREACHED();
        // Lower the flag.
        CheckForCFNavigation(browser, true);
      } else {
        // The navigate-in-gcf flag will be cleared in
        // HttpNegotiatePatch::ReportProgress when the mime type is reported.
      }
    }
  } else if (in_arg && VT_BSTR == V_VT(in_arg)) {
    if (StrStrI(V_BSTR(in_arg), kChromeContentPrefix)) {
      // OnHttpEquiv is invoked for meta tags within sub frames as well.
      // We want to switch renderers only for the top level frame.
      // The theory here is that if there are any existing embedded items
      // (frames or iframes) in the current document, then the http-equiv
      // notification is coming from those and not the top level document.
      // The embedded items should only be created once the top level
      // doc has been created.
      if (!DocumentHasEmbeddedItems(browser))
        MarkBrowserOnThreadForCFNavigation(browser);
    }
  }

  return original_httpequiv(browser, shell_view, done, in_arg, out_arg);
}

Bho* Bho::GetCurrentThreadBhoInstance() {
  DCHECK(bho_current_thread_instance_.Pointer()->Get() != NULL);
  return bho_current_thread_instance_.Pointer()->Get();
}

namespace {
// Utility function that prevents the current module from ever being unloaded.
void PinModule() {
  FilePath module_path;
  if (PathService::Get(base::FILE_MODULE, &module_path)) {
    HMODULE unused;
    if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN,
                           module_path.value().c_str(), &unused)) {
      NOTREACHED() << "Failed to pin module " << module_path.value().c_str()
                   << " , last error: " << GetLastError();
    }
  } else {
    NOTREACHED() << "Could not get module path.";
  }
}
}  // namespace

bool PatchHelper::InitializeAndPatchProtocolsIfNeeded() {
  bool ret = false;

  _pAtlModule->m_csStaticDataInitAndTypeInfo.Lock();

  if (state_ == UNKNOWN) {
    // If we're going to start patching things, we'd better make sure that we
    // stick around for ever more:
    PinModule();

    HttpNegotiatePatch::Initialize();

    bool patch_protocol = GetConfigBool(false, kPatchProtocols);
    if (patch_protocol) {
      ProtocolSinkWrap::PatchProtocolHandlers();
      state_ = PATCH_PROTOCOL;
    } else {
      state_ = PATCH_IBROWSER;
    }
    ret = true;
  }

  _pAtlModule->m_csStaticDataInitAndTypeInfo.Unlock();

  return ret;
}

void PatchHelper::PatchBrowserService(IBrowserService* browser_service) {
  DCHECK(state_ == PATCH_IBROWSER);
  if (!IS_PATCHED(IBrowserService)) {
    vtable_patch::PatchInterfaceMethods(browser_service,
                                        IBrowserService_PatchInfo);
  }
}

void PatchHelper::UnpatchIfNeeded() {
  if (state_ == PATCH_PROTOCOL) {
    ProtocolSinkWrap::UnpatchProtocolHandlers();
  } else if (state_ == PATCH_IBROWSER) {
    vtable_patch::UnpatchInterfaceMethods(IBrowserService_PatchInfo);
  }

  HttpNegotiatePatch::Uninitialize();

  state_ = UNKNOWN;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if !OS(WIN) && !OS(ANDROID)
#include "SkFontConfigInterface.h"
#endif
#include "SkFontMgr.h"
#include "SkStream.h"
#include "SkTypeface.h"
#include "platform/NotImplemented.h"
#include "platform/fonts/AlternateFontFamily.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/FontFaceCreationParams.h"
#include "platform/fonts/SimpleFontData.h"
#include "public/platform/Platform.h"
#include "public/platform/linux/WebSandboxSupport.h"
#include "wtf/Assertions.h"
#include "wtf/text/AtomicString.h"
#include "wtf/text/CString.h"
#include <unicode/locid.h>

#if !OS(WIN) && !OS(ANDROID)
static SkStream* streamForFontconfigInterfaceId(int fontconfigInterfaceId)
{
    SkAutoTUnref<SkFontConfigInterface> fci(SkFontConfigInterface::RefGlobal());
    SkFontConfigInterface::FontIdentity fontIdentity;
    fontIdentity.fID = fontconfigInterfaceId;
    return fci->openStream(fontIdentity);
}
#endif

namespace WebCore {

void FontCache::platformInit()
{
}

PassRefPtr<SimpleFontData> FontCache::fallbackOnStandardFontStyle(
    const FontDescription& fontDescription, UChar32 character)
{
    FontDescription substituteDescription(fontDescription);
    substituteDescription.setStyle(FontStyleNormal);
    substituteDescription.setWeight(FontWeightNormal);

    FontFaceCreationParams creationParams(substituteDescription.family().family());
    FontPlatformData* substitutePlatformData = getFontPlatformData(substituteDescription, creationParams);
    if (substitutePlatformData && substitutePlatformData->fontContainsCharacter(character)) {
        FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
        platformData.setSyntheticBold(fontDescription.weight() >= FontWeight600);
        platformData.setSyntheticItalic(fontDescription.style() == FontStyleItalic);
        return fontDataFromFontPlatformData(&platformData, DoNotRetain);
    }

    return nullptr;
}

#if !OS(WIN) && !OS(ANDROID)
PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*)
{
    // First try the specified font with standard style & weight.
    if (fontDescription.style() == FontStyleItalic
        || fontDescription.weight() >= FontWeight600) {
        RefPtr<SimpleFontData> fontData = fallbackOnStandardFontStyle(
            fontDescription, c);
        if (fontData)
            return fontData;
    }

    FontCache::PlatformFallbackFont fallbackFont;
    FontCache::getFontForCharacter(c, "", &fallbackFont);
    if (fallbackFont.name.isEmpty())
        return nullptr;

    FontFaceCreationParams creationParams;
    creationParams = FontFaceCreationParams(fallbackFont.filename, fallbackFont.fontconfigInterfaceId, fallbackFont.ttcIndex);

    // Changes weight and/or italic of given FontDescription depends on
    // the result of fontconfig so that keeping the correct font mapping
    // of the given character. See http://crbug.com/32109 for details.
    bool shouldSetSyntheticBold = false;
    bool shouldSetSyntheticItalic = false;
    FontDescription description(fontDescription);
    if (fallbackFont.isBold && description.weight() < FontWeightBold)
        description.setWeight(FontWeightBold);
    if (!fallbackFont.isBold && description.weight() >= FontWeightBold) {
        shouldSetSyntheticBold = true;
        description.setWeight(FontWeightNormal);
    }
    if (fallbackFont.isItalic && description.style() == FontStyleNormal)
        description.setStyle(FontStyleItalic);
    if (!fallbackFont.isItalic && description.style() == FontStyleItalic) {
        shouldSetSyntheticItalic = true;
        description.setStyle(FontStyleNormal);
    }

    FontPlatformData* substitutePlatformData = getFontPlatformData(description, creationParams);
    if (!substitutePlatformData)
        return nullptr;
    FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
    platformData.setSyntheticBold(shouldSetSyntheticBold);
    platformData.setSyntheticItalic(shouldSetSyntheticItalic);
    return fontDataFromFontPlatformData(&platformData, DoNotRetain);
}

#endif // !OS(WIN) && !OS(ANDROID)

PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
{
    const FontFaceCreationParams fallbackCreationParams(getFallbackFontFamily(description));
    const FontPlatformData* fontPlatformData = getFontPlatformData(description, fallbackCreationParams);

    // We should at least have Sans or Arial which is the last resort fallback of SkFontHost ports.
    if (!fontPlatformData) {
        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, sansCreationParams, (AtomicString("Sans", AtomicString::ConstructFromLiteral)));
        fontPlatformData = getFontPlatformData(description, sansCreationParams);
    }
    if (!fontPlatformData) {
        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, arialCreationParams, (AtomicString("Arial", AtomicString::ConstructFromLiteral)));
        fontPlatformData = getFontPlatformData(description, arialCreationParams);
    }

    ASSERT(fontPlatformData);
    return fontDataFromFontPlatformData(fontPlatformData, shouldRetain);
}

PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, CString& name)
{
#if !OS(WIN) && !OS(ANDROID)
    if (creationParams.creationType() == CreateFontByFciIdAndTtcIndex) {
        // TODO(dro): crbug.com/381620 Use creationParams.ttcIndex() after
        // https://code.google.com/p/skia/issues/detail?id=1186 gets fixed.
        SkTypeface* typeface = nullptr;
        if (blink::Platform::current()->sandboxSupport())
            typeface = SkTypeface::CreateFromStream(streamForFontconfigInterfaceId(creationParams.fontconfigInterfaceId()));
        else
            typeface = SkTypeface::CreateFromFile(creationParams.filename().data());

        if (typeface)
            return adoptRef(typeface);
    }
#endif

    AtomicString family = creationParams.family();
    // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
    // the fallback name (like "monospace") that fontconfig understands.
    if (!family.length() || family.startsWith("-webkit-")) {
        name = getFallbackFontFamily(fontDescription).string().utf8();
    } else {
        // convert the name to utf8
        name = family.utf8();
    }

    int style = SkTypeface::kNormal;
    if (fontDescription.weight() >= FontWeight600)
        style |= SkTypeface::kBold;
    if (fontDescription.style())
        style |= SkTypeface::kItalic;

#if OS(WIN)
    if (s_sideloadedFonts) {
        HashMap<String, SkTypeface*>::iterator sideloadedFont = s_sideloadedFonts->find(name.data());
        if (sideloadedFont != s_sideloadedFonts->end()) {
            return adoptRef(sideloadedFont->value);
        }
    }
    // FIXME: Use SkFontStyle and matchFamilyStyle instead of legacyCreateTypeface.
    if (m_fontManager)
        return adoptRef(m_fontManager->legacyCreateTypeface(name.data(), style));
#endif

    return adoptRef(SkTypeface::CreateFromName(name.data(), static_cast<SkTypeface::Style>(style)));
}

#if !OS(WIN)
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, float fontSize)
{
    CString name;
    RefPtr<SkTypeface> tf(createTypeface(fontDescription, creationParams, name));
    if (!tf)
        return 0;

    FontPlatformData* result = new FontPlatformData(tf,
        name.data(),
        fontSize,
        (fontDescription.weight() >= FontWeight600 && !tf->isBold()) || fontDescription.isSyntheticBold(),
        (fontDescription.style() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
        fontDescription.orientation(),
        fontDescription.useSubpixelPositioning());
    return result;
}
#endif // !OS(WIN)

} // namespace WebCore
<commit_msg>Add more Windows-specific fonts to fallback path<commit_after>/*
 * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if !OS(WIN) && !OS(ANDROID)
#include "SkFontConfigInterface.h"
#endif
#include "SkFontMgr.h"
#include "SkStream.h"
#include "SkTypeface.h"
#include "platform/NotImplemented.h"
#include "platform/fonts/AlternateFontFamily.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/FontFaceCreationParams.h"
#include "platform/fonts/SimpleFontData.h"
#include "public/platform/Platform.h"
#include "public/platform/linux/WebSandboxSupport.h"
#include "wtf/Assertions.h"
#include "wtf/text/AtomicString.h"
#include "wtf/text/CString.h"
#include <unicode/locid.h>

#if !OS(WIN) && !OS(ANDROID)
static SkStream* streamForFontconfigInterfaceId(int fontconfigInterfaceId)
{
    SkAutoTUnref<SkFontConfigInterface> fci(SkFontConfigInterface::RefGlobal());
    SkFontConfigInterface::FontIdentity fontIdentity;
    fontIdentity.fID = fontconfigInterfaceId;
    return fci->openStream(fontIdentity);
}
#endif

namespace WebCore {

void FontCache::platformInit()
{
}

PassRefPtr<SimpleFontData> FontCache::fallbackOnStandardFontStyle(
    const FontDescription& fontDescription, UChar32 character)
{
    FontDescription substituteDescription(fontDescription);
    substituteDescription.setStyle(FontStyleNormal);
    substituteDescription.setWeight(FontWeightNormal);

    FontFaceCreationParams creationParams(substituteDescription.family().family());
    FontPlatformData* substitutePlatformData = getFontPlatformData(substituteDescription, creationParams);
    if (substitutePlatformData && substitutePlatformData->fontContainsCharacter(character)) {
        FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
        platformData.setSyntheticBold(fontDescription.weight() >= FontWeight600);
        platformData.setSyntheticItalic(fontDescription.style() == FontStyleItalic);
        return fontDataFromFontPlatformData(&platformData, DoNotRetain);
    }

    return nullptr;
}

#if !OS(WIN) && !OS(ANDROID)
PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*)
{
    // First try the specified font with standard style & weight.
    if (fontDescription.style() == FontStyleItalic
        || fontDescription.weight() >= FontWeight600) {
        RefPtr<SimpleFontData> fontData = fallbackOnStandardFontStyle(
            fontDescription, c);
        if (fontData)
            return fontData;
    }

    FontCache::PlatformFallbackFont fallbackFont;
    FontCache::getFontForCharacter(c, "", &fallbackFont);
    if (fallbackFont.name.isEmpty())
        return nullptr;

    FontFaceCreationParams creationParams;
    creationParams = FontFaceCreationParams(fallbackFont.filename, fallbackFont.fontconfigInterfaceId, fallbackFont.ttcIndex);

    // Changes weight and/or italic of given FontDescription depends on
    // the result of fontconfig so that keeping the correct font mapping
    // of the given character. See http://crbug.com/32109 for details.
    bool shouldSetSyntheticBold = false;
    bool shouldSetSyntheticItalic = false;
    FontDescription description(fontDescription);
    if (fallbackFont.isBold && description.weight() < FontWeightBold)
        description.setWeight(FontWeightBold);
    if (!fallbackFont.isBold && description.weight() >= FontWeightBold) {
        shouldSetSyntheticBold = true;
        description.setWeight(FontWeightNormal);
    }
    if (fallbackFont.isItalic && description.style() == FontStyleNormal)
        description.setStyle(FontStyleItalic);
    if (!fallbackFont.isItalic && description.style() == FontStyleItalic) {
        shouldSetSyntheticItalic = true;
        description.setStyle(FontStyleNormal);
    }

    FontPlatformData* substitutePlatformData = getFontPlatformData(description, creationParams);
    if (!substitutePlatformData)
        return nullptr;
    FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
    platformData.setSyntheticBold(shouldSetSyntheticBold);
    platformData.setSyntheticItalic(shouldSetSyntheticItalic);
    return fontDataFromFontPlatformData(&platformData, DoNotRetain);
}

#endif // !OS(WIN) && !OS(ANDROID)

PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
{
    const FontFaceCreationParams fallbackCreationParams(getFallbackFontFamily(description));
    const FontPlatformData* fontPlatformData = getFontPlatformData(description, fallbackCreationParams);

    // We should at least have Sans or Arial which is the last resort fallback of SkFontHost ports.
    if (!fontPlatformData) {
        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, sansCreationParams, (AtomicString("Sans", AtomicString::ConstructFromLiteral)));
        fontPlatformData = getFontPlatformData(description, sansCreationParams);
    }
    if (!fontPlatformData) {
        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, arialCreationParams, (AtomicString("Arial", AtomicString::ConstructFromLiteral)));
        fontPlatformData = getFontPlatformData(description, arialCreationParams);
    }
#if OS(WIN)
    // Try some more Windows-specific fallbacks.
    if (!fontPlatformData) {
        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, msuigothicCreationParams, (AtomicString("MS UI Gothic", AtomicString::ConstructFromLiteral)));
        fontPlatformData = getFontPlatformData(description, msuigothicCreationParams);
    }
    if (!fontPlatformData) {
        DEFINE_STATIC_LOCAL(const FontFaceCreationParams, mssansserifCreationParams, (AtomicString("Microsoft Sans Serif", AtomicString::ConstructFromLiteral)));
        fontPlatformData = getFontPlatformData(description, mssansserifCreationParams);
    }
#endif

    ASSERT(fontPlatformData);
    return fontDataFromFontPlatformData(fontPlatformData, shouldRetain);
}

PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, CString& name)
{
#if !OS(WIN) && !OS(ANDROID)
    if (creationParams.creationType() == CreateFontByFciIdAndTtcIndex) {
        // TODO(dro): crbug.com/381620 Use creationParams.ttcIndex() after
        // https://code.google.com/p/skia/issues/detail?id=1186 gets fixed.
        SkTypeface* typeface = nullptr;
        if (blink::Platform::current()->sandboxSupport())
            typeface = SkTypeface::CreateFromStream(streamForFontconfigInterfaceId(creationParams.fontconfigInterfaceId()));
        else
            typeface = SkTypeface::CreateFromFile(creationParams.filename().data());

        if (typeface)
            return adoptRef(typeface);
    }
#endif

    AtomicString family = creationParams.family();
    // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
    // the fallback name (like "monospace") that fontconfig understands.
    if (!family.length() || family.startsWith("-webkit-")) {
        name = getFallbackFontFamily(fontDescription).string().utf8();
    } else {
        // convert the name to utf8
        name = family.utf8();
    }

    int style = SkTypeface::kNormal;
    if (fontDescription.weight() >= FontWeight600)
        style |= SkTypeface::kBold;
    if (fontDescription.style())
        style |= SkTypeface::kItalic;

#if OS(WIN)
    if (s_sideloadedFonts) {
        HashMap<String, SkTypeface*>::iterator sideloadedFont = s_sideloadedFonts->find(name.data());
        if (sideloadedFont != s_sideloadedFonts->end()) {
            return adoptRef(sideloadedFont->value);
        }
    }
    // FIXME: Use SkFontStyle and matchFamilyStyle instead of legacyCreateTypeface.
    if (m_fontManager)
        return adoptRef(m_fontManager->legacyCreateTypeface(name.data(), style));
#endif

    return adoptRef(SkTypeface::CreateFromName(name.data(), static_cast<SkTypeface::Style>(style)));
}

#if !OS(WIN)
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const FontFaceCreationParams& creationParams, float fontSize)
{
    CString name;
    RefPtr<SkTypeface> tf(createTypeface(fontDescription, creationParams, name));
    if (!tf)
        return 0;

    FontPlatformData* result = new FontPlatformData(tf,
        name.data(),
        fontSize,
        (fontDescription.weight() >= FontWeight600 && !tf->isBold()) || fontDescription.isSyntheticBold(),
        (fontDescription.style() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
        fontDescription.orientation(),
        fontDescription.useSubpixelPositioning());
    return result;
}
#endif // !OS(WIN)

} // namespace WebCore
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed 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.

#include <os.hpp>
#include <kernel.hpp>
#include <kernel/rng.hpp>
#include <service>
#include <cstdio>
#include <cinttypes>
#include <util/fixed_vector.hpp>
#include <system_log>
#define MYINFO(X,...) INFO("Kernel", X, ##__VA_ARGS__)

//#define ENABLE_PROFILERS
#ifdef ENABLE_PROFILERS
#include <profile>
#define PROFILE(name)  ScopedProfiler __CONCAT(sp, __COUNTER__){name};
#else
#define PROFILE(name) /* name */
#endif

using namespace util;

extern char _start;
extern char _end;
extern char _ELF_START_;
extern char _TEXT_START_;
extern char _LOAD_START_;
extern char _ELF_END_;

//uintptr_t OS::liveupdate_loc_   = 0;

kernel::State __kern_state;

kernel::State& kernel::state() noexcept {
  return __kern_state;
}

util::KHz os::cpu_freq() {
  return kernel::cpu_freq();
}

const uintptr_t elf_binary_size_ {(uintptr_t)&_ELF_END_ - (uintptr_t)&_ELF_START_};

// stdout redirection
using Print_vec = Fixed_vector<os::print_func, 8>;
static Print_vec os_print_handlers(Fixedvector_Init::UNINIT);

// Plugins
struct Plugin_desc {
  Plugin_desc(os::Plugin f, const char* n) : func{f}, name{n} {}

  os::Plugin  func;
  const char* name;
};
static Fixed_vector<Plugin_desc, 16> plugins(Fixedvector_Init::UNINIT);

__attribute__((weak))
size_t kernel::liveupdate_phys_size(size_t /*phys_max*/) noexcept {
  return 4096;
};

__attribute__((weak))
size_t kernel::liveupdate_phys_loc(size_t phys_max) noexcept {
  return phys_max - liveupdate_phys_size(phys_max);
};

__attribute__((weak))
void kernel::setup_liveupdate(uintptr_t)
{
  // without LiveUpdate: storage location is at the last page?
  kernel::state().liveupdate_loc = kernel::heap_max() & ~(uintptr_t) 0xFFF;
}

const char* os::cmdline_args() noexcept {
  return kernel::cmdline();
}

extern kernel::ctor_t __plugin_ctors_start;
extern kernel::ctor_t __plugin_ctors_end;
extern kernel::ctor_t __service_ctors_start;
extern kernel::ctor_t __service_ctors_end;

void os::register_plugin(Plugin delg, const char* name){
  MYINFO("Registering plugin %s", name);
  plugins.emplace_back(delg, name);
}

extern void __arch_reboot();
void os::reboot() noexcept
{
  __arch_reboot();
}
void os::shutdown() noexcept
{
  kernel::state().running = false;
}

void kernel::post_start()
{
  // Enable timestamps (if present)
  kernel::state().timestamps_ready = true;

  // LiveUpdate needs some initialization, although only if present
  kernel::setup_liveupdate();

  // Initialize the system log if plugin is present.
  // Dependent on the liveupdate location being set
  SystemLog::initialize();

  MYINFO("Initializing RNG");
  PROFILE("RNG init");
  RNG::get().init();

  // Seed rand with 32 bits from RNG
  srand(rng_extract_uint32());

  // Custom initialization functions
  MYINFO("Initializing plugins");
  kernel::run_ctors(&__plugin_ctors_start, &__plugin_ctors_end);

  // Run plugins
  PROFILE("Plugins init");
  for (auto plugin : plugins) {
    INFO2("* Initializing %s", plugin.name);
    plugin.func();
  }

  MYINFO("Running service constructors");
  FILLINE('-');
  // the boot sequence is over when we get to plugins/Service::start
  kernel::state().boot_sequence_passed = true;

    // Run service constructors
  kernel::run_ctors(&__service_ctors_start, &__service_ctors_end);

  PROFILE("Service::start");
  // begin service start
  FILLINE('=');
  printf(" IncludeOS %s (%s / %u-bit)\n",
         os::version(), os::arch(),
         static_cast<unsigned>(sizeof(uintptr_t)) * 8);
  printf(" +--> Running [ %s ]\n", Service::name());
  FILLINE('~');
#if defined(LIBFUZZER_ENABLED) || defined(ARP_PASSTHROUGH) || defined(DISABLE_INET_CHECKSUMS)
  printf(" +--> WARNiNG: Environment unsafe for production\n");
  FILLINE('~');
#endif

  Service::start();
}

void os::add_stdout(os::print_func func)
{
  os_print_handlers.push_back(func);
}
__attribute__((weak))
bool os_enable_boot_logging = false;
__attribute__((weak))
bool os_default_stdout = false;

#include <isotime>
bool contains(const char* str, size_t len, char c)
{
  for (size_t i = 0; i < len; i++) if (str[i] == c) return true;
  return false;
}

void os::print(const char* str, const size_t len)
{
  if (UNLIKELY(! kernel::libc_initialized())) {
    kernel::default_stdout(str, len);
    return;
  }

  /** TIMESTAMPING **/
  if (kernel::timestamps() && kernel::timestamps_ready() && !kernel::is_panicking())
  {
    static bool apply_ts = true;
    if (apply_ts)
    {
      std::string ts = "[" + isotime::now() + "] ";
      for (const auto& callback : os_print_handlers) {
        callback(ts.c_str(), ts.size());
      }
      apply_ts = false;
    }
    const bool has_newline = contains(str, len, '\n');
    if (has_newline) apply_ts = true;
  }
  /** TIMESTAMPING **/

  if (os_enable_boot_logging || kernel::is_booted() || kernel::is_panicking())
  {
    for (const auto& callback : os_print_handlers) {
      callback(str, len);
    }
  }
}

void os::print_timestamps(const bool enabled)
{
  kernel::state().timestamps = enabled;
}
<commit_msg>kernel: Disable plugin construction on MacOS<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed 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.

#include <os.hpp>
#include <kernel.hpp>
#include <kernel/rng.hpp>
#include <service>
#include <cstdio>
#include <cinttypes>
#include <util/fixed_vector.hpp>
#include <system_log>
#define MYINFO(X,...) INFO("Kernel", X, ##__VA_ARGS__)

//#define ENABLE_PROFILERS
#ifdef ENABLE_PROFILERS
#include <profile>
#define PROFILE(name)  ScopedProfiler __CONCAT(sp, __COUNTER__){name};
#else
#define PROFILE(name) /* name */
#endif

using namespace util;

extern char _start;
extern char _end;
extern char _ELF_START_;
extern char _TEXT_START_;
extern char _LOAD_START_;
extern char _ELF_END_;

//uintptr_t OS::liveupdate_loc_   = 0;

kernel::State __kern_state;

kernel::State& kernel::state() noexcept {
  return __kern_state;
}

util::KHz os::cpu_freq() {
  return kernel::cpu_freq();
}

const uintptr_t elf_binary_size_ {(uintptr_t)&_ELF_END_ - (uintptr_t)&_ELF_START_};

// stdout redirection
using Print_vec = Fixed_vector<os::print_func, 8>;
static Print_vec os_print_handlers(Fixedvector_Init::UNINIT);

// Plugins
struct Plugin_desc {
  Plugin_desc(os::Plugin f, const char* n) : func{f}, name{n} {}

  os::Plugin  func;
  const char* name;
};
static Fixed_vector<Plugin_desc, 16> plugins(Fixedvector_Init::UNINIT);

__attribute__((weak))
size_t kernel::liveupdate_phys_size(size_t /*phys_max*/) noexcept {
  return 4096;
};

__attribute__((weak))
size_t kernel::liveupdate_phys_loc(size_t phys_max) noexcept {
  return phys_max - liveupdate_phys_size(phys_max);
};

__attribute__((weak))
void kernel::setup_liveupdate(uintptr_t)
{
  // without LiveUpdate: storage location is at the last page?
  kernel::state().liveupdate_loc = kernel::heap_max() & ~(uintptr_t) 0xFFF;
}

const char* os::cmdline_args() noexcept {
  return kernel::cmdline();
}

extern kernel::ctor_t __plugin_ctors_start;
extern kernel::ctor_t __plugin_ctors_end;
extern kernel::ctor_t __service_ctors_start;
extern kernel::ctor_t __service_ctors_end;

void os::register_plugin(Plugin delg, const char* name){
  MYINFO("Registering plugin %s", name);
  plugins.emplace_back(delg, name);
}

extern void __arch_reboot();
void os::reboot() noexcept
{
  __arch_reboot();
}
void os::shutdown() noexcept
{
  kernel::state().running = false;
}

void kernel::post_start()
{
  // Enable timestamps (if present)
  kernel::state().timestamps_ready = true;

  // LiveUpdate needs some initialization, although only if present
  kernel::setup_liveupdate();

  // Initialize the system log if plugin is present.
  // Dependent on the liveupdate location being set
  SystemLog::initialize();

  MYINFO("Initializing RNG");
  PROFILE("RNG init");
  RNG::get().init();

  // Seed rand with 32 bits from RNG
  srand(rng_extract_uint32());

#ifndef __MACH__
  // Custom initialization functions
  MYINFO("Initializing plugins");
  kernel::run_ctors(&__plugin_ctors_start, &__plugin_ctors_end);
#endif

  // Run plugins
  PROFILE("Plugins init");
  for (auto plugin : plugins) {
    INFO2("* Initializing %s", plugin.name);
    plugin.func();
  }

  MYINFO("Running service constructors");
  FILLINE('-');
  // the boot sequence is over when we get to plugins/Service::start
  kernel::state().boot_sequence_passed = true;

    // Run service constructors
  kernel::run_ctors(&__service_ctors_start, &__service_ctors_end);

  PROFILE("Service::start");
  // begin service start
  FILLINE('=');
  printf(" IncludeOS %s (%s / %u-bit)\n",
         os::version(), os::arch(),
         static_cast<unsigned>(sizeof(uintptr_t)) * 8);
  printf(" +--> Running [ %s ]\n", Service::name());
  FILLINE('~');
#if defined(LIBFUZZER_ENABLED) || defined(ARP_PASSTHROUGH) || defined(DISABLE_INET_CHECKSUMS)
  printf(" +--> WARNiNG: Environment unsafe for production\n");
  FILLINE('~');
#endif

  Service::start();
}

void os::add_stdout(os::print_func func)
{
  os_print_handlers.push_back(func);
}
__attribute__((weak))
bool os_enable_boot_logging = false;
__attribute__((weak))
bool os_default_stdout = false;

#include <isotime>
bool contains(const char* str, size_t len, char c)
{
  for (size_t i = 0; i < len; i++) if (str[i] == c) return true;
  return false;
}

void os::print(const char* str, const size_t len)
{
  if (UNLIKELY(! kernel::libc_initialized())) {
    kernel::default_stdout(str, len);
    return;
  }

  /** TIMESTAMPING **/
  if (kernel::timestamps() && kernel::timestamps_ready() && !kernel::is_panicking())
  {
    static bool apply_ts = true;
    if (apply_ts)
    {
      std::string ts = "[" + isotime::now() + "] ";
      for (const auto& callback : os_print_handlers) {
        callback(ts.c_str(), ts.size());
      }
      apply_ts = false;
    }
    const bool has_newline = contains(str, len, '\n');
    if (has_newline) apply_ts = true;
  }
  /** TIMESTAMPING **/

  if (os_enable_boot_logging || kernel::is_booted() || kernel::is_panicking())
  {
    for (const auto& callback : os_print_handlers) {
      callback(str, len);
    }
  }
}

void os::print_timestamps(const bool enabled)
{
  kernel::state().timestamps = enabled;
}
<|endoftext|>


<commit_before>// @(#)root/foam:$Name:  $:$Id: TFoamMaxwt.cxx,v 1.4 2005/04/12 10:01:56 brun Exp $
// Author: S. Jadach <mailto:Stanislaw.jadach@ifj.edu.pl>, P.Sawicki <mailto:Pawel.Sawicki@ifj.edu.pl>

//____________________________________________________________________________
//
// Class  TFoamMaxwt
// =================
// Small auxiliary class for controlling MC weight.
// It provides certain measure of the "maximum weight"
// depending on small user-parameter "epsilon".
// It creates and uses 2 histograms of the TH1D class.
// User defines no. of bins nBin,  nBin=1000 is  recommended
// wmax defines weight range (1,wmax), it is adjusted "manually"
//
//____________________________________________________________________________

#include "Riostream.h"
#include "TMath.h"
#include "TH1.h"
#include "TFoamMaxwt.h"

ClassImp(TFoamMaxwt);

//____________________________________________________________________________
TFoamMaxwt::TFoamMaxwt()
{
// Constructor for streamer
  fNent = 0;
  fnBin = 0;
  fWtHst1 = 0;
  fWtHst2 = 0;
}

//____________________________________________________________________________
TFoamMaxwt::TFoamMaxwt(Double_t wmax, const Int_t nBin)
{
// Principal user constructor
  fNent = 0;
  fnBin = nBin;
  fwmax = wmax;
  fWtHst1 = new TH1D("TFoamMaxwt_hst_Wt1","Histo of weight   ",nBin,0.0,wmax);
  fWtHst2 = new TH1D("TFoamMaxwt_hst_Wt2","Histo of weight**2",nBin,0.0,wmax);
  fWtHst1->SetDirectory(0);// exclude from diskfile
  fWtHst2->SetDirectory(0);// and enable deleting
}

//______________________________________________________________________________
TFoamMaxwt::TFoamMaxwt(TFoamMaxwt &From): TObject(From)
{
// Explicit COPY CONSTRUCTOR (unused, so far)
  fnBin   = From.fnBin;
  fwmax   = From.fwmax;
  fWtHst1 = From.fWtHst1;
  fWtHst2 = From.fWtHst2;
  Error("TFoamMaxwt","COPY CONSTRUCTOR NOT TESTED!");
}

//_______________________________________________________________________________
TFoamMaxwt::~TFoamMaxwt()
{
// Destructor
  delete fWtHst1; // For this SetDirectory(0) is needed!
  delete fWtHst2; //
  fWtHst1=0;
  fWtHst2=0;
}
//_______________________________________________________________________________
void TFoamMaxwt::Reset()
{
// Reseting weight analysis
  fNent = 0;
  fWtHst1->Reset();
  fWtHst2->Reset();
}

//_______________________________________________________________________________
TFoamMaxwt& TFoamMaxwt::operator =(TFoamMaxwt &From)
{
// substitution =
  if (&From == this) return *this;
  fnBin = From.fnBin;
  fwmax = From.fwmax;
  fWtHst1 = From.fWtHst1;
  fWtHst2 = From.fWtHst2;
  return *this;
}

//________________________________________________________________________________
void TFoamMaxwt::Fill(Double_t wt)
{
// Filling analysed weight
  fNent =  fNent+1.0;
  fWtHst1->Fill(wt,1.0);
  fWtHst2->Fill(wt,wt);
}

//________________________________________________________________________________
void TFoamMaxwt::Make(Double_t eps, Double_t &MCeff)
{
// Calculates Efficiency= AveWt/WtLim for a given tolerance level epsilon<<1
// To be called at the end of the MC run.

  Double_t WtLim,AveWt;
  GetMCeff(eps, MCeff, WtLim);
  AveWt = MCeff*WtLim;
  cout<< "00000000000000000000000000000000000000000000000000000000000000000000000"<<endl;
  cout<< "00 -->WtLim: No_evt ="<<fNent<<"   <Wt> = "<<AveWt<<"  WtLim=  "<<WtLim<<endl;
  cout<< "00 -->WtLim: For eps = "<<eps  <<"    EFFICIENCY <Wt>/WtLim= "<<MCeff<<endl;
  cout<< "00000000000000000000000000000000000000000000000000000000000000000000000"<<endl;
}

//_________________________________________________________________________________
void TFoamMaxwt::GetMCeff(Double_t eps, Double_t &MCeff, Double_t &WtLim)
{
// Calculates Efficiency= AveWt/WtLim for a given tolerance level epsilon<<1
// using information stored in two histograms.
// To be called at the end of the MC run.

  Int_t ib,ibX;
  Double_t LowEdge,Bin,Bin1;
  Double_t AveWt, AveWt1;

  fWtHst1->Print();
  fWtHst2->Print();

// Convention on bin-numbering: nb=1 for 1-st bin, undeflow nb=0, overflow nb=Nb+1
  Double_t sum   = 0.0;
  Double_t sumWt = 0.0;
  for(ib=0;ib<=fnBin+1;ib++){
    sum   += fWtHst1->GetBinContent(ib);
    sumWt += fWtHst2->GetBinContent(ib);
  }
  if( (sum == 0.0) || (sumWt == 0.0) ){
    cout<<"TFoamMaxwt::Make: zero content of histogram !!!,sum,sumWt ="<<sum<<sumWt<<endl;
  }
  AveWt = sumWt/sum;
  //--------------------------------------
  for( ibX=fnBin+1; ibX>0; ibX--){
    LowEdge = (ibX-1.0)*fwmax/fnBin;
    sum   = 0.0;
    sumWt = 0.0;
    for( ib=0; ib<=fnBin+1; ib++){
      Bin  = fWtHst1->GetBinContent(ib);
      Bin1 = fWtHst2->GetBinContent(ib);
      if(ib >= ibX) Bin1=LowEdge*Bin;
      sum   += Bin;
      sumWt += Bin1;
    }
    AveWt1 = sumWt/sum;
    if( TMath::Abs(1.0-AveWt1/AveWt) > eps ) break;
  }
  //---------------------------
  if(ibX == (fnBin+1) ){
    WtLim = 1.0e200;
    MCeff   = 0.0;
    cout<< "+++++ WtLim undefined. Higher uper limit in histogram"<<endl;
  }else if( ibX == 1){
    WtLim = 0.0;
    MCeff   =-1.0;
    cout<< "+++++ WtLim undefined. Lower uper limit or more bins "<<endl;
  }else{
    WtLim= (ibX)*fwmax/fnBin; // We over-estimate WtLim, under-estimate MCeff
    MCeff  = AveWt/WtLim;
  }
}
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//      End of    Class  TFoamMaxwt                                          //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
<commit_msg>remove a const declaration in one constructor<commit_after>// @(#)root/foam:$Name:  $:$Id: TFoamMaxwt.cxx,v 1.5 2005/04/12 12:31:39 brun Exp $
// Author: S. Jadach <mailto:Stanislaw.jadach@ifj.edu.pl>, P.Sawicki <mailto:Pawel.Sawicki@ifj.edu.pl>

//____________________________________________________________________________
//
// Class  TFoamMaxwt
// =================
// Small auxiliary class for controlling MC weight.
// It provides certain measure of the "maximum weight"
// depending on small user-parameter "epsilon".
// It creates and uses 2 histograms of the TH1D class.
// User defines no. of bins nBin,  nBin=1000 is  recommended
// wmax defines weight range (1,wmax), it is adjusted "manually"
//
//____________________________________________________________________________

#include "Riostream.h"
#include "TMath.h"
#include "TH1.h"
#include "TFoamMaxwt.h"

ClassImp(TFoamMaxwt);

//____________________________________________________________________________
TFoamMaxwt::TFoamMaxwt()
{
// Constructor for streamer
  fNent = 0;
  fnBin = 0;
  fWtHst1 = 0;
  fWtHst2 = 0;
}

//____________________________________________________________________________
TFoamMaxwt::TFoamMaxwt(Double_t wmax, Int_t nBin)
{
// Principal user constructor
  fNent = 0;
  fnBin = nBin;
  fwmax = wmax;
  fWtHst1 = new TH1D("TFoamMaxwt_hst_Wt1","Histo of weight   ",nBin,0.0,wmax);
  fWtHst2 = new TH1D("TFoamMaxwt_hst_Wt2","Histo of weight**2",nBin,0.0,wmax);
  fWtHst1->SetDirectory(0);// exclude from diskfile
  fWtHst2->SetDirectory(0);// and enable deleting
}

//______________________________________________________________________________
TFoamMaxwt::TFoamMaxwt(TFoamMaxwt &From): TObject(From)
{
// Explicit COPY CONSTRUCTOR (unused, so far)
  fnBin   = From.fnBin;
  fwmax   = From.fwmax;
  fWtHst1 = From.fWtHst1;
  fWtHst2 = From.fWtHst2;
  Error("TFoamMaxwt","COPY CONSTRUCTOR NOT TESTED!");
}

//_______________________________________________________________________________
TFoamMaxwt::~TFoamMaxwt()
{
// Destructor
  delete fWtHst1; // For this SetDirectory(0) is needed!
  delete fWtHst2; //
  fWtHst1=0;
  fWtHst2=0;
}
//_______________________________________________________________________________
void TFoamMaxwt::Reset()
{
// Reseting weight analysis
  fNent = 0;
  fWtHst1->Reset();
  fWtHst2->Reset();
}

//_______________________________________________________________________________
TFoamMaxwt& TFoamMaxwt::operator =(TFoamMaxwt &From)
{
// substitution =
  if (&From == this) return *this;
  fnBin = From.fnBin;
  fwmax = From.fwmax;
  fWtHst1 = From.fWtHst1;
  fWtHst2 = From.fWtHst2;
  return *this;
}

//________________________________________________________________________________
void TFoamMaxwt::Fill(Double_t wt)
{
// Filling analysed weight
  fNent =  fNent+1.0;
  fWtHst1->Fill(wt,1.0);
  fWtHst2->Fill(wt,wt);
}

//________________________________________________________________________________
void TFoamMaxwt::Make(Double_t eps, Double_t &MCeff)
{
// Calculates Efficiency= AveWt/WtLim for a given tolerance level epsilon<<1
// To be called at the end of the MC run.

  Double_t WtLim,AveWt;
  GetMCeff(eps, MCeff, WtLim);
  AveWt = MCeff*WtLim;
  cout<< "00000000000000000000000000000000000000000000000000000000000000000000000"<<endl;
  cout<< "00 -->WtLim: No_evt ="<<fNent<<"   <Wt> = "<<AveWt<<"  WtLim=  "<<WtLim<<endl;
  cout<< "00 -->WtLim: For eps = "<<eps  <<"    EFFICIENCY <Wt>/WtLim= "<<MCeff<<endl;
  cout<< "00000000000000000000000000000000000000000000000000000000000000000000000"<<endl;
}

//_________________________________________________________________________________
void TFoamMaxwt::GetMCeff(Double_t eps, Double_t &MCeff, Double_t &WtLim)
{
// Calculates Efficiency= AveWt/WtLim for a given tolerance level epsilon<<1
// using information stored in two histograms.
// To be called at the end of the MC run.

  Int_t ib,ibX;
  Double_t LowEdge,Bin,Bin1;
  Double_t AveWt, AveWt1;

  fWtHst1->Print();
  fWtHst2->Print();

// Convention on bin-numbering: nb=1 for 1-st bin, undeflow nb=0, overflow nb=Nb+1
  Double_t sum   = 0.0;
  Double_t sumWt = 0.0;
  for(ib=0;ib<=fnBin+1;ib++){
    sum   += fWtHst1->GetBinContent(ib);
    sumWt += fWtHst2->GetBinContent(ib);
  }
  if( (sum == 0.0) || (sumWt == 0.0) ){
    cout<<"TFoamMaxwt::Make: zero content of histogram !!!,sum,sumWt ="<<sum<<sumWt<<endl;
  }
  AveWt = sumWt/sum;
  //--------------------------------------
  for( ibX=fnBin+1; ibX>0; ibX--){
    LowEdge = (ibX-1.0)*fwmax/fnBin;
    sum   = 0.0;
    sumWt = 0.0;
    for( ib=0; ib<=fnBin+1; ib++){
      Bin  = fWtHst1->GetBinContent(ib);
      Bin1 = fWtHst2->GetBinContent(ib);
      if(ib >= ibX) Bin1=LowEdge*Bin;
      sum   += Bin;
      sumWt += Bin1;
    }
    AveWt1 = sumWt/sum;
    if( TMath::Abs(1.0-AveWt1/AveWt) > eps ) break;
  }
  //---------------------------
  if(ibX == (fnBin+1) ){
    WtLim = 1.0e200;
    MCeff   = 0.0;
    cout<< "+++++ WtLim undefined. Higher uper limit in histogram"<<endl;
  }else if( ibX == 1){
    WtLim = 0.0;
    MCeff   =-1.0;
    cout<< "+++++ WtLim undefined. Lower uper limit or more bins "<<endl;
  }else{
    WtLim= (ibX)*fwmax/fnBin; // We over-estimate WtLim, under-estimate MCeff
    MCeff  = AveWt/WtLim;
  }
}
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//      End of    Class  TFoamMaxwt                                          //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include "brawlmd5.h"
#include "brawlextract.h"
#include "find_children.h"
#include "usage.h"

using namespace System;
using namespace System::Collections::Generic;
using namespace System::ComponentModel;
using namespace System::IO;
using namespace System::Reflection;
using namespace System::Text::RegularExpressions;
using namespace BrawlLib::SSBB::ResourceNodes;
using BrawlLS::MD5;

int usage(String^ error_msg) {
	if (error_msg->Length != 0) Console::Error->WriteLine(error_msg + "\n");
	Console::Error->WriteLine(gcnew String(usage_line));
	Console::Error->WriteLine(gcnew String(usage_help_line));
	return 1;
}

enum class MDL0PrintType {
	ALWAYS, NEVER, SELECTIVE
};

enum class ProgramBehavior {
	UNDEFINED, NORMAL, EXTRACT_ALL
};

template < class T, class U >
Boolean isinst(U u) {
	return dynamic_cast< T >(u) != nullptr;
}

void print_recursive(TextWriter^ outstream,
	String^ format, String^ prefix, ResourceNode^ node,
	MDL0PrintType modelsDeep, bool stpmValues, bool isRoot, int maxdepth);
void printf_obj(TextWriter^ outstream, String^ format, String^ prefix, Object^ obj);
void print_properties(TextWriter^ outstream, String^ prefix, ResourceNode^ node);

int brawlls(array<String^>^ args, TextWriter^ outwriter) {
	if (args->Length == 0) {
		return usage("");
	}

	String^ filename;
	String^ nodepath;
	String^ format;
	MDL0PrintType modelsDeep = MDL0PrintType::SELECTIVE; // --mdl0, --no-mdl0

	// affects printout only
	bool recursive = false, // -R
		stpmValues = true, // --stpm, --no-stpm
		boneValues = true, // --bone, --no-bone
		showtype = false, // -t
		printSelf = false, // -d, --self
		printMD5 = false, // -m
		fullpath = false; // --full-path

	// affects node search
	bool searchChildren = false; // -c

	ProgramBehavior behavior = ProgramBehavior::UNDEFINED;
	List<String^> behavior_arguments; // arguments not otherwise defined that come after the behavior

	for each(String^ argument in args) {
		if (argument == "--help" || argument == "/?") {
			Console::WriteLine(gcnew String(usage_line));
			Console::WriteLine(gcnew String(usage_desc));
			return 0;
		}
		if (argument == "--formathelp") {
			Console::WriteLine(gcnew String(format_help));
			return 0;
		}
		if (argument == "--xallhelp") {
			Console::WriteLine(gcnew String(xall_help));
			return 0;
		}
		if (argument == "--self") printSelf = true;
		else if (argument == "--stpm") stpmValues = true;
		else if (argument == "--no-stpm") stpmValues = false;
		else if (argument == "--bone") boneValues = true;
		else if (argument == "--no-bone") boneValues = false;
		else if (argument == "--mdl0") modelsDeep = MDL0PrintType::ALWAYS;
		else if (argument == "--no-mdl0") modelsDeep = MDL0PrintType::NEVER;
		else if (argument == "--full-path") fullpath = true;
		else if (argument->StartsWith("--format=")) format = argument->Substring(9);
		else if (argument->StartsWith("-") && argument->Length > 1) {
			for each(char c in argument->Substring(1)) {
				if (c == 'd') printSelf = true;
				else if (c == 'R') recursive = true;
				else if (c == 't') showtype = true;
				else if (c == 'm') printMD5 = true;
				else if (c == 'c') searchChildren = true;
				else {
					return usage("Invalid argument: " + argument);
				}
			}
		} else {
			if (filename == nullptr) filename = argument;
			else if (behavior == ProgramBehavior::UNDEFINED && argument == "xall") behavior = ProgramBehavior::EXTRACT_ALL;
			else if (behavior != ProgramBehavior::UNDEFINED) behavior_arguments.Add(argument);
			else if (nodepath == nullptr) nodepath = argument;
			else return usage("Error: too many arguments: " + filename + " " + nodepath + " " + argument);
		}
	}
	if (behavior == ProgramBehavior::UNDEFINED) behavior = ProgramBehavior::NORMAL;

	if (filename == "-") {
		String^ tmpfile = Path::GetTempFileName();
		Stream^ stdin = Console::OpenStandardInput();
		Stream^ outstream = gcnew FileStream(tmpfile, FileMode::Create, FileAccess::Write);
		array<unsigned char>^ buffer = gcnew array<unsigned char>(2048);
		int bytes;
		while ((bytes = stdin->Read(buffer, 0, buffer->Length)) > 0) {
			outstream->Write(buffer, 0, bytes);
		}
		outstream->Close();
		filename = tmpfile;
	}

	if (filename == nullptr) return usage("Error: no filename given.");
	if (!File::Exists(filename)) return usage("Error: file not found: " + filename);

	if (format == nullptr) {
		format = "%~+%i" +
			(fullpath ? " %p" : " %n") +
			(showtype ? " %t" : "") +
			(boneValues ? " %b" : "") +
			(printMD5 ? " %m" : "");
	}

	ResourceNode^ node = NodeFactory::FromFile(nullptr, filename);
	List<ResourceNode^> matchingNodes;
	find_children(node, nodepath, %matchingNodes, searchChildren);

	if (matchingNodes.Count == 0) return usage("No nodes found matching path: " + nodepath);

	if (behavior == ProgramBehavior::NORMAL && printSelf) {
		for each(ResourceNode^ child in matchingNodes) {
			printf_obj(outwriter, format, "", child);
		}
	} else if (matchingNodes.Count > 1) {
		Console::Error->WriteLine("Search matched " + matchingNodes.Count + " nodes. Use -d or --self to list them.");
		return 1;
	} else if (behavior == ProgramBehavior::EXTRACT_ALL) {
		if (behavior_arguments.Count == 0) {
			Console::Error->WriteLine("Error: no output directory specified");
			Console::Error->WriteLine(gcnew String(xall_help));
			return 1;
		}
		return extract_all(matchingNodes[0], %behavior_arguments);
	} else if (matchingNodes[0]->Children->Count == 0) {
		Console::Error->WriteLine("The node " + matchingNodes[0]->Name + " does not have any children.");
		return 0;
	} else {
		int maxdepth = recursive ? -1 : 1;
		print_recursive(outwriter, format, "", matchingNodes[0], modelsDeep, stpmValues, true, maxdepth);
	}
}

int main(array<String^>^ args) {
	brawlls(args, Console::Out);
}

void print_recursive(TextWriter^ outstream, String^ format, String^ prefix, ResourceNode^ node, MDL0PrintType modelsDeep, bool stpmValues, bool isRoot, int maxdepth) {
	if (!isRoot) {
		printf_obj(outstream, format, prefix, node);
		prefix += "  ";
	}

	if (maxdepth == 0) return;

	if (isinst<STPMEntryNode^>(node) && stpmValues) {
		print_properties(outstream, prefix, node);
	} else {
		if (isinst<MDL0Node^>(node)) {
			if (modelsDeep == MDL0PrintType::NEVER) {
				return;
			} else if (modelsDeep == MDL0PrintType::SELECTIVE && !isRoot && !node->Name->EndsWith("osition")) {
				return;
			}
		}

		int newdepth = maxdepth < 0
			? -1
			: maxdepth - 1;
		for each(ResourceNode^ child in node->Children) {
			print_recursive(outstream, format, prefix, child, modelsDeep, stpmValues, false, newdepth);
		}
	}
	delete node; // calls Dispose(). this may improve performance slightly, but we can't use these nodes later in the program
}

void printf_obj(TextWriter^ outstream, String^ format, String^ prefix, Object^ obj) {
	String^ name = obj == nullptr
		? "null"
		: obj->ToString();
	String^ bone = "";
	if (isinst<MDL0BoneNode^>(obj)) {
		MDL0BoneNode^ b = (MDL0BoneNode^)obj;
		bone = "T" + b->Translation;
		bone += " R" + b->Rotation;
		bone += " S" + b->Scale;
	}
	String^ index = "";
	String^ md5 = "";
	String^ size = "";
	String^ path = "";
	if (isinst<ResourceNode^>(obj)) {
		ResourceNode^ node = (ResourceNode^)obj;
		if (format->Contains("%m")) { // don't do this if we don't need the data - this does save some time
			if (isinst<MDL0GroupNode^>(node) || isinst<BRESGroupNode^>(node)) {
				// concat children data and use that instead
				md5 = "Children:" + MD5::MD5Str(node->Children);
			} else if (isinst<BRESEntryNode^>(node)) {
				String^ tmp = Path::GetTempFileName();
				node->Export(tmp);
				md5 = "MD5(Ex):" + MD5::MD5Str(tmp);
				File::Delete(tmp);
			} else {
				md5 = "MD5:" + MD5::MD5Str(node);
			}
		}
		index = node->Index + "";
		size = node->OriginalSource.Length + "";
		while (node->Parent != nullptr) {
			path = node->Name + "/" + path;
			node = node->Parent;
		}
		if (path->EndsWith("/")) path = path->Substring(0, path->Length - 1);
	}
	String^ line = format
		->Replace("%~", prefix)
		->Replace("%n", name)
		->Replace("%p", path)
		->Replace("%i", index)
		->Replace("%t", "(" + obj->GetType()->Name + ")")
		->Replace("%b", bone)
		->Replace("%m", md5)
		->Replace("%s", size)
		->Replace("%%", "%");
	outstream->WriteLine(line);
}

void print_properties(TextWriter^ outstream, String^ prefix, ResourceNode^ node) {
	for each(PropertyInfo^ entry in node->GetType()->GetProperties()) {
		for each(Attribute^ attribute in entry->GetCustomAttributes(false)) {
			if (isinst<CategoryAttribute^>(attribute)) {
				Object^ val = entry->GetValue(node, nullptr);
				String^ valstr = val == nullptr
					? "null"
					: val->ToString();
				outstream->WriteLine(prefix + entry->Name + " " + valstr);
			}
		}
	}
}
<commit_msg>Remove export behavior - no longer needed - leads to major speedup<commit_after>#include "brawlmd5.h"
#include "brawlextract.h"
#include "find_children.h"
#include "usage.h"

using namespace System;
using namespace System::Collections::Generic;
using namespace System::ComponentModel;
using namespace System::IO;
using namespace System::Reflection;
using namespace System::Text::RegularExpressions;
using namespace BrawlLib::SSBB::ResourceNodes;
using BrawlLS::MD5;

int usage(String^ error_msg) {
	if (error_msg->Length != 0) Console::Error->WriteLine(error_msg + "\n");
	Console::Error->WriteLine(gcnew String(usage_line));
	Console::Error->WriteLine(gcnew String(usage_help_line));
	return 1;
}

enum class MDL0PrintType {
	ALWAYS, NEVER, SELECTIVE
};

enum class ProgramBehavior {
	UNDEFINED, NORMAL, EXTRACT_ALL
};

template < class T, class U >
Boolean isinst(U u) {
	return dynamic_cast< T >(u) != nullptr;
}

void print_recursive(TextWriter^ outstream,
	String^ format, String^ prefix, ResourceNode^ node,
	MDL0PrintType modelsDeep, bool stpmValues, bool isRoot, int maxdepth);
void printf_obj(TextWriter^ outstream, String^ format, String^ prefix, Object^ obj);
void print_properties(TextWriter^ outstream, String^ prefix, ResourceNode^ node);

int brawlls(array<String^>^ args, TextWriter^ outwriter) {
	if (args->Length == 0) {
		return usage("");
	}

	String^ filename;
	String^ nodepath;
	String^ format;
	MDL0PrintType modelsDeep = MDL0PrintType::SELECTIVE; // --mdl0, --no-mdl0

	// affects printout only
	bool recursive = false, // -R
		stpmValues = true, // --stpm, --no-stpm
		boneValues = true, // --bone, --no-bone
		showtype = false, // -t
		printSelf = false, // -d, --self
		printMD5 = false, // -m
		fullpath = false; // --full-path

	// affects node search
	bool searchChildren = false; // -c

	ProgramBehavior behavior = ProgramBehavior::UNDEFINED;
	List<String^> behavior_arguments; // arguments not otherwise defined that come after the behavior

	for each(String^ argument in args) {
		if (argument == "--help" || argument == "/?") {
			Console::WriteLine(gcnew String(usage_line));
			Console::WriteLine(gcnew String(usage_desc));
			return 0;
		}
		if (argument == "--formathelp") {
			Console::WriteLine(gcnew String(format_help));
			return 0;
		}
		if (argument == "--xallhelp") {
			Console::WriteLine(gcnew String(xall_help));
			return 0;
		}
		if (argument == "--self") printSelf = true;
		else if (argument == "--stpm") stpmValues = true;
		else if (argument == "--no-stpm") stpmValues = false;
		else if (argument == "--bone") boneValues = true;
		else if (argument == "--no-bone") boneValues = false;
		else if (argument == "--mdl0") modelsDeep = MDL0PrintType::ALWAYS;
		else if (argument == "--no-mdl0") modelsDeep = MDL0PrintType::NEVER;
		else if (argument == "--full-path") fullpath = true;
		else if (argument->StartsWith("--format=")) format = argument->Substring(9);
		else if (argument->StartsWith("-") && argument->Length > 1) {
			for each(char c in argument->Substring(1)) {
				if (c == 'd') printSelf = true;
				else if (c == 'R') recursive = true;
				else if (c == 't') showtype = true;
				else if (c == 'm') printMD5 = true;
				else if (c == 'c') searchChildren = true;
				else {
					return usage("Invalid argument: " + argument);
				}
			}
		} else {
			if (filename == nullptr) filename = argument;
			else if (behavior == ProgramBehavior::UNDEFINED && argument == "xall") behavior = ProgramBehavior::EXTRACT_ALL;
			else if (behavior != ProgramBehavior::UNDEFINED) behavior_arguments.Add(argument);
			else if (nodepath == nullptr) nodepath = argument;
			else return usage("Error: too many arguments: " + filename + " " + nodepath + " " + argument);
		}
	}
	if (behavior == ProgramBehavior::UNDEFINED) behavior = ProgramBehavior::NORMAL;

	if (filename == "-") {
		String^ tmpfile = Path::GetTempFileName();
		Stream^ stdin = Console::OpenStandardInput();
		Stream^ outstream = gcnew FileStream(tmpfile, FileMode::Create, FileAccess::Write);
		array<unsigned char>^ buffer = gcnew array<unsigned char>(2048);
		int bytes;
		while ((bytes = stdin->Read(buffer, 0, buffer->Length)) > 0) {
			outstream->Write(buffer, 0, bytes);
		}
		outstream->Close();
		filename = tmpfile;
	}

	if (filename == nullptr) return usage("Error: no filename given.");
	if (!File::Exists(filename)) return usage("Error: file not found: " + filename);

	if (format == nullptr) {
		format = "%~+%i" +
			(fullpath ? " %p" : " %n") +
			(showtype ? " %t" : "") +
			(boneValues ? " %b" : "") +
			(printMD5 ? " %m" : "");
	}

	ResourceNode^ node = NodeFactory::FromFile(nullptr, filename);
	List<ResourceNode^> matchingNodes;
	find_children(node, nodepath, %matchingNodes, searchChildren);

	if (matchingNodes.Count == 0) return usage("No nodes found matching path: " + nodepath);

	if (behavior == ProgramBehavior::NORMAL && printSelf) {
		for each(ResourceNode^ child in matchingNodes) {
			printf_obj(outwriter, format, "", child);
		}
	} else if (matchingNodes.Count > 1) {
		Console::Error->WriteLine("Search matched " + matchingNodes.Count + " nodes. Use -d or --self to list them.");
		return 1;
	} else if (behavior == ProgramBehavior::EXTRACT_ALL) {
		if (behavior_arguments.Count == 0) {
			Console::Error->WriteLine("Error: no output directory specified");
			Console::Error->WriteLine(gcnew String(xall_help));
			return 1;
		}
		return extract_all(matchingNodes[0], %behavior_arguments);
	} else if (matchingNodes[0]->Children->Count == 0) {
		Console::Error->WriteLine("The node " + matchingNodes[0]->Name + " does not have any children.");
		return 0;
	} else {
		int maxdepth = recursive ? -1 : 1;
		print_recursive(outwriter, format, "", matchingNodes[0], modelsDeep, stpmValues, true, maxdepth);
	}
}

int main(array<String^>^ args) {
	brawlls(args, Console::Out);
}

void print_recursive(TextWriter^ outstream, String^ format, String^ prefix, ResourceNode^ node, MDL0PrintType modelsDeep, bool stpmValues, bool isRoot, int maxdepth) {
	if (!isRoot) {
		printf_obj(outstream, format, prefix, node);
		prefix += "  ";
	}

	if (maxdepth == 0) return;

	if (isinst<STPMEntryNode^>(node) && stpmValues) {
		print_properties(outstream, prefix, node);
	} else {
		if (isinst<MDL0Node^>(node)) {
			if (modelsDeep == MDL0PrintType::NEVER) {
				return;
			} else if (modelsDeep == MDL0PrintType::SELECTIVE && !isRoot && !node->Name->EndsWith("osition")) {
				return;
			}
		}

		int newdepth = maxdepth < 0
			? -1
			: maxdepth - 1;
		for each(ResourceNode^ child in node->Children) {
			print_recursive(outstream, format, prefix, child, modelsDeep, stpmValues, false, newdepth);
		}
	}
	delete node; // calls Dispose(). this may improve performance slightly, but we can't use these nodes later in the program
}

void printf_obj(TextWriter^ outstream, String^ format, String^ prefix, Object^ obj) {
	String^ name = obj == nullptr
		? "null"
		: obj->ToString();
	String^ bone = "";
	if (isinst<MDL0BoneNode^>(obj)) {
		MDL0BoneNode^ b = (MDL0BoneNode^)obj;
		bone = "T" + b->Translation;
		bone += " R" + b->Rotation;
		bone += " S" + b->Scale;
	}
	String^ index = "";
	String^ md5 = "";
	String^ size = "";
	String^ path = "";
	if (isinst<ResourceNode^>(obj)) {
		ResourceNode^ node = (ResourceNode^)obj;
		if (format->Contains("%m")) { // don't do this if we don't need the data - this does save some time
			if (isinst<MDL0GroupNode^>(node) || isinst<BRESGroupNode^>(node)) {
				// concat children data and use that instead
				md5 = "Children:" + MD5::MD5Str(node->Children);
			} else {
				md5 = "MD5:" + MD5::MD5Str(node);
			}
		}
		index = node->Index + "";
		size = node->OriginalSource.Length + "";
		while (node->Parent != nullptr) {
			path = node->Name + "/" + path;
			node = node->Parent;
		}
		if (path->EndsWith("/")) path = path->Substring(0, path->Length - 1);
	}
	String^ line = format
		->Replace("%~", prefix)
		->Replace("%n", name)
		->Replace("%p", path)
		->Replace("%i", index)
		->Replace("%t", "(" + obj->GetType()->Name + ")")
		->Replace("%b", bone)
		->Replace("%m", md5)
		->Replace("%s", size)
		->Replace("%%", "%");
	outstream->WriteLine(line);
}

void print_properties(TextWriter^ outstream, String^ prefix, ResourceNode^ node) {
	for each(PropertyInfo^ entry in node->GetType()->GetProperties()) {
		for each(Attribute^ attribute in entry->GetCustomAttributes(false)) {
			if (isinst<CategoryAttribute^>(attribute)) {
				Object^ val = entry->GetValue(node, nullptr);
				String^ valstr = val == nullptr
					? "null"
					: val->ToString();
				outstream->WriteLine(prefix + entry->Name + " " + valstr);
			}
		}
	}
}
<|endoftext|>


<commit_before>
<commit_msg>Delete 1.cpp<commit_after><|endoftext|>


<commit_before>#include "win32.h"

#include <time.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
#include <io.h>
#include <stdlib.h>

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

// implementation from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
namespace CVD {

long long get_time_of_day_ns()
{
    FILETIME ft;
    long long tmpres = 0;
    static int tzflag;

	//Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
	GetSystemTimeAsFileTime(&ft);

	tmpres |= ft.dwHighDateTime;
	tmpres <<= 32;
	tmpres |= ft.dwLowDateTime;

	//tempres is in 100ns increments
	//Convert it to ns
	tmpres *= 100

	/*converting file time to unix epoch*/
	tmpres -= DELTA_EPOCH_IN_MICROSECS * (long long)1000;

    return tmpres;
}

namespace Internal {

void * aligned_alloc(size_t count, size_t alignment){
    return _aligned_malloc(count, alignment);
}

void aligned_free(void * memory){
    _aligned_free(memory);
}

} // namespace Internal

// returns path component from a general path string
static std::string get_path( const std::string & p){
	char drive[_MAX_DRIVE];
	char dir[_MAX_DIR];
	char out[1024];

	errno_t ret = _splitpath_s(p.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
	assert(0 == ret);
	_makepath(out, drive, dir, NULL, NULL);
	return std::string(out);
}

// simple implementation of globlist after MSDN example for _findfirst
std::vector<std::string> globlist(const std::string& gl)
{
	std::vector<std::string> ret;

	struct _finddatai64_t c_file;
	intptr_t hFile;

	// get the path component to stick it to the front again
	const std::string path = get_path(gl);

	// Find first file in current directory
	if( (hFile = _findfirsti64( gl.c_str(), &c_file )) != -1L ){
		do {
			ret.push_back(path + c_file.name);
		} while( _findnexti64( hFile, &c_file ) == 0 );
		_findclose( hFile );
	}
	std::sort(ret.begin(), ret.end());
	return ret;
}

} // namespace CVD
<commit_msg>Fix minor compile error.<commit_after>#include "win32.h"

#include <time.h>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
#include <io.h>
#include <stdlib.h>

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

// implementation from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
namespace CVD {

long long get_time_of_day_ns()
{
    FILETIME ft;
    long long tmpres = 0;
    static int tzflag;

	//Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
	GetSystemTimeAsFileTime(&ft);

	tmpres |= ft.dwHighDateTime;
	tmpres <<= 32;
	tmpres |= ft.dwLowDateTime;

	//tempres is in 100ns increments
	//Convert it to ns
	tmpres *= 100;

	/*converting file time to unix epoch*/
	tmpres -= DELTA_EPOCH_IN_MICROSECS * (long long)1000;

    return tmpres;
}

namespace Internal {

void * aligned_alloc(size_t count, size_t alignment){
    return _aligned_malloc(count, alignment);
}

void aligned_free(void * memory){
    _aligned_free(memory);
}

} // namespace Internal

// returns path component from a general path string
static std::string get_path( const std::string & p){
	char drive[_MAX_DRIVE];
	char dir[_MAX_DIR];
	char out[1024];

	errno_t ret = _splitpath_s(p.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
	assert(0 == ret);
	_makepath(out, drive, dir, NULL, NULL);
	return std::string(out);
}

// simple implementation of globlist after MSDN example for _findfirst
std::vector<std::string> globlist(const std::string& gl)
{
	std::vector<std::string> ret;

	struct _finddatai64_t c_file;
	intptr_t hFile;

	// get the path component to stick it to the front again
	const std::string path = get_path(gl);

	// Find first file in current directory
	if( (hFile = _findfirsti64( gl.c_str(), &c_file )) != -1L ){
		do {
			ret.push_back(path + c_file.name);
		} while( _findnexti64( hFile, &c_file ) == 0 );
		_findclose( hFile );
	}
	std::sort(ret.begin(), ret.end());
	return ret;
}

} // namespace CVD
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "cmd_pub.h"

#include <fcntl.h>

#include <string>
#include <vector>

#include "download.h"
#include "manifest.h"
#include "notify/messages.h"
#include "notify/publisher_http.h"
#include "util/pointer.h"
#include "util/posix.h"
#include "util/string.h"

namespace {

const LogFacilities& kLogInfo = DefaultLogging::info;
const LogFacilities& kLogError = DefaultLogging::error;

const int kMaxPoolHandles = 1;
const bool kUseSystemPorxy = true;
const unsigned kDownloadTimeout = 60;  // 1 minute
const unsigned kDownloadRetries = 1;   // 2 attempts in total

}  // namespace

namespace notify {

int DoPublish(const std::string& server_url, const std::string& repository_url,
              bool verbose) {
  const std::string repo_url = MakeCanonicalPath(repository_url);

  LogCvmfs(kLogCvmfs, kLogInfo, "Parameters: ");
  LogCvmfs(kLogCvmfs, kLogInfo, "  CVMFS repository URL: %s",
           repo_url.c_str());
  LogCvmfs(kLogCvmfs, kLogInfo, "  Notification server URL: %s",
           server_url.c_str());

  // Extract repository name from repository URL
  const std::vector<std::string> repo_url_tokens = SplitString(repo_url, '/');
  const std::string repository_name = repo_url_tokens.back();

  // Download repository manifest
  std::string manifest_contents;
  const std::string manifest_url = repo_url + "/.cvmfspublished";
  if (HasPrefix(repo_url, "http://", false)) {
    perf::Statistics stats;
    UniquePtr<download::DownloadManager> download_manager(
        new download::DownloadManager());
    assert(download_manager.IsValid());
    download_manager->Init(kMaxPoolHandles, kUseSystemPorxy,
                           perf::StatisticsTemplate("download", &stats));

    download_manager->SetTimeout(kDownloadTimeout, kDownloadTimeout);
    download_manager->SetRetryParameters(kDownloadRetries, 500, 2000);

    download::JobInfo download_manifest(&manifest_url, false, false, NULL);
    download::Failures retval = download_manager->Fetch(&download_manifest);
    if (retval != download::kFailOk) {
      LogCvmfs(kLogCvmfs, kLogError, "Failed to download manifest (%d - %s)",
               retval, download::Code2Ascii(retval));
      return 6;
    }
    manifest_contents = std::string(download_manifest.destination_mem.data,
                                    download_manifest.destination_mem.pos);
    free(download_manifest.destination_mem.data);
  } else {
    int fd = open(manifest_url.c_str(), O_RDONLY);
    if (fd == -1) {
      LogCvmfs(kLogCvmfs, kLogInfo, "Could not open manifest file");
      return 7;
    }
    if (!SafeReadToString(fd, &manifest_contents)) {
      LogCvmfs(kLogCvmfs, kLogInfo, "Could not read manifest file");
      close(fd);
      return 8;
    }
    close(fd);
  }

  UniquePtr<manifest::Manifest> manifest(manifest::Manifest::LoadMem(
      reinterpret_cast<const unsigned char*>(manifest_contents.data()),
      manifest_contents.size()));

  if (verbose) {
    LogCvmfs(kLogCvmfs, kLogInfo, "Current repository manifest:\n%s",
             manifest->ExportString().c_str());
  }

  // Publish message
  UniquePtr<notify::Publisher> publisher(new notify::PublisherHTTP(server_url));

  std::string msg_text;
  notify::msg::Activity msg;
  msg.version_ = 1;
  msg.timestamp_ = StringifyTime(std::time(NULL), true);
  msg.repository_ = repository_name;
  msg.manifest_ = manifest_contents;
  msg.ToJSONString(&msg_text);

  if (!publisher->Publish(msg_text, repository_name)) {
    LogCvmfs(kLogCvmfs, kLogError, "Could not publish notification");
    return 9;
  }

  assert(publisher->Finalize());

  return 0;
}

}  // namespace notify
<commit_msg>Fix memory leak<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "cmd_pub.h"

#include <fcntl.h>

#include <string>
#include <vector>

#include "download.h"
#include "manifest.h"
#include "notify/messages.h"
#include "notify/publisher_http.h"
#include "util/pointer.h"
#include "util/posix.h"
#include "util/string.h"

namespace {

const LogFacilities& kLogInfo = DefaultLogging::info;
const LogFacilities& kLogError = DefaultLogging::error;

const int kMaxPoolHandles = 1;
const bool kUseSystemPorxy = true;
const unsigned kDownloadTimeout = 60;  // 1 minute
const unsigned kDownloadRetries = 1;   // 2 attempts in total

}  // namespace

namespace notify {

int DoPublish(const std::string& server_url, const std::string& repository_url,
              bool verbose) {
  const std::string repo_url = MakeCanonicalPath(repository_url);

  LogCvmfs(kLogCvmfs, kLogInfo, "Parameters: ");
  LogCvmfs(kLogCvmfs, kLogInfo, "  CVMFS repository URL: %s",
           repo_url.c_str());
  LogCvmfs(kLogCvmfs, kLogInfo, "  Notification server URL: %s",
           server_url.c_str());

  // Extract repository name from repository URL
  const std::vector<std::string> repo_url_tokens = SplitString(repo_url, '/');
  const std::string repository_name = repo_url_tokens.back();

  // Download repository manifest
  std::string manifest_contents;
  const std::string manifest_url = repo_url + "/.cvmfspublished";
  if (HasPrefix(repo_url, "http://", false)) {
    perf::Statistics stats;
    UniquePtr<download::DownloadManager> download_manager(
        new download::DownloadManager());
    assert(download_manager.IsValid());
    download_manager->Init(kMaxPoolHandles, kUseSystemPorxy,
                           perf::StatisticsTemplate("download", &stats));

    download_manager->SetTimeout(kDownloadTimeout, kDownloadTimeout);
    download_manager->SetRetryParameters(kDownloadRetries, 500, 2000);

    download::JobInfo download_manifest(&manifest_url, false, false, NULL);
    download::Failures retval = download_manager->Fetch(&download_manifest);
    if (retval != download::kFailOk) {
      LogCvmfs(kLogCvmfs, kLogError, "Failed to download manifest (%d - %s)",
               retval, download::Code2Ascii(retval));
      download_manager->Fini();
      return 6;
    }
    manifest_contents = std::string(download_manifest.destination_mem.data,
                                    download_manifest.destination_mem.pos);
    free(download_manifest.destination_mem.data);
    download_manager->Fini();
  } else {
    int fd = open(manifest_url.c_str(), O_RDONLY);
    if (fd == -1) {
      LogCvmfs(kLogCvmfs, kLogInfo, "Could not open manifest file");
      return 7;
    }
    if (!SafeReadToString(fd, &manifest_contents)) {
      LogCvmfs(kLogCvmfs, kLogInfo, "Could not read manifest file");
      close(fd);
      return 8;
    }
    close(fd);
  }

  UniquePtr<manifest::Manifest> manifest(manifest::Manifest::LoadMem(
      reinterpret_cast<const unsigned char*>(manifest_contents.data()),
      manifest_contents.size()));

  if (verbose) {
    LogCvmfs(kLogCvmfs, kLogInfo, "Current repository manifest:\n%s",
             manifest->ExportString().c_str());
  }

  // Publish message
  UniquePtr<notify::Publisher> publisher(new notify::PublisherHTTP(server_url));

  std::string msg_text;
  notify::msg::Activity msg;
  msg.version_ = 1;
  msg.timestamp_ = StringifyTime(std::time(NULL), true);
  msg.repository_ = repository_name;
  msg.manifest_ = manifest_contents;
  msg.ToJSONString(&msg_text);

  if (!publisher->Publish(msg_text, repository_name)) {
    LogCvmfs(kLogCvmfs, kLogError, "Could not publish notification");
    return 9;
  }

  assert(publisher->Finalize());

  return 0;
}

}  // namespace notify
<|endoftext|>