<commit_before>#include "textureatlas.h"

#include <iostream>

namespace mw {

	void TextureAtlas::uploadSdlSurfaceToTexture(SDL_Surface* image, SDL_Rect dstRec, Texture& texture) {
		// In computer memory?
		if (texture.imageData_->texture_ == 0) {
			image = SDL_ConvertSurface(image, texture.imageData_->preLoadSurface_->format, 0);
			SDL_BlitSurface(image, 0, texture.imageData_->preLoadSurface_, &dstRec);
		} else { // In graphic memory.
			helper::invert(image);
			SDL_Surface* surface = helper::createSurface(image->w, image->h);
			SDL_BlitSurface(image, 0, surface, &image->clip_rect);

#if MW_OPENGLES2
			texture.bindTexture();
			mw::glTexSubImage2D(GL_TEXTURE_2D, 0,
				dstRec.x, texture.height_ - image->h - dstRec.y, // Sdl uses upp-left, opengl uses down-left.
				image->w, image->h,
				GL_RGBA,
				GL_UNSIGNED_BYTE,
				surface->pixels);
#else // MW_OPENGLES2
			glTexSubImage2D(GL_TEXTURE_2D, 0,
				dstRec.x, texture.height_ - image->h - dstRec.y, // Sdl uses upp-left, opengl uses down-left.
				image->w, image->h,
				GL_RGBA,
				GL_UNSIGNED_BYTE,
				surface->pixels);
#endif // MW_OPENGLES2
			SDL_FreeSurface(surface);
		}
	}

	std::shared_ptr<TextureAtlas::Node> TextureAtlas::Node::createRoot(std::shared_ptr<Node>& root, int width, int height, SDL_Surface* image) {
		// Image doesn't fit?
		if (image->w > width || image->h > height) {
			// Image to large!
			return 0;
		}
		root = std::make_shared<Node>(0, 0, width, height);
		return root->insert(image);;
	}

	std::shared_ptr<TextureAtlas::Node> TextureAtlas::Node::insert(SDL_Surface* image) {
		return insert(0, image);
	}

	TextureAtlas::Node::Node(int x, int y, int w, int h) : image_(0) {
		rect_.x = x;
		rect_.y = y;
		rect_.w = w;
		rect_.h = h;
	}

	std::shared_ptr<TextureAtlas::Node> TextureAtlas::Node::insert(int currentDepth, SDL_Surface* image) {
		// Is not a leaf!
		if (left_ != 0 && right_ != 0) {
			auto node = left_->insert(currentDepth + 1, image);
			if (node != 0) {
				// Image inserted.
				return node;
			}
			// Image didn't fit, try the other node.
			return right_->insert(currentDepth + 1, image);
		} else {
			if (image_ != 0) {
				// Node is already filled!
				return 0;
			}

			if (image->w > rect_.w || image->h > rect_.h) {
				// Image to large!
				return 0;
			}

			// Fits perfectly?
			if (image->w == rect_.w && image->h == rect_.h) {
				image_ = image;
			}

			// Must split the node in half.
			if (currentDepth % 2 == 0) { // Split vertical.
				left_ = std::make_shared<Node>(rect_.x, rect_.y, rect_.w, image->h); // Up.
				right_ = std::make_shared<Node>(rect_.x, rect_.y + image->h, rect_.w, rect_.h - image->h); // Down.
			} else { // Split horizontal.
				left_ = std::make_shared<Node>(rect_.x, rect_.y, image->w, rect_.h); // Left.
				right_ = std::make_shared<Node>(rect_.x + image->w, rect_.y, rect_.w - image->w, rect_.h); // Right.
			}

			// Insert the image in the left node.
			left_->image_ = image;
			return left_;
		}
	}

	TextureAtlas::TextureAtlas() : root_(0), width_(0), height_(0) {
	}

	TextureAtlas::TextureAtlas(int width, int height, std::function<void()> filter) : root_(0), width_(width), height_(width) {
		texture_ = Texture(width, height, filter);
	}

	Sprite TextureAtlas::add(std::string filename, std::string uniqueKey) {
		int size = images_.size();
		Sprite& sprite = images_[filename + uniqueKey];

		if (size != images_.size()) {
			SDL_Surface* image = IMG_Load(filename.c_str());
			if (image != 0) {
				sprite = add(image);
				SDL_FreeSurface(image);
				return sprite;
			} else {
				images_.erase(filename + uniqueKey);
				std::cerr << "\nImage " << filename << " failed to load: " << IMG_GetError() << std::endl;
			}
		}
		return Sprite();
	}

	Sprite TextureAtlas::add(SDL_Surface* image, std::string uniqueKey) {
		std::shared_ptr<Node> node;
		if (texture_.isValid()) {
			if (root_ == 0) {
				node = Node::createRoot(root_, width_, height_, image);
			} else {
				node = root_->insert(image);
			}
		}
		if (node != 0) {
			SDL_Rect rect = node->getRect();
			uploadSdlSurfaceToTexture(image, rect, texture_);
			Sprite& sprite = images_[uniqueKey];
			sprite = Sprite(texture_, (float) rect.x, (float) (texture_.getHeight() - rect.y), (float) rect.w, (float) rect.h);
			return sprite;
		}
		return Sprite();
	}

	Sprite TextureAtlas::get(std::string key) const {
		auto it = images_.find(key);
		if (it != images_.end()) {
			return it->second;
		}
		return Sprite();
	}

} // Namespace mw.
<commit_msg>Bug fix! Missed to bind the texture in non GLES mode.<commit_after>#include "textureatlas.h"

#include <iostream>

namespace mw {

	void TextureAtlas::uploadSdlSurfaceToTexture(SDL_Surface* image, SDL_Rect dstRec, Texture& texture) {
		// In computer memory?
		if (texture.imageData_->texture_ == 0) {
			image = SDL_ConvertSurface(image, texture.imageData_->preLoadSurface_->format, 0);
			SDL_BlitSurface(image, 0, texture.imageData_->preLoadSurface_, &dstRec);
		} else { // In graphic memory.
			helper::invert(image);
			SDL_Surface* surface = helper::createSurface(image->w, image->h);
			SDL_BlitSurface(image, 0, surface, &image->clip_rect);
			texture.bindTexture();
#if MW_OPENGLES2
			mw::glTexSubImage2D(GL_TEXTURE_2D, 0,
				dstRec.x, texture.height_ - image->h - dstRec.y, // Sdl uses upp-left, opengl uses down-left.
				image->w, image->h,
				GL_RGBA,
				GL_UNSIGNED_BYTE,
				surface->pixels);
#else // MW_OPENGLES2
			glTexSubImage2D(GL_TEXTURE_2D, 0,
				dstRec.x, texture.height_ - image->h - dstRec.y, // Sdl uses upp-left, opengl uses down-left.
				image->w, image->h,
				GL_RGBA,
				GL_UNSIGNED_BYTE,
				surface->pixels);
#endif // MW_OPENGLES2
			SDL_FreeSurface(surface);
		}
	}

	std::shared_ptr<TextureAtlas::Node> TextureAtlas::Node::createRoot(std::shared_ptr<Node>& root, int width, int height, SDL_Surface* image) {
		// Image doesn't fit?
		if (image->w > width || image->h > height) {
			// Image to large!
			return 0;
		}
		root = std::make_shared<Node>(0, 0, width, height);
		return root->insert(image);;
	}

	std::shared_ptr<TextureAtlas::Node> TextureAtlas::Node::insert(SDL_Surface* image) {
		return insert(0, image);
	}

	TextureAtlas::Node::Node(int x, int y, int w, int h) : image_(0) {
		rect_.x = x;
		rect_.y = y;
		rect_.w = w;
		rect_.h = h;
	}

	std::shared_ptr<TextureAtlas::Node> TextureAtlas::Node::insert(int currentDepth, SDL_Surface* image) {
		// Is not a leaf!
		if (left_ != 0 && right_ != 0) {
			auto node = left_->insert(currentDepth + 1, image);
			if (node != 0) {
				// Image inserted.
				return node;
			}
			// Image didn't fit, try the other node.
			return right_->insert(currentDepth + 1, image);
		} else {
			if (image_ != 0) {
				// Node is already filled!
				return 0;
			}

			if (image->w > rect_.w || image->h > rect_.h) {
				// Image to large!
				return 0;
			}

			// Fits perfectly?
			if (image->w == rect_.w && image->h == rect_.h) {
				image_ = image;
			}

			// Must split the node in half.
			if (currentDepth % 2 == 0) { // Split vertical.
				left_ = std::make_shared<Node>(rect_.x, rect_.y, rect_.w, image->h); // Up.
				right_ = std::make_shared<Node>(rect_.x, rect_.y + image->h, rect_.w, rect_.h - image->h); // Down.
			} else { // Split horizontal.
				left_ = std::make_shared<Node>(rect_.x, rect_.y, image->w, rect_.h); // Left.
				right_ = std::make_shared<Node>(rect_.x + image->w, rect_.y, rect_.w - image->w, rect_.h); // Right.
			}

			// Insert the image in the left node.
			left_->image_ = image;
			return left_;
		}
	}

	TextureAtlas::TextureAtlas() : root_(0), width_(0), height_(0) {
	}

	TextureAtlas::TextureAtlas(int width, int height, std::function<void()> filter) : root_(0), width_(width), height_(width) {
		texture_ = Texture(width, height, filter);
	}

	Sprite TextureAtlas::add(std::string filename, std::string uniqueKey) {
		int size = images_.size();
		Sprite& sprite = images_[filename + uniqueKey];

		if (size != images_.size()) {
			SDL_Surface* image = IMG_Load(filename.c_str());
			if (image != 0) {
				sprite = add(image);
				SDL_FreeSurface(image);
				return sprite;
			} else {
				images_.erase(filename + uniqueKey);
				std::cerr << "\nImage " << filename << " failed to load: " << IMG_GetError() << std::endl;
			}
		}
		return Sprite();
	}

