<commit_before>#ifndef STAN_MATH_REV_CORE_ARENA_MATRIX_HPP
#define STAN_MATH_REV_CORE_ARENA_MATRIX_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/rev/core/chainable_alloc.hpp>
#include <stan/math/rev/core/chainablestack.hpp>

namespace stan {
namespace math {

/**
 * Equivalent to `Eigen::Matrix`, except that the data is stored on AD stack.
 * That makes these objects triviali destructible and usable in `vari`s.
 *
 * @tparam MatrixType Eigen matrix type this works as (`MatrixXd`, `VectorXd`
 * ...)
 */
template <typename MatrixType>
class arena_matrix : public Eigen::Map<MatrixType> {
 public:
  using Scalar = value_type_t<MatrixType>;
  using Base = Eigen::Map<MatrixType>;
  using PlainObject = std::decay_t<MatrixType>;
  static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime;
  static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime;

  /**
   * Default constructor.
   */
  arena_matrix()
      : Base::Map(nullptr,
                  RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime,
                  ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {
  }

  /**
   * Constructs `arena_matrix` with given number of rows and columns.
   * @param rows number of rows
   * @param cols number of columns
   */
  arena_matrix(Eigen::Index rows, Eigen::Index cols)
      : Base::Map(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(
                      rows * cols),
          rows, cols) {}

  /**
   * Constructs `arena_matrix` with given size. This only works if
   * `MatrixType` is row or col vector.
   * @param size number of elements
   */
  explicit arena_matrix(Eigen::Index size)
      : Base::Map(
          ChainableStack::instance_->memalloc_.alloc_array<Scalar>(size),
          size) {}

  /**
   * Constructs `arena_matrix` from an expression.
   * @param other expression
   */
  template <typename T, require_eigen_t<T>* = nullptr>
  arena_matrix(const T& other)  // NOLINT
      : Base::Map(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(
                      other.size()),
                  other.rows(), other.cols()) {
    *this = other;
  }
  /**
   * Constructs `arena_matrix` from an expression.
   * @param other expression
   */
  arena_matrix(const Base& other)  // NOLINT
      : Base::Map(other) {}

  /**
   * Copy constructor.
   * @param other matrix to copy from
   */
  arena_matrix(const arena_matrix<MatrixType>& other)
      : Base::Map(const_cast<Scalar*>(other.data()), other.rows(),
                  other.cols()) {}

  // without this using, compiler prefers combination of implicit construction
  // and copy assignment to the inherited operator when assigned an expression
  using Base::operator=;

  /**
   * Copy assignment operator.
   * @param other matrix to copy from
   * @return `*this`
   */
  arena_matrix& operator=(const arena_matrix<MatrixType>& other) {
    // placement new changes what data map points to - there is no allocation
    new (this)
        Base(const_cast<Scalar*>(other.data()), other.rows(), other.cols());
    return *this;
  }

  /**
   * Assignment operator for assigning an expression.
   * @param a expression to evaluate into this
   * @return `*this`
   */
  template <typename T>
  arena_matrix& operator=(const T& a) {
    // placement new changes what data map points to - there is no allocation
    new (this)
        Base(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(a.size()),
             a.rows(), a.cols());
    Base::operator=(a);
    return *this;
  }
};

}  // namespace math
}  // namespace stan

namespace Eigen {
namespace internal {

template <typename T>
struct traits<stan::math::arena_matrix<T>> {
  using base = traits<Eigen::Map<T>>;
  enum {
    PlainObjectTypeInnerSize = base::PlainObjectTypeInnerSize,
    InnerStrideAtCompileTime = base::InnerStrideAtCompileTime,
    OuterStrideAtCompileTime = base::OuterStrideAtCompileTime,
    Alignment = base::Alignment,
    PlainObjectTypeInnerSize = base::Flags
  };
};

}  // namespace internal
}  // namespace Eigen

#endif
<commit_msg>another typo<commit_after>#ifndef STAN_MATH_REV_CORE_ARENA_MATRIX_HPP
#define STAN_MATH_REV_CORE_ARENA_MATRIX_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/rev/core/chainable_alloc.hpp>
#include <stan/math/rev/core/chainablestack.hpp>

namespace stan {
namespace math {

/**
 * Equivalent to `Eigen::Matrix`, except that the data is stored on AD stack.
 * That makes these objects triviali destructible and usable in `vari`s.
 *
 * @tparam MatrixType Eigen matrix type this works as (`MatrixXd`, `VectorXd`
 * ...)
 */
template <typename MatrixType>
class arena_matrix : public Eigen::Map<MatrixType> {
 public:
  using Scalar = value_type_t<MatrixType>;
  using Base = Eigen::Map<MatrixType>;
  using PlainObject = std::decay_t<MatrixType>;
  static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime;
  static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime;

