<commit_before>// Copyright (c) 2012 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 "content/renderer/renderer_main_platform_delegate.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "content/common/sandbox_win.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/injection_test_win.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/render_thread_impl.h"
#include "sandbox/win/src/sandbox.h"
#include "skia/ext/vector_platform_device_emf_win.h"
#include "third_party/WebKit/public/web/win/WebFontRendering.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"

#ifdef ENABLE_VTUNE_JIT_INTERFACE
#include "v8/src/third_party/vtune/v8-vtune.h"
#endif

#include <dwrite.h>

namespace content {
namespace {

// Windows-only skia sandbox support
// These are used for GDI-path rendering.
void SkiaPreCacheFont(const LOGFONT& logfont) {
  RenderThread* render_thread = RenderThread::Get();
  if (render_thread) {
    render_thread->PreCacheFont(logfont);
  }
}

void SkiaPreCacheFontCharacters(const LOGFONT& logfont,
                                const wchar_t* text,
                                unsigned int text_length) {
  RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
  if (render_thread_impl) {
    render_thread_impl->PreCacheFontCharacters(
        logfont,
        base::string16(text, text_length));
  }
}

// Windows-only DirectWrite support. These warm up the DirectWrite paths
// before sandbox lock down to allow Skia access to the Font Manager service.
bool CreateDirectWriteFactory(IDWriteFactory** factory) {
  typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
  DWriteCreateFactoryProc dwrite_create_factory_proc =
      reinterpret_cast<DWriteCreateFactoryProc>(
          GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
  if (!dwrite_create_factory_proc)
    return false;
  CHECK(SUCCEEDED(
      dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
                                 __uuidof(IDWriteFactory),
                                 reinterpret_cast<IUnknown**>(factory))));
  return true;
}

void WarmupDirectWrite() {
  base::win::ScopedComPtr<IDWriteFactory> factory;
  if (!CreateDirectWriteFactory(factory.Receive()))
    return;

  base::win::ScopedComPtr<IDWriteFontCollection> font_collection;
  CHECK(SUCCEEDED(
      factory->GetSystemFontCollection(font_collection.Receive(), FALSE)));
  base::win::ScopedComPtr<IDWriteFontFamily> font_family;

  UINT32 index;
  BOOL exists;
  CHECK(SUCCEEDED(
      font_collection->FindFamilyName(L"Times New Roman", &index, &exists)));
  CHECK(exists);
  CHECK(
      SUCCEEDED(font_collection->GetFontFamily(index, font_family.Receive())));
  base::win::ScopedComPtr<IDWriteFont> font;
  base::win::ScopedComPtr<IDWriteFontFace> font_face;
  CHECK(SUCCEEDED(font_family->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
                                                    DWRITE_FONT_STRETCH_NORMAL,
                                                    DWRITE_FONT_STYLE_NORMAL,
                                                    font.Receive())));
  CHECK(SUCCEEDED(font->CreateFontFace(font_face.Receive())));
  DWRITE_GLYPH_METRICS gm;
  UINT16 glyph = L'S';
  CHECK(SUCCEEDED(font_face->GetDesignGlyphMetrics(&glyph, 1, &gm)));
}

}  // namespace

RendererMainPlatformDelegate::RendererMainPlatformDelegate(
    const MainFunctionParams& parameters)
        : parameters_(parameters),
          sandbox_test_module_(NULL) {
}

RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
}

void RendererMainPlatformDelegate::PlatformInitialize() {
  const CommandLine& command_line = parameters_.command_line;

#ifdef ENABLE_VTUNE_JIT_INTERFACE
  if (command_line.HasSwitch(switches::kEnableVtune))
    vTune::InitializeVtuneForV8();
#endif

  // Be mindful of what resources you acquire here. They can be used by
  // malicious code if the renderer gets compromised.
  bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);

  bool use_direct_write = ShouldUseDirectWrite();
  if (!no_sandbox) {
    // ICU DateFormat class (used in base/time_format.cc) needs to get the
    // Olson timezone ID by accessing the registry keys under
    // HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.
    // After TimeZone::createDefault is called once here, the timezone ID is
    // cached and there's no more need to access the registry. If the sandbox
    // is disabled, we don't have to make this dummy call.
    scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());

    if (use_direct_write) {
      WarmupDirectWrite();
    } else {
      SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
      skia::SetSkiaEnsureTypefaceCharactersAccessible(
          SkiaPreCacheFontCharacters);
    }
  }
  blink::WebFontRendering::setUseDirectWrite(use_direct_write);
  blink::WebFontRendering::setUseSubpixelPositioning(use_direct_write);
}

void RendererMainPlatformDelegate::PlatformUninitialize() {
}

bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
  const CommandLine& command_line = parameters_.command_line;

  DVLOG(1) << "Started renderer with " << command_line.GetCommandLineString();

  sandbox::TargetServices* target_services =
      parameters_.sandbox_info->target_services;

  if (target_services && !no_sandbox) {
      std::wstring test_dll_name =
          command_line.GetSwitchValueNative(switches::kTestSandbox);
    if (!test_dll_name.empty()) {
      sandbox_test_module_ = LoadLibrary(test_dll_name.c_str());
      DCHECK(sandbox_test_module_);
      if (!sandbox_test_module_) {
        return false;
      }
    }
  }
  return true;
}

bool RendererMainPlatformDelegate::EnableSandbox() {
  sandbox::TargetServices* target_services =
      parameters_.sandbox_info->target_services;

  if (target_services) {
    // Cause advapi32 to load before the sandbox is turned on.
    unsigned int dummy_rand;
    rand_s(&dummy_rand);
    // Warm up language subsystems before the sandbox is turned on.
    ::GetUserDefaultLangID();
    ::GetUserDefaultLCID();

    target_services->LowerToken();
    return true;
  }
  return false;
}

void RendererMainPlatformDelegate::RunSandboxTests(bool no_sandbox) {
  if (sandbox_test_module_) {
    RunRendererTests run_security_tests =
        reinterpret_cast<RunRendererTests>(GetProcAddress(sandbox_test_module_,
                                                          kRenderTestCall));
    DCHECK(run_security_tests);
    if (run_security_tests) {
      int test_count = 0;
      DVLOG(1) << "Running renderer security tests";
      BOOL result = run_security_tests(&test_count);
      CHECK(result) << "Test number " << test_count << " has failed.";
    }
  }
}

}  // namespace content
<commit_msg>Use skia warmup for DirectWrite<commit_after>// Copyright (c) 2012 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 "content/renderer/renderer_main_platform_delegate.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "content/common/sandbox_win.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/injection_test_win.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/render_thread_impl.h"
#include "sandbox/win/src/sandbox.h"
#include "skia/ext/vector_platform_device_emf_win.h"
#include "third_party/WebKit/public/web/win/WebFontRendering.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
#include "third_party/skia/include/ports/SkFontMgr.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"

#ifdef ENABLE_VTUNE_JIT_INTERFACE
#include "v8/src/third_party/vtune/v8-vtune.h"
#endif

#include <dwrite.h>

namespace content {
namespace {

// Windows-only skia sandbox support
// These are used for GDI-path rendering.
void SkiaPreCacheFont(const LOGFONT& logfont) {
  RenderThread* render_thread = RenderThread::Get();
  if (render_thread) {
    render_thread->PreCacheFont(logfont);
  }
}

void SkiaPreCacheFontCharacters(const LOGFONT& logfont,
                                const wchar_t* text,
                                unsigned int text_length) {
  RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
  if (render_thread_impl) {
    render_thread_impl->PreCacheFontCharacters(
        logfont,
        base::string16(text, text_length));
  }
}

// Windows-only DirectWrite support. These warm up the DirectWrite paths
// before sandbox lock down to allow Skia access to the Font Manager service.
void CreateDirectWriteFactory(IDWriteFactory** factory) {
  typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
  DWriteCreateFactoryProc dwrite_create_factory_proc =
      reinterpret_cast<DWriteCreateFactoryProc>(
          GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
  CHECK(dwrite_create_factory_proc);
  CHECK(SUCCEEDED(
      dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_ISOLATED,
                                 __uuidof(IDWriteFactory),
                                 reinterpret_cast<IUnknown**>(factory))));
}

void WarmupDirectWrite() {
  // The objects used here are intentionally not freed as we want the Skia
  // code to use these objects after warmup.
  IDWriteFactory* factory;
  CreateDirectWriteFactory(&factory);
  blink::WebFontRendering::setDirectWriteFactory(factory);
  SkFontMgr* fontmgr = SkFontMgr_New_DirectWrite(factory);
  SkTypeface* typeface = fontmgr->legacyCreateTypeface("Times New Roman", 0);
  SkPaint paint_warmup;
  paint_warmup.setTypeface(typeface);
  wchar_t glyph = L'S';
  paint_warmup.measureText(&glyph, 2);
}

}  // namespace

RendererMainPlatformDelegate::RendererMainPlatformDelegate(
    const MainFunctionParams& parameters)
        : parameters_(parameters),
          sandbox_test_module_(NULL) {
}

RendererMainPlatformDelegate::~RendererMainPlatformDelegate() {
}

void RendererMainPlatformDelegate::PlatformInitialize() {
  const CommandLine& command_line = parameters_.command_line;

#ifdef ENABLE_VTUNE_JIT_INTERFACE
  if (command_line.HasSwitch(switches::kEnableVtune))
    vTune::InitializeVtuneForV8();
#endif

  // Be mindful of what resources you acquire here. They can be used by
  // malicious code if the renderer gets compromised.
  bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);

  bool use_direct_write = ShouldUseDirectWrite();
  if (!no_sandbox) {
    // ICU DateFormat class (used in base/time_format.cc) needs to get the
    // Olson timezone ID by accessing the registry keys under
    // HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.
    // After TimeZone::createDefault is called once here, the timezone ID is
    // cached and there's no more need to access the registry. If the sandbox
    // is disabled, we don't have to make this dummy call.
    scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());

    if (use_direct_write) {
      WarmupDirectWrite();
    } else {
      SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
      skia::SetSkiaEnsureTypefaceCharactersAccessible(
          SkiaPreCacheFontCharacters);
    }
  }
  blink::WebFontRendering::setUseDirectWrite(use_direct_write);
  blink::WebFontRendering::setUseSubpixelPositioning(use_direct_write);
}

void RendererMainPlatformDelegate::PlatformUninitialize() {
}

bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) {
  const CommandLine& command_line = parameters_.command_line;

  DVLOG(1) << "Started renderer with " << command_line.GetCommandLineString();

  sandbox::TargetServices* target_services =
      parameters_.sandbox_info->target_services;

  if (target_services && !no_sandbox) {
      std::wstring test_dll_name =
          command_line.GetSwitchValueNative(switches::kTestSandbox);
    if (!test_dll_name.empty()) {
      sandbox_test_module_ = LoadLibrary(test_dll_name.c_str());
      DCHECK(sandbox_test_module_);
      if (!sandbox_test_module_) {
        return false;
      }
    }
  }
  return true;
}