	Sprite TextureAtlas::add(SDL_Surface* image, std::string uniqueKey) {
		std::shared_ptr<Node> node;
		if (texture_.isValid()) {
			if (root_ == 0) {
				node = Node::createRoot(root_, width_, height_, image);
			} else {
				node = root_->insert(image);
			}
		}
		if (node != 0) {
			SDL_Rect rect = node->getRect();
			uploadSdlSurfaceToTexture(image, rect, texture_);
			Sprite& sprite = images_[uniqueKey];
			sprite = Sprite(texture_, (float) rect.x, (float) (texture_.getHeight() - rect.y), (float) rect.w, (float) rect.h);
			return sprite;
		}
		return Sprite();
	}

	Sprite TextureAtlas::get(std::string key) const {
		auto it = images_.find(key);
		if (it != images_.end()) {
			return it->second;
		}
		return Sprite();
	}

} // Namespace mw.
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* libvisio
 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
 * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
 *
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
 * instead of those above.
 */

#include <string>
#include "VSDInternalStream.h"
#include "libvisio_utils.h"

#define VSD_NUM_ELEMENTS(array) sizeof(array)/sizeof(array[0])

uint8_t libvisio::readU8(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint8_t))
    return *(uint8_t const *)(p);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

uint16_t libvisio::readU16(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint16_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint16_t))
    return (uint16_t)p[0]|((uint16_t)p[1]<<8);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

uint32_t libvisio::readU32(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint32_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint32_t))
    return (uint32_t)p[0]|((uint32_t)p[1]<<8)|((uint32_t)p[2]<<16)|((uint32_t)p[3]<<24);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

uint64_t libvisio::readU64(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint64_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint64_t))
    return (uint64_t)p[0]|((uint64_t)p[1]<<8)|((uint64_t)p[2]<<16)|((uint64_t)p[3]<<24)|((uint64_t)p[4]<<32)|((uint64_t)p[5]<<40)|((uint64_t)p[6]<<48)|((uint64_t)p[7]<<56);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

double libvisio::readDouble(WPXInputStream *input)
{
  union
  {
    uint64_t u;
    double d;
  } tmpUnion;

  tmpUnion.u = readU64(input);

  return tmpUnion.d;
}

void libvisio::appendFromBase64(WPXBinaryData &data, const unsigned char *base64String, size_t base64StringLength)
{
  static const std::string base64Chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

  VSDInternalStream tmpStream(base64String, base64StringLength);

  unsigned i = 0;
  char tmpCharsToDecode[4];
  while (!tmpStream.atEOS())
  {
    const char tmpChar = (char)readU8(&tmpStream);
    if (!isalnum(tmpChar) && (tmpChar != '+') && (tmpChar != '/') && (tmpChar != '='))
      continue;
    if (tmpChar == '=')
      break;
    tmpCharsToDecode[i++] = tmpChar;
    if (i == 4)
    {
      for (unsigned k = 0; k < 4; i++)
        tmpCharsToDecode[k] = base64Chars.find(tmpCharsToDecode[k]);

      data.append((unsigned char)((tmpCharsToDecode[0] << 2) + ((tmpCharsToDecode[1] & 0x30) >> 4)));
      data.append((unsigned char)(((tmpCharsToDecode[1] & 0xf) << 4) + ((tmpCharsToDecode[2] & 0x3c) >> 2)));
      data.append((unsigned char)(((tmpCharsToDecode[2] & 0x3) << 6) + tmpCharsToDecode[3]));
    }
    i = 0;
  }

  if (i)
  {
    while (i < 4)
      tmpCharsToDecode[i++] = 0;

    for (unsigned k = 0; k < 4; i++)
      tmpCharsToDecode[k] = base64Chars.find(tmpCharsToDecode[k]);

    data.append((unsigned char)((tmpCharsToDecode[0] << 2) + ((tmpCharsToDecode[1] & 0x30) >> 4)));
    data.append((unsigned char)(((tmpCharsToDecode[1] & 0xf) << 4) + ((tmpCharsToDecode[2] & 0x3c) >> 2)));
    data.append((unsigned char)(((tmpCharsToDecode[2] & 0x3) << 6) + tmpCharsToDecode[3]));
  }
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>Slight modification of the base 64 decoder<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* libvisio
 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
 * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
 *
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
 * instead of those above.
 */

#include <string>
#include "VSDInternalStream.h"
#include "libvisio_utils.h"

#define VSD_NUM_ELEMENTS(array) sizeof(array)/sizeof(array[0])

uint8_t libvisio::readU8(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint8_t))
    return *(uint8_t const *)(p);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

uint16_t libvisio::readU16(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint16_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint16_t))
    return (uint16_t)p[0]|((uint16_t)p[1]<<8);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

uint32_t libvisio::readU32(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint32_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint32_t))
    return (uint32_t)p[0]|((uint32_t)p[1]<<8)|((uint32_t)p[2]<<16)|((uint32_t)p[3]<<24);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

uint64_t libvisio::readU64(WPXInputStream *input)
{
  if (!input || input->atEOS())
  {
    VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
    throw EndOfStreamException();
  }
  unsigned long numBytesRead;
  uint8_t const *p = input->read(sizeof(uint64_t), numBytesRead);

  if (p && numBytesRead == sizeof(uint64_t))
    return (uint64_t)p[0]|((uint64_t)p[1]<<8)|((uint64_t)p[2]<<16)|((uint64_t)p[3]<<24)|((uint64_t)p[4]<<32)|((uint64_t)p[5]<<40)|((uint64_t)p[6]<<48)|((uint64_t)p[7]<<56);
  VSD_DEBUG_MSG(("Throwing EndOfStreamException\n"));
  throw EndOfStreamException();
}

double libvisio::readDouble(WPXInputStream *input)
{
  union
  {
    uint64_t u;
    double d;
  } tmpUnion;

  tmpUnion.u = readU64(input);

  return tmpUnion.d;
}

void libvisio::appendFromBase64(WPXBinaryData &data, const unsigned char *base64String, size_t base64StringLength)
{
  static const std::string base64Chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

  VSDInternalStream tmpStream(base64String, base64StringLength);

  unsigned i = 0;
  char tmpCharsToDecode[4];
  while (!tmpStream.atEOS())
  {
    const char tmpChar = (char)readU8(&tmpStream);
    if (!isalnum(tmpChar) && (tmpChar != '+') && (tmpChar != '/') && (tmpChar != '='))
      continue;
    if (tmpChar == '=')
      break;
    tmpCharsToDecode[i++] = tmpChar;
    if (i == 4)
    {
      for (unsigned k = 0; k < 4; i++)
        tmpCharsToDecode[k] = base64Chars.find(tmpCharsToDecode[k]);

      data.append((unsigned char)((tmpCharsToDecode[0] << 2) | ((tmpCharsToDecode[1] & 0x30) >> 4)));
      data.append((unsigned char)(((tmpCharsToDecode[1] & 0xf) << 4) | ((tmpCharsToDecode[2] & 0x3c) >> 2)));
      data.append((unsigned char)(((tmpCharsToDecode[2] & 0x3) << 6) | tmpCharsToDecode[3]));
    }
    i = 0;
  }

  if (i)
  {
    for (unsigned k = 0; k < 4; k++)
    {
      if (k < i)
        tmpCharsToDecode[k] = base64Chars.find(tmpCharsToDecode[k]);
      else
        tmpCharsToDecode[k] = 0;
    }

    data.append((unsigned char)((tmpCharsToDecode[0] << 2) | ((tmpCharsToDecode[1] & 0x30) >> 4)));
    if (i > 1)
    {
      data.append((unsigned char)(((tmpCharsToDecode[1] & 0xf) << 4) | ((tmpCharsToDecode[2] & 0x3c) >> 2)));
      if (i > 2)
        data.append((unsigned char)(((tmpCharsToDecode[2] & 0x3) << 6) | tmpCharsToDecode[3]));
    }
  }
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "build/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#include <objidl.h>
#include <mlang.h>
#endif

#include "chrome/renderer/render_process_impl.h"

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/sys_info.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/render_messages.h"
#include "chrome/renderer/render_thread.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_view.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message_utils.h"
#include "media/base/media.h"
#include "media/base/media_switches.h"
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/surface/transport_dib.h"
#include "webkit/plugins/npapi/plugin_instance.h"
#include "webkit/plugins/npapi/plugin_lib.h"
#include "webkit/glue/webkit_glue.h"

#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#elif defined(OS_WIN)
#include "app/win/iat_patch_function.h"
#endif

#if defined(OS_LINUX)
#include "content/renderer/renderer_sandbox_support_linux.h"
#endif

#if defined(OS_WIN)

static app::win::IATPatchFunction g_iat_patch_createdca;
HDC WINAPI CreateDCAPatch(LPCSTR driver_name,
                          LPCSTR device_name,
                          LPCSTR output,
                          const void* init_data) {
  DCHECK(std::string("DISPLAY") == std::string(driver_name));
  DCHECK(!device_name);
  DCHECK(!output);
  DCHECK(!init_data);

  // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
  return CreateCompatibleDC(NULL);
}

static app::win::IATPatchFunction g_iat_patch_get_font_data;
DWORD WINAPI GetFontDataPatch(HDC hdc,
                              DWORD table,
                              DWORD offset,
                              LPVOID buffer,
                              DWORD length) {
  int rv = GetFontData(hdc, table, offset, buffer, length);
  if (rv == GDI_ERROR && hdc) {
    HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));

    LOGFONT logfont;
    if (GetObject(font, sizeof(LOGFONT), &logfont)) {
      std::vector<char> font_data;
      if (RenderThread::current()->Send(new ViewHostMsg_PreCacheFont(logfont)))
        rv = GetFontData(hdc, table, offset, buffer, length);
    }
  }
  return rv;
}

#endif