  /**
   * Default constructor.
   */
  arena_matrix()
      : Base::Map(nullptr,
                  RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime,
                  ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {
  }

  /**
   * Constructs `arena_matrix` with given number of rows and columns.
   * @param rows number of rows
   * @param cols number of columns
   */
  arena_matrix(Eigen::Index rows, Eigen::Index cols)
      : Base::Map(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(
                      rows * cols),
          rows, cols) {}

  /**
   * Constructs `arena_matrix` with given size. This only works if
   * `MatrixType` is row or col vector.
   * @param size number of elements
   */
  explicit arena_matrix(Eigen::Index size)
      : Base::Map(
          ChainableStack::instance_->memalloc_.alloc_array<Scalar>(size),
          size) {}

  /**
   * Constructs `arena_matrix` from an expression.
   * @param other expression
   */
  template <typename T, require_eigen_t<T>* = nullptr>
  arena_matrix(const T& other)  // NOLINT
      : Base::Map(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(
                      other.size()),
                  other.rows(), other.cols()) {
    *this = other;
  }
  /**
   * Constructs `arena_matrix` from an expression.
   * @param other expression
   */
  arena_matrix(const Base& other)  // NOLINT
      : Base::Map(other) {}

  /**
   * Copy constructor.
   * @param other matrix to copy from
   */
  arena_matrix(const arena_matrix<MatrixType>& other)
      : Base::Map(const_cast<Scalar*>(other.data()), other.rows(),
                  other.cols()) {}

  // without this using, compiler prefers combination of implicit construction
  // and copy assignment to the inherited operator when assigned an expression
  using Base::operator=;

  /**
   * Copy assignment operator.
   * @param other matrix to copy from
   * @return `*this`
   */
  arena_matrix& operator=(const arena_matrix<MatrixType>& other) {
    // placement new changes what data map points to - there is no allocation
    new (this)
        Base(const_cast<Scalar*>(other.data()), other.rows(), other.cols());
    return *this;
  }

  /**
   * Assignment operator for assigning an expression.
   * @param a expression to evaluate into this
   * @return `*this`
   */
  template <typename T>
  arena_matrix& operator=(const T& a) {
    // placement new changes what data map points to - there is no allocation
    new (this)
        Base(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(a.size()),
             a.rows(), a.cols());
    Base::operator=(a);
    return *this;
  }
};

}  // namespace math
}  // namespace stan

namespace Eigen {
namespace internal {

template <typename T>
struct traits<stan::math::arena_matrix<T>> {
  using base = traits<Eigen::Map<T>>;
  enum {
    PlainObjectTypeInnerSize = base::PlainObjectTypeInnerSize,
    InnerStrideAtCompileTime = base::InnerStrideAtCompileTime,
    OuterStrideAtCompileTime = base::OuterStrideAtCompileTime,
    Alignment = base::Alignment,
    Flags = base::Flags
  };
};

}  // namespace internal
}  // namespace Eigen

#endif
<|endoftext|>


<commit_before>#include "WinHTTPClient.h"

#include "BasicAuth.h"

#include <cstdio>
#include <cstring>
#include <cassert>
#include <cctype>

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#include <sysinfoapi.h>

#define strcasecmp _stricmp
#endif

#include <iostream>
#include <URI.h>
#include <winhttp.h>

using namespace std;

static wstring from_utf8(const std::string & s) {
  std::unique_ptr<wchar_t[]> tmp(new wchar_t[s.size() + 1]);
  auto r = MultiByteToWideChar(CP_UTF8, 0, s.data(), -1, tmp.get(), s.size() + 1);
  return wstring(tmp.get(), static_cast<size_t>(r));
}

static string to_utf8(const wstring & s) {
  std::unique_ptr<char[]> tmp(new char[4 * s.size() + 1]);
  auto r = WideCharToMultiByte(CP_UTF8,
			       0,
			       s.data(),
			       -1,
			       tmp.get(),
			       4*s.size() + 1,
			       NULL,
			       NULL);
  return string(tmp.get(), static_cast<size_t>(r));
}

static long long get_current_time_ms() {
#ifdef WIN32
  FILETIME ft_now;
  GetSystemTimeAsFileTime(&ft_now);
  long long ll_now = (LONGLONG)ft_now.dwLowDateTime + (((LONGLONG)ft_now.dwHighDateTime) << 32LL);
  ll_now /= 10000;
  return ll_now - 116444736000000000LL;
#else
  struct timeval tv;
  int r = gettimeofday(&tv, 0);
  if (r == 0) {
    return (long long)1000 * tv.tv_sec + tv.tv_usec / 1000;
  } else {
    return 0;
  }
#endif
}

class WinHTTPClient : public HTTPClient {
 public:
   WinHTTPClient(const std::string& user_agent, bool enable_cookies = true, bool enable_keepalive = true)
     : HTTPClient(user_agent, enable_cookies, enable_keepalive)
   {
     auto ua_text = from_utf8(getUserAgent());
     // Use WinHttpOpen to obtain a session handle.
     session_ = WinHttpOpen(ua_text.c_str(),
       WINHTTP_ACCESS_TYPE_NO_PROXY,
       WINHTTP_NO_PROXY_NAME,
       WINHTTP_NO_PROXY_BYPASS, 0);

     DWORD decompression = WINHTTP_DECOMPRESSION_FLAG_ALL;
     WinHttpSetOption(session_, WINHTTP_OPTION_DECOMPRESSION, &decompression, sizeof(decompression));

#if 0
     DWORD protocols = WINHTTP_PROTOCOL_FLAG_HTTP2;
     WinHttpSetOption(session_, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &protocols, sizeof(protocols));
     DWORD secure_protocols = WINHTTP_FLAG_SECURE_PROTOCOL_ALL;
     WinHttpSetOption(session_, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
#endif
   }

  ~WinHTTPClient() {
    WinHttpCloseHandle(session_);
  }

  void request(const HTTPRequest & req, const Authorization & auth, HTTPClientInterface & callback) override {
    URI uri(req.getURI());

    auto target_scheme = uri.getScheme();
    auto target_host = from_utf8(uri.getDomain());
    auto target_port = uri.getPort();

    auto target_path0 = uri.getPath();
    if (!uri.getQueryString().empty()) target_path0 += "?" + uri.getQueryString();

    auto target_path = from_utf8(target_path0);

    bool is_secure = false;
    if (target_scheme == "http") {
      if (!target_port) target_port = INTERNET_DEFAULT_HTTP_PORT;
    } else if (target_scheme == "https") {
      if (!target_port) target_port = INTERNET_DEFAULT_HTTPS_PORT;
      is_secure = true;
    } else {
      return;
    }

    auto hConnect = WinHttpConnect(session_, target_host.c_str(), target_port, 0);
    if (hConnect) {
      string tmp0 = "created handle for host: " + uri.getDomain() + ", port: " + to_string(target_port) + "\n";
      OutputDebugStringA(tmp0.c_str());

      // WINHTTP_OPTION_CONNECT_TIMEOUT (ms)
      // WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT (ms)
      // WINHTTP_OPTION_RECEIVE_TIMEOUT (ms)
      // WINHTTP_OPTION_RESOLVE_TIMEOUT (ms)
      // WINHTTP_OPTION_SEND_TIMEOUT (ms)

      wstring request_type;
      bool has_data = true;
      switch (req.getType()) {
      case HTTPRequest::GET:
	request_type = L"GET";
	has_data = false;
	break;
      case HTTPRequest::POST:
	request_type = L"POST";
	break;
      case HTTPRequest::OPTIONS:
	request_type = L"OPTIONS";
	break;
      }

      DWORD dwFlags = WINHTTP_FLAG_ESCAPE_DISABLE | WINHTTP_FLAG_ESCAPE_DISABLE_QUERY;
      if (is_secure) dwFlags |= WINHTTP_FLAG_SECURE;

      auto hRequest = WinHttpOpenRequest(hConnect, request_type.c_str(), target_path.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);
      if (hRequest) {
	DWORD disabled_features = 0;
	if (!req.getFollowLocation()) disabled_features |= WINHTTP_DISABLE_REDIRECTS;
	if (!enable_keepalive) disabled_features |= WINHTTP_DISABLE_KEEP_ALIVE;
	if (!enable_cookies) disabled_features |= WINHTTP_DISABLE_COOKIES;
	WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &disabled_features, sizeof(disabled_features));

	string tmp2 = "created request, path: " + target_path0 + "\n";
	OutputDebugStringA(tmp2.c_str());

	map<string, string> combined_headers;
	for (auto & hd : default_headers) {
	  combined_headers[hd.first] = hd.second;
	}
	for (auto & hd : req.getHeaders()) {
	  combined_headers[hd.first] = hd.second;
	}

	if (req.getType() == HTTPRequest::POST || req.getType() == HTTPRequest::OPTIONS) {
	  if (!req.getContentType().empty()) {
	    combined_headers["Content-Type"] = req.getContentType();
	  }
	}

	const BasicAuth * basic = dynamic_cast<const BasicAuth *>(&auth);
	if (basic) {
	  // FIXME: implement
	} else {
	  string auth_header = auth.createHeader();
	  if (!auth_header.empty()) {
	    combined_headers[auth.getHeaderName()] = auth_header;
	  }
	}

	for (auto & [ name, value ] : combined_headers) {
	  auto header0 = name + ": " + value;
	  auto header = from_utf8(header0 + "\r\n");
	  string tmp3 = "adding header: " + header0 + "\n";
	  OutputDebugStringA(tmp3.c_str());

	  WinHttpAddRequestHeaders(hRequest, header.c_str(), -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD);
	}

	auto & postData = req.getContent();

	OutputDebugStringA("Sending request\n");

	bool req_r = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (void*)postData.data(), postData.size(), postData.size(), 0);

	if (is_secure && !req_r) {
	  OutputDebugStringA("Retrying request\n");
	  DWORD security_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE | SECURITY_FLAG_IGNORE_ALL_CERT_ERRORS;
	  WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &security_flags, sizeof(security_flags));
	  req_r = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (void*)postData.data(), postData.size(), postData.size(), 0);
	}

	if (req_r && WinHttpReceiveResponse(hRequest, NULL)) {
	  OutputDebugStringA("Received response\n");

	  bool terminate = false;

#if 0
	  DWORD dwStatusCode = 0;
	  DWORD dwSize = sizeof(dwStatusCode);

	  if (WinHttpQueryHeaders(hRequest,
	    WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
	    WINHTTP_HEADER_NAME_BY_INDEX,
	    &dwStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX)) {
	    string tmp3 = "got result code: " + to_string(dwStatusCode) + "\n";
	    OutputDebugStringA(tmp3.c_str());
	    callback.handleResultCode(dwStatusCode);
	  }
	  else {
	    string tmp3 = "failed to get response code: " + to_string(GetLastError());
	    OutputDebugStringA(tmp3.c_str());
	  }
#endif
	  DWORD headerSize = 0;
	  WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &headerSize, WINHTTP_NO_HEADER_INDEX);

	  string tmp3 = "got header size: " + to_string(headerSize) + "\n";
	  OutputDebugStringA(tmp3.c_str());
	  // Allocate buffer by header length
	  // If the function fails and ERROR_INSUFFICIENT_BUFFER is returned, lpdwBufferLength specifies the number of bytes that the application must allocate to receive the string.
	  if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
	    wstring headerBuffer(headerSize / sizeof(wchar_t), 0);
	    if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, headerBuffer.data(), &headerSize, WINHTTP_NO_HEADER_INDEX)) {
	      string headers = to_utf8(headerBuffer);
	      OutputDebugStringA(headers.c_str());
	      if (!callback.handleHeaderChunk(headers.size(), headers.data())) {
		terminate = true;
	      }
	    } else {
	      string tmp4 = "Failed to get headers: " + to_string(GetLastError()) + "\n";
	      OutputDebugStringA(tmp4.c_str());
	    }
	  } else {
	    OutputDebugStringA("Failed to get headers\n");
	  }

	  while (!terminate) {
	    // Check for available data to get data size in bytes
	    DWORD dwSize = 0;
	    if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) {
	      break;
	    }
	    if (!dwSize) {
	      break;  //data size 0
	    }

	    // Allocate buffer by data size
	    unique_ptr<char[]> outBuffer(new char[dwSize + 1]);
	    // Read data from server
	    DWORD dwDownloaded = 0;
	    if (WinHttpReadData(hRequest, outBuffer.get(), dwSize, &dwDownloaded)) {
	      bool r = callback.handleChunk(dwDownloaded, outBuffer.get());
	      if (!r) break;
	    }
	    else {
	      break;
	    }

	    if (!dwDownloaded) break;
	    if (!callback.onIdle()) break;
	  }

	  callback.handleDisconnect();
	} else {
	  string tmp3 = "connection failed: " + to_string(GetLastError()) + "\n";
	  OutputDebugStringA(tmp3.c_str());
	}

	WinHttpCloseHandle(hRequest);
      }
      WinHttpCloseHandle(hConnect);
    }
  }

  void clearCookies() override {
  }

protected:
  HINTERNET session_;
};

std::unique_ptr<HTTPClient>
WinHTTPClientFactory::createClient2(const std::string & _user_agent, bool _enable_cookies, bool _enable_keepalive) {
  return std::unique_ptr<WinHTTPClient>(new WinHTTPClient(_user_agent, _enable_cookies, _enable_keepalive));
}
<commit_msg>Add error reporting<commit_after>#include "WinHTTPClient.h"

#include "BasicAuth.h"

#include <cstdio>
#include <cstring>
#include <cassert>
#include <cctype>

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#include <sysinfoapi.h>

#define strcasecmp _stricmp
#endif

#include <iostream>
#include <URI.h>
#include <winhttp.h>

using namespace std;

static wstring from_utf8(const std::string & s) {
  std::unique_ptr<wchar_t[]> tmp(new wchar_t[s.size() + 1]);
  auto r = MultiByteToWideChar(CP_UTF8, 0, s.data(), -1, tmp.get(), s.size() + 1);
  return wstring(tmp.get(), static_cast<size_t>(r));
}

static string to_utf8(const wstring & s) {
  std::unique_ptr<char[]> tmp(new char[4 * s.size() + 1]);
  auto r = WideCharToMultiByte(CP_UTF8,
			       0,
			       s.data(),
			       -1,
			       tmp.get(),
			       4*s.size() + 1,
			       NULL,
			       NULL);
  return string(tmp.get(), static_cast<size_t>(r));
}