bool RendererMainPlatformDelegate::EnableSandbox() {
  sandbox::TargetServices* target_services =
      parameters_.sandbox_info->target_services;

  if (target_services) {
    // Cause advapi32 to load before the sandbox is turned on.
    unsigned int dummy_rand;
    rand_s(&dummy_rand);
    // Warm up language subsystems before the sandbox is turned on.
    ::GetUserDefaultLangID();
    ::GetUserDefaultLCID();

    target_services->LowerToken();
    return true;
  }
  return false;
}

void RendererMainPlatformDelegate::RunSandboxTests(bool no_sandbox) {
  if (sandbox_test_module_) {
    RunRendererTests run_security_tests =
        reinterpret_cast<RunRendererTests>(GetProcAddress(sandbox_test_module_,
                                                          kRenderTestCall));
    DCHECK(run_security_tests);
    if (run_security_tests) {
      int test_count = 0;
      DVLOG(1) << "Running renderer security tests";
      BOOL result = run_security_tests(&test_count);
      CHECK(result) << "Test number " << test_count << " has failed.";
    }
  }
}

}  // namespace content
<|endoftext|>


<commit_before>#include "./assemble.h"

#include <png.h>

#include <fstream>
#include <tbb/mutex.h>

uint8_t* global_image;
int32_t* global_image_depth;
int32_t g_width;
int32_t g_height;
int32_t g_x_min = 0;
int32_t g_y_min = 0;
int32_t g_x_max = 0;
int32_t g_y_max = 0;
uint16_t g_header_size = 0;
std::string g_filename = "";

std::pair<int, int> projectCoords(std::pair<int, int> p, int phi) {
  if (phi == 0) return p;
  int cos_phi = phi % 2 - 1;
  if (!phi) cos_phi = 1;
  int sin_phi = phi % 2;
  if (phi == 3) sin_phi = -1;
  return std::make_pair(p.first * cos_phi - p.second * sin_phi,
                        p.first * sin_phi + p.second * cos_phi);
}

int render_tile(Image<uint8_t>& image,
                std::pair<int, int> projected) {
  uint16_t width = image.cols;
  uint16_t height = image.rows;

  static tbb::mutex render_mutex;

  for (size_t i = 0; i < 1u * width * height; ++i) {
    size_t index = i * 4;
    std::swap(image.data[index], image.data[index + 2]);
  }
  int32_t pos = (projected.second * g_width
               + projected.first) * 4;
  render_mutex.lock();
  if (g_filename.size()) {
    std::fstream pam(g_filename.c_str());
    pam.seekp(g_header_size + pos, std::ios_base::cur);
    for (size_t i = 0; i < height; ++i) {
      for (size_t j = 0; j < width; ++j) {
        if (image.data[i * width * 4 + j * 4 + 3] != 0 &&
            global_image_depth[pos >> 2] <= projected.second) {
          pam.write(reinterpret_cast<const char*>
                    (&(image.data[i * width * 4 + j * 4])), 4);
        } else {
          pam.seekp(4, std::ios_base::cur);
        }
      }
      pam.seekp((g_width - width) * 4, std::ios_base::cur);
    }
  } else {
    for (size_t i = 0; i < height; ++i) {
      for (size_t j = 0; j < width; ++j) {
        if (image.data[i * width * 4 + j * 4 + 3] != 0 &&
            global_image_depth[pos >> 2] <= projected.second) {
          std::copy(&image.data[i * width * 4 + j * 4],
                    &image.data[i * width * 4 + j * 4] + 4,
                    global_image + pos);
          global_image_depth[pos >> 2] = projected.second;
        }
        pos += 4;
      }
      pos += (g_width - width) * 4;
    }
  }
  render_mutex.unlock();
  return 0;
}

uint16_t writeHeader(std::string filename,
                   std::pair<int, int> min_norm,
                   std::pair<int, int> max_norm,
                   const nbt& bf) {
  if (bf.set().isometric) {
    g_width =  g_x_max - g_x_min + 64;
    g_height = g_y_max - g_y_min + 288;
  } else {
    g_width =  (max_norm.first - min_norm.first + 1) * 16;
    g_height = (max_norm.second - min_norm.second + 1) * 16;
    if (bf.set().oblique) g_height += 128;
  }
  uint16_t header_size = 0;
  if (filename.size()) {
    g_filename = filename;
    std::stringstream ss;
    ss << "P7\n"
       << "WIDTH "     << g_width << "\n"
       << "HEIGHT "    << g_height << "\n"
       << "DEPTH "     << 4 << "\n"
       << "MAXVAL "    << 255 << "\n"
       << "TUPLTYPE "  << "RGB_ALPHA" << "\n"
       << "ENDHDR"     << "\n";
    g_header_size = header_size = static_cast<uint16_t>(ss.str().size());
    std::ofstream pam(filename.c_str());
    pam << ss.str();

    pam.seekp(g_width * g_height * 4 - 1, std::ios_base::cur);
    pam.put('\0');
    global_image_depth = new int32_t[g_width * g_height];
  } else {
    global_image = new uint8_t[g_width * g_height * 4];
    global_image_depth = new int32_t[g_width * g_height];
  }
  return header_size;
}

void ApplyFoo::operator() (const tbb::blocked_range<std::vector<int>
                                                         ::iterator>& r) const {
  for(std::vector<int>::iterator j=r.begin(); j!=r.end(); ++j) {
    bool result = false;
    std::pair<int, int> bp = projectCoords(std::make_pair(*j, i_),
                                      (4 - bf_->set().rotate) % 4);
    Image<uint8_t> image = bf_->getImage(bp.first, bp.second, &result);
    if (!result) {
      continue;
    }
    *index_ += 1;
    bp = projectCoords(bp, bf_->set().rotate);
    int offset_x = (bp.first - min_norm_.first) * 16;
    int offset_y = (bp.second - min_norm_.second) * 16;
    if (bf_->set().isometric) {
      bp = std::make_pair(2 * bp.first - 2 * bp.second, bp.first + bp.second);
      offset_x = bp.first * 16 - g_x_min;
      offset_y = bp.second * 16 - g_y_min;
    }
    render_tile(image, std::make_pair(offset_x, offset_y));
  }
}
ApplyFoo::ApplyFoo(nbt* bf, int i, tbb::atomic<size_t>* index,
                   std::pair<int, int> min_norm)
        : bf_(bf), i_(i), index_(index), min_norm_(min_norm) {}

Settings getSettings() {
  Settings set;
  set.topview = true;
  set.oblique = false;
  set.isometric = false;
  set.heightmap = false;
  set.color = false;
  set.shadow_strength = 0;
  set.shadow_quality = true;
  set.shadow_quality_ultra = true;
  set.relief_strength = 0;
  set.sun_direction = 2;
  set.rotate = 1;
  set.nightmode = 0;
  set.sun_direction = (set.sun_direction + ((set.rotate + 3) % 4) * 2) % 8;
  set.shadow = set.shadow_strength;
  set.relief = set.relief_strength;
  return set;
}

void calculateMinMaxPoint(std::pair<int, int>& min_norm,
                          std::pair<int, int>& max_norm,
                          const nbt& bf) {
  std::pair<int, int> min(bf.xPos_min(), bf.zPos_min());
  std::pair<int, int> max(bf.xPos_max(), bf.zPos_max());
  min = projectCoords(min, bf.set().rotate);
  max = projectCoords(max, bf.set().rotate);
  min_norm = std::make_pair(std::min(min.first, max.first),
                            std::min(min.second, max.second));
  max_norm = std::make_pair(std::max(min.first, max.first),
                            std::max(min.second, max.second));
}

void pamToPng(std::string png_name) {
  FILE* pam = NULL;
  if (g_filename.size()) {
    pam = fopen(g_filename.c_str(), "rb");
    fseek(pam, g_header_size, SEEK_CUR);
  }
  FILE* out = fopen(png_name.c_str(), "wb");
  png_struct* pngP;
  png_info* infoP;
  pngP = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  infoP = png_create_info_struct(pngP);
  png_set_IHDR(pngP, infoP, static_cast<png_uint_32>(g_width),
                            static_cast<png_uint_32>(g_height), 8,
               PNG_COLOR_TYPE_RGB_ALPHA,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_DEFAULT,
               PNG_FILTER_TYPE_DEFAULT);
  png_init_io(pngP, out);
  png_write_info(pngP, infoP);

  png_byte* pngRow = new png_byte[g_width * 4];
  for (int32_t i = 0; i < g_height; ++i) {
    if (pam) {
      fread(pngRow, 4, static_cast<size_t>(g_width), pam);
    } else {
      std::copy(global_image + i * g_width * 4,
                global_image + (i + 1) * g_width * 4,
                pngRow);
    }
    png_write_row(pngP, pngRow);
  }
  delete[] pngRow;

  png_write_end(pngP, infoP);
  png_destroy_write_struct(&pngP, &infoP);
  fclose(out);
  if (pam) {
    fclose(pam);
    delete[] global_image_depth;
  } else {
    delete[] global_image;
    delete[] global_image_depth;
  }
}

size_t fillTiles(std::list<std::vector<int> >& tiles, const nbt& bf,
                 const std::pair<int, int>& min_norm,
                 const std::pair<int, int>& max_norm,
                 boost::progress_display& show_progress) {
  size_t tiles_nr = 0;
  std::list<std::vector<int> >::iterator it = tiles.begin();
  for (int i = min_norm.second; i <= max_norm.second; ++i) {
    for (int j = min_norm.first; j <= max_norm.first; ++j) {
      std::pair<int, int> p = projectCoords(std::make_pair(j, i),
                                            (4 - bf.set().rotate) % 4);
      boost::filesystem::path path;
      if (bf.exists(p.first, p.second, path)) {
        p = projectCoords(p, bf.set().rotate);
        it->push_back(p.first);
        if (bf.set().isometric) {
          p = std::make_pair(32 * p.first - 32 * p.second, 16 * (p.first + p.second));
        }
        if (p.first < g_x_min) {
          g_x_min = p.first;
        }
        if (p.second < g_y_min) {
          g_y_min = p.second;
        }
        if (p.first > g_x_max) {
          g_x_max = p.first;
        }
        if (p.second > g_y_max) {
          g_y_max = p.second;
        }
      }
    }
    tiles_nr += it->size();
    ++it;
    ++show_progress;
  }
  return tiles_nr;
}

<commit_msg>style in assemble.cpp/h<commit_after>#include "./assemble.h"

#include <png.h>

#include <fstream>
#include <tbb/mutex.h>