RenderProcessImpl::RenderProcessImpl()
    : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
          base::TimeDelta::FromSeconds(5),
          this, &RenderProcessImpl::ClearTransportDIBCache)),
      transport_dib_next_sequence_number_(0) {
  in_process_plugins_ = InProcessPlugins();
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i)
    shared_mem_cache_[i] = NULL;

#if defined(OS_WIN)
  // HACK:  See http://b/issue?id=1024307 for rationale.
  if (GetModuleHandle(L"LPK.DLL") == NULL) {
    // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works
    // when buffering into a EMF buffer for printing.
    typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs);
    GdiInitializeLanguagePack gdi_init_lpk =
        reinterpret_cast<GdiInitializeLanguagePack>(GetProcAddress(
            GetModuleHandle(L"GDI32.DLL"),
            "GdiInitializeLanguagePack"));
    DCHECK(gdi_init_lpk);
    if (gdi_init_lpk) {
      gdi_init_lpk(0);
    }
  }
#endif

  // Out of process dev tools rely upon auto break behavior.
  webkit_glue::SetJavaScriptFlags(
      "--debugger-auto-break"
      // Enable lazy in-memory profiling.
      " --prof --prof-lazy --logfile=*");

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
    webkit_glue::SetJavaScriptFlags(
        command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
  }

  if (command_line.HasSwitch(switches::kEnableWatchdog)) {
    // TODO(JAR): Need to implement renderer IO msgloop watchdog.
  }

  if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
    base::StatisticsRecorder::set_dump_on_exit(true);
  }

  // Note that under Linux, the media library will normally already have
  // been initialized by the Zygote before this instance became a Renderer.
  FilePath media_path;
  if (PathService::Get(chrome::DIR_MEDIA_LIBS, &media_path))
    media::InitializeMediaLibrary(media_path);

#if !defined(OS_MACOSX)
  // TODO(hclam): Add more checks here. Currently this is not used.
  if (media::IsMediaLibraryInitialized() &&
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableOpenMax)) {
    media::InitializeOpenMaxLibrary(media_path);
  }
#endif

#if defined(OS_WIN)
  // Need to patch a few functions for font loading to work correctly.
  FilePath pdf;
  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&
      file_util::PathExists(pdf)) {
    g_iat_patch_createdca.Patch(
        pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch);
    g_iat_patch_get_font_data.Patch(
        pdf.value().c_str(), "gdi32.dll", "GetFontData", GetFontDataPatch);
  }
#endif

#if defined(OS_LINUX)
  // Remoting requires NSS to function properly.
  if (command_line.HasSwitch(switches::kEnableRemoting)) {
#if defined(USE_NSS)
    // We are going to fork to engage the sandbox and we have not loaded
    // any security modules so it is safe to disable the fork check in NSS.
    base::DisableNSSForkCheck();
    base::ForceNSSNoDBInit();
    base::EnsureNSSInit();
#else
    // TODO(bulach): implement openssl support.
    NOTREACHED() << "Remoting is not supported for openssl";
#endif
  }
#endif
}

RenderProcessImpl::~RenderProcessImpl() {
  // TODO(port): Try and limit what we pull in for our non-Win unit test bundle.
#ifndef NDEBUG
  // log important leaked objects
  webkit_glue::CheckForLeaks();
#endif

  GetShutDownEvent()->Signal();
  ClearTransportDIBCache();
}

bool RenderProcessImpl::InProcessPlugins() {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
#if defined(OS_LINUX)
  // Plugin processes require a UI message loop, and the Linux message loop
  // implementation only allows one UI loop per process.
  if (command_line.HasSwitch(switches::kInProcessPlugins))
    NOTIMPLEMENTED() << ": in process plugins not supported on Linux";
  return command_line.HasSwitch(switches::kInProcessPlugins);
#else
  return command_line.HasSwitch(switches::kInProcessPlugins) ||
         command_line.HasSwitch(switches::kSingleProcess);
#endif
}

// -----------------------------------------------------------------------------
// Platform specific code for dealing with bitmap transport...

TransportDIB* RenderProcessImpl::CreateTransportDIB(size_t size) {
#if defined(OS_WIN) || defined(OS_LINUX)
  // Windows and Linux create transport DIBs inside the renderer
  return TransportDIB::Create(size, transport_dib_next_sequence_number_++);
#elif defined(OS_MACOSX)  // defined(OS_WIN) || defined(OS_LINUX)
  // Mac creates transport DIBs in the browser, so we need to do a sync IPC to
  // get one.  The TransportDIB is cached in the browser.
  TransportDIB::Handle handle;
  IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, true, &handle);
  if (!main_thread()->Send(msg))
    return NULL;
  if (handle.fd < 0)
    return NULL;
  return TransportDIB::Map(handle);
#endif  // defined(OS_MACOSX)
}

void RenderProcessImpl::FreeTransportDIB(TransportDIB* dib) {
  if (!dib)
    return;

#if defined(OS_MACOSX)
  // On Mac we need to tell the browser that it can drop a reference to the
  // shared memory.
  IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id());
  main_thread()->Send(msg);
#endif

  delete dib;
}

// -----------------------------------------------------------------------------

skia::PlatformCanvas* RenderProcessImpl::GetDrawingCanvas(
    TransportDIB** memory, const gfx::Rect& rect) {
  int width = rect.width();
  int height = rect.height();
  const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width());
#if defined(OS_LINUX)
  const size_t max_size = base::SysInfo::MaxSharedMemorySize();
#else
  const size_t max_size = 0;
#endif

  // If the requested size is too big, reduce the height. Ideally we might like
  // to reduce the width as well to make the size reduction more "balanced", but
  // it rarely comes up in practice.
  if ((max_size != 0) && (height * stride > max_size))
    height = max_size / stride;

  const size_t size = height * stride;

  if (!GetTransportDIBFromCache(memory, size)) {
    *memory = CreateTransportDIB(size);
    if (!*memory)
      return NULL;
  }

  return (*memory)->GetPlatformCanvas(width, height);
}

void RenderProcessImpl::ReleaseTransportDIB(TransportDIB* mem) {
  if (PutSharedMemInCache(mem)) {
    shared_mem_cache_cleaner_.Reset();
    return;
  }

  FreeTransportDIB(mem);
}

bool RenderProcessImpl::UseInProcessPlugins() const {
  return in_process_plugins_;
}

bool RenderProcessImpl::HasInitializedMediaLibrary() const {
  return media::IsMediaLibraryInitialized();
}

bool RenderProcessImpl::GetTransportDIBFromCache(TransportDIB** mem,
                                             size_t size) {
  // look for a cached object that is suitable for the requested size.
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
    if (shared_mem_cache_[i] &&
        size <= shared_mem_cache_[i]->size()) {
      *mem = shared_mem_cache_[i];
      shared_mem_cache_[i] = NULL;
      return true;
    }
  }

  return false;
}

int RenderProcessImpl::FindFreeCacheSlot(size_t size) {
  // simple algorithm:
  //  - look for an empty slot to store mem, or
  //  - if full, then replace smallest entry which is smaller than |size|
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
    if (shared_mem_cache_[i] == NULL)
      return i;
  }

  size_t smallest_size = size;
  int smallest_index = -1;

  for (size_t i = 1; i < arraysize(shared_mem_cache_); ++i) {
    const size_t entry_size = shared_mem_cache_[i]->size();
    if (entry_size < smallest_size) {
      smallest_size = entry_size;
      smallest_index = i;
    }
  }

  if (smallest_index != -1) {
    FreeTransportDIB(shared_mem_cache_[smallest_index]);
    shared_mem_cache_[smallest_index] = NULL;
  }

  return smallest_index;
}

bool RenderProcessImpl::PutSharedMemInCache(TransportDIB* mem) {
  const int slot = FindFreeCacheSlot(mem->size());
  if (slot == -1)
    return false;

  shared_mem_cache_[slot] = mem;
  return true;
}

void RenderProcessImpl::ClearTransportDIBCache() {
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
    if (shared_mem_cache_[i]) {
      FreeTransportDIB(shared_mem_cache_[i]);
      shared_mem_cache_[i] = NULL;
    }
  }
}
<commit_msg>Fix NSS in single process mode<commit_after>// Copyright (c) 2011 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 "build/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#include <objidl.h>
#include <mlang.h>
#endif

#include "chrome/renderer/render_process_impl.h"

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/sys_info.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/render_messages.h"
#include "chrome/renderer/render_thread.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_view.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message_utils.h"
#include "media/base/media.h"
#include "media/base/media_switches.h"
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/surface/transport_dib.h"
#include "webkit/plugins/npapi/plugin_instance.h"
#include "webkit/plugins/npapi/plugin_lib.h"
#include "webkit/glue/webkit_glue.h"

#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#elif defined(OS_WIN)
#include "app/win/iat_patch_function.h"
#endif

#if defined(OS_LINUX)
#include "content/renderer/renderer_sandbox_support_linux.h"
#endif

#if defined(OS_WIN)

static app::win::IATPatchFunction g_iat_patch_createdca;
HDC WINAPI CreateDCAPatch(LPCSTR driver_name,
                          LPCSTR device_name,
                          LPCSTR output,
                          const void* init_data) {
  DCHECK(std::string("DISPLAY") == std::string(driver_name));
  DCHECK(!device_name);
  DCHECK(!output);
  DCHECK(!init_data);

  // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
  return CreateCompatibleDC(NULL);
}

static app::win::IATPatchFunction g_iat_patch_get_font_data;
DWORD WINAPI GetFontDataPatch(HDC hdc,
                              DWORD table,
                              DWORD offset,
                              LPVOID buffer,
                              DWORD length) {
  int rv = GetFontData(hdc, table, offset, buffer, length);
  if (rv == GDI_ERROR && hdc) {
    HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));

    LOGFONT logfont;
    if (GetObject(font, sizeof(LOGFONT), &logfont)) {
      std::vector<char> font_data;
      if (RenderThread::current()->Send(new ViewHostMsg_PreCacheFont(logfont)))
        rv = GetFontData(hdc, table, offset, buffer, length);
    }
  }
  return rv;
}