static long long get_current_time_ms() {
#ifdef WIN32
  FILETIME ft_now;
  GetSystemTimeAsFileTime(&ft_now);
  long long ll_now = (LONGLONG)ft_now.dwLowDateTime + (((LONGLONG)ft_now.dwHighDateTime) << 32LL);
  ll_now /= 10000;
  return ll_now - 116444736000000000LL;
#else
  struct timeval tv;
  int r = gettimeofday(&tv, 0);
  if (r == 0) {
    return (long long)1000 * tv.tv_sec + tv.tv_usec / 1000;
  } else {
    return 0;
  }
#endif
}

class WinHTTPClient : public HTTPClient {
 public:
   WinHTTPClient(const std::string& user_agent, bool enable_cookies = true, bool enable_keepalive = true)
     : HTTPClient(user_agent, enable_cookies, enable_keepalive)
   {
     auto ua_text = from_utf8(getUserAgent());
     // Use WinHttpOpen to obtain a session handle.
     session_ = WinHttpOpen(ua_text.c_str(),
       WINHTTP_ACCESS_TYPE_NO_PROXY,
       WINHTTP_NO_PROXY_NAME,
       WINHTTP_NO_PROXY_BYPASS, 0);

     DWORD decompression = WINHTTP_DECOMPRESSION_FLAG_ALL;
     WinHttpSetOption(session_, WINHTTP_OPTION_DECOMPRESSION, &decompression, sizeof(decompression));

#if 0
     DWORD protocols = WINHTTP_PROTOCOL_FLAG_HTTP2;
     WinHttpSetOption(session_, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &protocols, sizeof(protocols));
     DWORD secure_protocols = WINHTTP_FLAG_SECURE_PROTOCOL_ALL;
     WinHttpSetOption(session_, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
#endif
   }

  ~WinHTTPClient() {
    if (session_) {
      WinHttpCloseHandle(session_);
    }
  }

  void request(const HTTPRequest & req, const Authorization & auth, HTTPClientInterface & callback) override {
    if (!session_) {
      callback.handleErrorText("Not initialized");
      return;
    }
    URI uri(req.getURI());

    auto target_scheme = uri.getScheme();
    auto target_host = from_utf8(uri.getDomain());
    auto target_port = uri.getPort();

    auto target_path0 = uri.getPath();
    if (!uri.getQueryString().empty()) target_path0 += "?" + uri.getQueryString();

    auto target_path = from_utf8(target_path0);

    bool is_secure = false;
    if (target_scheme == "http") {
      if (!target_port) target_port = INTERNET_DEFAULT_HTTP_PORT;
    } else if (target_scheme == "https") {
      if (!target_port) target_port = INTERNET_DEFAULT_HTTPS_PORT;
      is_secure = true;
    } else {
      return;
    }

    auto hConnect = WinHttpConnect(session_, target_host.c_str(), target_port, 0);
    if (!hConnect) {
      callback.handleErrorText("Could not create connection handle: " + to_string(GetLastError()));
    } else {
      // WINHTTP_OPTION_CONNECT_TIMEOUT (ms)
      // WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT (ms)
      // WINHTTP_OPTION_RECEIVE_TIMEOUT (ms)
      // WINHTTP_OPTION_RESOLVE_TIMEOUT (ms)
      // WINHTTP_OPTION_SEND_TIMEOUT (ms)

      wstring request_type;
      bool has_data = true;
      switch (req.getType()) {
      case HTTPRequest::GET:
	request_type = L"GET";
	has_data = false;
	break;
      case HTTPRequest::POST:
	request_type = L"POST";
	break;
      case HTTPRequest::OPTIONS:
	request_type = L"OPTIONS";
	break;
      }

      DWORD dwFlags = WINHTTP_FLAG_ESCAPE_DISABLE | WINHTTP_FLAG_ESCAPE_DISABLE_QUERY;
      if (is_secure) dwFlags |= WINHTTP_FLAG_SECURE;

      auto hRequest = WinHttpOpenRequest(hConnect, request_type.c_str(), target_path.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);
      if (!hRequest) {
	callback.handleErrorText("Could not create request: " + to_string(GetLastError()));
      } else {
	DWORD disabled_features = 0;
	if (!req.getFollowLocation()) disabled_features |= WINHTTP_DISABLE_REDIRECTS;
	if (!enable_keepalive) disabled_features |= WINHTTP_DISABLE_KEEP_ALIVE;
	if (!enable_cookies) disabled_features |= WINHTTP_DISABLE_COOKIES;
	if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &disabled_features, sizeof(disabled_features))) {
	  OutputDebugStringA("Could not set options");
	}

	map<string, string> combined_headers;
	for (auto & hd : default_headers) {
	  combined_headers[hd.first] = hd.second;
	}
	for (auto & hd : req.getHeaders()) {
	  combined_headers[hd.first] = hd.second;
	}

	if (req.getType() == HTTPRequest::POST || req.getType() == HTTPRequest::OPTIONS) {
	  if (!req.getContentType().empty()) {
	    combined_headers["Content-Type"] = req.getContentType();
	  }
	}

	const BasicAuth * basic = dynamic_cast<const BasicAuth *>(&auth);
	if (basic) {
	  // FIXME: implement
	} else {
	  string auth_header = auth.createHeader();
	  if (!auth_header.empty()) {
	    combined_headers[auth.getHeaderName()] = auth_header;
	  }
	}

	for (auto & [ name, value ] : combined_headers) {
	  auto header0 = name + ": " + value;
	  auto header = from_utf8(header0 + "\r\n");
	  string tmp3 = "adding header: " + header0 + "\n";
	  OutputDebugStringA(tmp3.c_str());

	  WinHttpAddRequestHeaders(hRequest, header.c_str(), -1, WINHTTP_ADDREQ_FLAG_REPLACE | WINHTTP_ADDREQ_FLAG_ADD);
	}

	auto & postData = req.getContent();

	OutputDebugStringA("Sending request\n");

	bool req_r = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (void*)postData.data(), postData.size(), postData.size(), 0);

	if (is_secure && !req_r && GetLastError() == 12175) {
	  OutputDebugStringA("Retrying request\n");
	  DWORD security_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE | SECURITY_FLAG_IGNORE_ALL_CERT_ERRORS;
	  WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &security_flags, sizeof(security_flags));
	  req_r = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (void*)postData.data(), postData.size(), postData.size(), 0);
	}

	if (!req_r) {
	  callback.handleErrorText("Could not send request: " + to_string(GetLastError()));
	} else if (WinHttpReceiveResponse(hRequest, NULL)) {
	  OutputDebugStringA("Received response\n");

	  bool terminate = false;

	  DWORD headerSize = 0;
	  WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &headerSize, WINHTTP_NO_HEADER_INDEX);

	  // Allocate buffer by header length
	  // If the function fails and ERROR_INSUFFICIENT_BUFFER is returned, lpdwBufferLength specifies the number of bytes that the application must allocate to receive the string.
	  if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
	    wstring headerBuffer(headerSize / sizeof(wchar_t), 0);
	    if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, headerBuffer.data(), &headerSize, WINHTTP_NO_HEADER_INDEX)) {
	      string headers = to_utf8(headerBuffer);
	      OutputDebugStringA(headers.c_str());
	      if (!callback.handleHeaderChunk(headers.size(), headers.data())) {
		terminate = true;
	      }
	    } else {
	      callback.handleErrorText("Failed to get headers: " + to_string(GetLastError()));
	      terminate = true;
	    }
	  } else {
	    callback.handleErrorText("Failed to get headers: no headers");
	    terminate = true;
	  }

	  while (!terminate) {
	    // Check for available data to get data size in bytes
	    DWORD dwSize = 0;
	    if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) {
	      break;
	    }
	    if (!dwSize) {
	      break;  //data size 0
	    }

	    // Allocate buffer by data size
	    unique_ptr<char[]> outBuffer(new char[dwSize + 1]);
	    // Read data from server
	    DWORD dwDownloaded = 0;
	    if (WinHttpReadData(hRequest, outBuffer.get(), dwSize, &dwDownloaded)) {
	      bool r = callback.handleChunk(dwDownloaded, outBuffer.get());
	      if (!r) break;
	    }
	    else {
	      break;
	    }

	    if (!dwDownloaded) break;
	    if (!callback.onIdle()) break;
	  }

	  callback.handleDisconnect();
	} else {
	  callback.handleErrorText("Failed to receive response: " + to_string(GetLastError()));
	}

	WinHttpCloseHandle(hRequest);
      }
      WinHttpCloseHandle(hConnect);
    }
  }

  void clearCookies() override {
  }

protected:
  HINTERNET session_;
};