uint8_t* global_image;
int32_t* global_image_depth;
int32_t g_width;
int32_t g_height;
int32_t g_x_min = 0;
int32_t g_y_min = 0;
int32_t g_x_max = 0;
int32_t g_y_max = 0;
uint16_t g_header_size = 0;
std::string g_filename = "";

std::pair<int, int> projectCoords(std::pair<int, int> p, int phi) {
  if (phi == 0) return p;
  int cos_phi = phi % 2 - 1;
  if (!phi) cos_phi = 1;
  int sin_phi = phi % 2;
  if (phi == 3) sin_phi = -1;
  return std::make_pair(p.first * cos_phi - p.second * sin_phi,
                        p.first * sin_phi + p.second * cos_phi);
}

int render_tile(Image<uint8_t>& image,
                std::pair<int, int> projected) {
  uint16_t width = image.cols;
  uint16_t height = image.rows;

  static tbb::mutex render_mutex;

  for (size_t i = 0; i < 1u * width * height; ++i) {
    size_t index = i * 4;
    std::swap(image.data[index], image.data[index + 2]);
  }
  int32_t pos = (projected.second * g_width
               + projected.first) * 4;
  render_mutex.lock();
  if (g_filename.size()) {
    std::fstream pam(g_filename.c_str());
    pam.seekp(g_header_size + pos, std::ios_base::cur);
    for (size_t i = 0; i < height; ++i) {
      for (size_t j = 0; j < width; ++j) {
        if (image.data[i * width * 4 + j * 4 + 3] != 0 &&
            global_image_depth[pos >> 2] <= projected.second) {
          pam.write(reinterpret_cast<const char*>
                    (&(image.data[i * width * 4 + j * 4])), 4);
        } else {
          pam.seekp(4, std::ios_base::cur);
        }
      }
      pam.seekp((g_width - width) * 4, std::ios_base::cur);
    }
  } else {
    for (size_t i = 0; i < height; ++i) {
      for (size_t j = 0; j < width; ++j) {
        if (image.data[i * width * 4 + j * 4 + 3] != 0 &&
            global_image_depth[pos >> 2] <= projected.second) {
          std::copy(&image.data[i * width * 4 + j * 4],
                    &image.data[i * width * 4 + j * 4] + 4,
                    global_image + pos);
          global_image_depth[pos >> 2] = projected.second;
        }
        pos += 4;
      }
      pos += (g_width - width) * 4;
    }
  }
  render_mutex.unlock();
  return 0;
}

uint16_t writeHeader(std::string filename,
                   std::pair<int, int> min_norm,
                   std::pair<int, int> max_norm,
                   const nbt& bf) {
  if (bf.set().isometric) {
    g_width =  g_x_max - g_x_min + 64;
    g_height = g_y_max - g_y_min + 288;
  } else {
    g_width =  (max_norm.first - min_norm.first + 1) * 16;
    g_height = (max_norm.second - min_norm.second + 1) * 16;
    if (bf.set().oblique) g_height += 128;
  }
  uint16_t header_size = 0;
  if (filename.size()) {
    g_filename = filename;
    std::stringstream ss;
    ss << "P7\n"
       << "WIDTH "     << g_width << "\n"
       << "HEIGHT "    << g_height << "\n"
       << "DEPTH "     << 4 << "\n"
       << "MAXVAL "    << 255 << "\n"
       << "TUPLTYPE "  << "RGB_ALPHA" << "\n"
       << "ENDHDR"     << "\n";
    g_header_size = header_size = static_cast<uint16_t>(ss.str().size());
    std::ofstream pam(filename.c_str());
    pam << ss.str();

    pam.seekp(g_width * g_height * 4 - 1, std::ios_base::cur);
    pam.put('\0');
    global_image_depth = new int32_t[g_width * g_height];
  } else {
    global_image = new uint8_t[g_width * g_height * 4];
    global_image_depth = new int32_t[g_width * g_height];
  }
  return header_size;
}

void ApplyFoo::operator() (const tbb::blocked_range<std::vector<int>
                                                         ::iterator>& r) const {
  for (std::vector<int>::iterator j = r.begin(); j != r.end(); ++j) {
    bool result = false;
    std::pair<int, int> bp = projectCoords(std::make_pair(*j, i_),
                                      (4 - bf_->set().rotate) % 4);
    Image<uint8_t> image = bf_->getImage(bp.first, bp.second, &result);
    if (!result) {
      continue;
    }
    *index_ += 1;
    bp = projectCoords(bp, bf_->set().rotate);
    int offset_x = (bp.first - min_norm_.first) * 16;
    int offset_y = (bp.second - min_norm_.second) * 16;
    if (bf_->set().isometric) {
      bp = std::make_pair(2 * bp.first - 2 * bp.second, bp.first + bp.second);
      offset_x = bp.first * 16 - g_x_min;
      offset_y = bp.second * 16 - g_y_min;
    }
    render_tile(image, std::make_pair(offset_x, offset_y));
  }
}
ApplyFoo::ApplyFoo(nbt* bf, int i, tbb::atomic<size_t>* index,
                   std::pair<int, int> min_norm)
        : bf_(bf), i_(i), index_(index), min_norm_(min_norm) {}

Settings getSettings() {
  Settings set;
  set.topview = true;
  set.oblique = false;
  set.isometric = false;
  set.heightmap = false;
  set.color = false;
  set.shadow_strength = 0;
  set.shadow_quality = true;
  set.shadow_quality_ultra = true;
  set.relief_strength = 0;
  set.sun_direction = 2;
  set.rotate = 1;
  set.nightmode = 0;
  set.sun_direction = (set.sun_direction + ((set.rotate + 3) % 4) * 2) % 8;
  set.shadow = set.shadow_strength;
  set.relief = set.relief_strength;
  return set;
}

void calculateMinMaxPoint(std::pair<int, int>& min_norm,
                          std::pair<int, int>& max_norm,
                          const nbt& bf) {
  std::pair<int, int> min(bf.xPos_min(), bf.zPos_min());
  std::pair<int, int> max(bf.xPos_max(), bf.zPos_max());
  min = projectCoords(min, bf.set().rotate);
  max = projectCoords(max, bf.set().rotate);
  min_norm = std::make_pair(std::min(min.first, max.first),
                            std::min(min.second, max.second));
  max_norm = std::make_pair(std::max(min.first, max.first),
                            std::max(min.second, max.second));
}

void pamToPng(std::string png_name) {
  FILE* pam = NULL;
  if (g_filename.size()) {
    pam = fopen(g_filename.c_str(), "rb");
    fseek(pam, g_header_size, SEEK_CUR);
  }
  FILE* out = fopen(png_name.c_str(), "wb");
  png_struct* pngP;
  png_info* infoP;
  pngP = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  infoP = png_create_info_struct(pngP);
  png_set_IHDR(pngP, infoP, static_cast<png_uint_32>(g_width),
                            static_cast<png_uint_32>(g_height), 8,
               PNG_COLOR_TYPE_RGB_ALPHA,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_DEFAULT,
               PNG_FILTER_TYPE_DEFAULT);
  png_init_io(pngP, out);
  png_write_info(pngP, infoP);

  png_byte* pngRow = new png_byte[g_width * 4];
  for (int32_t i = 0; i < g_height; ++i) {
    if (pam) {
      fread(pngRow, 4, static_cast<size_t>(g_width), pam);
    } else {
      std::copy(global_image + i * g_width * 4,
                global_image + (i + 1) * g_width * 4,
                pngRow);
    }
    png_write_row(pngP, pngRow);
  }
  delete[] pngRow;

  png_write_end(pngP, infoP);
  png_destroy_write_struct(&pngP, &infoP);
  fclose(out);
  if (pam) {
    fclose(pam);
    delete[] global_image_depth;
  } else {
    delete[] global_image;
    delete[] global_image_depth;
  }
}

size_t fillTiles(std::list<std::vector<int> >& tiles, const nbt& bf,
                 const std::pair<int, int>& min_norm,
                 const std::pair<int, int>& max_norm,
                 boost::progress_display& show_progress) {
  size_t tiles_nr = 0;
  std::list<std::vector<int> >::iterator it = tiles.begin();
  for (int i = min_norm.second; i <= max_norm.second; ++i) {
    for (int j = min_norm.first; j <= max_norm.first; ++j) {
      std::pair<int, int> p = projectCoords(std::make_pair(j, i),
                                            (4 - bf.set().rotate) % 4);
      boost::filesystem::path path;
      if (bf.exists(p.first, p.second, path)) {
        p = projectCoords(p, bf.set().rotate);
        it->push_back(p.first);
        if (bf.set().isometric) {
          p = std::make_pair(32 * p.first - 32 * p.second,
                             16 * (p.first + p.second));
        }
        if (p.first < g_x_min) {
          g_x_min = p.first;
        }
        if (p.second < g_y_min) {
          g_y_min = p.second;
        }
        if (p.first > g_x_max) {
          g_x_max = p.first;
        }
        if (p.second > g_y_max) {
          g_y_max = p.second;
        }
      }
    }
    tiles_nr += it->size();
    ++it;
    ++show_progress;
  }
  return tiles_nr;
}

<|endoftext|>


<commit_before>#include "connectiontester.h"

#include <QNetworkConfigurationManager>
#include <QNetworkConfiguration>
#include <QNetworkSession>
#include <QHostAddress>

#include <QNetworkInterface>
#include <QCoreApplication>
#include <QByteArray>
#include <QFile>
#include <QTextStream>
#include <QStringList>
#include <QProcess>
#include <QDebug>

#ifdef Q_OS_LINUX
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#elif defined(Q_OS_WIN)
#include <WinSock2.h>
#include <IPHlpApi.h>
#pragma comment(lib, "IPHLPAPI.lib")
#undef interface
#endif // Q_OS_LINUX

class ConnectionTester::Private
{
    Q_DECLARE_TR_FUNCTIONS(ConnectionTester::Private)

public:
    Private(ConnectionTester* q)
    : q(q)
    , result(ConnectionTester::Offline)
    {
    }

    ConnectionTester* q;

    ConnectionTester::ResultType result;

    void checkInterfaces();
    void checkSlow();

    QString findDefaultGateway() const;
    QString findDefaultDNS() const;
    bool canPing(const QString& host) const;

#ifdef Q_OS_MAC
    QString scutilHelper(const QByteArray &command, const QString& searchKey) const;
#endif // Q_OS_MAC
};