#endif

RenderProcessImpl::RenderProcessImpl()
    : ALLOW_THIS_IN_INITIALIZER_LIST(shared_mem_cache_cleaner_(
          base::TimeDelta::FromSeconds(5),
          this, &RenderProcessImpl::ClearTransportDIBCache)),
      transport_dib_next_sequence_number_(0) {
  in_process_plugins_ = InProcessPlugins();
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i)
    shared_mem_cache_[i] = NULL;

#if defined(OS_WIN)
  // HACK:  See http://b/issue?id=1024307 for rationale.
  if (GetModuleHandle(L"LPK.DLL") == NULL) {
    // Makes sure lpk.dll is loaded by gdi32 to make sure ExtTextOut() works
    // when buffering into a EMF buffer for printing.
    typedef BOOL (__stdcall *GdiInitializeLanguagePack)(int LoadedShapingDLLs);
    GdiInitializeLanguagePack gdi_init_lpk =
        reinterpret_cast<GdiInitializeLanguagePack>(GetProcAddress(
            GetModuleHandle(L"GDI32.DLL"),
            "GdiInitializeLanguagePack"));
    DCHECK(gdi_init_lpk);
    if (gdi_init_lpk) {
      gdi_init_lpk(0);
    }
  }
#endif

  // Out of process dev tools rely upon auto break behavior.
  webkit_glue::SetJavaScriptFlags(
      "--debugger-auto-break"
      // Enable lazy in-memory profiling.
      " --prof --prof-lazy --logfile=*");

  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
    webkit_glue::SetJavaScriptFlags(
        command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
  }

  if (command_line.HasSwitch(switches::kEnableWatchdog)) {
    // TODO(JAR): Need to implement renderer IO msgloop watchdog.
  }

  if (command_line.HasSwitch(switches::kDumpHistogramsOnExit)) {
    base::StatisticsRecorder::set_dump_on_exit(true);
  }

  // Note that under Linux, the media library will normally already have
  // been initialized by the Zygote before this instance became a Renderer.
  FilePath media_path;
  if (PathService::Get(chrome::DIR_MEDIA_LIBS, &media_path))
    media::InitializeMediaLibrary(media_path);

#if !defined(OS_MACOSX)
  // TODO(hclam): Add more checks here. Currently this is not used.
  if (media::IsMediaLibraryInitialized() &&
      CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableOpenMax)) {
    media::InitializeOpenMaxLibrary(media_path);
  }
#endif

#if defined(OS_WIN)
  // Need to patch a few functions for font loading to work correctly.
  FilePath pdf;
  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&
      file_util::PathExists(pdf)) {
    g_iat_patch_createdca.Patch(
        pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch);
    g_iat_patch_get_font_data.Patch(
        pdf.value().c_str(), "gdi32.dll", "GetFontData", GetFontDataPatch);
  }
#endif

#if defined(OS_LINUX)
  // Remoting requires NSS to function properly.

  if (!command_line.HasSwitch(switches::kSingleProcess) &&
      command_line.HasSwitch(switches::kEnableRemoting)) {
#if defined(USE_NSS)
    // We are going to fork to engage the sandbox and we have not loaded
    // any security modules so it is safe to disable the fork check in NSS.
    base::DisableNSSForkCheck();
    base::ForceNSSNoDBInit();
    base::EnsureNSSInit();
#else
    // TODO(bulach): implement openssl support.
    NOTREACHED() << "Remoting is not supported for openssl";
#endif
  }
#endif
}

RenderProcessImpl::~RenderProcessImpl() {
  // TODO(port): Try and limit what we pull in for our non-Win unit test bundle.
#ifndef NDEBUG
  // log important leaked objects
  webkit_glue::CheckForLeaks();
#endif

  GetShutDownEvent()->Signal();
  ClearTransportDIBCache();
}

bool RenderProcessImpl::InProcessPlugins() {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
#if defined(OS_LINUX)
  // Plugin processes require a UI message loop, and the Linux message loop
  // implementation only allows one UI loop per process.
  if (command_line.HasSwitch(switches::kInProcessPlugins))
    NOTIMPLEMENTED() << ": in process plugins not supported on Linux";
  return command_line.HasSwitch(switches::kInProcessPlugins);
#else
  return command_line.HasSwitch(switches::kInProcessPlugins) ||
         command_line.HasSwitch(switches::kSingleProcess);
#endif
}

// -----------------------------------------------------------------------------
// Platform specific code for dealing with bitmap transport...

TransportDIB* RenderProcessImpl::CreateTransportDIB(size_t size) {
#if defined(OS_WIN) || defined(OS_LINUX)
  // Windows and Linux create transport DIBs inside the renderer
  return TransportDIB::Create(size, transport_dib_next_sequence_number_++);
#elif defined(OS_MACOSX)  // defined(OS_WIN) || defined(OS_LINUX)
  // Mac creates transport DIBs in the browser, so we need to do a sync IPC to
  // get one.  The TransportDIB is cached in the browser.
  TransportDIB::Handle handle;
  IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(size, true, &handle);
  if (!main_thread()->Send(msg))
    return NULL;
  if (handle.fd < 0)
    return NULL;
  return TransportDIB::Map(handle);
#endif  // defined(OS_MACOSX)
}

void RenderProcessImpl::FreeTransportDIB(TransportDIB* dib) {
  if (!dib)
    return;

#if defined(OS_MACOSX)
  // On Mac we need to tell the browser that it can drop a reference to the
  // shared memory.
  IPC::Message* msg = new ViewHostMsg_FreeTransportDIB(dib->id());
  main_thread()->Send(msg);
#endif

  delete dib;
}

// -----------------------------------------------------------------------------

skia::PlatformCanvas* RenderProcessImpl::GetDrawingCanvas(
    TransportDIB** memory, const gfx::Rect& rect) {
  int width = rect.width();
  int height = rect.height();
  const size_t stride = skia::PlatformCanvas::StrideForWidth(rect.width());
#if defined(OS_LINUX)
  const size_t max_size = base::SysInfo::MaxSharedMemorySize();
#else
  const size_t max_size = 0;
#endif

  // If the requested size is too big, reduce the height. Ideally we might like
  // to reduce the width as well to make the size reduction more "balanced", but
  // it rarely comes up in practice.
  if ((max_size != 0) && (height * stride > max_size))
    height = max_size / stride;

  const size_t size = height * stride;

  if (!GetTransportDIBFromCache(memory, size)) {
    *memory = CreateTransportDIB(size);
    if (!*memory)
      return NULL;
  }

  return (*memory)->GetPlatformCanvas(width, height);
}

void RenderProcessImpl::ReleaseTransportDIB(TransportDIB* mem) {
  if (PutSharedMemInCache(mem)) {
    shared_mem_cache_cleaner_.Reset();
    return;
  }

  FreeTransportDIB(mem);
}

bool RenderProcessImpl::UseInProcessPlugins() const {
  return in_process_plugins_;
}

bool RenderProcessImpl::HasInitializedMediaLibrary() const {
  return media::IsMediaLibraryInitialized();
}

bool RenderProcessImpl::GetTransportDIBFromCache(TransportDIB** mem,
                                             size_t size) {
  // look for a cached object that is suitable for the requested size.
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
    if (shared_mem_cache_[i] &&
        size <= shared_mem_cache_[i]->size()) {
      *mem = shared_mem_cache_[i];
      shared_mem_cache_[i] = NULL;
      return true;
    }
  }

  return false;
}

int RenderProcessImpl::FindFreeCacheSlot(size_t size) {
  // simple algorithm:
  //  - look for an empty slot to store mem, or
  //  - if full, then replace smallest entry which is smaller than |size|
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
    if (shared_mem_cache_[i] == NULL)
      return i;
  }

  size_t smallest_size = size;
  int smallest_index = -1;

  for (size_t i = 1; i < arraysize(shared_mem_cache_); ++i) {
    const size_t entry_size = shared_mem_cache_[i]->size();
    if (entry_size < smallest_size) {
      smallest_size = entry_size;
      smallest_index = i;
    }
  }

  if (smallest_index != -1) {
    FreeTransportDIB(shared_mem_cache_[smallest_index]);
    shared_mem_cache_[smallest_index] = NULL;
  }

  return smallest_index;
}

bool RenderProcessImpl::PutSharedMemInCache(TransportDIB* mem) {
  const int slot = FindFreeCacheSlot(mem->size());
  if (slot == -1)
    return false;

  shared_mem_cache_[slot] = mem;
  return true;
}

void RenderProcessImpl::ClearTransportDIBCache() {
  for (size_t i = 0; i < arraysize(shared_mem_cache_); ++i) {
    if (shared_mem_cache_[i]) {
      FreeTransportDIB(shared_mem_cache_[i]);
      shared_mem_cache_[i] = NULL;
    }
  }
}
<|endoftext|>


<commit_before>/*
* DSA
* (C) 1999-2010,2014,2016 Jack Lloyd
* (C) 2016 René Korthaus
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/dsa.h>
#include <botan/keypair.h>
#include <botan/pow_mod.h>
#include <botan/reducer.h>
#include <botan/rng.h>
#include <botan/internal/pk_ops_impl.h>

#if defined(BOTAN_HAS_RFC6979_GENERATOR)
  #include <botan/emsa.h>
  #include <botan/rfc6979.h>
#endif

namespace Botan {

/*
* DSA_PublicKey Constructor
*/
DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
   {
   m_group = grp;
   m_y = y1;
   }

/*
* Create a DSA private key
*/
DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
                               const DL_Group& grp,
                               const BigInt& x_arg)
   {
   m_group = grp;

   if(x_arg == 0)
      m_x = BigInt::random_integer(rng, 2, group_q());
   else
      m_x = x_arg;

   m_y = m_group.power_g_p(m_x);
   }

DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
                               const secure_vector<uint8_t>& key_bits) :
   DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
   {
   m_y = m_group.power_g_p(m_x);
   }