std::unique_ptr<HTTPClient>
WinHTTPClientFactory::createClient2(const std::string & _user_agent, bool _enable_cookies, bool _enable_keepalive) {
  return std::unique_ptr<WinHTTPClient>(new WinHTTPClient(_user_agent, _enable_cookies, _enable_keepalive));
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file
#include "KeyTable.hpp"

#include <memory>

#include <XalanDOM/XalanElement.hpp>
#include <XalanDOM/XalanNamedNodeMap.hpp>
#include <XalanDOM/XalanNode.hpp>
#include <XalanDOM/XalanNodeList.hpp>

#include <DOMSupport/DOMServices.hpp>

#include <XPath/XPath.hpp>

#include "KeyDeclaration.hpp"
#include "StylesheetExecutionContext.hpp"
#include "XSLTProcessorException.hpp"

XALAN_CPP_NAMESPACE_BEGIN

const MutableNodeRefList	KeyTable::s_dummyList;

KeyTable::KeyTable(
			XalanNode*							startNode,
			const PrefixResolver&				resolver,
			const KeyDeclarationVectorType&		keyDeclarations,
			StylesheetExecutionContext&			executionContext) :
	m_keys()
{
    XalanNode*	pos = startNode;

	const KeyDeclarationVectorType::size_type	nDeclarations =
			keyDeclarations.size();

    // Do a non-recursive pre-walk over the tree.
    while(0 != pos)
    {
		// We're going to have to walk the attribute list
		// if it's an element, so get the attributes.
		const XalanNamedNodeMap*	attrs = 0;

		int							nNodes = 0;

		if(XalanNode::ELEMENT_NODE == pos->getNodeType())
		{
			attrs = pos->getAttributes();

			nNodes = attrs->getLength();

			if(0 == nNodes)
			{
				attrs = 0;
			}
		}

		// Walk the primary node, and each of the attributes.
		// This loop is a little strange... it is meant to always
		// execute once, then execute for each of the attributes.
		XalanNode*	testNode = pos;

		for(int nodeIndex = -1; nodeIndex < nNodes;)
		{
			// Walk through each of the declarations made with xsl:key
			for(unsigned int i = 0; i < nDeclarations; ++i)
			{
				const KeyDeclaration&	kd = keyDeclarations[i];

				if (executionContext.getInConstruction(kd) == true)
				{
					throw XSLTProcessorException(
							TranscodeFromLocalCodePage("The use of the key() function in the \"match\" or \"use\" attribute of xsl:key is illegal!"),
							TranscodeFromLocalCodePage("XSLTKeyIllegalKeyFunctionException"));
				}
				else
				{
					executionContext.beginConstruction(kd);

					// See if our node matches the given key declaration according to
					// the match attribute on xsl:key.
					assert(kd.getMatchPattern() != 0);

					const XPath::eMatchScore	score =
							kd.getMatchPattern()->getMatchScore(testNode,
																resolver,
																executionContext);

					if(score != XPath::eMatchScoreNone)
					{
						processKeyDeclaration(
							m_keys,
							kd,
							testNode,
							resolver,
							executionContext);
					}

					executionContext.endConstruction(kd);
				} // if (kd.getInConstruction() == true)
			} // end for(int i = 0; i < nDeclarations; ++i)

			++nodeIndex;

			if(0 != attrs)
			{
				testNode = attrs->item(nodeIndex);
			}
		} // for(int nodeIndex = -1; nodeIndex < nNodes;)

		// The rest of this is getting the next prewalk position in
		// the tree.
		XalanNode*	nextNode = pos->getFirstChild();

		while(0 == nextNode)
		{
			if(startNode == pos)
			{
				break;
			}
			else
			{
				nextNode = pos->getNextSibling();

				if(0 == nextNode)
				{
					pos = pos->getParentNode();

					if((startNode == pos) || (0 == pos))
					{
						nextNode = 0;
						break;
					}
				}
			}
		}

		pos = nextNode;
    } // while(0 != pos)

	if (m_keys.empty() == false)
	{
		const KeysMapType::iterator		theEnd = m_keys.end();
		KeysMapType::iterator			theCurrent = m_keys.begin();
		assert(theCurrent != theEnd);

		do
		{
			NodeListMapType&	theCurrentNodeListMap = (*theCurrent).second;

			if (theCurrentNodeListMap.empty() == false)
			{
				const NodeListMapType::iterator		theEnd = theCurrentNodeListMap.end();
				NodeListMapType::iterator			theCurrent = theCurrentNodeListMap.begin();
				assert(theCurrent != theEnd);

				do
				{
					(*theCurrent).second.setDocumentOrder();

					++theCurrent;
				}
				while(theCurrent != theEnd);
			}

			++theCurrent;
		}
		while(theCurrent != theEnd);
	}
} // end constructor

KeyTable::~KeyTable()
{
}

const MutableNodeRefList&
KeyTable::getNodeSetByKey(
					  const XalanQName&			qname,
					  const XalanDOMString&		ref) const
{
	const KeysMapType::const_iterator	i = m_keys.find(qname);

	if (i != m_keys.end())
	{
		const NodeListMapType&	theMap = (*i).second;

		const NodeListMapType::const_iterator	j = theMap.find(ref);

		if (j != theMap.end())
		{
			return (*j).second;
		}
	}

	// It makes things much easier if we always return
	// a list of nodes.  So this is just an empty one
	// to return when the ref is not found.
	return s_dummyList;
}

inline void
addIfNotFound(
			StylesheetExecutionContext&		executionContext,
			MutableNodeRefList&				theNodeList,
			XalanNode*						theNode)
{
	theNodeList.addNodeInDocOrder(theNode, executionContext);
}

void
KeyTable::processKeyDeclaration(
			KeysMapType&					theKeys,
			const KeyDeclaration&			kd,
			XalanNode*						testNode,
			const PrefixResolver&			resolver,
			StylesheetExecutionContext&		executionContext)
{
	// Query from the node, according the the select pattern in the
	// use attribute in xsl:key.
	assert(kd.getUse() != 0);

	const XObjectPtr	xuse(kd.getUse()->execute(testNode, resolver, NodeRefList(), executionContext));

	if(xuse->getType() != XObject::eTypeNodeSet)
	{
		assert(kd.getQName() != 0);

		addIfNotFound(
			executionContext,
			theKeys[*kd.getQName()][xuse->str()],
			testNode);
	}
	else
	{
		const NodeRefListBase&	nl = xuse->nodeset();

		// Use each node in the node list as a key value that we'll be
		// able to use to look up the given node.
		const NodeRefListBase::size_type	nUseValues = nl.getLength();

		StylesheetExecutionContext::GetAndReleaseCachedString	theGuard(executionContext);

		XalanDOMString&		nodeData = theGuard.get();

		// Use each node in the node list as a key value that we'll be
		// able to use to look up the given node.
		for(unsigned int i = 0; i < nUseValues; ++i)
		{
			// Get the string value of the node to use as the result of the
			// expression.
			assert(nl.item(i) != 0);

			DOMServices::getNodeData(*nl.item(i), nodeData);

			assert(kd.getQName() != 0);

			addIfNotFound(
				executionContext,
				theKeys[*kd.getQName()][nodeData],
				testNode);

			clear(nodeData);
		}
	}
}

XALAN_CPP_NAMESPACE_END
<commit_msg>Report line/column number and URI in exception.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file
#include "KeyTable.hpp"

#include <memory>

#include <XalanDOM/XalanElement.hpp>
#include <XalanDOM/XalanNamedNodeMap.hpp>
#include <XalanDOM/XalanNode.hpp>
#include <XalanDOM/XalanNodeList.hpp>

#include <DOMSupport/DOMServices.hpp>

#include <XPath/XPath.hpp>

#include "KeyDeclaration.hpp"
#include "StylesheetExecutionContext.hpp"
#include "XSLTProcessorException.hpp"

XALAN_CPP_NAMESPACE_BEGIN

const MutableNodeRefList	KeyTable::s_dummyList;

KeyTable::KeyTable(
			XalanNode*							startNode,
			const PrefixResolver&				resolver,
			const KeyDeclarationVectorType&		keyDeclarations,
			StylesheetExecutionContext&			executionContext) :
	m_keys()
{
    XalanNode*	pos = startNode;

	const KeyDeclarationVectorType::size_type	nDeclarations =
			keyDeclarations.size();

    // Do a non-recursive pre-walk over the tree.
    while(0 != pos)
    {
		// We're going to have to walk the attribute list
		// if it's an element, so get the attributes.
		const XalanNamedNodeMap*	attrs = 0;

		int							nNodes = 0;

		if(XalanNode::ELEMENT_NODE == pos->getNodeType())
		{
			attrs = pos->getAttributes();

			nNodes = attrs->getLength();

			if(0 == nNodes)
			{
				attrs = 0;
			}
		}

		// Walk the primary node, and each of the attributes.
		// This loop is a little strange... it is meant to always
		// execute once, then execute for each of the attributes.
		XalanNode*	testNode = pos;

		for(int nodeIndex = -1; nodeIndex < nNodes;)
		{
			// Walk through each of the declarations made with xsl:key
			for(unsigned int i = 0; i < nDeclarations; ++i)
			{
				const KeyDeclaration&	kd = keyDeclarations[i];

				if (executionContext.getInConstruction(kd) == true)
				{
					assert(kd.getURI() != 0);

					throw XSLTProcessorException(
							TranscodeFromLocalCodePage("The use of the key() function in the \"match\" or \"use\" attribute of xsl:key is illegal!"),
							*kd.getURI(),
							kd.getLineNumber(),
							kd.getColumnNumber(),
							TranscodeFromLocalCodePage("XSLTKeyIllegalKeyFunctionException"));
				}
				else
				{
					executionContext.beginConstruction(kd);

					// See if our node matches the given key declaration according to
					// the match attribute on xsl:key.
					assert(kd.getMatchPattern() != 0);

					const XPath::eMatchScore	score =
							kd.getMatchPattern()->getMatchScore(testNode,
																resolver,
																executionContext);

					if(score != XPath::eMatchScoreNone)
					{
						processKeyDeclaration(
							m_keys,
							kd,
							testNode,
							resolver,
							executionContext);
					}

					executionContext.endConstruction(kd);
				} // if (kd.getInConstruction() == true)
			} // end for(int i = 0; i < nDeclarations; ++i)

			++nodeIndex;

			if(0 != attrs)
			{
				testNode = attrs->item(nodeIndex);
			}
		} // for(int nodeIndex = -1; nodeIndex < nNodes;)

		// The rest of this is getting the next prewalk position in
		// the tree.
		XalanNode*	nextNode = pos->getFirstChild();

		while(0 == nextNode)
		{
			if(startNode == pos)
			{
				break;
			}
			else
			{
				nextNode = pos->getNextSibling();

				if(0 == nextNode)
				{
					pos = pos->getParentNode();

					if((startNode == pos) || (0 == pos))
					{
						nextNode = 0;
						break;
					}
				}
			}
		}

		pos = nextNode;
    } // while(0 != pos)

	if (m_keys.empty() == false)
	{
		const KeysMapType::iterator		theEnd = m_keys.end();
		KeysMapType::iterator			theCurrent = m_keys.begin();
		assert(theCurrent != theEnd);

		do
		{
			NodeListMapType&	theCurrentNodeListMap = (*theCurrent).second;

			if (theCurrentNodeListMap.empty() == false)
			{
				const NodeListMapType::iterator		theEnd = theCurrentNodeListMap.end();
				NodeListMapType::iterator			theCurrent = theCurrentNodeListMap.begin();
				assert(theCurrent != theEnd);

				do
				{
					(*theCurrent).second.setDocumentOrder();

					++theCurrent;
				}
				while(theCurrent != theEnd);
			}

			++theCurrent;
		}
		while(theCurrent != theEnd);
	}
} // end constructor

KeyTable::~KeyTable()
{
}

const MutableNodeRefList&
KeyTable::getNodeSetByKey(
					  const XalanQName&			qname,
					  const XalanDOMString&		ref) const
{
	const KeysMapType::const_iterator	i = m_keys.find(qname);

	if (i != m_keys.end())
	{
		const NodeListMapType&	theMap = (*i).second;

		const NodeListMapType::const_iterator	j = theMap.find(ref);

		if (j != theMap.end())
		{
			return (*j).second;
		}
	}

	// It makes things much easier if we always return
	// a list of nodes.  So this is just an empty one
	// to return when the ref is not found.
	return s_dummyList;
}

inline void
addIfNotFound(
			StylesheetExecutionContext&		executionContext,
			MutableNodeRefList&				theNodeList,
			XalanNode*						theNode)
{
	theNodeList.addNodeInDocOrder(theNode, executionContext);
}

void
KeyTable::processKeyDeclaration(
			KeysMapType&					theKeys,
			const KeyDeclaration&			kd,
			XalanNode*						testNode,
			const PrefixResolver&			resolver,
			StylesheetExecutionContext&		executionContext)
{
	// Query from the node, according the the select pattern in the
	// use attribute in xsl:key.
	assert(kd.getUse() != 0);

	const XObjectPtr	xuse(kd.getUse()->execute(testNode, resolver, NodeRefList(), executionContext));

	if(xuse->getType() != XObject::eTypeNodeSet)
	{
		assert(kd.getQName() != 0);

		addIfNotFound(
			executionContext,
			theKeys[*kd.getQName()][xuse->str()],
			testNode);
	}
	else
	{
		const NodeRefListBase&	nl = xuse->nodeset();

		// Use each node in the node list as a key value that we'll be
		// able to use to look up the given node.
		const NodeRefListBase::size_type	nUseValues = nl.getLength();

		StylesheetExecutionContext::GetAndReleaseCachedString	theGuard(executionContext);

		XalanDOMString&		nodeData = theGuard.get();

		// Use each node in the node list as a key value that we'll be
		// able to use to look up the given node.
		for(unsigned int i = 0; i < nUseValues; ++i)
		{
			// Get the string value of the node to use as the result of the
			// expression.
			assert(nl.item(i) != 0);

			DOMServices::getNodeData(*nl.item(i), nodeData);

			assert(kd.getQName() != 0);

			addIfNotFound(
				executionContext,
				theKeys[*kd.getQName()][nodeData],
				testNode);

			clear(nodeData);
		}
	}
}

XALAN_CPP_NAMESPACE_END
<|endoftext|>


<commit_before><commit_msg>coverity#704921 Dereference after null check<commit_after><|endoftext|>


<commit_before>#include <string.h>
#include <stdio.h>

#include "httpServer.h"
#include "logging.h"

HttpServer::HttpServer(int portNr)
{
    listenSocket.listen(static_cast<uint16_t>(portNr));
    selector.add(listenSocket);
}

HttpServer::~HttpServer()
{
    listenSocket.close();
    for(unsigned int n=0; n<connections.size(); n++)
        delete connections[n];
    for(unsigned int n=0; n<handlers.size(); n++)
        delete handlers[n];
}

void HttpServer::update(float /*delta*/)
{
    if (selector.wait(sf::microseconds(1)))
    {
        if (selector.isReady(listenSocket))
        {
            HttpServerConnection* connection = new HttpServerConnection(this);
            if (listenSocket.accept(connection->socket) == sf::Socket::Done)
            {
                connections.push_back(connection);
                selector.add(connection->socket);
            }else{
                delete connection;
            }
        }
        for(unsigned int n=0; n<connections.size(); n++)
        {
            if (selector.isReady(connections[n]->socket))
            {
                if (!connections[n]->read())
                {
                    selector.remove(connections[n]->socket);
                    delete connections[n];
                    connections.erase(connections.begin() + n);
                }
            }
        }
    }
}

HttpServerConnection::HttpServerConnection(HttpServer* server)
: server(server)
{
    recvBufferCount = 0;
    status = METHOD;
}

bool HttpServerConnection::read()
{
    char buffer[1024];
    size_t size;
    if (socket.receive(buffer, sizeof(buffer), size) != sf::Socket::Done)
        return false;
    if (recvBufferCount + size > recvBufferSize)
        size = recvBufferSize - recvBufferCount;
    if (size < 1)
        return false;
    memcpy(recvBuffer + recvBufferCount, buffer, size);
    recvBufferCount += size;

    while(true)
    {
        char* ptr = (char*)memchr(recvBuffer, '\n', recvBufferCount);
        if (!ptr)
            break;
        *ptr = '\0';
        string line(recvBuffer);
        ptr++;
        size_t len = ptr - recvBuffer;
        recvBufferCount -= len;
        memmove(recvBuffer, ptr, recvBufferCount);
        if (line.endswith("\r"))
            line = line.substr(0, -1);
        if (!handleLine(line))
            return false;
    }
    return true;
}

/** \brief Decode a percent-encoded URI
 * Uri decoding according to RFC1630, RFC1738, RFC2396
 * Credits: Jin Qing
 * \param sSrc const string&   Percent-encoded URI
 * \return string              Decoded URI-string
 *
 */
string HttpServerConnection::UriDecode(const string & sSrc)
{
   // Note from RFC1630: "Sequences which start with a percent
   // sign but are not followed by two hexadecimal characters
   // (0-9, A-F) are reserved for future extension"

   const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
   const size_t SRC_LEN = sSrc.length();
   const unsigned char * const SRC_END = pSrc + SRC_LEN;
   // last decodable '%'
   const unsigned char * const SRC_LAST_DEC = SRC_END - 2;

   char * const pStart = new char[SRC_LEN];
   char * pEnd = pStart;

   while (pSrc < SRC_LAST_DEC)
   {
      if (*pSrc == '%')
      {
         char dec1, dec2;
         if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
            && -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
         {
            *pEnd++ = (dec1 << 4) + dec2;
            pSrc += 3;
            continue;
         }
      }

      *pEnd++ = *pSrc++;
   }

   // the last 2- chars
   while (pSrc < SRC_END)
      *pEnd++ = *pSrc++;

   std::string sResult(pStart, pEnd);
   delete [] pStart;
   return (string) sResult;
}

/**< Map to convert between character encodings */
const signed char HttpServerConnection::HEX2DEC[256] =
{
    /*       0  1  2  3   4  5  6  7   8  9  A  B   C  D  E  F */
    /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 3 */  0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,

    /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,

    /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,

    /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
};

/** \brief Parse a URL, splitting it in its part and optional parameters
 *
 * \param sSrc const string&  URL
 * \return void
 *
 */
void HttpServerConnection::parseUri(const string & sSrc)
{
    string uri = UriDecode(sSrc);
    std::size_t found = uri.find('?');
    if (found==std::string::npos)
    {
        request.path = uri;
        return;
    }
    else
    {
        std::vector<string> parts = uri.split("?", 1);
        request.path = parts[0];

        std::vector<string> parameters = parts[1].split("&");
        for (unsigned int n=0; n<parameters.size(); n++)
        {
            string param = parameters[n];
            found = param.find('=');
            if (found==std::string::npos)
            {
                request.parameters[param] = "";
                LOG(DEBUG) << "HTTP Parameter: " << param;
            }
            else
            {
                if (param.endswith('='))
                {
                    auto param_end = static_cast<int>(param.length()) - 1;
                    auto param_key = param.substr(0, param_end);
                    request.parameters[param_key] = "";
                    LOG(DEBUG) << "HTTP Parameter: " << param_key;
                }
                else
                {
                    std::vector<string> items = param.split("=", 1);
                    request.parameters[items[0]] = items[1];
                    LOG(DEBUG) << "HTTP Parameter: " << items[0] << " = " << items[1];
                }
            }
        }
    }
    LOG(DEBUG) << "HTTP Path: " << request.path;
}

bool HttpServerConnection::handleLine(string line)
{
    switch(status)
    {
    case METHOD:{
        std::vector<string> parts = line.split();
        if (parts.size() != 3)
            return false;
        request.method = parts[0];
        parseUri(parts[1]);
        status = HEADERS;
        }break;
    case HEADERS:
        if (line.length() == 0)
        {
            request.post_data = "";
            if (request.method == "POST")
            {
                if (request.headers.find("content-length") != request.headers.end())
                {
                    unsigned int body_length = request.headers["content-length"].toInt();
                    if (body_length > recvBufferSize)
                        return false;
                    while (body_length > recvBufferCount)
                    {
                        size_t received;
                        if (socket.receive(recvBuffer + recvBufferCount, body_length - recvBufferCount, received) != sf::Socket::Done)
                            return false;
                        recvBufferCount += received;
                    }
                    request.post_data = string(recvBuffer, body_length);
                    recvBufferCount -= body_length;
                    memmove(recvBuffer, recvBuffer + body_length, recvBufferCount);
                }
            }
            status = METHOD;
#ifdef DEBUG
            for (std::unordered_map<string, string>::iterator iter = request.headers.begin(); iter != request.headers.end(); iter++)
            {
                string key=iter->first;
                string value=iter->second;
                LOG(DEBUG) << "HTTP header: (" << key << ", " << value << ")";
            }
#endif // DEBUG
            handleRequest();
        }else{
            std::vector<string> parts = line.split(":", 1);
            if (parts.size() != 2)
                LOG(WARNING) << "Invalid HTTP header: " << line;
            else
                request.headers[parts[0].strip().lower()] = parts[1];
        }
        break;
    }
    return true;
}

void HttpServerConnection::handleRequest()
{
    reply_code = 200;
    headers_send = false;

    for(unsigned int n=0; n<server->handlers.size(); n++)
    {
        if (server->handlers[n]->handleRequest(request, this))
            break;
        if (headers_send)
            break;
    }

    if (!headers_send)
    {
        reply_code = 404;
        string replyData = "File not found";
        sendData(replyData.c_str(), replyData.size());
    }
    string end_chunk = "0\r\n\r\n";
    socket.send(end_chunk.c_str(), end_chunk.size());
    request.parameters.clear();
}

void HttpServerConnection::sendHeaders()
{
    string reply = string("HTTP/1.1 ") + string(reply_code) + " OK\r\n";
    reply += "Content-type: text/html\r\n";
    reply += "Connection: Keep-Alive\r\n";
    reply += "Transfer-Encoding: chunked\r\n";
    reply += "\r\n";
    socket.send(reply.c_str(), reply.size());
    headers_send = true;
}

void HttpServerConnection::sendData(const char* data, size_t data_length)
{
    if (!headers_send)
        sendHeaders();
    if (data_length < 1)
        return;
    string chunk_len_string = string::hex(static_cast<int>(data_length)) + "\r\n";
    socket.send(chunk_len_string.c_str(), chunk_len_string.size());
    socket.send(data, data_length);
    socket.send("\r\n", 2);
}

bool HttpRequestFileHandler::handleRequest(HttpRequest& request, HttpServerConnection* connection)
{
    string replyData = "";
    FILE* f = NULL;
    if (request.path == "/")
        request.path = "/index.html";
    if (request.path.find("..") != -1)
        return false;

    string fullPath = base_path + request.path;
    f = fopen(fullPath.c_str(), "rb");
    if (!f)
        return false;

    while(true)
    {
        char buffer[1024];
        size_t n = fread(buffer, 1, sizeof(buffer), f);
        if (n < 1)
            break;
        connection->sendData(buffer, n);
    }
    fclose(f);
    return true;
}
<commit_msg>Prevent out of bounds read (#119)<commit_after>#include <string.h>
#include <stdio.h>

#include "httpServer.h"
#include "logging.h"

HttpServer::HttpServer(int portNr)
{
    listenSocket.listen(static_cast<uint16_t>(portNr));
    selector.add(listenSocket);
}

HttpServer::~HttpServer()
{
    listenSocket.close();
    for(unsigned int n=0; n<connections.size(); n++)
        delete connections[n];
    for(unsigned int n=0; n<handlers.size(); n++)
        delete handlers[n];
}

void HttpServer::update(float /*delta*/)
{
    if (selector.wait(sf::microseconds(1)))
    {
        if (selector.isReady(listenSocket))
        {
            HttpServerConnection* connection = new HttpServerConnection(this);
            if (listenSocket.accept(connection->socket) == sf::Socket::Done)
            {
                connections.push_back(connection);
                selector.add(connection->socket);
            }else{
                delete connection;
            }
        }
        for(unsigned int n=0; n<connections.size(); n++)
        {
            if (selector.isReady(connections[n]->socket))
            {
                if (!connections[n]->read())
                {
                    selector.remove(connections[n]->socket);
                    delete connections[n];
                    connections.erase(connections.begin() + n);
                }
            }
        }
    }
}

HttpServerConnection::HttpServerConnection(HttpServer* server)
: server(server)
{
    recvBufferCount = 0;
    status = METHOD;
}

bool HttpServerConnection::read()
{
    char buffer[1024];
    size_t size;
    if (socket.receive(buffer, sizeof(buffer), size) != sf::Socket::Done)
        return false;
    if (recvBufferCount + size > recvBufferSize)
        size = recvBufferSize - recvBufferCount;
    if (size < 1)
        return false;
    memcpy(recvBuffer + recvBufferCount, buffer, size);
    recvBufferCount += size;

    while(true)
    {
        char* ptr = (char*)memchr(recvBuffer, '\n', recvBufferCount);
        if (!ptr)
            break;
        *ptr = '\0';
        string line(recvBuffer);
        ptr++;
        size_t len = ptr - recvBuffer;
        recvBufferCount -= len;
        memmove(recvBuffer, ptr, recvBufferCount);
        if (line.endswith("\r"))
            line = line.substr(0, -1);
        if (!handleLine(line))
            return false;
    }
    return true;
}

/** \brief Decode a percent-encoded URI
 * Uri decoding according to RFC1630, RFC1738, RFC2396
 * Credits: Jin Qing
 * \param sSrc const string&   Percent-encoded URI
 * \return string              Decoded URI-string
 *
 */
string HttpServerConnection::UriDecode(const string & sSrc)
{
   // Note from RFC1630: "Sequences which start with a percent
   // sign but are not followed by two hexadecimal characters
   // (0-9, A-F) are reserved for future extension"

   const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
   const size_t SRC_LEN = sSrc.length();
   const unsigned char * const SRC_END = pSrc + SRC_LEN;
   // last decodable '%'
   const unsigned char * const SRC_LAST_DEC = SRC_END - 2;

   char * const pStart = new char[SRC_LEN];
   char * pEnd = pStart;

   while (pSrc < SRC_LAST_DEC)
   {
      if (*pSrc == '%')
      {
         char dec1, dec2;
         if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
            && -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
         {
            *pEnd++ = (dec1 << 4) + dec2;
            pSrc += 3;
            continue;
         }
      }

      *pEnd++ = *pSrc++;
   }

   // the last 2- chars
   while (pSrc < SRC_END)
      *pEnd++ = *pSrc++;

   std::string sResult(pStart, pEnd);
   delete [] pStart;
   return (string) sResult;
}

/**< Map to convert between character encodings */
const signed char HttpServerConnection::HEX2DEC[256] =
{
    /*       0  1  2  3   4  5  6  7   8  9  A  B   C  D  E  F */
    /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 3 */  0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,

    /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,

    /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,

    /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
};

/** \brief Parse a URL, splitting it in its part and optional parameters
 *
 * \param sSrc const string&  URL
 * \return void
 *
 */
void HttpServerConnection::parseUri(const string & sSrc)
{
    string uri = UriDecode(sSrc);
    std::size_t found = uri.find('?');
    if (found==std::string::npos)
    {
        request.path = uri;
        return;
    }
    else
    {
        std::vector<string> parts = uri.split("?", 1);
        request.path = parts[0];

        std::vector<string> parameters;
        if (parts.size()>1)
        {
            parameters = parts[1].split("&");
        }
        for (unsigned int n=0; n<parameters.size(); n++)
        {
            string param = parameters[n];
            found = param.find('=');
            if (found==std::string::npos)
            {
                request.parameters[param] = "";
                LOG(DEBUG) << "HTTP Parameter: " << param;
            }
            else
            {
                if (param.endswith('='))
                {
                    auto param_end = static_cast<int>(param.length()) - 1;
                    auto param_key = param.substr(0, param_end);
                    request.parameters[param_key] = "";
                    LOG(DEBUG) << "HTTP Parameter: " << param_key;
                }
                else
                {
                    std::vector<string> items = param.split("=", 1);
                    request.parameters[items[0]] = items[1];
                    LOG(DEBUG) << "HTTP Parameter: " << items[0] << " = " << items[1];
                }
            }
        }
    }
    LOG(DEBUG) << "HTTP Path: " << request.path;
}

bool HttpServerConnection::handleLine(string line)
{
    switch(status)
    {
    case METHOD:{
        std::vector<string> parts = line.split();
        if (parts.size() != 3)
            return false;
        request.method = parts[0];
        parseUri(parts[1]);
        status = HEADERS;
        }break;
    case HEADERS:
        if (line.length() == 0)
        {
            request.post_data = "";
            if (request.method == "POST")
            {
                if (request.headers.find("content-length") != request.headers.end())
                {
                    unsigned int body_length = request.headers["content-length"].toInt();
                    if (body_length > recvBufferSize)
                        return false;
                    while (body_length > recvBufferCount)
                    {
                        size_t received;
                        if (socket.receive(recvBuffer + recvBufferCount, body_length - recvBufferCount, received) != sf::Socket::Done)
                            return false;
                        recvBufferCount += received;
                    }
                    request.post_data = string(recvBuffer, body_length);
                    recvBufferCount -= body_length;
                    memmove(recvBuffer, recvBuffer + body_length, recvBufferCount);
                }
            }
            status = METHOD;
#ifdef DEBUG
            for (std::unordered_map<string, string>::iterator iter = request.headers.begin(); iter != request.headers.end(); iter++)
            {
                string key=iter->first;
                string value=iter->second;
                LOG(DEBUG) << "HTTP header: (" << key << ", " << value << ")";
            }
#endif // DEBUG
            handleRequest();
        }else{
            std::vector<string> parts = line.split(":", 1);
            if (parts.size() != 2)
                LOG(WARNING) << "Invalid HTTP header: " << line;
            else
                request.headers[parts[0].strip().lower()] = parts[1];
        }
        break;
    }
    return true;
}

void HttpServerConnection::handleRequest()
{
    reply_code = 200;
    headers_send = false;

    for(unsigned int n=0; n<server->handlers.size(); n++)
    {
        if (server->handlers[n]->handleRequest(request, this))
            break;
        if (headers_send)
            break;
    }

    if (!headers_send)
    {
        reply_code = 404;
        string replyData = "File not found";
        sendData(replyData.c_str(), replyData.size());
    }
    string end_chunk = "0\r\n\r\n";
    socket.send(end_chunk.c_str(), end_chunk.size());
    request.parameters.clear();
}

void HttpServerConnection::sendHeaders()
{
    string reply = string("HTTP/1.1 ") + string(reply_code) + " OK\r\n";
    reply += "Content-type: text/html\r\n";
    reply += "Connection: Keep-Alive\r\n";
    reply += "Transfer-Encoding: chunked\r\n";
    reply += "\r\n";
    socket.send(reply.c_str(), reply.size());
    headers_send = true;
}

void HttpServerConnection::sendData(const char* data, size_t data_length)
{
    if (!headers_send)
        sendHeaders();
    if (data_length < 1)
        return;
    string chunk_len_string = string::hex(static_cast<int>(data_length)) + "\r\n";
    socket.send(chunk_len_string.c_str(), chunk_len_string.size());
    socket.send(data, data_length);
    socket.send("\r\n", 2);
}

bool HttpRequestFileHandler::handleRequest(HttpRequest& request, HttpServerConnection* connection)
{
    string replyData = "";
    FILE* f = NULL;
    if (request.path == "/")
        request.path = "/index.html";
    if (request.path.find("..") != -1)
        return false;

    string fullPath = base_path + request.path;
    f = fopen(fullPath.c_str(), "rb");
    if (!f)
        return false;

    while(true)
    {
        char buffer[1024];
        size_t n = fread(buffer, 1, sizeof(buffer), f);
        if (n < 1)
            break;
        connection->sendData(buffer, n);
    }
    fclose(f);
    return true;
}
<|endoftext|>


<commit_before>#include "DriverService.h"
#include "Signal.h"

namespace sensekit {

    sensekit_status_t DriverService::initialize()
    {
        m_driverAdapter.initialize(
            DriverService::adapter_deviceConnected,
            DriverService::adapter_deviceDisconnected,
            DriverService::adapter_deviceChanged,
            this);

        return SENSEKIT_STATUS_SUCCESS;
    }

    Device* DriverService::find_device(size_t deviceId)
    {
        auto it = std::find_if(m_devices.begin(),
                               m_devices.end(),
                               [deviceId] (Device* d) -> bool
                               {
                                   return d->get_device_id() == deviceId;
                               });

        if (it != m_devices.end())
        {
            return *it;
        }
        else
        {
            return nullptr;
        }

    }

    bool DriverService::device_exists(const Device& device)
    {
        auto it = std::find_if(m_devices.begin(),
                               m_devices.end(),
                               [device] (Device* d) -> bool
                               {
                                   return *d == device;
                               });

        return it != m_devices.end();
    }

    bool DriverService::remove_device(const Device* device)
    {
        auto it = std::find(m_devices.begin(), m_devices.end(), device);

        if (it != m_devices.end())
        {
            m_devices.erase(it);
            return true;
        }

        return false;
    }

    void DriverService::adapter_deviceConnected(DriverAdapter* adapter, device_handle_t deviceHandle, void* context)
    {
        DriverService* service = static_cast<DriverService*>(context);
        Device* device = new Device(*adapter, deviceHandle);

        if (!service->device_exists(*device))
        {
            service->m_devices.push_back(device);
            service->m_connectedSignal.raise(device);
        }
        else
        {
            delete device;
        }
    }

    void DriverService::adapter_deviceDisconnected(device_handle_t deviceHandle, void* context)
    {
        DriverService* service = static_cast<DriverService*>(context);

        Device* device = service->find_device(Device::DeviceId(deviceHandle));

        if (device != nullptr)
        {
            service->m_disconnectedSignal.raise(device);
            service->remove_device(device);

            delete device;
        }
    }

    void DriverService::adapter_deviceChanged(device_handle_t deviceHandle, void* context)
    {
        DriverService* service = static_cast<DriverService*>(context);

        Device* device = service->find_device(Device::DeviceId(deviceHandle));

        if (device != nullptr)
        {
            service->m_changedSignal.raise(device);
        }
    }

    sensekit_status_t DriverService::terminate()
    {
        m_driverAdapter.terminate();

        return SENSEKIT_STATUS_SUCCESS;
    }
}
<commit_msg>Add missing header include.<commit_after>#include "DriverService.h"
#include "Signal.h"

#include <algorithm>

namespace sensekit {

    sensekit_status_t DriverService::initialize()
    {
        m_driverAdapter.initialize(
            DriverService::adapter_deviceConnected,
            DriverService::adapter_deviceDisconnected,
            DriverService::adapter_deviceChanged,
            this);

        return SENSEKIT_STATUS_SUCCESS;
    }

    Device* DriverService::find_device(size_t deviceId)
    {
        auto it = std::find_if(m_devices.begin(),
                               m_devices.end(),
                               [deviceId] (Device* d) -> bool
                               {
                                   return d->get_device_id() == deviceId;
                               });

        if (it != m_devices.end())
        {
            return *it;
        }
        else
        {
            return nullptr;
        }

    }

    bool DriverService::device_exists(const Device& device)
    {
        auto it = std::find_if(m_devices.begin(),
                               m_devices.end(),
                               [device] (Device* d) -> bool
                               {
                                   return *d == device;
                               });

        return it != m_devices.end();
    }

    bool DriverService::remove_device(const Device* device)
    {
        auto it = std::find(m_devices.begin(), m_devices.end(), device);

        if (it != m_devices.end())
        {
            m_devices.erase(it);
            return true;
        }

        return false;
    }

    void DriverService::adapter_deviceConnected(DriverAdapter* adapter, device_handle_t deviceHandle, void* context)
    {
        DriverService* service = static_cast<DriverService*>(context);
        Device* device = new Device(*adapter, deviceHandle);

        if (!service->device_exists(*device))
        {
            service->m_devices.push_back(device);
            service->m_connectedSignal.raise(device);
        }
        else
        {
            delete device;
        }
    }

    void DriverService::adapter_deviceDisconnected(device_handle_t deviceHandle, void* context)
    {
        DriverService* service = static_cast<DriverService*>(context);

        Device* device = service->find_device(Device::DeviceId(deviceHandle));

        if (device != nullptr)
        {
            service->m_disconnectedSignal.raise(device);
            service->remove_device(device);

            delete device;
        }
    }

    void DriverService::adapter_deviceChanged(device_handle_t deviceHandle, void* context)
    {
        DriverService* service = static_cast<DriverService*>(context);

        Device* device = service->find_device(Device::DeviceId(deviceHandle));

        if (device != nullptr)
        {
            service->m_changedSignal.raise(device);
        }
    }

    sensekit_status_t DriverService::terminate()
    {
        m_driverAdapter.terminate();

        return SENSEKIT_STATUS_SUCCESS;
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: itrpaint.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2003-12-01 17:22:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _ITRPAINT_HXX
#define _ITRPAINT_HXX

#include "itrtxt.hxx"

class SwSaveClip;          // SwTxtPainter
class SwMultiPortion;

/*************************************************************************
 *                      class SwTxtPainter
 *************************************************************************/

class SwTxtPainter : public SwTxtCursor
{
    sal_Bool bPaintDrop;

    SwLinePortion *CalcPaintOfst( const SwRect &rPaint );
    void CheckSpecialUnderline( const SwLinePortion* pPor,
                                long nAdjustBaseLine = 0 );
protected:
    void CtorInit( SwTxtFrm *pFrm, SwTxtPaintInfo *pInf );
    inline SwTxtPainter() { }
public:
    inline SwTxtPainter( SwTxtFrm *pFrm, SwTxtPaintInfo *pInf )
           { CtorInit( pFrm, pInf ); }
    void DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
                       const sal_Bool bUnderSz );
    void PaintDropPortion();
#ifdef BIDI
    // if PaintMultiPortion is called recursively, we have to pass the
    // surrounding SwBidiPortion
    void PaintMultiPortion( const SwRect &rPaint, SwMultiPortion& rMulti,
                            const SwMultiPortion* pEnvPor = 0 );
#else
    void PaintMultiPortion( const SwRect &rPaint, SwMultiPortion& rMulti );
#endif
    inline void SetPaintDrop( const sal_Bool bNew ) { bPaintDrop = bNew; }
    inline sal_Bool IsPaintDrop() const { return bPaintDrop; }
    inline SwTxtPaintInfo &GetInfo()
        { return (SwTxtPaintInfo&)SwTxtIter::GetInfo(); }
    inline const SwTxtPaintInfo &GetInfo() const
        { return (const SwTxtPaintInfo&)SwTxtIter::GetInfo(); }
};

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.6.902); FILE MERGED 2005/09/05 13:40:52 rt 1.6.902.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: itrpaint.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 04:55:29 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _ITRPAINT_HXX
#define _ITRPAINT_HXX

#include "itrtxt.hxx"

class SwSaveClip;          // SwTxtPainter
class SwMultiPortion;

/*************************************************************************
 *                      class SwTxtPainter
 *************************************************************************/

class SwTxtPainter : public SwTxtCursor
{
    sal_Bool bPaintDrop;

    SwLinePortion *CalcPaintOfst( const SwRect &rPaint );
    void CheckSpecialUnderline( const SwLinePortion* pPor,
                                long nAdjustBaseLine = 0 );
protected:
    void CtorInit( SwTxtFrm *pFrm, SwTxtPaintInfo *pInf );
    inline SwTxtPainter() { }
public:
    inline SwTxtPainter( SwTxtFrm *pFrm, SwTxtPaintInfo *pInf )
           { CtorInit( pFrm, pInf ); }
    void DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
                       const sal_Bool bUnderSz );
    void PaintDropPortion();
#ifdef BIDI
    // if PaintMultiPortion is called recursively, we have to pass the
    // surrounding SwBidiPortion
    void PaintMultiPortion( const SwRect &rPaint, SwMultiPortion& rMulti,
                            const SwMultiPortion* pEnvPor = 0 );
#else
    void PaintMultiPortion( const SwRect &rPaint, SwMultiPortion& rMulti );
#endif
    inline void SetPaintDrop( const sal_Bool bNew ) { bPaintDrop = bNew; }
    inline sal_Bool IsPaintDrop() const { return bPaintDrop; }
    inline SwTxtPaintInfo &GetInfo()
        { return (SwTxtPaintInfo&)SwTxtIter::GetInfo(); }
    inline const SwTxtPaintInfo &GetInfo() const
        { return (const SwTxtPaintInfo&)SwTxtIter::GetInfo(); }
};

#endif
<|endoftext|>


<commit_before><commit_msg>coverity#1158442 Uninitialized scalar field<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ww8graf.hxx,v $
 *
 *  $Revision: 1.18 $
 *
 *  last change: $Author: obo $ $Date: 2005-11-16 13:54:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */

#ifndef _WW8GRAF_HXX
#define _WW8GRAF_HXX

#ifndef __SGI_STL_VECTOR
#include <vector>
#endif
#ifndef __SGI_STL_STACK
#include <stack>
#endif
#ifndef SW_WRITERHELPER
#include "writerhelper.hxx"
#endif

struct EscherShape
{
    ULONG mnEscherShapeOrder;
    ULONG mnNoInlines;
    // --> OD 2004-12-13 #117915# - new member <mbInHeaderFooter>
    bool mbInHeaderFooter;
    EscherShape( ULONG nEscherShapeOrder,
                 bool _bInHeaderFooter )
        : mnEscherShapeOrder(nEscherShapeOrder),
          mnNoInlines(0),
          mbInHeaderFooter( _bInHeaderFooter )
    {}
    // <--
};

class wwZOrderer
{
private:
    // --> OD 2004-12-13 #117915# - consider that objects in page header/footer
    // are always behind objects in page body. Thus, assure, that in vector
    // <maEscherLayer> objects in page header|footer are inserted before
    // objects in page body - see method <GetEscherObjectPos(..)>.
    //No of objects in doc before starting (always 0 unless using file->insert
    //and probably 0 then as well
    std::vector<EscherShape> maEscherLayer;
    // <--
    typedef std::vector<EscherShape>::iterator myeiter;

    std::vector<short> maDrawHeight;
    typedef std::vector<short>::iterator myditer;

    std::stack<USHORT> maIndexes;

    sw::util::SetLayer maSetLayer;

    ULONG mnNoInitialObjects;
    ULONG mnInlines;
    SdrPage* mpDrawPg;
    const SvxMSDffShapeOrders *mpShapeOrders;

    USHORT GetEscherObjectIdx(ULONG nSpId);
    myeiter MapEscherIdxToIter(ULONG nIdx);
    // --> OD 2004-12-13 #117915# - new parameter <_bInHeaderFooter>, indicating
    // that object is in header or footer
    ULONG GetEscherObjectPos( ULONG nSpId,
                              const bool _bInHeaderFooter );
    // <--
    ULONG GetDrawingObjectPos(short nWwHeight);
    bool InsertObject(SdrObject *pObject, ULONG nPos);
public:
    wwZOrderer(const sw::util::SetLayer &rSetLayer, SdrPage* pDrawPg,
        const SvxMSDffShapeOrders *pShapeOrders);
    void InsertTextLayerObject(SdrObject* pObject);
    /*
     cmc: We should have have seperate ZOrder classes for 95- and 97+ and
     instantiate the appropiate one at run time.
     */
    void InsertDrawingObject(SdrObject* pObj, short nWwHeight);
    // --> OD 2004-12-13 #117915# - new parameter <_bInHeaderFooter>, indicating
    // that object is in header or footer
    void InsertEscherObject( SdrObject* pObject,
                             ULONG nSpId,
                             const bool _bInHeaderFooter );
    // <--
    void InsideEscher(ULONG nIndex);
    void OutsideEscher();
};

void WW8FSPAShadowToReal( WW8_FSPA_SHADOW* pFSPAS, WW8_FSPA* pPic );
#endif

/* vi:set tabstop=4 shiftwidth=4 expandtab: */
<commit_msg>INTEGRATION: CWS changefileheader (1.18.1116); FILE MERGED 2008/04/01 12:54:50 thb 1.18.1116.2: #i85898# Stripping all external header guards 2008/03/31 16:55:51 rt 1.18.1116.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ww8graf.hxx,v $
 * $Revision: 1.19 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */

#ifndef _WW8GRAF_HXX
#define _WW8GRAF_HXX

#ifndef __SGI_STL_VECTOR
#include <vector>
#endif
#ifndef __SGI_STL_STACK
#include <stack>
#endif
#include "writerhelper.hxx"

struct EscherShape
{
    ULONG mnEscherShapeOrder;
    ULONG mnNoInlines;
    // --> OD 2004-12-13 #117915# - new member <mbInHeaderFooter>
    bool mbInHeaderFooter;
    EscherShape( ULONG nEscherShapeOrder,
                 bool _bInHeaderFooter )
        : mnEscherShapeOrder(nEscherShapeOrder),
          mnNoInlines(0),
          mbInHeaderFooter( _bInHeaderFooter )
    {}
    // <--
};

class wwZOrderer
{
private:
    // --> OD 2004-12-13 #117915# - consider that objects in page header/footer
    // are always behind objects in page body. Thus, assure, that in vector
    // <maEscherLayer> objects in page header|footer are inserted before
    // objects in page body - see method <GetEscherObjectPos(..)>.
    //No of objects in doc before starting (always 0 unless using file->insert
    //and probably 0 then as well
    std::vector<EscherShape> maEscherLayer;
    // <--
    typedef std::vector<EscherShape>::iterator myeiter;

    std::vector<short> maDrawHeight;
    typedef std::vector<short>::iterator myditer;

    std::stack<USHORT> maIndexes;

    sw::util::SetLayer maSetLayer;

    ULONG mnNoInitialObjects;
    ULONG mnInlines;
    SdrPage* mpDrawPg;
    const SvxMSDffShapeOrders *mpShapeOrders;

    USHORT GetEscherObjectIdx(ULONG nSpId);
    myeiter MapEscherIdxToIter(ULONG nIdx);
    // --> OD 2004-12-13 #117915# - new parameter <_bInHeaderFooter>, indicating
    // that object is in header or footer
    ULONG GetEscherObjectPos( ULONG nSpId,
                              const bool _bInHeaderFooter );
    // <--
    ULONG GetDrawingObjectPos(short nWwHeight);
    bool InsertObject(SdrObject *pObject, ULONG nPos);
public:
    wwZOrderer(const sw::util::SetLayer &rSetLayer, SdrPage* pDrawPg,
        const SvxMSDffShapeOrders *pShapeOrders);
    void InsertTextLayerObject(SdrObject* pObject);
    /*
     cmc: We should have have seperate ZOrder classes for 95- and 97+ and
     instantiate the appropiate one at run time.
     */
    void InsertDrawingObject(SdrObject* pObj, short nWwHeight);
    // --> OD 2004-12-13 #117915# - new parameter <_bInHeaderFooter>, indicating
    // that object is in header or footer
    void InsertEscherObject( SdrObject* pObject,
                             ULONG nSpId,
                             const bool _bInHeaderFooter );
    // <--
    void InsideEscher(ULONG nIndex);
    void OutsideEscher();
};

void WW8FSPAShadowToReal( WW8_FSPA_SHADOW* pFSPAS, WW8_FSPA* pPic );
#endif

/* vi:set tabstop=4 shiftwidth=4 expandtab: */
<|endoftext|>


<commit_before><commit_msg>read block in one swoop, rather than char by char<commit_after><|endoftext|>


<commit_before>#pragma once

namespace HomieInternals {
  // config mode

  const char PROGMEM_CONFIG_CORS[] PROGMEM = "HTTP/1.1 204 No Content\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: PUT\r\nAccess-Control-Allow-Headers: Content-Type\r\n\r\n";
  const char PROGMEM_CONFIG_APPLICATION_JSON[] PROGMEM = "application/json";
  const char PROGMEM_CONFIG_JSON_FAILURE_BEGINNING[] PROGMEM = "{\"success\":false,\"error\":\"";
  const char PROGMEM_CONFIG_NETWORKS_FAILURE[] PROGMEM = "{\"error\": \"Initial Wi-Fi scan not finished yet\"}";
}
<commit_msg>Attempt to fix CORS issue #48<commit_after>#pragma once

namespace HomieInternals {
  // config mode

  const char PROGMEM_CONFIG_CORS[] PROGMEM = "HTTP/1.1 204 No Content\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: PUT,POST\r\nAccess-Control-Allow-Headers: Content-Type,Accept,Origin\r\n\r\n";
  const char PROGMEM_CONFIG_APPLICATION_JSON[] PROGMEM = "application/json";
  const char PROGMEM_CONFIG_JSON_FAILURE_BEGINNING[] PROGMEM = "{\"success\":false,\"error\":\"";
  const char PROGMEM_CONFIG_NETWORKS_FAILURE[] PROGMEM = "{\"error\": \"Initial Wi-Fi scan not finished yet\"}";
}
<|endoftext|>