void ConnectionTester::Private::checkInterfaces()
{
    QNetworkConfigurationManager mgr;

    if ( !mgr.isOnline() ) {
        qDebug() << "Offline. Checking why ...";

        emit q->message(tr("Offline."), ConnectionTester::Info);

        QList<QNetworkConfiguration> configs;
        foreach(const QNetworkConfiguration config, mgr.allConfigurations(QNetworkConfiguration::Active)) {
            QNetworkSession session(config);
            QNetworkInterface iface = session.interface();
            if ( !iface.isValid() )
                qDebug() << config.name() << "invalid interface";
            else {
                // Ignore loopback devices
                if ( !iface.flags().testFlag(QNetworkInterface::IsLoopBack) )
                    configs.append(config);
            }
        }

        if ( configs.isEmpty() )
            emit q->message(tr("There are no active network devices. Please check your cables!"), ConnectionTester::Info);
        else {
            // There is some interface, now we have to check routings and dns
            // TODO: What now?
        }
    } else {
        //emit q->message(tr("Some interface is online. Checking ..."), ConnectionTester::Info);

        QString gw = findDefaultGateway();
        if ( gw.isEmpty() || gw == "0.0.0.0" )
            q->message(tr("You don't have a default gateway defined. Please check your DHCP/network settings!"), ConnectionTester::Info);
        else {
            if (!canPing(gw))
                q->message(tr("You can't access your default gateway!"), ConnectionTester::Info);
            else if (!canPing("8.8.8.8"))
                q->message(tr("Your default gateway does not forward your connections!"), ConnectionTester::Info);
            else if (!canPing("google.com"))
                q->message(tr("Your DNS resolution seems broken. Internet access works without DNS."), ConnectionTester::Info);
            else
                q->message(tr("Your connection seems to be fine"), ConnectionTester::Info);
        }

        QString dns = findDefaultDNS();
        if ( dns.isEmpty() )
            q->message(tr("You don't have a default dns server defined. Please check your DHCP/network settings!"), ConnectionTester::Info);
    }

    /*
    foreach(const QNetworkConfiguration& config, mgr.allConfigurations()) {
        // Ignore unknown and bluetooth devices
        if (config.bearerType() == QNetworkConfiguration::BearerUnknown ||
            config.bearerType() == QNetworkConfiguration::BearerBluetooth )
        {
            continue;
        }

        qDebug() << config.bearerTypeName() << config.name() << config.state();
    }*/
}

void ConnectionTester::Private::checkSlow()
{
    QNetworkConfigurationManager mgr;

    QNetworkConfiguration config = mgr.defaultConfiguration();
}

QString ConnectionTester::Private::findDefaultGateway() const
{
    // Inspiration: https://github.com/xbmc/xbmc/blob/8edff7ead55f1a31e55425d47885dc96d3d55105/xbmc/network/linux/NetworkLinux.cpp#L165
    QString gw;

#ifdef Q_OS_LINUX
    QFile file("/proc/net/route");
    if ( !file.open(QIODevice::ReadOnly) ) {
        qDebug() << "Failed to open kernel route" << file.errorString();
        return QString();
    }

    QTextStream stream(&file);
    QString line = stream.readLine();
    while (!line.isEmpty()) {
        QStringList parts = line.split('\t');
        if ( !parts.isEmpty() ) {
            if ( parts.at(1) == "00000000" ) { // Find the default route
                QString ip = parts.at(2);
                QStringList realIp;

                for(int pos=0; pos < ip.size(); pos += 2) {
                    QString block = ip.mid(pos, 2);

                    realIp.prepend( QString::number(block.toInt(NULL, 16)) );
                }

                return realIp.join(".");
            }
        }

        line = stream.readLine();
    }
#elif defined(Q_OS_MAC)
    gw = scutilHelper("show State:/Network/Global/IPv4", "Router");
#elif defined(Q_OS_WIN)
    IP_ADAPTER_INFO* pAdapterInfo = new IP_ADAPTER_INFO;

    ULONG outbufferLength = sizeof(IP_ADAPTER_INFO);
    if ( ::GetAdaptersInfo(pAdapterInfo, &outbufferLength) == ERROR_BUFFER_OVERFLOW ) {
        delete pAdapterInfo;
        pAdapterInfo = (IP_ADAPTER_INFO*)malloc(outbufferLength);
    }

    if ( ::GetAdaptersInfo(pAdapterInfo, &outbufferLength) == NO_ERROR ) {
        IP_ADAPTER_INFO* pAdapter = pAdapterInfo;
        while (pAdapter) {
            QString temp = QString::fromLatin1(pAdapter->GatewayList.IpAddress.String);
            if ( temp != "0.0.0.0" )
                gw = temp;

            pAdapter = pAdapter->Next;
        }
    }

    delete pAdapterInfo;
#endif

    return gw;
}