/*
* Check Private DSA Parameters
*/
bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
   {
   if(!DL_Scheme_PrivateKey::check_key(rng, strong) || m_x >= group_q())
      return false;

   if(!strong)
      return true;

   return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
   }

namespace {

/**
* Object that can create a DSA signature
*/
class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
   {
   public:
      DSA_Signature_Operation(const DSA_PrivateKey& dsa, const std::string& emsa) :
         PK_Ops::Signature_with_EMSA(emsa),
         m_group(dsa.get_group()),
         m_x(dsa.get_x()),
         m_mod_q(dsa.group_q())
         {
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
         m_rfc6979_hash = hash_for_emsa(emsa);
#endif
         }

      size_t max_input_bits() const override { return m_group.get_q().bits(); }

      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
                                   RandomNumberGenerator& rng) override;
   private:
      const DL_Group m_group;
      const BigInt& m_x;
      Modular_Reducer m_mod_q;
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
      std::string m_rfc6979_hash;
#endif
   };

secure_vector<uint8_t>
DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
                                  RandomNumberGenerator& rng)
   {
   const BigInt& q = m_group.get_q();

   BigInt i(msg, msg_len, q.bits());

   while(i >= q)
      i -= q;

#if defined(BOTAN_HAS_RFC6979_GENERATOR)
   BOTAN_UNUSED(rng);
   const BigInt k = generate_rfc6979_nonce(m_x, q, i, m_rfc6979_hash);
#else
   const BigInt k = BigInt::random_integer(rng, 1, q);
#endif

   BigInt s = inverse_mod(k, q);
   const BigInt r = m_mod_q.reduce(m_group.power_g_p(k));

   s = m_mod_q.multiply(s, mul_add(m_x, r, i));

   // With overwhelming probability, a bug rather than actual zero r/s
   if(r.is_zero() || s.is_zero())
      throw Internal_Error("Computed zero r/s during DSA signature");

   return BigInt::encode_fixed_length_int_pair(r, s, q.bytes());
   }

/**
* Object that can verify a DSA signature
*/
class DSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
   {
   public:
      DSA_Verification_Operation(const DSA_PublicKey& dsa,
                                 const std::string& emsa) :
         PK_Ops::Verification_with_EMSA(emsa),
         m_group(dsa.get_group()),
         m_y(dsa.get_y()),
         m_mod_q(dsa.group_q())
         {}

      size_t max_input_bits() const override { return m_group.get_q().bits(); }

      bool with_recovery() const override { return false; }

      bool verify(const uint8_t msg[], size_t msg_len,
                  const uint8_t sig[], size_t sig_len) override;
   private:
      const DL_Group m_group;
      const BigInt& m_y;

      Modular_Reducer m_mod_q;
   };

bool DSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
                                        const uint8_t sig[], size_t sig_len)
   {
   const BigInt& q = m_group.get_q();
   const size_t q_bytes = q.bytes();

   if(sig_len != 2*q_bytes || msg_len > q_bytes)
      return false;

   BigInt r(sig, q_bytes);
   BigInt s(sig + q_bytes, q_bytes);
   BigInt i(msg, msg_len, q.bits());

   if(r <= 0 || r >= q || s <= 0 || s >= q)
      return false;

   s = inverse_mod(s, q);

   const BigInt sr = m_mod_q.multiply(s, r);
   const BigInt si = m_mod_q.multiply(s, i);

   s = m_group.multi_exponentiate(si, m_y, sr);

   return (m_mod_q.reduce(s) == r);
   }

}

std::unique_ptr<PK_Ops::Verification>
DSA_PublicKey::create_verification_op(const std::string& params,
                                      const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Verification>(new DSA_Verification_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

std::unique_ptr<PK_Ops::Signature>
DSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
                                    const std::string& params,
                                    const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Signature>(new DSA_Signature_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

}
<commit_msg>Remove unused include<commit_after>/*
* DSA
* (C) 1999-2010,2014,2016 Jack Lloyd
* (C) 2016 René Korthaus
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/dsa.h>
#include <botan/keypair.h>
#include <botan/reducer.h>
#include <botan/rng.h>
#include <botan/internal/pk_ops_impl.h>

#if defined(BOTAN_HAS_RFC6979_GENERATOR)
  #include <botan/emsa.h>
  #include <botan/rfc6979.h>
#endif

namespace Botan {

/*
* DSA_PublicKey Constructor
*/
DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1)
   {
   m_group = grp;
   m_y = y1;
   }

/*
* Create a DSA private key
*/
DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng,
                               const DL_Group& grp,
                               const BigInt& x_arg)
   {
   m_group = grp;

   if(x_arg == 0)
      m_x = BigInt::random_integer(rng, 2, group_q());
   else
      m_x = x_arg;

   m_y = m_group.power_g_p(m_x);
   }

DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
                               const secure_vector<uint8_t>& key_bits) :
   DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
   {
   m_y = m_group.power_g_p(m_x);
   }

/*
* Check Private DSA Parameters
*/
bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
   {
   if(!DL_Scheme_PrivateKey::check_key(rng, strong) || m_x >= group_q())
      return false;

   if(!strong)
      return true;

   return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
   }

namespace {

/**
* Object that can create a DSA signature
*/
class DSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
   {
   public:
      DSA_Signature_Operation(const DSA_PrivateKey& dsa, const std::string& emsa) :
         PK_Ops::Signature_with_EMSA(emsa),
         m_group(dsa.get_group()),
         m_x(dsa.get_x()),
         m_mod_q(dsa.group_q())
         {
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
         m_rfc6979_hash = hash_for_emsa(emsa);
#endif
         }

      size_t max_input_bits() const override { return m_group.get_q().bits(); }

      secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
                                   RandomNumberGenerator& rng) override;
   private:
      const DL_Group m_group;
      const BigInt& m_x;
      Modular_Reducer m_mod_q;
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
      std::string m_rfc6979_hash;
#endif
   };

secure_vector<uint8_t>
DSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
                                  RandomNumberGenerator& rng)
   {
   const BigInt& q = m_group.get_q();

   BigInt i(msg, msg_len, q.bits());

   while(i >= q)
      i -= q;

#if defined(BOTAN_HAS_RFC6979_GENERATOR)
   BOTAN_UNUSED(rng);
   const BigInt k = generate_rfc6979_nonce(m_x, q, i, m_rfc6979_hash);
#else
   const BigInt k = BigInt::random_integer(rng, 1, q);
#endif

   BigInt s = inverse_mod(k, q);
   const BigInt r = m_mod_q.reduce(m_group.power_g_p(k));

   s = m_mod_q.multiply(s, mul_add(m_x, r, i));

   // With overwhelming probability, a bug rather than actual zero r/s
   if(r.is_zero() || s.is_zero())
      throw Internal_Error("Computed zero r/s during DSA signature");

   return BigInt::encode_fixed_length_int_pair(r, s, q.bytes());
   }

/**
* Object that can verify a DSA signature
*/
class DSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
   {
   public:
      DSA_Verification_Operation(const DSA_PublicKey& dsa,
                                 const std::string& emsa) :
         PK_Ops::Verification_with_EMSA(emsa),
         m_group(dsa.get_group()),
         m_y(dsa.get_y()),
         m_mod_q(dsa.group_q())
         {}

      size_t max_input_bits() const override { return m_group.get_q().bits(); }

      bool with_recovery() const override { return false; }

      bool verify(const uint8_t msg[], size_t msg_len,
                  const uint8_t sig[], size_t sig_len) override;
   private:
      const DL_Group m_group;
      const BigInt& m_y;

      Modular_Reducer m_mod_q;
   };

bool DSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
                                        const uint8_t sig[], size_t sig_len)
   {
   const BigInt& q = m_group.get_q();
   const size_t q_bytes = q.bytes();

   if(sig_len != 2*q_bytes || msg_len > q_bytes)
      return false;

   BigInt r(sig, q_bytes);
   BigInt s(sig + q_bytes, q_bytes);
   BigInt i(msg, msg_len, q.bits());

   if(r <= 0 || r >= q || s <= 0 || s >= q)
      return false;

   s = inverse_mod(s, q);

   const BigInt sr = m_mod_q.multiply(s, r);
   const BigInt si = m_mod_q.multiply(s, i);

   s = m_group.multi_exponentiate(si, m_y, sr);

   return (m_mod_q.reduce(s) == r);
   }

}

std::unique_ptr<PK_Ops::Verification>
DSA_PublicKey::create_verification_op(const std::string& params,
                                      const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Verification>(new DSA_Verification_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

std::unique_ptr<PK_Ops::Signature>
DSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
                                    const std::string& params,
                                    const std::string& provider) const
   {
   if(provider == "base" || provider.empty())
      return std::unique_ptr<PK_Ops::Signature>(new DSA_Signature_Operation(*this, params));
   throw Provider_Not_Found(algo_name(), provider);
   }

}
<|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		09/2009
*/

#include "Precompiled.h"
#include "InputManager.h"

#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
#include <windows.h>
#endif

namespace input
{

#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32