QString ConnectionTester::Private::findDefaultDNS() const
{
    // Inspiration: https://github.com/xbmc/xbmc/blob/8edff7ead55f1a31e55425d47885dc96d3d55105/xbmc/network/linux/NetworkLinux.cpp#L411
#ifdef Q_OS_LINUX
    res_init();

    for(int i=0; i < _res.nscount; ++i) {
        return QString::fromLatin1(inet_ntoa( ((sockaddr_in*)&_res.nsaddr_list[0])->sin_addr ));
    }
#elif defined(Q_OS_WIN)
    QString dns;
    IP_ADAPTER_ADDRESSES* addresses = NULL;
    ULONG bufferSize = 0;
    if (::GetAdaptersAddresses(AF_INET, 0, NULL, addresses, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
        addresses = (IP_ADAPTER_ADDRESSES*)malloc(bufferSize);
        if (::GetAdaptersAddresses(AF_INET, 0, NULL, addresses, &bufferSize) == NO_ERROR) {
            IP_ADAPTER_ADDRESSES* addr = addresses;
            while (addr) {
                if ( addr->OperStatus == IfOperStatusUp ) {
                    IP_ADAPTER_DNS_SERVER_ADDRESS* p = addr->FirstDnsServerAddress;
                    while (p) {
                        if ( dns.isEmpty() )
                            dns = QHostAddress(p->Address.lpSockaddr).toString();

                        p = p->Next;
                    }
                }

                addr = addr->Next;
            }
        }
    }

    delete addresses;
    return dns;
#elif defined(Q_OS_MAC)
    return scutilHelper("show State:/Network/Global/DNS", "0");
#endif
    return QString();
}

bool ConnectionTester::Private::canPing(const QString &host) const
{
    QProcess process;
    QStringList args;

#ifdef Q_OS_LINUX
    process.setStandardOutputFile("/dev/null");
    process.setStandardErrorFile("/dev/null");

    args << "-c" << "1" // Amount of pings
         << "-n" // Don't resolve hostnames
         << "-W" << "1"; // Timeout
#elif defined(Q_OS_MAC)
    args.clear(); // Apple needs the host name at last
    args << "-c" << "1" // Amount of pings
         << "-t" << "1"; // Timeout
#elif defined(Q_OS_WIN)
    args << "-n" << "1" // Amount of pings
         << "-4" // Stay with IPv4 for now
         << "-w" << "1000"; // Timeout
#endif

    // Hostname is always the last parameter (necessary on osx/android!)
    args << host;

    process.start("ping", args);
    process.waitForFinished();

    return process.exitCode() == 0;
}

#ifdef Q_OS_MAC
QString ConnectionTester::Private::scutilHelper(const QByteArray& command, const QString &searchKey) const
{
    QString result;

    QProcess sc;
    QTextStream stream(&sc);
    sc.start("scutil");
    sc.waitForStarted();
    //sc.write("show State:/Network/Global/IPv4\n");
    sc.write(command);
    sc.write("\n");
    sc.waitForReadyRead();

    QString line = stream.readLine();
    while (!line.isEmpty()) {
        QStringList parts = line.split(':');
        if ( parts.size() == 2 ) {
            if ( parts.at(0).trimmed() == searchKey )
                result = parts.at(1).trimmed();
        }

        line = stream.readLine();
    }

    sc.write("exit\n");
    sc.waitForFinished();

    return result;
}
#endif // Q_OS_MAC

ConnectionTester::ConnectionTester(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}

ConnectionTester::~ConnectionTester()
{
    delete d;
}

void ConnectionTester::start()
{
    d->checkInterfaces();
}

ConnectionTester::ResultType ConnectionTester::result() const
{
    return d->result;
}
<commit_msg>Throw compiler errors on unsupported platforms.<commit_after>#include "connectiontester.h"

#include <QNetworkConfigurationManager>
#include <QNetworkConfiguration>
#include <QNetworkSession>
#include <QHostAddress>

#include <QNetworkInterface>
#include <QCoreApplication>
#include <QByteArray>
#include <QFile>
#include <QTextStream>
#include <QStringList>
#include <QProcess>
#include <QDebug>

#ifdef Q_OS_LINUX
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#elif defined(Q_OS_WIN)
#include <WinSock2.h>
#include <IPHlpApi.h>
#pragma comment(lib, "IPHLPAPI.lib")
#undef interface
#endif // Q_OS_LINUX

class ConnectionTester::Private
{
    Q_DECLARE_TR_FUNCTIONS(ConnectionTester::Private)

public:
    Private(ConnectionTester* q)
    : q(q)
    , result(ConnectionTester::Offline)
    {
    }

    ConnectionTester* q;

    ConnectionTester::ResultType result;

    void checkInterfaces();
    void checkSlow();

    QString findDefaultGateway() const;
    QString findDefaultDNS() const;
    bool canPing(const QString& host) const;

#ifdef Q_OS_MAC
    QString scutilHelper(const QByteArray &command, const QString& searchKey) const;
#endif // Q_OS_MAC
};

void ConnectionTester::Private::checkInterfaces()
{
    QNetworkConfigurationManager mgr;

    if ( !mgr.isOnline() ) {
        qDebug() << "Offline. Checking why ...";

        emit q->message(tr("Offline."), ConnectionTester::Info);

        QList<QNetworkConfiguration> configs;
        foreach(const QNetworkConfiguration config, mgr.allConfigurations(QNetworkConfiguration::Active)) {
            QNetworkSession session(config);
            QNetworkInterface iface = session.interface();
            if ( !iface.isValid() )
                qDebug() << config.name() << "invalid interface";
            else {
                // Ignore loopback devices
                if ( !iface.flags().testFlag(QNetworkInterface::IsLoopBack) )
                    configs.append(config);
            }
        }

        if ( configs.isEmpty() )
            emit q->message(tr("There are no active network devices. Please check your cables!"), ConnectionTester::Info);
        else {
            // There is some interface, now we have to check routings and dns
            // TODO: What now?
        }
    } else {
        //emit q->message(tr("Some interface is online. Checking ..."), ConnectionTester::Info);

        QString gw = findDefaultGateway();
        if ( gw.isEmpty() || gw == "0.0.0.0" )
            q->message(tr("You don't have a default gateway defined. Please check your DHCP/network settings!"), ConnectionTester::Info);
        else {
            if (!canPing(gw))
                q->message(tr("You can't access your default gateway!"), ConnectionTester::Info);
            else if (!canPing("8.8.8.8"))
                q->message(tr("Your default gateway does not forward your connections!"), ConnectionTester::Info);
            else if (!canPing("google.com"))
                q->message(tr("Your DNS resolution seems broken. Internet access works without DNS."), ConnectionTester::Info);
            else
                q->message(tr("Your connection seems to be fine"), ConnectionTester::Info);
        }

        QString dns = findDefaultDNS();
        if ( dns.isEmpty() )
            q->message(tr("You don't have a default dns server defined. Please check your DHCP/network settings!"), ConnectionTester::Info);
    }

    /*
    foreach(const QNetworkConfiguration& config, mgr.allConfigurations()) {
        // Ignore unknown and bluetooth devices
        if (config.bearerType() == QNetworkConfiguration::BearerUnknown ||
            config.bearerType() == QNetworkConfiguration::BearerBluetooth )
        {
            continue;
        }

        qDebug() << config.bearerTypeName() << config.name() << config.state();
    }*/
}

void ConnectionTester::Private::checkSlow()
{
    QNetworkConfigurationManager mgr;

    QNetworkConfiguration config = mgr.defaultConfiguration();
}

QString ConnectionTester::Private::findDefaultGateway() const
{
    // Inspiration: https://github.com/xbmc/xbmc/blob/8edff7ead55f1a31e55425d47885dc96d3d55105/xbmc/network/linux/NetworkLinux.cpp#L165
    QString gw;

#ifdef Q_OS_LINUX
    QFile file("/proc/net/route");
    if ( !file.open(QIODevice::ReadOnly) ) {
        qDebug() << "Failed to open kernel route" << file.errorString();
        return QString();
    }

    QTextStream stream(&file);
    QString line = stream.readLine();
    while (!line.isEmpty()) {
        QStringList parts = line.split('\t');
        if ( !parts.isEmpty() ) {
            if ( parts.at(1) == "00000000" ) { // Find the default route
                QString ip = parts.at(2);
                QStringList realIp;

                for(int pos=0; pos < ip.size(); pos += 2) {
                    QString block = ip.mid(pos, 2);

                    realIp.prepend( QString::number(block.toInt(NULL, 16)) );
                }

                return realIp.join(".");
            }
        }

        line = stream.readLine();
    }
#elif defined(Q_OS_MAC)
    gw = scutilHelper("show State:/Network/Global/IPv4", "Router");
#elif defined(Q_OS_WIN)
    IP_ADAPTER_INFO* pAdapterInfo = new IP_ADAPTER_INFO;

    ULONG outbufferLength = sizeof(IP_ADAPTER_INFO);
    if ( ::GetAdaptersInfo(pAdapterInfo, &outbufferLength) == ERROR_BUFFER_OVERFLOW ) {
        delete pAdapterInfo;
        pAdapterInfo = (IP_ADAPTER_INFO*)malloc(outbufferLength);
    }

    if ( ::GetAdaptersInfo(pAdapterInfo, &outbufferLength) == NO_ERROR ) {
        IP_ADAPTER_INFO* pAdapter = pAdapterInfo;
        while (pAdapter) {
            QString temp = QString::fromLatin1(pAdapter->GatewayList.IpAddress.String);
            if ( temp != "0.0.0.0" )
                gw = temp;

            pAdapter = pAdapter->Next;
        }
    }

    delete pAdapterInfo;
#else
#error Platform gateway code missing!
#endif

    return gw;
}

QString ConnectionTester::Private::findDefaultDNS() const
{
    // Inspiration: https://github.com/xbmc/xbmc/blob/8edff7ead55f1a31e55425d47885dc96d3d55105/xbmc/network/linux/NetworkLinux.cpp#L411
#ifdef Q_OS_LINUX
    res_init();

    for(int i=0; i < _res.nscount; ++i) {
        return QString::fromLatin1(inet_ntoa( ((sockaddr_in*)&_res.nsaddr_list[0])->sin_addr ));
    }
#elif defined(Q_OS_WIN)
    QString dns;
    IP_ADAPTER_ADDRESSES* addresses = NULL;
    ULONG bufferSize = 0;
    if (::GetAdaptersAddresses(AF_INET, 0, NULL, addresses, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
        addresses = (IP_ADAPTER_ADDRESSES*)malloc(bufferSize);
        if (::GetAdaptersAddresses(AF_INET, 0, NULL, addresses, &bufferSize) == NO_ERROR) {
            IP_ADAPTER_ADDRESSES* addr = addresses;
            while (addr) {
                if ( addr->OperStatus == IfOperStatusUp ) {
                    IP_ADAPTER_DNS_SERVER_ADDRESS* p = addr->FirstDnsServerAddress;
                    while (p) {
                        if ( dns.isEmpty() )
                            dns = QHostAddress(p->Address.lpSockaddr).toString();

                        p = p->Next;
                    }
                }

                addr = addr->Next;
            }
        }
    }

    delete addresses;
    return dns;
#elif defined(Q_OS_MAC)
    return scutilHelper("show State:/Network/Global/DNS", "0");
#else
#error Platform dns code missing!
#endif
    return QString();
}

bool ConnectionTester::Private::canPing(const QString &host) const
{
    QProcess process;
    QStringList args;

#ifdef Q_OS_LINUX
    process.setStandardOutputFile("/dev/null");
    process.setStandardErrorFile("/dev/null");

    args << "-c" << "1" // Amount of pings
         << "-n" // Don't resolve hostnames
         << "-W" << "1"; // Timeout
#elif defined(Q_OS_MAC)
    args.clear(); // Apple needs the host name at last
    args << "-c" << "1" // Amount of pings
         << "-t" << "1"; // Timeout
#elif defined(Q_OS_WIN)
    args << "-n" << "1" // Amount of pings
         << "-4" // Stay with IPv4 for now
         << "-w" << "1000"; // Timeout
#else
#error Platform ping code missing!
#endif

    // Hostname is always the last parameter (necessary on osx/android!)
    args << host;

    process.start("ping", args);
    process.waitForFinished();

    return process.exitCode() == 0;
}

#ifdef Q_OS_MAC
QString ConnectionTester::Private::scutilHelper(const QByteArray& command, const QString &searchKey) const
{
    QString result;

    QProcess sc;
    QTextStream stream(&sc);
    sc.start("scutil");
    sc.waitForStarted();
    //sc.write("show State:/Network/Global/IPv4\n");
    sc.write(command);
    sc.write("\n");
    sc.waitForReadyRead();

    QString line = stream.readLine();
    while (!line.isEmpty()) {
        QStringList parts = line.split(':');
        if ( parts.size() == 2 ) {
            if ( parts.at(0).trimmed() == searchKey )
                result = parts.at(1).trimmed();
        }

        line = stream.readLine();
    }

    sc.write("exit\n");
    sc.waitForFinished();

    return result;
}
#endif // Q_OS_MAC

ConnectionTester::ConnectionTester(QObject *parent)
: QObject(parent)
, d(new Private(this))
{
}

ConnectionTester::~ConnectionTester()
{
    delete d;
}

void ConnectionTester::start()
{
    d->checkInterfaces();
}

ConnectionTester::ResultType ConnectionTester::result() const
{
    return d->result;
}
<|endoftext|>


<commit_before>#include "cappuccino.h"

int main(int argc, char *argv[]) {
	Cappuccino::Cappuccino(argc, argv);

	Cappuccino::document_root("html");
	Cappuccino::static_directory("public");

	Cappuccino::add_route("/", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);
		response.set_filename("index.html");
		return response;
	});

	Cappuccino::add_route("/gochiusa/<character_name>", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);
		response.add_replace_value("@name", "mizuki");
		response.add_replace_value("@waiter", req->url_params()["character_name"]);

		response.set_filename("chino.html");
		Logger::i(std::string(response));
		return response;
	});

	Cappuccino::add_route("/hello", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::TEXT);
		response.set_text("Hello world");
		return response;
	});

	Cappuccino::add_route("/json", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);
		response.set_filename("sample.json");
		response.add_header_value("Content-type", "json");
		return response;
	});

	Cappuccino::add_route("/cocoa", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		if(req->method() == Cappuccino::Request::POST){
			auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);

			response.add_replace_value("@order", req->get_param("order"));

			response.set_filename("cocoa.html");
			return response;
		}else{
			auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);
			response.add_replace_value("@order", "うさぎ");

			response.set_filename("cocoa.html");
			return response;
		}
	});

	Cappuccino::add_route("/chino", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);

		response.add_replace_value("@name", "mizuki");
		response.add_replace_value("@waiter", "香風智乃");

		response.set_filename("chino.html");

		return response;
	});

	Cappuccino::add_route("/rize", [&](Cappuccino::Request* req) -> Cappuccino::Response{
		auto res = Cappuccino::ResponseBuilder()
			.status(200, "OK")
			.http_version("1.1")
			.build();

		// Dumyu
		auto response = Cappuccino::Response(req->protocol(), Cappuccino::Response::FILE);
		return response;
	});
#ifdef TEST

	Cappuccino::add_spec("/ exist",[&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/", new Cappuccino::FakeRequest( "GET", "/"));
		if(res.find("Cappuccino", 0) != std::string::npos)
			return true;
		return false;
	});
	Cappuccino::add_spec("/hello plain text", [&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/hello", new Cappuccino::FakeRequest( "GET", "/hello"));
		if(res.find("Hello world", 0) != std::string::npos)
			return true;
		return false;
	});
	Cappuccino::add_spec("/hoge not exist",[&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/hoge", new Cappuccino::FakeRequest( "GET", "/hoge"));
		if(res.find("Page not found", 0) != std::string::npos)
			return true;
		return false;
	});
	Cappuccino::add_spec("/chino running replace",[&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/chino", new Cappuccino::FakeRequest( "GET", "/chino"));
		if(res.find("香風智乃", 0) != std::string::npos)
			return true;
		return false;
	});
	Cappuccino::add_spec("/gochiusa/chiya replace with url",[&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/gochiusa/chiya", new Cappuccino::FakeRequest( "GET", "/gochiusa/chiya"));
		if(res.find("chiya", 0) != std::string::npos)
			return true;
		return false;
	});
	Cappuccino::add_spec("/public/css/sample replace with url",[&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/gochiusa/chiya", new Cappuccino::FakeRequest( "GET", "/gochiusa/chiya"));
		if(res.find("chiya", 0) != std::string::npos)
			return true;
		return false;
	});

	// Get

	Cappuccino::add_spec("/gochiusa/sharo?name=chino get url paramaters",[&](Cappuccino::Application* app) -> bool{
		std::string res = app->access("/gochiusa/sharo?name=chino", new Cappuccino::FakeRequest( "GET", "/gochiusa/sharo?name=chino"));
		return true;
	});

	Cappuccino::testRun();

#else
	Cappuccino::run();