	MyGUI::Char translateWin32Text(MyGUI::KeyCode kc)
	{
		static WCHAR deadKey = 0;

		BYTE keyState[256];
		HKL  layout = GetKeyboardLayout(0);
		if ( GetKeyboardState(keyState) == 0 )
			return 0;

		int code = *((int*)&kc);
		unsigned int vk = MapVirtualKeyEx((UINT)code, 3, layout);
		if ( vk == 0 )
			return 0;

		WCHAR buff[3] = { 0, 0, 0 };
		int ascii = ToUnicodeEx(vk, (UINT)code, keyState, buff, 3, 0, layout);
		if (ascii == 1 && deadKey != '\0' )
		{
			// A dead key is stored and we have just converted a character key
			// Combine the two into a single character
			WCHAR wcBuff[3] = { buff[0], deadKey, '\0' };
			WCHAR out[3];

			deadKey = '\0';
			if (FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
				return out[0];
		}
		else if (ascii == 1)
		{
			// We have a single character
			deadKey = '\0';
			return buff[0];
		}
		else if (ascii == 2)
		{
			// Convert a non-combining diacritical mark into a combining diacritical mark
			// Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
			// http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
			switch (buff[0])
			{
			case 0x5E: // Circumflex accent:
				deadKey = 0x302;
				break;
			case 0x60: // Grave accent:
				deadKey = 0x300;
				break;
			case 0xA8: // Diaeresis:
				deadKey = 0x308;
				break;
			case 0xB4: // Acute accent:
				deadKey = 0x301;
				break;
			case 0xB8: // Cedilla:
				deadKey = 0x327;
				break;
			default:
				deadKey = buff[0];
				break;
			}
		}

		return 0;
	}

#endif

	InputManager::InputManager() :
		mInputManager(0),
		mKeyboard(0),
		mMouse(0),
		mCursorX(0),
		mCursorY(0)
	{
	}

	InputManager::~InputManager()
	{
	}

	void InputManager::createInput(size_t _handle)
	{
		std::ostringstream windowHndStr;
		windowHndStr << _handle;

		OIS::ParamList pl;
		pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));

		mInputManager = OIS::InputManager::createInputSystem(pl);

		mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
		mKeyboard->setEventCallback(this);

		mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));
		mMouse->setEventCallback(this);
	}

	void InputManager::destroyInput()
	{
		if (mInputManager)
		{
			if (mMouse)
			{
				mInputManager->destroyInputObject( mMouse );
				mMouse = nullptr;
			}
			if (mKeyboard)
			{
				mInputManager->destroyInputObject( mKeyboard );
				mKeyboard = nullptr;
			}
			OIS::InputManager::destroyInputSystem(mInputManager);
			mInputManager = nullptr;
		}
	}

	bool InputManager::mouseMoved(const OIS::MouseEvent& _arg)
	{
		mCursorX += _arg.state.X.rel;
		mCursorY += _arg.state.Y.rel;

		checkPosition();

		injectMouseMove(mCursorX, mCursorY, _arg.state.Z.abs);
		return true;
	}

	bool InputManager::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id)
	{
		injectMousePress(mCursorX, mCursorY, MyGUI::MouseButton::Enum(_id));
		return true;
	}

	bool InputManager::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id)
	{
		injectMouseRelease(mCursorX, mCursorY, MyGUI::MouseButton::Enum(_id));
		return true;
	}

	bool InputManager::keyPressed(const OIS::KeyEvent& _arg)
	{
		MyGUI::Char text = (MyGUI::Char)_arg.text;
		MyGUI::KeyCode key = MyGUI::KeyCode::Enum(_arg.key);
		int scan_code = key.toValue();

		if (scan_code > 70 && scan_code < 84)
		{
			static MyGUI::Char nums[13] = { 55, 56, 57, 45, 52, 53, 54, 43, 49, 50, 51, 48, 46 };
			text = nums[scan_code-71];
		}
		else if (key == MyGUI::KeyCode::Divide)
		{
			text = '/';
		}
		else
		{
#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
			text = translateWin32Text(key);
#endif
		}

		injectKeyPress(key, text);
		return true;
	}

	bool InputManager::keyReleased(const OIS::KeyEvent& _arg)
	{
		injectKeyRelease(MyGUI::KeyCode::Enum(_arg.key));
		return true;
	}

	void InputManager::captureInput()
	{
		if (mMouse) mMouse->capture();
		mKeyboard->capture();
	}

	void InputManager::setInputViewSize(int _width, int _height)
	{
		if (mMouse)
		{
			const OIS::MouseState& ms = mMouse->getMouseState();
			ms.width = _width;
			ms.height = _height;

			checkPosition();
		}
	}

	void InputManager::setMousePosition(int _x, int _y)
	{
		//const OIS::MouseState &ms = mMouse->getMouseState();
		mCursorX = _x;
		mCursorY = _y;

		checkPosition();
	}

	void InputManager::checkPosition()
	{
		const OIS::MouseState& ms = mMouse->getMouseState();

		if (mCursorX < 0)
			mCursorX = 0;
		else if (mCursorX >= ms.width)
			mCursorX = ms.width - 1;

		if (mCursorY < 0)
			mCursorY = 0;
		else if (mCursorY >= ms.height)
			mCursorY = ms.height - 1;
	}

	void InputManager::updateCursorPosition()
	{
		const OIS::MouseState& ms = mMouse->getMouseState();
		injectMouseMove(mCursorX, mCursorY, ms.Z.abs);
	}

} // namespace input
<commit_msg>fix input<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		09/2009
*/

#include "Precompiled.h"
#include "InputManager.h"

#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
#include <windows.h>
#endif

namespace input
{

#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32

	MyGUI::Char translateWin32Text(MyGUI::KeyCode kc)
	{
		static WCHAR deadKey = 0;

		BYTE keyState[256];
		HKL  layout = GetKeyboardLayout(0);
		if ( GetKeyboardState(keyState) == 0 )
			return 0;

		int code = *((int*)&kc);
		unsigned int vk = MapVirtualKeyEx((UINT)code, 3, layout);
		if ( vk == 0 )
			return 0;

		WCHAR buff[3] = { 0, 0, 0 };
		int ascii = ToUnicodeEx(vk, (UINT)code, keyState, buff, 3, 0, layout);
		if (ascii == 1 && deadKey != '\0' )
		{
			// A dead key is stored and we have just converted a character key
			// Combine the two into a single character
			WCHAR wcBuff[3] = { buff[0], deadKey, '\0' };
			WCHAR out[3];

			deadKey = '\0';
			if (FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
				return out[0];
		}
		else if (ascii == 1)
		{
			// We have a single character
			deadKey = '\0';
			return buff[0];
		}
		else if (ascii == 2)
		{
			// Convert a non-combining diacritical mark into a combining diacritical mark
			// Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
			// http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
			switch (buff[0])
			{
			case 0x5E: // Circumflex accent:
				deadKey = 0x302;
				break;
			case 0x60: // Grave accent:
				deadKey = 0x300;
				break;
			case 0xA8: // Diaeresis:
				deadKey = 0x308;
				break;
			case 0xB4: // Acute accent:
				deadKey = 0x301;
				break;
			case 0xB8: // Cedilla:
				deadKey = 0x327;
				break;
			default:
				deadKey = buff[0];
				break;
			}
		}

		return 0;
	}

#endif

	InputManager::InputManager() :
		mInputManager(0),
		mKeyboard(0),
		mMouse(0),
		mCursorX(0),
		mCursorY(0)
	{
	}

	InputManager::~InputManager()
	{
	}

	void InputManager::createInput(size_t _handle)
	{
		std::ostringstream windowHndStr;
		windowHndStr << _handle;

		OIS::ParamList pl;
		pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));

		mInputManager = OIS::InputManager::createInputSystem(pl);

		mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
		mKeyboard->setEventCallback(this);

		mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));
		mMouse->setEventCallback(this);
	}

	void InputManager::destroyInput()
	{
		if (mInputManager)
		{
			if (mMouse)
			{
				mInputManager->destroyInputObject( mMouse );
				mMouse = nullptr;
			}
			if (mKeyboard)
			{
				mInputManager->destroyInputObject( mKeyboard );
				mKeyboard = nullptr;
			}
			OIS::InputManager::destroyInputSystem(mInputManager);
			mInputManager = nullptr;
		}
	}

	bool InputManager::mouseMoved(const OIS::MouseEvent& _arg)
	{
		mCursorX += _arg.state.X.rel;
		mCursorY += _arg.state.Y.rel;

		checkPosition();

		injectMouseMove(mCursorX, mCursorY, _arg.state.Z.abs);
		return true;
	}

	bool InputManager::mousePressed(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id)
	{
		injectMousePress(mCursorX, mCursorY, MyGUI::MouseButton::Enum(_id));
		return true;
	}

	bool InputManager::mouseReleased(const OIS::MouseEvent& _arg, OIS::MouseButtonID _id)
	{
		injectMouseRelease(mCursorX, mCursorY, MyGUI::MouseButton::Enum(_id));
		return true;
	}

	bool InputManager::keyPressed(const OIS::KeyEvent& _arg)
	{
		MyGUI::Char text = (MyGUI::Char)_arg.text;
		MyGUI::KeyCode key = MyGUI::KeyCode::Enum(_arg.key);
		int scan_code = key.getValue();

		if (scan_code > 70 && scan_code < 84)
		{
			static MyGUI::Char nums[13] = { 55, 56, 57, 45, 52, 53, 54, 43, 49, 50, 51, 48, 46 };
			text = nums[scan_code-71];
		}
		else if (key == MyGUI::KeyCode::Divide)
		{
			text = '/';
		}
		else
		{
#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
			text = translateWin32Text(key);
#endif
		}

		injectKeyPress(key, text);
		return true;
	}

	bool InputManager::keyReleased(const OIS::KeyEvent& _arg)
	{
		injectKeyRelease(MyGUI::KeyCode::Enum(_arg.key));
		return true;
	}

	void InputManager::captureInput()
	{
		if (mMouse) mMouse->capture();
		mKeyboard->capture();
	}

	void InputManager::setInputViewSize(int _width, int _height)
	{
		if (mMouse)
		{
			const OIS::MouseState& ms = mMouse->getMouseState();
			ms.width = _width;
			ms.height = _height;

			checkPosition();
		}
	}

	void InputManager::setMousePosition(int _x, int _y)
	{
		//const OIS::MouseState &ms = mMouse->getMouseState();
		mCursorX = _x;
		mCursorY = _y;

		checkPosition();
	}

	void InputManager::checkPosition()
	{
		const OIS::MouseState& ms = mMouse->getMouseState();

		if (mCursorX < 0)
			mCursorX = 0;
		else if (mCursorX >= ms.width)
			mCursorX = ms.width - 1;

		if (mCursorY < 0)
			mCursorY = 0;
		else if (mCursorY >= ms.height)
			mCursorY = ms.height - 1;
	}

	void InputManager::updateCursorPosition()
	{
		const OIS::MouseState& ms = mMouse->getMouseState();
		injectMouseMove(mCursorX, mCursorY, ms.Z.abs);
	}

} // namespace input
<|endoftext|>


<commit_before>// -*-Mode: C++;-*-

// * BeginRiceCopyright *****************************************************
//
// $HeadURL$
// $Id$
//
// -----------------------------------
// Part of HPCToolkit (hpctoolkit.org)
// -----------------------------------
//
// Copyright ((c)) 2002-2010, Rice University
// 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 Rice University (RICE) 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 RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

// **************************************************************************
//
// File:
//    Unique.h
//
// Purpose:
//    Defines the Unique class (see below).
//
// Description:
//    Mixin for non-copyable objects or singleton objects.
//    All class definitions should contain copy constructors and assignment
//    operators.  Many class's objects, however, should never be copied.
//    If this is the case, the class should multiply inherit from the
//    Unique mixin class, which inhibits these operations.  The Unique
//    class additionally provides a mechanism for classes that should only
//    have single objects (a stronger form of a non-copyable object).
//    In this later case, the second constructor should be used and the
//    class name specified as a (const char*) string.
//
//    Note that for Unique objects, object equality amounts to pointer
//    equality, so equality and inequality operators can be easily defined.
//
// **************************************************************************

#ifndef support_Unique_h
#define support_Unique_h

// ************************* System Include Files ***************************

#include <set> // STL
#include <string>

// ************************** User Include Files ****************************

#include <include/uint.h>

// ************************* Variable Definitions ***************************

// *************************** Class Definitions ****************************

// **************************************************************************
//
//  Class:
//     Unique
//
//  Class Data Members:
//     String* className private -- the name of the class, if singleton.
//
//  Purpose:
//     1) Mixin for a class with objects that shouldn't be copied.
//     2) Mixin for a class which should have only a single object.
//
//  History:
//     09/24/96 - dbaker - Creation (adapted from Memento).
//
// **************************************************************************
class Unique
{
  protected:

    // Special Class Members

      Unique();
        // Default constructor.

      Unique(const char* theClassName);
        // Constructor for singleton object.

      virtual ~Unique();
        // Destructor.

  private:

      static std::set<std::string> classNameSet;
        // Where the set of class names are stored.

      Unique(const Unique& mo);
        // Copy constructor (explicitly not allowed).
        // has not implemetationm since compiler should complain
        // about inaccessability
      Unique& operator=(const Unique& mo);
        // Assignment operator (explicitly not allowed).
        // has not implemetationm, ...

      std::string className;
        // Saved class name or ""

};

// ********************** Extern Function Prototypes ************************

// Unique object equality.
inline bool operator==(const Unique& u1, const Unique& u2)
{
    return (&u1 == &u2);
}

// Unique object inequality.
inline bool operator!=(const Unique& u1, const Unique& u2)
{
    return !(u1 == u2);
}

#endif /* support_Unique_h */
<commit_msg>Cleanup.<commit_after>// -*-Mode: C++;-*-

// * BeginRiceCopyright *****************************************************
//
// $HeadURL$
// $Id$
//
// -----------------------------------
// Part of HPCToolkit (hpctoolkit.org)
// -----------------------------------
//
// Copyright ((c)) 2002-2010, Rice University
// 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 Rice University (RICE) 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 RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

// **************************************************************************
//
// File:
//    Unique.h
//
// Purpose:
//    Defines the Unique class (see below).
//
// Description:
//    Mixin for non-copyable objects or singleton objects.
//    All class definitions should contain copy constructors and assignment
//    operators.  Many class's objects, however, should never be copied.
//    If this is the case, the class should multiply inherit from the
//    Unique mixin class, which inhibits these operations.  The Unique
//    class additionally provides a mechanism for classes that should only
//    have single objects (a stronger form of a non-copyable object).
//    In this later case, the second constructor should be used and the
//    class name specified as a (const char*) string.
//
//    Note that for Unique objects, object equality amounts to pointer
//    equality, so equality and inequality operators can be easily defined.
//
// **************************************************************************

#ifndef support_Unique_h
#define support_Unique_h

// ************************* System Include Files ***************************

#include <set>
#include <string>

// ************************** User Include Files ****************************

#include <include/uint.h>

// ************************* Variable Definitions ***************************

// *************************** Class Definitions ****************************

// **************************************************************************
//
//  Class:
//     Unique
//
//  Class Data Members:
//     std::string className private -- the name of the class, if singleton.
//
//  Purpose:
//     1) Mixin for a class with objects that shouldn't be copied.
//     2) Mixin for a class which should have only a single object.
//
//  History:
//     09/24/96 - dbaker - Creation (adapted from Memento).
//
// **************************************************************************
class Unique
{
  protected:

    // Special Class Members

      Unique();
        // Default constructor.

      Unique(const char* theClassName);
        // Constructor for singleton object.

      virtual ~Unique();
        // Destructor.

  private:

      static std::set<std::string> classNameSet;
        // Where the set of class names are stored.

      Unique(const Unique& mo);
        // Copy constructor (explicitly not allowed).
        // has not implemetationm since compiler should complain
        // about inaccessability
      Unique& operator=(const Unique& mo);
        // Assignment operator (explicitly not allowed).
        // has not implemetationm, ...

      std::string className;
        // Saved class name or ""

};

// ********************** Extern Function Prototypes ************************

// Unique object equality.
inline bool operator==(const Unique& u1, const Unique& u2)
{
    return (&u1 == &u2);
}

// Unique object inequality.
inline bool operator!=(const Unique& u1, const Unique& u2)
{
    return !(u1 == u2);
}

#endif /* support_Unique_h */
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/pivot_command.hpp"

#include "vast/defaults.hpp"
#include "vast/detail/assert.hpp"
#include "vast/detail/make_io_stream.hpp"
#include "vast/error.hpp"
#include "vast/format/csv.hpp"
#include "vast/format/json.hpp"
#include "vast/format/pcap.hpp"
#include "vast/format/zeek.hpp"
#include "vast/logger.hpp"
#include "vast/scope_linked.hpp"
#include "vast/system/atoms.hpp"
#include "vast/system/read_query.hpp"
#include "vast/system/signal_monitor.hpp"
#include "vast/system/sink.hpp"
#include "vast/system/sink_command.hpp"
#include "vast/system/spawn_or_connect_to_node.hpp"
#include "vast/system/tracker.hpp"

#include <caf/event_based_actor.hpp>
#include <caf/scoped_actor.hpp>
#include <caf/settings.hpp>
#include <caf/stateful_actor.hpp>
#include <caf/typed_event_based_actor.hpp>

#include <csignal>
#include <string>
#include <string_view>

using namespace std::chrono_literals;