#endif

	return 0;
}<commit_msg>[Update] simple sample code<commit_after>#include "cappuccino.h"

int main(int argc, char *argv[]) {
	using namespace Cappuccino;
	Cappuccino::Cappuccino(argc, argv);

	Cappuccino::add_route("/",[](Request* request) -> Response{
		auto response = Cappuccino::ResponseBuilder()
					.status(200,"OK")
					.file("html/index.html")
					.build();
		return response;
	});

	run();
	return 0;
}<|endoftext|>


<commit_before>/*
    aboutdata.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2001,2002,2004 Klarlvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "aboutdata.h"

#include <klocale.h>

static const char kleopatra_version[] = "0.21";
static const char description[] = I18N_NOOP("KDE Key Manager");

struct about_data {
  const char * name;
  const char * desc;
  const char * email;
  const char * web;
};

static const about_data authors[] = {
  { "Marc Mutz", I18N_NOOP("Current Maintainer"), "mutz@kde.org", 0 },
  { "Steffen Hansen", I18N_NOOP("Former Maintainer"), "hansen@kde.org", 0 },
  { "Kalle Dalheimer", I18N_NOOP("Original Author"), "kalle@kde.org", 0 },
  { "Jesper Petersen", I18N_NOOP("Original Author"), "blackie@kde.org", 0 },
};

static const about_data credits[] = {
  { "David Faure",
    I18N_NOOP("Backend configuration framework, KIO integration"),
    "faure@kde.org", 0 },
  { "Michel Boyer de la Giroday",
    I18N_NOOP("Key-state dependant colors and fonts in the key list"),
    "michel@klaralvdalens-datakonsult.se", 0 },
  { "Daniel Molkentin",
    I18N_NOOP("Certificate Wizard KIOSK integration, infrastructure"),
    "molkentin@kde.org", 0 },
  { "Ralf Nolden",
    I18N_NOOP("Support for obsolete EMAIL RDN in Certificate Wizard"),
    "nolden@kde.org", 0 },
  { "Karl-Heinz Zimmer",
    I18N_NOOP("DN display ordering support, infrastructure"),
    "khz@kde.org", 0 },
};

AboutData::AboutData()
  : KAboutData( "kleopatra", I18N_NOOP("Kleopatra"),
		kleopatra_version, description, License_GPL,
		"(c) 2002 Steffen Hansen, Jesper Pedersen,\n"
		"Kalle Dalheimer, Klar\xC3\xA4lvdalens Datakonsult AB\n\n"
		"(c) 2004 Marc Mutz, Klar\xC3\xA4lvdalens Datakonsult AB" )
{
  using ::authors;
  using ::credits;
  for ( unsigned int i = 0 ; i < sizeof authors / sizeof *authors ; ++i )
    addAuthor( authors[i].name, authors[i].desc,
	       authors[i].email, authors[i].web );
  for ( unsigned int i = 0 ; i < sizeof credits / sizeof *credits ; ++i )
    addCredit( credits[i].name, credits[i].desc,
	       credits[i].email, credits[i].web );
}
<commit_msg>Long due version increase.<commit_after>/*
    aboutdata.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2001,2002,2004 Klarlvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include "aboutdata.h"

#include <klocale.h>

static const char kleopatra_version[] = "0.30";
static const char description[] = I18N_NOOP("KDE Key Manager");

struct about_data {
  const char * name;
  const char * desc;
  const char * email;
  const char * web;
};

static const about_data authors[] = {
  { "Marc Mutz", I18N_NOOP("Current Maintainer"), "mutz@kde.org", 0 },
  { "Steffen Hansen", I18N_NOOP("Former Maintainer"), "hansen@kde.org", 0 },
  { "Kalle Dalheimer", I18N_NOOP("Original Author"), "kalle@kde.org", 0 },
  { "Jesper Petersen", I18N_NOOP("Original Author"), "blackie@kde.org", 0 },
};

static const about_data credits[] = {
  { "David Faure",
    I18N_NOOP("Backend configuration framework, KIO integration"),
    "faure@kde.org", 0 },
  { "Michel Boyer de la Giroday",
    I18N_NOOP("Key-state dependant colors and fonts in the key list"),
    "michel@klaralvdalens-datakonsult.se", 0 },
  { "Daniel Molkentin",
    I18N_NOOP("Certificate Wizard KIOSK integration, infrastructure"),
    "molkentin@kde.org", 0 },
  { "Ralf Nolden",
    I18N_NOOP("Support for obsolete EMAIL RDN in Certificate Wizard"),
    "nolden@kde.org", 0 },
  { "Karl-Heinz Zimmer",
    I18N_NOOP("DN display ordering support, infrastructure"),
    "khz@kde.org", 0 },
};

AboutData::AboutData()
  : KAboutData( "kleopatra", I18N_NOOP("Kleopatra"),
		kleopatra_version, description, License_GPL,
		"(c) 2002 Steffen Hansen, Jesper Pedersen,\n"
		"Kalle Dalheimer, Klar\xC3\xA4lvdalens Datakonsult AB\n\n"
		"(c) 2004 Marc Mutz, Klar\xC3\xA4lvdalens Datakonsult AB" )
{
  using ::authors;
  using ::credits;
  for ( unsigned int i = 0 ; i < sizeof authors / sizeof *authors ; ++i )
    addAuthor( authors[i].name, authors[i].desc,
	       authors[i].email, authors[i].web );
  for ( unsigned int i = 0 ; i < sizeof credits / sizeof *credits ; ++i )
    addCredit( credits[i].name, credits[i].desc,
	       credits[i].email, credits[i].web );
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2016, Microsoft

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <sstream>

#include "gtest/gtest.h"

#include "BitFunnel/Utilities/Version.h"

namespace BitFunnel
{
    namespace VersionUnitTest
    {
        TEST(Manual, Trivial)
        {
            Version version(1, 1, 0);

            std::stringstream output;
            version.Write(output);

            Version version2(output);

            EXPECT_EQ(version.VersionMajor(), version2.VersionMajor());
            EXPECT_EQ(version.VersionMiddle(), version2.VersionMiddle());
            EXPECT_EQ(version.VersionMinor(), version2.VersionMinor());

            Version version3(1, 1, 1);
            EXPECT_TRUE(version.IsCompatibleWith(version3));

            Version version4(1, 2, 0);
            EXPECT_TRUE(!version.IsCompatibleWith(version4));

            Version version5(2, 1, 0);
            EXPECT_TRUE(!version.IsCompatibleWith(version5));

            Version version6 = version.IncrementMajor();
            EXPECT_EQ(version6.VersionMajor(), 2);
            EXPECT_EQ(version6.VersionMiddle(), 0);
            EXPECT_EQ(version6.VersionMinor(), 0);

            Version version7 = version.IncrementMiddle();
            EXPECT_EQ(version7.VersionMajor(), 1);
            EXPECT_EQ(version7.VersionMiddle(), 2);
            EXPECT_EQ(version7.VersionMinor(), 0);

            Version version8 = version.IncrementMinor();
            EXPECT_EQ(version8.VersionMajor(), 1);
            EXPECT_EQ(version8.VersionMiddle(), 1);
            EXPECT_EQ(version8.VersionMinor(), 1);
        }
    }
}
<commit_msg>Fix version test to avoid duplicate digits. Fixes #68.<commit_after>// The MIT License (MIT)

// Copyright (c) 2016, Microsoft

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <sstream>

#include "gtest/gtest.h"

#include "BitFunnel/Utilities/Version.h"

namespace BitFunnel
{
    namespace VersionUnitTest
    {
        TEST(Manual, Trivial)
        {
            Version version(1, 2, 3);

            std::stringstream output;
            version.Write(output);

            Version version2(output);

            EXPECT_EQ(version.VersionMajor(), version2.VersionMajor());
            EXPECT_EQ(version.VersionMiddle(), version2.VersionMiddle());
            EXPECT_EQ(version.VersionMinor(), version2.VersionMinor());

            Version version3(1, 2, 4);
            EXPECT_TRUE(version.IsCompatibleWith(version3));

            Version version4(1, 3, 0);
            EXPECT_TRUE(!version.IsCompatibleWith(version4));

            Version version5(2, 1, 0);
            EXPECT_TRUE(!version.IsCompatibleWith(version5));

            Version version6 = version.IncrementMajor();
            EXPECT_EQ(version6.VersionMajor(), 2);
            EXPECT_EQ(version6.VersionMiddle(), 0);
            EXPECT_EQ(version6.VersionMinor(), 0);

            Version version7 = version.IncrementMiddle();
            EXPECT_EQ(version7.VersionMajor(), 1);
            EXPECT_EQ(version7.VersionMiddle(), 3);
            EXPECT_EQ(version7.VersionMinor(), 0);

            Version version8 = version.IncrementMinor();
            EXPECT_EQ(version8.VersionMajor(), 1);
            EXPECT_EQ(version8.VersionMiddle(), 2);
            EXPECT_EQ(version8.VersionMinor(), 4);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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/browser/bookmarks/bookmark_codec.h"

#include "app/l10n_util.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"

using base::Time;

UniqueIDGenerator::UniqueIDGenerator() {
  Reset();
}

int UniqueIDGenerator::GetUniqueID(int id) {
  // If the given ID is already assigned, generate new ID.
  if (IsIdAssigned(id))
    id = current_max_ + 1;

  // Record the new ID as assigned.
  RecordId(id);

  if (id > current_max_)
    current_max_ = id;

  return id;
}

bool UniqueIDGenerator::IsIdAssigned(int id) const {
  // If the set is already instantiated, then use the set to determine if the
  // given ID is assigned. Otherwise use the current maximum to determine if the
  // given ID is assigned.
  if (assigned_ids_.get())
    return assigned_ids_->find(id) != assigned_ids_->end();
  else
    return id <= current_max_;
}

void UniqueIDGenerator::RecordId(int id) {
  // If the set is instantiated, then use the set.
  if (assigned_ids_.get()) {
    assigned_ids_->insert(id);
    return;
  }

  // The set is not yet instantiated. If the ID is current_max_ + 1, then just
  // update the current_max_. Otherwise, instantiate the set and add all IDs
  // from 0 to current_max_ to it.
  if (id == current_max_ + 1) {
    ++current_max_;
    return;
  }
  assigned_ids_.reset(new std::set<int>);
  for (int i = 0; i <= current_max_; ++i)
    assigned_ids_->insert(i);
  assigned_ids_->insert(id);
}

void UniqueIDGenerator::Reset() {
  current_max_ = 0;
  assigned_ids_.reset(NULL);
}

const wchar_t* BookmarkCodec::kRootsKey = L"roots";
const wchar_t* BookmarkCodec::kRootFolderNameKey = L"bookmark_bar";
const wchar_t* BookmarkCodec::kOtherBookmarkFolderNameKey = L"other";
const wchar_t* BookmarkCodec::kVersionKey = L"version";
const wchar_t* BookmarkCodec::kChecksumKey = L"checksum";
const wchar_t* BookmarkCodec::kIdKey = L"id";
const wchar_t* BookmarkCodec::kTypeKey = L"type";
const wchar_t* BookmarkCodec::kNameKey = L"name";
const wchar_t* BookmarkCodec::kDateAddedKey = L"date_added";
const wchar_t* BookmarkCodec::kURLKey = L"url";
const wchar_t* BookmarkCodec::kDateModifiedKey = L"date_modified";
const wchar_t* BookmarkCodec::kChildrenKey = L"children";
const wchar_t* BookmarkCodec::kTypeURL = L"url";
const wchar_t* BookmarkCodec::kTypeFolder = L"folder";

// Current version of the file.
static const int kCurrentVersion = 1;

BookmarkCodec::BookmarkCodec()
    : persist_ids_(false) {
}

BookmarkCodec::BookmarkCodec(bool persist_ids)
    : persist_ids_(persist_ids) {
}

Value* BookmarkCodec::Encode(BookmarkModel* model) {
  return Encode(model->GetBookmarkBarNode(), model->other_node());
}

Value* BookmarkCodec::Encode(BookmarkNode* bookmark_bar_node,
                             BookmarkNode* other_folder_node) {
  InitializeChecksum();
  DictionaryValue* roots = new DictionaryValue();
  roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node));
  roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node));

  DictionaryValue* main = new DictionaryValue();
  main->SetInteger(kVersionKey, kCurrentVersion);
  FinalizeChecksum();
  // We are going to store the computed checksum. So set stored checksum to be
  // the same as computed checksum.
  stored_checksum_ = computed_checksum_;
  main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_));
  main->Set(kRootsKey, roots);
  return main;
}

bool BookmarkCodec::Decode(BookmarkNode* bb_node,
                           BookmarkNode* other_folder_node,
                           int* max_id,
                           const Value& value) {
  id_generator_.Reset();
  stored_checksum_.clear();
  InitializeChecksum();
  bool success = DecodeHelper(bb_node, other_folder_node, max_id, value);
  FinalizeChecksum();
  *max_id = id_generator_.current_max() + 1;
  return success;
}

Value* BookmarkCodec::EncodeNode(BookmarkNode* node) {
  DictionaryValue* value = new DictionaryValue();
  std::string id;
  if (persist_ids_) {
    id = IntToString(node->id());
    value->SetString(kIdKey, id);
  }
  const std::wstring& title = node->GetTitle();
  value->SetString(kNameKey, title);
  value->SetString(kDateAddedKey,
                   Int64ToWString(node->date_added().ToInternalValue()));
  if (node->GetType() == history::StarredEntry::URL) {
    value->SetString(kTypeKey, kTypeURL);
    std::wstring url = UTF8ToWide(node->GetURL().possibly_invalid_spec());
    value->SetString(kURLKey, url);
    UpdateChecksumWithUrlNode(id, title, url);
  } else {
    value->SetString(kTypeKey, kTypeFolder);
    value->SetString(kDateModifiedKey,
                     Int64ToWString(node->date_group_modified().
                                    ToInternalValue()));
    UpdateChecksumWithFolderNode(id, title);

    ListValue* child_values = new ListValue();
    value->Set(kChildrenKey, child_values);
    for (int i = 0; i < node->GetChildCount(); ++i)
      child_values->Append(EncodeNode(node->GetChild(i)));
  }
  return value;
}

bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node,
                                 BookmarkNode* other_folder_node,
                                 int* max_id,
                                 const Value& value) {
  if (value.GetType() != Value::TYPE_DICTIONARY)
    return false;  // Unexpected type.

  const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value);

  int version;
  if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion)
    return false;  // Unknown version.

  Value* checksum_value;
  if (d_value.Get(kChecksumKey, &checksum_value)) {
    if (checksum_value->GetType() != Value::TYPE_STRING)
      return false;
    StringValue* checksum_value_str = static_cast<StringValue*>(checksum_value);
    if (!checksum_value_str->GetAsString(&stored_checksum_))
      return false;
  }

  Value* roots;
  if (!d_value.Get(kRootsKey, &roots))
    return false;  // No roots.

  if (roots->GetType() != Value::TYPE_DICTIONARY)
    return false;  // Invalid type for roots.

  DictionaryValue* roots_d_value = static_cast<DictionaryValue*>(roots);
  Value* root_folder_value;
  Value* other_folder_value;
  if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) ||
      root_folder_value->GetType() != Value::TYPE_DICTIONARY ||
      !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) ||
      other_folder_value->GetType() != Value::TYPE_DICTIONARY)
    return false;  // Invalid type for root folder and/or other folder.

  DecodeNode(*static_cast<DictionaryValue*>(root_folder_value), NULL,
             bb_node);
  DecodeNode(*static_cast<DictionaryValue*>(other_folder_value), NULL,
             other_folder_node);
  // Need to reset the type as decoding resets the type to FOLDER. Similarly
  // we need to reset the title as the title is persisted and restored from
  // the file.
  bb_node->type_ = history::StarredEntry::BOOKMARK_BAR;
  other_folder_node->type_ = history::StarredEntry::OTHER;
  bb_node->SetTitle(l10n_util::GetString(IDS_BOOMARK_BAR_FOLDER_NAME));
  other_folder_node->SetTitle(
      l10n_util::GetString(IDS_BOOMARK_BAR_OTHER_FOLDER_NAME));

  return true;
}

bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list,
                                   BookmarkNode* parent) {
  for (size_t i = 0; i < child_value_list.GetSize(); ++i) {
    Value* child_value;
    if (!child_value_list.Get(i, &child_value))
      return false;

    if (child_value->GetType() != Value::TYPE_DICTIONARY)
      return false;

    if (!DecodeNode(*static_cast<DictionaryValue*>(child_value), parent,
                    NULL)) {
      return false;
    }
  }
  return true;
}

bool BookmarkCodec::DecodeNode(const DictionaryValue& value,
                               BookmarkNode* parent,
                               BookmarkNode* node) {
  std::string id_string;
  int id = 0;
  if (persist_ids_) {
    if (value.GetString(kIdKey, &id_string))
      if (!StringToInt(id_string, &id))
        return false;
  }
  id = id_generator_.GetUniqueID(id);

  std::wstring title;
  if (!value.GetString(kNameKey, &title))
    return false;

  // TODO(sky): this should be more flexible. Don't hoark if we can't parse it
  // all.
  std::wstring date_added_string;
  if (!value.GetString(kDateAddedKey, &date_added_string))
    return false;

  std::wstring type_string;
  if (!value.GetString(kTypeKey, &type_string))
    return false;

  if (type_string != kTypeURL && type_string != kTypeFolder)
    return false;  // Unknown type.

  if (type_string == kTypeURL) {
    std::wstring url_string;
    if (!value.GetString(kURLKey, &url_string))
      return false;
    // TODO(sky): this should ignore the node if not a valid URL.
    if (!node)
      node = new BookmarkNode(id, GURL(WideToUTF8(url_string)));
    else
      NOTREACHED();  // In case of a URL type node should always be NULL.

    if (parent)
      parent->Add(parent->GetChildCount(), node);
    node->type_ = history::StarredEntry::URL;
    UpdateChecksumWithUrlNode(id_string, title, url_string);
  } else {
    std::wstring last_modified_date;
    if (!value.GetString(kDateModifiedKey, &last_modified_date))
      return false;

    Value* child_values;
    if (!value.Get(kChildrenKey, &child_values))
      return false;

    if (child_values->GetType() != Value::TYPE_LIST)
      return false;

    if (!node) {
      node = new BookmarkNode(id, GURL());
    } else {
      // If a new node is not created, explicitly assign ID to the existing one.
      DCHECK(id != 0);
      node->set_id(id);
    }

    node->type_ = history::StarredEntry::USER_GROUP;
    node->date_group_modified_ = Time::FromInternalValue(
        StringToInt64(WideToUTF16Hack(last_modified_date)));

    if (parent)
      parent->Add(parent->GetChildCount(), node);

    UpdateChecksumWithFolderNode(id_string, title);
    if (!DecodeChildren(*static_cast<ListValue*>(child_values), node))
      return false;
  }

  node->SetTitle(title);
  node->date_added_ = Time::FromInternalValue(
      StringToInt64(WideToUTF16Hack(date_added_string)));
  return true;
}

void BookmarkCodec::UpdateChecksum(const std::string& str) {
  MD5Update(&md5_context_, str.data(), str.length() * sizeof(char));
}

void BookmarkCodec::UpdateChecksum(const std::wstring& str) {
  MD5Update(&md5_context_, str.data(), str.length() * sizeof(wchar_t));
}

void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id,
                                              const std::wstring& title,
                                              const std::wstring& url) {
  UpdateChecksum(id);
  UpdateChecksum(title);
  UpdateChecksum(kTypeURL);
  UpdateChecksum(url);
}

void BookmarkCodec::UpdateChecksumWithFolderNode(const std::string& id,
                                                 const std::wstring& title) {
  UpdateChecksum(id);
  UpdateChecksum(title);
  UpdateChecksum(kTypeFolder);
}

void BookmarkCodec::InitializeChecksum() {
  MD5Init(&md5_context_);
}

void BookmarkCodec::FinalizeChecksum() {
  MD5Digest digest;
  MD5Final(&digest, &md5_context_);
  computed_checksum_ = MD5DigestToBase16(digest);
}
<commit_msg>Should provide checks while loading bookmarks<commit_after>// Copyright (c) 2006-2008 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/browser/bookmarks/bookmark_codec.h"

#include "app/l10n_util.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"

using base::Time;

UniqueIDGenerator::UniqueIDGenerator() {
  Reset();
}

int UniqueIDGenerator::GetUniqueID(int id) {
  // If the given ID is already assigned, generate new ID.
  if (IsIdAssigned(id))
    id = current_max_ + 1;

  // Record the new ID as assigned.
  RecordId(id);

  if (id > current_max_)
    current_max_ = id;

  return id;
}

bool UniqueIDGenerator::IsIdAssigned(int id) const {
  // If the set is already instantiated, then use the set to determine if the
  // given ID is assigned. Otherwise use the current maximum to determine if the
  // given ID is assigned.
  if (assigned_ids_.get())
    return assigned_ids_->find(id) != assigned_ids_->end();
  else
    return id <= current_max_;
}

void UniqueIDGenerator::RecordId(int id) {
  // If the set is instantiated, then use the set.
  if (assigned_ids_.get()) {
    assigned_ids_->insert(id);
    return;
  }

  // The set is not yet instantiated. If the ID is current_max_ + 1, then just
  // update the current_max_. Otherwise, instantiate the set and add all IDs
  // from 0 to current_max_ to it.
  if (id == current_max_ + 1) {
    ++current_max_;
    return;
  }
  assigned_ids_.reset(new std::set<int>);
  for (int i = 0; i <= current_max_; ++i)
    assigned_ids_->insert(i);
  assigned_ids_->insert(id);
}

void UniqueIDGenerator::Reset() {
  current_max_ = 0;
  assigned_ids_.reset(NULL);
}

const wchar_t* BookmarkCodec::kRootsKey = L"roots";
const wchar_t* BookmarkCodec::kRootFolderNameKey = L"bookmark_bar";
const wchar_t* BookmarkCodec::kOtherBookmarkFolderNameKey = L"other";
const wchar_t* BookmarkCodec::kVersionKey = L"version";
const wchar_t* BookmarkCodec::kChecksumKey = L"checksum";
const wchar_t* BookmarkCodec::kIdKey = L"id";
const wchar_t* BookmarkCodec::kTypeKey = L"type";
const wchar_t* BookmarkCodec::kNameKey = L"name";
const wchar_t* BookmarkCodec::kDateAddedKey = L"date_added";
const wchar_t* BookmarkCodec::kURLKey = L"url";
const wchar_t* BookmarkCodec::kDateModifiedKey = L"date_modified";
const wchar_t* BookmarkCodec::kChildrenKey = L"children";
const wchar_t* BookmarkCodec::kTypeURL = L"url";
const wchar_t* BookmarkCodec::kTypeFolder = L"folder";

// Current version of the file.
static const int kCurrentVersion = 1;

BookmarkCodec::BookmarkCodec()
    : persist_ids_(false) {
}

BookmarkCodec::BookmarkCodec(bool persist_ids)
    : persist_ids_(persist_ids) {
}

Value* BookmarkCodec::Encode(BookmarkModel* model) {
  return Encode(model->GetBookmarkBarNode(), model->other_node());
}

Value* BookmarkCodec::Encode(BookmarkNode* bookmark_bar_node,
                             BookmarkNode* other_folder_node) {
  InitializeChecksum();
  DictionaryValue* roots = new DictionaryValue();
  roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node));
  roots->Set(kOtherBookmarkFolderNameKey, EncodeNode(other_folder_node));

  DictionaryValue* main = new DictionaryValue();
  main->SetInteger(kVersionKey, kCurrentVersion);
  FinalizeChecksum();
  // We are going to store the computed checksum. So set stored checksum to be
  // the same as computed checksum.
  stored_checksum_ = computed_checksum_;
  main->Set(kChecksumKey, Value::CreateStringValue(computed_checksum_));
  main->Set(kRootsKey, roots);
  return main;
}

bool BookmarkCodec::Decode(BookmarkNode* bb_node,
                           BookmarkNode* other_folder_node,
                           int* max_id,
                           const Value& value) {
  id_generator_.Reset();
  stored_checksum_.clear();
  InitializeChecksum();
  bool success = DecodeHelper(bb_node, other_folder_node, max_id, value);
  FinalizeChecksum();
  *max_id = id_generator_.current_max() + 1;
  return success;
}

Value* BookmarkCodec::EncodeNode(BookmarkNode* node) {
  DictionaryValue* value = new DictionaryValue();
  std::string id;
  if (persist_ids_) {
    id = IntToString(node->id());
    value->SetString(kIdKey, id);
  }
  const std::wstring& title = node->GetTitle();
  value->SetString(kNameKey, title);
  value->SetString(kDateAddedKey,
                   Int64ToWString(node->date_added().ToInternalValue()));
  if (node->GetType() == history::StarredEntry::URL) {
    value->SetString(kTypeKey, kTypeURL);
    std::wstring url = UTF8ToWide(node->GetURL().possibly_invalid_spec());
    value->SetString(kURLKey, url);
    UpdateChecksumWithUrlNode(id, title, url);
  } else {
    value->SetString(kTypeKey, kTypeFolder);
    value->SetString(kDateModifiedKey,
                     Int64ToWString(node->date_group_modified().
                                    ToInternalValue()));
    UpdateChecksumWithFolderNode(id, title);

    ListValue* child_values = new ListValue();
    value->Set(kChildrenKey, child_values);
    for (int i = 0; i < node->GetChildCount(); ++i)
      child_values->Append(EncodeNode(node->GetChild(i)));
  }
  return value;
}

bool BookmarkCodec::DecodeHelper(BookmarkNode* bb_node,
                                 BookmarkNode* other_folder_node,
                                 int* max_id,
                                 const Value& value) {
  if (value.GetType() != Value::TYPE_DICTIONARY)
    return false;  // Unexpected type.

  const DictionaryValue& d_value = static_cast<const DictionaryValue&>(value);

  int version;
  if (!d_value.GetInteger(kVersionKey, &version) || version != kCurrentVersion)
    return false;  // Unknown version.

  Value* checksum_value;
  if (d_value.Get(kChecksumKey, &checksum_value)) {
    if (checksum_value->GetType() != Value::TYPE_STRING)
      return false;
    StringValue* checksum_value_str = static_cast<StringValue*>(checksum_value);
    if (!checksum_value_str->GetAsString(&stored_checksum_))
      return false;
  }

  Value* roots;
  if (!d_value.Get(kRootsKey, &roots))
    return false;  // No roots.

  if (roots->GetType() != Value::TYPE_DICTIONARY)
    return false;  // Invalid type for roots.

  DictionaryValue* roots_d_value = static_cast<DictionaryValue*>(roots);
  Value* root_folder_value;
  Value* other_folder_value;
  if (!roots_d_value->Get(kRootFolderNameKey, &root_folder_value) ||
      root_folder_value->GetType() != Value::TYPE_DICTIONARY ||
      !roots_d_value->Get(kOtherBookmarkFolderNameKey, &other_folder_value) ||
      other_folder_value->GetType() != Value::TYPE_DICTIONARY)
    return false;  // Invalid type for root folder and/or other folder.

  DecodeNode(*static_cast<DictionaryValue*>(root_folder_value), NULL,
             bb_node);
  DecodeNode(*static_cast<DictionaryValue*>(other_folder_value), NULL,
             other_folder_node);
  // Need to reset the type as decoding resets the type to FOLDER. Similarly
  // we need to reset the title as the title is persisted and restored from
  // the file.
  bb_node->type_ = history::StarredEntry::BOOKMARK_BAR;
  other_folder_node->type_ = history::StarredEntry::OTHER;
  bb_node->SetTitle(l10n_util::GetString(IDS_BOOMARK_BAR_FOLDER_NAME));
  other_folder_node->SetTitle(
      l10n_util::GetString(IDS_BOOMARK_BAR_OTHER_FOLDER_NAME));

  return true;
}

bool BookmarkCodec::DecodeChildren(const ListValue& child_value_list,
                                   BookmarkNode* parent) {
  for (size_t i = 0; i < child_value_list.GetSize(); ++i) {
    Value* child_value;
    if (!child_value_list.Get(i, &child_value))
      return false;

    if (child_value->GetType() != Value::TYPE_DICTIONARY)
      return false;

    DecodeNode(*static_cast<DictionaryValue*>(child_value), parent, NULL);
  }
  return true;
}

bool BookmarkCodec::DecodeNode(const DictionaryValue& value,
                               BookmarkNode* parent,
                               BookmarkNode* node) {
  std::string id_string;
  int id = 0;
  if (persist_ids_) {
    if (value.GetString(kIdKey, &id_string))
      if (!StringToInt(id_string, &id))
        return false;
  }
  id = id_generator_.GetUniqueID(id);

  std::wstring title;
  if (!value.GetString(kNameKey, &title))
    title = std::wstring();

  std::wstring date_added_string;
  if (!value.GetString(kDateAddedKey, &date_added_string))
    date_added_string = Int64ToWString(Time::Now().ToInternalValue());

  std::wstring type_string;
  if (!value.GetString(kTypeKey, &type_string))
    return false;

  if (type_string != kTypeURL && type_string != kTypeFolder)
    return false;  // Unknown type.

  if (type_string == kTypeURL) {
    std::wstring url_string;
    if (!value.GetString(kURLKey, &url_string))
      return false;

    if (!node)
      node = new BookmarkNode(id, GURL(WideToUTF8(url_string)));
    else
      return false; // Node invalid.

    if (parent)
      parent->Add(parent->GetChildCount(), node);
    node->type_ = history::StarredEntry::URL;
    UpdateChecksumWithUrlNode(id_string, title, url_string);
  } else {
    std::wstring last_modified_date;
    if (!value.GetString(kDateModifiedKey, &last_modified_date))
      last_modified_date = Int64ToWString(Time::Now().ToInternalValue());

    Value* child_values;
    if (!value.Get(kChildrenKey, &child_values))
      return false;

    if (child_values->GetType() != Value::TYPE_LIST)
      return false;

    if (!node) {
      node = new BookmarkNode(id, GURL());
    } else {
      // If a new node is not created, explicitly assign ID to the existing one.
      DCHECK(id != 0);
      node->set_id(id);
    }

    node->type_ = history::StarredEntry::USER_GROUP;
    node->date_group_modified_ = Time::FromInternalValue(
        StringToInt64(WideToUTF16Hack(last_modified_date)));

    if (parent)
      parent->Add(parent->GetChildCount(), node);

    UpdateChecksumWithFolderNode(id_string, title);
    if (!DecodeChildren(*static_cast<ListValue*>(child_values), node))
      return false;
  }

  node->SetTitle(title);
  node->date_added_ = Time::FromInternalValue(
      StringToInt64(WideToUTF16Hack(date_added_string)));
  return true;
}

void BookmarkCodec::UpdateChecksum(const std::string& str) {
  MD5Update(&md5_context_, str.data(), str.length() * sizeof(char));
}

void BookmarkCodec::UpdateChecksum(const std::wstring& str) {
  MD5Update(&md5_context_, str.data(), str.length() * sizeof(wchar_t));
}

void BookmarkCodec::UpdateChecksumWithUrlNode(const std::string& id,
                                              const std::wstring& title,
                                              const std::wstring& url) {
  UpdateChecksum(id);
  UpdateChecksum(title);
  UpdateChecksum(kTypeURL);
  UpdateChecksum(url);
}

void BookmarkCodec::UpdateChecksumWithFolderNode(const std::string& id,
                                                 const std::wstring& title) {
  UpdateChecksum(id);
  UpdateChecksum(title);
  UpdateChecksum(kTypeFolder);
}

void BookmarkCodec::InitializeChecksum() {
  MD5Init(&md5_context_);
}

void BookmarkCodec::FinalizeChecksum() {
  MD5Digest digest;
  MD5Final(&digest, &md5_context_);
  computed_checksum_ = MD5DigestToBase16(digest);
}
<|endoftext|>