namespace vast::system {

namespace {

template <class Writer>
caf::expected<caf::actor>
make_writer(caf::actor_system& sys, const caf::settings& options) {
  using defaults = typename Writer::defaults;
  using ostream_ptr = std::unique_ptr<std::ostream>;
  std::string category = defaults::category;
  if constexpr (std::is_constructible_v<Writer, ostream_ptr>) {
    auto output = get_or(options, category + ".write", defaults::write);
    auto uds = get_or(options, category + ".uds", false);
    auto out = detail::make_output_stream(output, uds);
    if (!out)
      return out.error();
    Writer writer{std::move(*out)};
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  } else {
    Writer writer;
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  }
}

} // namespace

caf::message
pivot_command(const command::invocation& invocation, caf::actor_system& sys) {
  VAST_TRACE(invocation);
  // Read query from input file, STDIN or CLI arguments.
  auto query = read_query(invocation, "export.read", size_t{1});
  if (!query)
    return caf::make_message(std::move(query.error()));
  auto& options = invocation.options;
  auto& target = invocation.arguments[0];
  // using caf::get_or;
  auto limit
    = get_or(options, "export.max-events", defaults::export_::max_events);
  caf::actor writer;
  if (detail::starts_with(target, "pcap")) {
    using defaults_t = defaults::export_::pcap;
    std::string category = defaults_t::category;
    auto output = get_or(options, category + ".write", defaults_t::write);
    auto flush = get_or(options, category + ".flush-interval",
                        defaults_t::flush_interval);
    format::pcap::writer w{output, flush};
    writer = sys.spawn(sink<format::pcap::writer>, std::move(w), limit);
  } else if (detail::starts_with(target, "suricata")) {
    auto w = make_writer<format::json::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else if (detail::starts_with(target, "zeek")) {
    auto w = make_writer<format::zeek::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else
    return make_message(make_error(ec::unimplemented, "pivoting is only "
                                                      "implemented for pcap, "
                                                      "suricata and zeek"));
  caf::scoped_actor self{sys};
  // Get VAST node.
  auto node_opt
    = spawn_or_connect_to_node(self, invocation.options, content(sys.config()));
  if (auto err = caf::get_if<caf::error>(&node_opt))
    return caf::make_message(std::move(*err));
  auto& node = caf::holds_alternative<caf::actor>(node_opt)
                 ? caf::get<caf::actor>(node_opt)
                 : caf::get<scope_linked_actor>(node_opt).get();
  VAST_ASSERT(node != nullptr);
  // TODO(ch9412): Factor guard into a function.
  // Start signal monitor.
  std::thread sig_mon_thread;
  auto guard = signal_monitor::run_guarded(sig_mon_thread, sys, 750ms, self);
  // Spawn exporter at the node.
  caf::actor exp;
  auto exporter_invocation
    = command::invocation{invocation.options, "spawn exporter", {*query}};
  VAST_DEBUG(invocation.full_name,
             "spawns exporter with parameters:", exporter_invocation);
  error err;
  self->request(node, caf::infinite, std::move(exporter_invocation))
    .receive(
      [&](caf::actor& a) {
        exp = std::move(a);
        if (!exp)
          err = make_error(ec::invalid_result, "remote spawn returned nullptr");
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  // Spawn pivoter at the node.
  caf::actor piv;
  auto pivoter_invocation = command::invocation{
    invocation.options, "spawn pivoter", {invocation.arguments[0], *query}};
  VAST_DEBUG(invocation.full_name,
             "spawns exporter with parameters:", pivoter_invocation);
  self->request(node, caf::infinite, std::move(pivoter_invocation))
    .receive(
      [&](caf::actor& a) {
        piv = std::move(a);
        if (!piv)
          err = make_error(ec::invalid_result, "remote spawn returned nullptr");
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(exp, caf::exit_reason::user_shutdown);
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  self->request(node, caf::infinite, get_atom::value)
    .receive(
      [&](const std::string& id, system::registry& reg) {
        // Assign accountant to sink.
        VAST_DEBUG(invocation.full_name, "assigns accountant from node", id,
                   "to new sink");
        auto er = reg.components[id].find("accountant");
        if (er != reg.components[id].end()) {
          auto accountant = er->second.actor;
          self->send(writer, caf::actor_cast<accountant_type>(accountant));
        }
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  self->monitor(writer);
  self->monitor(piv);
  // Start the exporter.
  self->send(exp, system::sink_atom::value, piv);
  self->send(piv, system::sink_atom::value, writer);
  self->send(exp, system::run_atom::value);
  auto stop = false;
  self
    ->do_receive(
      [&](caf::down_msg& msg) {
        if (msg.source == node) {
          VAST_DEBUG_ANON(__func__, "received DOWN from node");
          self->send_exit(writer, caf::exit_reason::user_shutdown);
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
        } else if (msg.source == piv) {
          VAST_DEBUG(invocation.full_name, "received DOWN from pivoter");
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(writer, caf::exit_reason::user_shutdown);
        } else if (msg.source == writer) {
          VAST_DEBUG(invocation.full_name, "received DOWN from sink");
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
        } else {
          VAST_ASSERT(!"received DOWN from inexplicable actor");
        }
        if (msg.reason) {
          VAST_WARNING(invocation.full_name, "received error message:",
                       self->system().render(msg.reason));
          err = std::move(msg.reason);
        }
        stop = true;
      },
      [&](system::signal_atom, int signal) {
        VAST_DEBUG(invocation.full_name, "got " << ::strsignal(signal));
        if (signal == SIGINT || signal == SIGTERM) {
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
          self->send_exit(writer, caf::exit_reason::user_shutdown);
        }
      })
    .until([&] { return stop; });
  if (err)
    return caf::make_message(std::move(err));
  return caf::none;
}

} // namespace vast::system
<commit_msg>Fix pivoter lifetime management<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/pivot_command.hpp"

#include "vast/defaults.hpp"
#include "vast/detail/assert.hpp"
#include "vast/detail/make_io_stream.hpp"
#include "vast/error.hpp"
#include "vast/format/csv.hpp"
#include "vast/format/json.hpp"
#include "vast/format/pcap.hpp"
#include "vast/format/zeek.hpp"
#include "vast/logger.hpp"
#include "vast/scope_linked.hpp"
#include "vast/system/atoms.hpp"
#include "vast/system/read_query.hpp"
#include "vast/system/signal_monitor.hpp"
#include "vast/system/sink.hpp"
#include "vast/system/sink_command.hpp"
#include "vast/system/spawn_or_connect_to_node.hpp"
#include "vast/system/tracker.hpp"

#include <caf/event_based_actor.hpp>
#include <caf/scoped_actor.hpp>
#include <caf/settings.hpp>
#include <caf/stateful_actor.hpp>
#include <caf/typed_event_based_actor.hpp>

#include <csignal>
#include <string>
#include <string_view>

using namespace std::chrono_literals;

namespace vast::system {

namespace {

template <class Writer>
caf::expected<caf::actor>
make_writer(caf::actor_system& sys, const caf::settings& options) {
  using defaults = typename Writer::defaults;
  using ostream_ptr = std::unique_ptr<std::ostream>;
  std::string category = defaults::category;
  if constexpr (std::is_constructible_v<Writer, ostream_ptr>) {
    auto output = get_or(options, category + ".write", defaults::write);
    auto uds = get_or(options, category + ".uds", false);
    auto out = detail::make_output_stream(output, uds);
    if (!out)
      return out.error();
    Writer writer{std::move(*out)};
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  } else {
    Writer writer;
    return sys.spawn(sink<Writer>, std::move(writer), max_events);
  }
}

} // namespace

caf::message
pivot_command(const command::invocation& invocation, caf::actor_system& sys) {
  VAST_TRACE(invocation);
  // Read query from input file, STDIN or CLI arguments.
  auto query = read_query(invocation, "export.read", size_t{1});
  if (!query)
    return caf::make_message(std::move(query.error()));
  auto& options = invocation.options;
  auto& target = invocation.arguments[0];
  // using caf::get_or;
  auto limit
    = get_or(options, "export.max-events", defaults::export_::max_events);
  caf::actor writer;
  if (detail::starts_with(target, "pcap")) {
    using defaults_t = defaults::export_::pcap;
    std::string category = defaults_t::category;
    auto output = get_or(options, category + ".write", defaults_t::write);
    auto flush = get_or(options, category + ".flush-interval",
                        defaults_t::flush_interval);
    format::pcap::writer w{output, flush};
    writer = sys.spawn(sink<format::pcap::writer>, std::move(w), limit);
  } else if (detail::starts_with(target, "suricata")) {
    auto w = make_writer<format::json::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else if (detail::starts_with(target, "zeek")) {
    auto w = make_writer<format::zeek::writer>(sys, invocation.options);
    if (!w)
      return make_message(w.error());
    writer = *w;
  } else
    return make_message(make_error(ec::unimplemented, "pivoting is only "
                                                      "implemented for pcap, "
                                                      "suricata and zeek"));
  caf::scoped_actor self{sys};
  // Get VAST node.
  auto node_opt
    = spawn_or_connect_to_node(self, invocation.options, content(sys.config()));
  if (auto err = caf::get_if<caf::error>(&node_opt))
    return caf::make_message(std::move(*err));
  auto& node = caf::holds_alternative<caf::actor>(node_opt)
                 ? caf::get<caf::actor>(node_opt)
                 : caf::get<scope_linked_actor>(node_opt).get();
  VAST_ASSERT(node != nullptr);
  // TODO(ch9412): Factor guard into a function.
  // Start signal monitor.
  std::thread sig_mon_thread;
  auto guard = signal_monitor::run_guarded(sig_mon_thread, sys, 750ms, self);
  // Spawn exporter at the node.
  caf::actor exp;
  auto exporter_invocation
    = command::invocation{invocation.options, "spawn exporter", {*query}};
  VAST_DEBUG(invocation.full_name,
             "spawns exporter with parameters:", exporter_invocation);
  error err;
  self->request(node, caf::infinite, std::move(exporter_invocation))
    .receive(
      [&](caf::actor& a) {
        exp = std::move(a);
        if (!exp)
          err = make_error(ec::invalid_result, "remote spawn returned nullptr");
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  // Spawn pivoter at the node.
  caf::actor piv;
  auto pivoter_invocation = command::invocation{
    invocation.options, "spawn pivoter", {invocation.arguments[0], *query}};
  VAST_DEBUG(invocation.full_name,
             "spawns exporter with parameters:", pivoter_invocation);
  self->request(node, caf::infinite, std::move(pivoter_invocation))
    .receive(
      [&](caf::actor& a) {
        piv = std::move(a);
        if (!piv)
          err = make_error(ec::invalid_result, "remote spawn returned nullptr");
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(exp, caf::exit_reason::user_shutdown);
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  self->request(node, caf::infinite, get_atom::value)
    .receive(
      [&](const std::string& id, system::registry& reg) {
        // Assign accountant to sink.
        VAST_DEBUG(invocation.full_name, "assigns accountant from node", id,
                   "to new sink");
        auto er = reg.components[id].find("accountant");
        if (er != reg.components[id].end()) {
          auto accountant = er->second.actor;
          self->send(writer, caf::actor_cast<accountant_type>(accountant));
        }
      },
      [&](error& e) { err = std::move(e); });
  if (err) {
    self->send_exit(writer, caf::exit_reason::user_shutdown);
    return caf::make_message(std::move(err));
  }
  self->monitor(writer);
  self->monitor(piv);
  // Start the exporter.
  self->send(exp, system::sink_atom::value, piv);
  // (Ab)use query_statistics as done message.
  self->send(exp, system::statistics_atom::value, piv);
  self->send(piv, system::sink_atom::value, writer);
  self->send(exp, system::run_atom::value);
  auto stop = false;
  self
    ->do_receive(
      [&](caf::down_msg& msg) {
        if (msg.source == node) {
          VAST_DEBUG_ANON(__func__, "received DOWN from node");
          self->send_exit(writer, caf::exit_reason::user_shutdown);
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
        } else if (msg.source == piv) {
          VAST_DEBUG(invocation.full_name, "received DOWN from pivoter");
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(writer, caf::exit_reason::user_shutdown);
        } else if (msg.source == writer) {
          VAST_DEBUG(invocation.full_name, "received DOWN from sink");
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
        } else {
          VAST_ASSERT(!"received DOWN from inexplicable actor");
        }
        if (msg.reason) {
          VAST_WARNING(invocation.full_name, "received error message:",
                       self->system().render(msg.reason));
          err = std::move(msg.reason);
        }
        stop = true;
      },
      [&](system::signal_atom, int signal) {
        VAST_DEBUG(invocation.full_name, "got " << ::strsignal(signal));
        if (signal == SIGINT || signal == SIGTERM) {
          self->send_exit(exp, caf::exit_reason::user_shutdown);
          self->send_exit(piv, caf::exit_reason::user_shutdown);
          self->send_exit(writer, caf::exit_reason::user_shutdown);
        }
      })
    .until([&] { return stop; });
  if (err)
    return caf::make_message(std::move(err));
  return caf::none;
}

} // namespace vast::system
<|endoftext|>