<commit_before>#include "io.hpp"
#include "string.hpp"
#include "fixnum.hpp"
#include "array.hpp"
#include "../platform/platform.hpp"
#include "../runtime.hpp"
#include "../stream.hpp"

namespace Mirb
{
	void IO::assert_stream()
	{
		if(!stream)
			raise(context->io_error, "IO object is closed");
	}

	IO::~IO()
	{
		if(stream && flag)
			delete stream;
	}

	void IO::close()
	{
		if(stream)
		{
			if(flag)
				delete stream;
			stream = 0;
		}
	}

	value_t IO::rb_close(IO *io)
	{
		io->close();

		return value_nil;
	}

	value_t IO::rb_print(IO *io, size_t argc, value_t argv[])
	{
		io->assert_stream();

		for(size_t i = 0; i < argc; ++i)
			io->stream->print(cast_string(argv[i])->string);

		return value_nil;
	}

	value_t IO::rb_puts(IO *io, size_t argc, value_t argv[])
	{
		io->assert_stream();

		for(size_t i = 0; i < argc; ++i)
			io->stream->puts(cast_string(argv[i])->string);

		return value_nil;
	}

	value_t rb_read(IO *io, intptr_t length)
	{
		io->assert_stream();

		if(length == Fixnum::undef)
			return io->stream->read().to_string();
		else
		{
			if(length < 0)
				raise(context->argument_error, "Can't read a negative size");

			return io->stream->read((size_t)length).to_string();
		}
	}

	value_t rb_gets(IO *io)
	{
		io->assert_stream();

		auto result = io->stream->gets();

		if(result.size())
			return result.to_string();
		else
			return value_nil;
	}

	value_t rb_each_line(IO *io, value_t block)
	{
		OnStack<2> os(io, block);

		while(true)
		{
			io->assert_stream();

			CharArray line = io->stream->gets();

			if(line.size())
				yield(block, line.to_string());
			else
				break;
		}

		return io;
	}

	value_t IO::rb_readlines(String *path)
	{
		Stream *file;

		Platform::wrap([&] {
			file = Platform::open(path->string, Platform::Read, Platform::Open);
		});

		auto result = Array::allocate();

		while(true)
		{
			CharArray line = file->gets();

			if(line.size())
				result->vector.push(line.to_string());
			else
				break;
		}

		return result;
	}

	void IO::initialize()
	{
		context->io_class = define_class("IO", context->object_class);

		singleton_method<String, &rb_readlines>(context->io_class, "readlines");

		method<Self<IO>, &rb_close>(context->io_class, "close");
		method<Self<IO>, Optional<Arg::Fixnum>, &rb_read>(context->io_class, "read");
		method<Self<IO>, Arg::Block, &rb_each_line>(context->io_class, "each_line");
		method<Self<IO>, Arg::Count, Arg::Values, &rb_print>(context->io_class, "print");
		method<Self<IO>, Arg::Count, Arg::Values, &rb_puts>(context->io_class, "puts");
		method<Self<IO>, &rb_gets>(context->io_class, "gets");
	}
};

<commit_msg>Fixed a bug with IO#readlines<commit_after>#include "io.hpp"
#include "string.hpp"
#include "fixnum.hpp"
#include "array.hpp"
#include "../platform/platform.hpp"
#include "../runtime.hpp"
#include "../stream.hpp"

namespace Mirb
{
	void IO::assert_stream()
	{
		if(!stream)
			raise(context->io_error, "IO object is closed");
	}

	IO::~IO()
	{
		if(stream && flag)
			delete stream;
	}

	void IO::close()
	{
		if(stream)
		{
			if(flag)
				delete stream;
			stream = 0;
		}
	}

	value_t IO::rb_close(IO *io)
	{
		io->close();

		return value_nil;
	}

	value_t IO::rb_print(IO *io, size_t argc, value_t argv[])
	{
		io->assert_stream();

		for(size_t i = 0; i < argc; ++i)
			io->stream->print(cast_string(argv[i])->string);

		return value_nil;
	}

	value_t IO::rb_puts(IO *io, size_t argc, value_t argv[])
	{
		io->assert_stream();

		for(size_t i = 0; i < argc; ++i)
			io->stream->puts(cast_string(argv[i])->string);

		return value_nil;
	}

	value_t rb_read(IO *io, intptr_t length)
	{
		io->assert_stream();

		if(length == Fixnum::undef)
			return io->stream->read().to_string();
		else
		{
			if(length < 0)
				raise(context->argument_error, "Can't read a negative size");

			return io->stream->read((size_t)length).to_string();
		}
	}

	value_t rb_gets(IO *io)
	{
		io->assert_stream();

		auto result = io->stream->gets();

		if(result.size())
			return result.to_string();
		else
			return value_nil;
	}

	value_t rb_each_line(IO *io, value_t block)
	{
		OnStack<2> os(io, block);

		while(true)
		{
			io->assert_stream();

			CharArray line = io->stream->gets();

			if(line.size())
				yield(block, line.to_string());
			else
				break;
		}

		return io;
	}

	value_t IO::rb_readlines(String *path)
	{
		Stream *file;

		Platform::wrap([&] {
			file = Platform::open(path->string, Platform::Read, Platform::Open);
		});

		Finally finally([&] {
			delete file;
		});

		auto result = Array::allocate();

		while(true)
		{
			CharArray line = file->gets();

			if(line.size())
				result->vector.push(line.to_string());
			else
				break;
		}

		return result;
	}

	void IO::initialize()
	{
		context->io_class = define_class("IO", context->object_class);

		singleton_method<String, &rb_readlines>(context->io_class, "readlines");

		method<Self<IO>, &rb_close>(context->io_class, "close");
		method<Self<IO>, Optional<Arg::Fixnum>, &rb_read>(context->io_class, "read");
		method<Self<IO>, Arg::Block, &rb_each_line>(context->io_class, "each_line");
		method<Self<IO>, Arg::Count, Arg::Values, &rb_print>(context->io_class, "print");
		method<Self<IO>, Arg::Count, Arg::Values, &rb_puts>(context->io_class, "puts");
		method<Self<IO>, &rb_gets>(context->io_class, "gets");
	}
};

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-json/JSONRPCCodec.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedWriter.h"
#include "fnord-http/statshttpservlet.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-rpc/RPCClient.h"
#include "CustomerNamespace.h"
#include "frontend/CMFrontend.h"
#include "frontend/LookupServlet.h"

using fnord::StringUtil;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "statsd_addr",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "127.0.0.1:8192",
      "Statsd addr",
      "<addr>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  fnord::thread::EventLoop event_loop;
  HTTPRPCClient rpc_client(&event_loop);

  /* set up tracker log feed writer */
  fnord::feeds::RemoteFeedWriter tracker_log_feed(&rpc_client);
  tracker_log_feed.addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver01.nue01.production.fnrd.net",
      16);

  tracker_log_feed.addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver02.nue01.production.fnrd.net",
      16);

  tracker_log_feed.exportStats("/cm-frontend/global/tracker_log_writer");

  /* set up frontend */
  cm::CMFrontend frontend(&tracker_log_feed);

  /* set up dawanda */
  auto dwn_ns = new cm::CustomerNamespace("dawanda");
  dwn_ns->addVHost("dwnapps.net");
  dwn_ns->loadTrackingJS("customers/dawanda/track.js");

  RefPtr<feeds::RemoteFeedWriter> dwn_index_request_feed(
      new feeds::RemoteFeedWriter(&rpc_client));

  dwn_index_request_feed->addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "dawanda.index_requests.feedserver01.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "dawanda.index_requests.feedserver02.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->exportStats(
      "/cm-frontend/global/index_request_writer");

  frontend.addCustomer(dwn_ns, dwn_index_request_feed);

  /* set up public http server */
  fnord::http::HTTPRouter http_router;
  http_router.addRouteByPrefixMatch("/", &frontend);
  fnord::http::HTTPServer http_server(&http_router, &event_loop);
  http_server.listen(flags.getInt("http_port"));
  http_server.stats()->exportStats(
      "/cm-frontend/global/http/inbound");
  http_server.stats()->exportStats(
      StringUtil::format(
          "/cm-frontend/by-host/$0/http/inbound",
          cm::cmHostname()));

  /* stats reporting */
  fnord::stats::StatsdAgent statsd_agent(
      fnord::net::InetAddr::resolve(flags.getString("statsd_addr")),
      10 * fnord::kMicrosPerSecond);

  statsd_agent.start();

  event_loop.run();
  return 0;
}

<commit_msg>rename feed...<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-json/JSONRPCCodec.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedWriter.h"
#include "fnord-http/statshttpservlet.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-rpc/RPCClient.h"
#include "CustomerNamespace.h"
#include "frontend/CMFrontend.h"
#include "frontend/LookupServlet.h"

using fnord::StringUtil;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "statsd_addr",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "127.0.0.1:8192",
      "Statsd addr",
      "<addr>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  fnord::thread::EventLoop event_loop;
  HTTPRPCClient rpc_client(&event_loop);

  /* set up tracker log feed writer */
  fnord::feeds::RemoteFeedWriter tracker_log_feed(&rpc_client);
  tracker_log_feed.addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver01.nue01.production.fnrd.net",
      16);

  tracker_log_feed.addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "tracker_log.feedserver02.nue01.production.fnrd.net",
      16);

  tracker_log_feed.exportStats("/cm-frontend/global/tracker_log_writer");

  /* set up frontend */
  cm::CMFrontend frontend(&tracker_log_feed);

  /* set up dawanda */
  auto dwn_ns = new cm::CustomerNamespace("dawanda");
  dwn_ns->addVHost("dwnapps.net");
  dwn_ns->loadTrackingJS("customers/dawanda/track.js");

  RefPtr<feeds::RemoteFeedWriter> dwn_index_request_feed(
      new feeds::RemoteFeedWriter(&rpc_client));

  dwn_index_request_feed->addTargetFeed(
      URI("http://s01.nue01.production.fnrd.net:7001/rpc"),
      "index_requests.feedserver01.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->addTargetFeed(
      URI("http://s02.nue01.production.fnrd.net:7001/rpc"),
      "index_requests.feedserver02.nue01.production.fnrd.net",
      16);

  dwn_index_request_feed->exportStats(
      "/cm-frontend/global/index_request_writer");

  frontend.addCustomer(dwn_ns, dwn_index_request_feed);

  /* set up public http server */
  fnord::http::HTTPRouter http_router;
  http_router.addRouteByPrefixMatch("/", &frontend);
  fnord::http::HTTPServer http_server(&http_router, &event_loop);
  http_server.listen(flags.getInt("http_port"));
  http_server.stats()->exportStats(
      "/cm-frontend/global/http/inbound");
  http_server.stats()->exportStats(
      StringUtil::format(
          "/cm-frontend/by-host/$0/http/inbound",
          cm::cmHostname()));

  /* stats reporting */
  fnord::stats::StatsdAgent statsd_agent(
      fnord::net::InetAddr::resolve(flags.getString("statsd_addr")),
      10 * fnord::kMicrosPerSecond);

  statsd_agent.start();

  event_loop.run();
  return 0;
}

<|endoftext|>


<commit_before>/*
* (C) 2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "apps.h"
#include <fstream>
#include <botan/auto_rng.h>

#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509cert.h>
#include <botan/x509_crl.h>
#include <botan/pkcs8.h>
#endif

#if defined(BOTAN_HAS_TLS)
#include <botan/tls_client.h>
#endif

namespace {

#if defined(BOTAN_HAS_TLS)

class Fuzzer_Creds : public Credentials_Manager
   {
   public:
      void verify_certificate_chain(const std::string& type,
                                    const std::string& purported_hostname,
                                    const std::vector<X509_Certificate>& cert_chain) override
         {
         try
            {
            Credentials_Manager::verify_certificate_chain(type,
                                                          purported_hostname,
                                                          cert_chain);
            }
         catch(std::exception& e) {}
         }

      std::string psk_identity_hint(const std::string&, const std::string&) override { return "psk_hint"; }
      std::string psk_identity(const std::string&, const std::string&) { return "psk_id"; }
      SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
         {
         return SymmetricKey("AABBCCDDEEFF00112233445566778899");
         }
   };

#endif

int fuzzer(int argc, char* argv[])
   {
   if(argc != 3)
      {
      std::cout << "Usage: " << argv[0] << " [type] [input_file]\n";
      std::cout << "Hook for fuzzers such as afl (produces no output)\n";
      std::cout << "Types: cert crl privkey tls_client\n";
      return 1;
      }

   const std::string type = argv[1];
   const std::string input = argv[2];

   AutoSeeded_RNG rng;

#if defined(BOTAN_HAS_X509_CERTIFICATES)
   if(type == "cert")
      {
      X509_Certificate cert(input);
      return 0;
      }

   if(type == "crl")
      {
      X509_CRL crl(input);
      return 0;
      }

   if(type == "privkey")
      {
      std::unique_ptr<Private_Key>(PKCS8::load_key(input, rng));
      return 0;
      }

#endif

#if defined(BOTAN_HAS_TLS)
   if(type == "tls_client")
      {
      auto dev_null = [](const byte[], size_t) {};

      auto ignore_alerts = [](TLS::Alert, const byte[], size_t) {};
      auto ignore_hs = [](const TLS::Session&) { return true; };

      TLS::Session_Manager_In_Memory session_manager(rng);
      TLS::Policy policy;
      TLS::Protocol_Version client_offer = TLS::Protocol_Version::TLS_V12;
      TLS::Server_Information info("server.name", 443);
      const std::vector<std::string> protocols_to_offer = { "fuzz/1.0", "http/1.1", "bunny/1.21.3" };
      Fuzzer_Creds creds;

      TLS::Client client(dev_null,
                         dev_null,
                         ignore_alerts,
                         ignore_hs,
                         session_manager,
                         creds,
                         policy,
                         rng,
                         info,
                         client_offer,
                         protocols_to_offer);

      std::ifstream in(input.c_str());

      std::vector<byte> buf(1024);

      try
         {
         while(in.good())
            {
            in.read((char*)&buf[0], buf.size());
            size_t got = in.gcount();
            client.received_data(&buf[0], got);
            }
         }
      catch(std::exception& e)
         {
         return 0;
         }
      return 0;
      }
#endif

   std::cout << "Unknown type '" << type << "'\n";
   return 1;
   }

REGISTER_APP(fuzzer);

}
<commit_msg>Add override and fix signature of Fuzzer_Creds::psk_identity()<commit_after>/*
* (C) 2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "apps.h"
#include <fstream>
#include <botan/auto_rng.h>

#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509cert.h>
#include <botan/x509_crl.h>
#include <botan/pkcs8.h>
#endif

#if defined(BOTAN_HAS_TLS)
#include <botan/tls_client.h>
#endif

namespace {

#if defined(BOTAN_HAS_TLS)

class Fuzzer_Creds : public Credentials_Manager
   {
   public:
      void verify_certificate_chain(const std::string& type,
                                    const std::string& purported_hostname,
                                    const std::vector<X509_Certificate>& cert_chain) override
         {
         try
            {
            Credentials_Manager::verify_certificate_chain(type,
                                                          purported_hostname,
                                                          cert_chain);
            }
         catch(std::exception& e) {}
         }

      std::string psk_identity_hint(const std::string&, const std::string&) override { return "psk_hint"; }
      std::string psk_identity(const std::string&, const std::string&, const std::string&) override { return "psk_id"; }
      SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
         {
         return SymmetricKey("AABBCCDDEEFF00112233445566778899");
         }
   };

#endif

int fuzzer(int argc, char* argv[])
   {
   if(argc != 3)
      {
      std::cout << "Usage: " << argv[0] << " [type] [input_file]\n";
      std::cout << "Hook for fuzzers such as afl (produces no output)\n";
      std::cout << "Types: cert crl privkey tls_client\n";
      return 1;
      }

   const std::string type = argv[1];
   const std::string input = argv[2];

   AutoSeeded_RNG rng;

#if defined(BOTAN_HAS_X509_CERTIFICATES)
   if(type == "cert")
      {
      X509_Certificate cert(input);
      return 0;
      }

   if(type == "crl")
      {
      X509_CRL crl(input);
      return 0;
      }

   if(type == "privkey")
      {
      std::unique_ptr<Private_Key>(PKCS8::load_key(input, rng));
      return 0;
      }

#endif

#if defined(BOTAN_HAS_TLS)
   if(type == "tls_client")
      {
      auto dev_null = [](const byte[], size_t) {};

      auto ignore_alerts = [](TLS::Alert, const byte[], size_t) {};
      auto ignore_hs = [](const TLS::Session&) { return true; };

      TLS::Session_Manager_In_Memory session_manager(rng);
      TLS::Policy policy;
      TLS::Protocol_Version client_offer = TLS::Protocol_Version::TLS_V12;
      TLS::Server_Information info("server.name", 443);
      const std::vector<std::string> protocols_to_offer = { "fuzz/1.0", "http/1.1", "bunny/1.21.3" };
      Fuzzer_Creds creds;

      TLS::Client client(dev_null,
                         dev_null,
                         ignore_alerts,
                         ignore_hs,
                         session_manager,
                         creds,
                         policy,
                         rng,
                         info,
                         client_offer,
                         protocols_to_offer);

      std::ifstream in(input.c_str());

      std::vector<byte> buf(1024);

      try
         {
         while(in.good())
            {
            in.read((char*)&buf[0], buf.size());
            size_t got = in.gcount();
            client.received_data(&buf[0], got);
            }
         }
      catch(std::exception& e)
         {
         return 0;
         }
      return 0;
      }
#endif

   std::cout << "Unknown type '" << type << "'\n";
   return 1;
   }

REGISTER_APP(fuzzer);

}
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   OgreMaterialUtils.cpp
 *  @brief  Contains some often needed utlitity functions when dealing with OGRE material scripts.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "MemoryLeakCheck.h"
#include "OgreMaterialUtils.h"
#include "OgreRenderingModule.h"
#include "OgreConversionUtils.h"
#include "AssetAPI.h"
#include <Ogre.h>

namespace OgreRenderer
{
    std::string BaseMaterials[] = {
        "LitTextured", // normal
        "UnlitTextured", // normal fullbright
        "LitTexturedAdd", // additive
        "UnlitTexturedAdd", // additive fullbright
        "LitTexturedSoftAlpha", // forced soft alpha
        "UnlitTexturedSoftAlpha", // forced soft alpha fullbright
        "LitTexturedVCol", // vertexcolor
        "UnlitTexturedVCol", // vertexcolor fullbright
        "LitTexturedSoftAlphaVCol", // vertexcolor forced soft alpha
        "UnlitTexturedSoftAlphaVCol" // vertexcolor forced soft alpha fullbright
    };

    std::string AlphaBaseMaterials[] = {
        "LitTexturedSoftAlpha", // soft alpha
        "UnlitTexturedSoftAlpha", // soft alpha fullbright
        "LitTexturedAdd", // additive
        "UnlitTexturedAdd", // additive fullbright
        "LitTexturedSoftAlpha", // forced soft alpha
        "UnlitTexturedSoftAlpha", // forced soft alpha fullbright
        "LitTexturedSoftAlphaVCol", // vertexcolor soft alpha
        "UnlitTexturedSoftAlphaVCol", // vertexcolor soft alpha fullbright
        "LitTexturedSoftAlphaVCol", // vertexcolor forced soft alpha
        "UnlitTexturedSoftAlphaVCol" // vertexcolor forced soft alpha fullbright
    };

    std::string MaterialSuffix[] = {
        "", // normal
        "fb", // normal fullbright
        "add", // additive
        "fbadd", // additive fullbright
        "alpha", // forced alpha
        "fbalpha", // forced alpha fullbright
        "vcol", // vertex color
        "fbvcol", // vertex color fullbright
        "vcolalpha", // vertex color alpha
        "fbvcolalpha" // vertex color alpha fullbright
    };

    bool IsMaterialSuffixValid(const std::string& suffix)
    {
        for(uint i = 0; i < MAX_MATERIAL_VARIATIONS; ++i)
        {
            if (suffix == MaterialSuffix[i])
                return true;
        }

        return false;
    }

    std::string GetMaterialSuffix(uint variation)
    {
        if (variation >= MAX_MATERIAL_VARIATIONS)
        {
            ::LogWarning("Requested suffix for non-existing material variation " + QString::number(variation));
            variation = 0;
        }

        return MaterialSuffix[variation];
    }

    uint GetMaterialVariation(const std::string& suffix)
    {
        for(uint i = 0; i < MAX_MATERIAL_VARIATIONS; ++i)
            if (suffix == MaterialSuffix[i])
                return i;
        return 0;
    }

    Ogre::MaterialPtr CloneMaterial(const std::string& sourceMaterialName, const std::string &newName)
    {
        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mm.getByName(AssetAPI::SanitateAssetRef(sourceMaterialName));

        if (!material.get())
        {
             ::LogWarning("Failed to clone material \"" + sourceMaterialName + "\". It was not found.");
             return Ogre::MaterialPtr();
        }
        material = material->clone(AssetAPI::SanitateAssetRef(newName));
        if (!material.get())
        {
             ::LogWarning("Failed to clone material \"" + sourceMaterialName + "\" to name \"" + AssetAPI::SanitateAssetRef(newName) + "\"");
             return Ogre::MaterialPtr();
        }
        return material;
    }

    Ogre::MaterialPtr GetOrCreateLitTexturedMaterial(const std::string& materialName)
    {
        std::string baseMaterialName = "LitTextured";

        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mm.getByName(AssetAPI::SanitateAssetRef(materialName));

        if (!material.get())
        {
            Ogre::MaterialPtr baseMaterial = mm.getByName(AssetAPI::SanitateAssetRef(baseMaterialName));
            if (baseMaterial.isNull())
                return Ogre::MaterialPtr();

            material = baseMaterial->clone(AssetAPI::SanitateAssetRef(materialName));
        }

        assert(material.get());
        return material;
    }

    Ogre::MaterialPtr GetOrCreateUnlitTexturedMaterial(const std::string& materialName)
    {
        std::string baseMaterialName = "UnlitTextured";

        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mm.getByName(AssetAPI::SanitateAssetRef(materialName));

        if (!material.get())
        {
            Ogre::MaterialPtr baseMaterial = mm.getByName(AssetAPI::SanitateAssetRef(baseMaterialName));
            if (baseMaterial.isNull())
                return Ogre::MaterialPtr();
            material = baseMaterial->clone(AssetAPI::SanitateAssetRef(materialName));
        }

        assert(material.get());
        return material;
    }

    Ogre::MaterialPtr GetOrCreateLegacyMaterial(const std::string& texture_name, const std::string& suffix)
    {
        uint variation = GetMaterialVariation(suffix);
        return GetOrCreateLegacyMaterial(texture_name, variation);
    }

    Ogre::MaterialPtr GetOrCreateLegacyMaterial(const std::string& texture_name, uint variation)
    {
        if (variation >= MAX_MATERIAL_VARIATIONS)
        {
            ::LogWarning("Requested suffix for non-existing material variation " + QString::number(variation));
            variation = 0;
        }
        const std::string& suffix = MaterialSuffix[variation];

        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();

        std::string material_name = sanitatedtexname + suffix;
        Ogre::MaterialPtr material = mm.getByName(material_name);

        if (!material.get())
        {
            material = mm.create(material_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
            assert(material.get());
        }
        else
            return material;

        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);
        bool has_alpha = false;
        if (!tex.isNull())
        {
            // As far as the legacy materials are concerned, DXT1 is not alpha
            if (tex->getFormat() == Ogre::PF_DXT1)
                has_alpha = false;
            else if (Ogre::PixelUtil::hasAlpha(tex->getFormat()))
                has_alpha = true;
        }

        Ogre::MaterialPtr base_material;
        if (!has_alpha)
            base_material = mm.getByName(BaseMaterials[variation]);
        else
            base_material = mm.getByName(AlphaBaseMaterials[variation]);
        if (!base_material.get())
        {
            ::LogError("Could not find " + MaterialSuffix[variation] + " base material for " + texture_name);
            return Ogre::MaterialPtr();
        }

        base_material->copyDetailsTo(material);
        SetTextureUnitOnMaterial(material, texture_name, 0);

        return material;
    }

    void UpdateLegacyMaterials(const std::string& texture_name)
    {
        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();

        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);
        bool has_alpha = false;
        if (!tex.isNull())
            if (Ogre::PixelUtil::hasAlpha(tex->getFormat()))
                has_alpha = true;

        for(uint i = 0; i < MAX_MATERIAL_VARIATIONS; ++i)
        {
            std::string material_name = sanitatedtexname + MaterialSuffix[i];
            Ogre::MaterialPtr material = mm.getByName(material_name);

            if (!material.get())
                continue;

            Ogre::MaterialPtr base_material;
            if (!has_alpha)
                base_material = mm.getByName(BaseMaterials[i]);
            else
                base_material = mm.getByName(AlphaBaseMaterials[i]);
            if (!base_material.get())
            {
                ::LogError("Could not find " + MaterialSuffix[i] + " base material for " + texture_name);
                continue;
            }

            base_material->copyDetailsTo(material);
            SetTextureUnitOnMaterial(material, texture_name, 0);
        }
    }

    void SetTextureUnitOnMaterial(Ogre::MaterialPtr material, const std::string& texture_name, uint index)
    {
        if (material.isNull())
            return;

        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);

        Ogre::Material::TechniqueIterator iter = material->getTechniqueIterator();
        while(iter.hasMoreElements())
        {
            Ogre::Technique *tech = iter.getNext();
            assert(tech);
            Ogre::Technique::PassIterator passIter = tech->getPassIterator();
            while(passIter.hasMoreElements())
            {
                Ogre::Pass *pass = passIter.getNext();

                Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();
                uint cmp_index = 0;

                while(texIter.hasMoreElements())
                {
                    Ogre::TextureUnitState *texUnit = texIter.getNext();
                    if (index == cmp_index)
                    {
                        if (tex.get())
                            texUnit->setTextureName(sanitatedtexname);
                        else
                            texUnit->setTextureName("TextureMissing.png");

                        return; // We found and replaced the index we wanted to - can early-out return without looping the rest of the indices for nothing.
                    }
                    cmp_index++;
                }
            }
        }
    }

    void ReplaceTextureOnMaterial(Ogre::MaterialPtr material, const std::string& original_name, const std::string& texture_name)
    {
        if (material.isNull())
            return;

        std::string sanitatedorgname = AssetAPI::SanitateAssetRef(original_name);
        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);

        Ogre::Material::TechniqueIterator iter = material->getTechniqueIterator();
        while(iter.hasMoreElements())
        {
            Ogre::Technique *tech = iter.getNext();
            assert(tech);
            Ogre::Technique::PassIterator passIter = tech->getPassIterator();
            while(passIter.hasMoreElements())
            {
                Ogre::Pass *pass = passIter.getNext();

                Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();

                while(texIter.hasMoreElements())
                {
                    Ogre::TextureUnitState *texUnit = texIter.getNext();
                    if (texUnit->getTextureName() == sanitatedorgname)
                    {
                        if (tex.get())
                            texUnit->setTextureName(sanitatedtexname);
                        else
                            texUnit->setTextureName("TextureMissing.png");
                    }
                }
            }
        }
    }

    void GetTextureNamesFromMaterial(Ogre::MaterialPtr material, StringVector& textures)
    {
        textures.clear();
        if (material.isNull())
            return;

        // Use a set internally to avoid duplicates
        std::set<std::string> textures_set;

        Ogre::Material::TechniqueIterator iter = material->getTechniqueIterator();
        while(iter.hasMoreElements())
        {
            Ogre::Technique *tech = iter.getNext();
            assert(tech);
            Ogre::Technique::PassIterator passIter = tech->getPassIterator();
            while(passIter.hasMoreElements())
            {
                Ogre::Pass *pass = passIter.getNext();

                Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();

                while(texIter.hasMoreElements())
                {
                    Ogre::TextureUnitState *texUnit = texIter.getNext();
                    const std::string& texname = texUnit->getTextureName();

                    if (!texname.empty())
                        textures_set.insert(texname);
                }
            }
        }

        std::set<std::string>::iterator i = textures_set.begin();

        while(i != textures_set.end())
        {
            textures.push_back(*i);
            ++i;
        }
    }

    void RemoveMaterial(Ogre::MaterialPtr& material)
    {
        if (!material.isNull())
        {
            std::string material_name = material->getName();
            material.setNull();

            try
            {
                Ogre::MaterialManager::getSingleton().remove(material_name);
            }
            catch(Ogre::Exception& e)
            {
                ::LogDebug("Failed to remove Ogre material:" + std::string(e.what()));
            }
        }
    }

    bool ProcessBraces(const std::string& line, int& braceLevel)
    {
        if (line == "{")
        {
            ++braceLevel;
            return true;
        }
        else if (line == "}")
        {
            --braceLevel;
            return true;
        }
        else return false;
    }
}
<commit_msg>Include MemoryLeakCheck.h last. Otherwise won't compile in debug mode.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   OgreMaterialUtils.cpp
 *  @brief  Contains some often needed utlitity functions when dealing with OGRE material scripts.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "OgreMaterialUtils.h"
#include "OgreRenderingModule.h"
#include "OgreConversionUtils.h"
#include "AssetAPI.h"
#include <Ogre.h>
#include "MemoryLeakCheck.h"

namespace OgreRenderer
{
    std::string BaseMaterials[] = {
        "LitTextured", // normal
        "UnlitTextured", // normal fullbright
        "LitTexturedAdd", // additive
        "UnlitTexturedAdd", // additive fullbright
        "LitTexturedSoftAlpha", // forced soft alpha
        "UnlitTexturedSoftAlpha", // forced soft alpha fullbright
        "LitTexturedVCol", // vertexcolor
        "UnlitTexturedVCol", // vertexcolor fullbright
        "LitTexturedSoftAlphaVCol", // vertexcolor forced soft alpha
        "UnlitTexturedSoftAlphaVCol" // vertexcolor forced soft alpha fullbright
    };

    std::string AlphaBaseMaterials[] = {
        "LitTexturedSoftAlpha", // soft alpha
        "UnlitTexturedSoftAlpha", // soft alpha fullbright
        "LitTexturedAdd", // additive
        "UnlitTexturedAdd", // additive fullbright
        "LitTexturedSoftAlpha", // forced soft alpha
        "UnlitTexturedSoftAlpha", // forced soft alpha fullbright
        "LitTexturedSoftAlphaVCol", // vertexcolor soft alpha
        "UnlitTexturedSoftAlphaVCol", // vertexcolor soft alpha fullbright
        "LitTexturedSoftAlphaVCol", // vertexcolor forced soft alpha
        "UnlitTexturedSoftAlphaVCol" // vertexcolor forced soft alpha fullbright
    };

    std::string MaterialSuffix[] = {
        "", // normal
        "fb", // normal fullbright
        "add", // additive
        "fbadd", // additive fullbright
        "alpha", // forced alpha
        "fbalpha", // forced alpha fullbright
        "vcol", // vertex color
        "fbvcol", // vertex color fullbright
        "vcolalpha", // vertex color alpha
        "fbvcolalpha" // vertex color alpha fullbright
    };

    bool IsMaterialSuffixValid(const std::string& suffix)
    {
        for(uint i = 0; i < MAX_MATERIAL_VARIATIONS; ++i)
        {
            if (suffix == MaterialSuffix[i])
                return true;
        }

        return false;
    }

    std::string GetMaterialSuffix(uint variation)
    {
        if (variation >= MAX_MATERIAL_VARIATIONS)
        {
            ::LogWarning("Requested suffix for non-existing material variation " + QString::number(variation));
            variation = 0;
        }

        return MaterialSuffix[variation];
    }

    uint GetMaterialVariation(const std::string& suffix)
    {
        for(uint i = 0; i < MAX_MATERIAL_VARIATIONS; ++i)
            if (suffix == MaterialSuffix[i])
                return i;
        return 0;
    }

    Ogre::MaterialPtr CloneMaterial(const std::string& sourceMaterialName, const std::string &newName)
    {
        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mm.getByName(AssetAPI::SanitateAssetRef(sourceMaterialName));

        if (!material.get())
        {
             ::LogWarning("Failed to clone material \"" + sourceMaterialName + "\". It was not found.");
             return Ogre::MaterialPtr();
        }
        material = material->clone(AssetAPI::SanitateAssetRef(newName));
        if (!material.get())
        {
             ::LogWarning("Failed to clone material \"" + sourceMaterialName + "\" to name \"" + AssetAPI::SanitateAssetRef(newName) + "\"");
             return Ogre::MaterialPtr();
        }
        return material;
    }

    Ogre::MaterialPtr GetOrCreateLitTexturedMaterial(const std::string& materialName)
    {
        std::string baseMaterialName = "LitTextured";

        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mm.getByName(AssetAPI::SanitateAssetRef(materialName));

        if (!material.get())
        {
            Ogre::MaterialPtr baseMaterial = mm.getByName(AssetAPI::SanitateAssetRef(baseMaterialName));
            if (baseMaterial.isNull())
                return Ogre::MaterialPtr();

            material = baseMaterial->clone(AssetAPI::SanitateAssetRef(materialName));
        }

        assert(material.get());
        return material;
    }

    Ogre::MaterialPtr GetOrCreateUnlitTexturedMaterial(const std::string& materialName)
    {
        std::string baseMaterialName = "UnlitTextured";

        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mm.getByName(AssetAPI::SanitateAssetRef(materialName));

        if (!material.get())
        {
            Ogre::MaterialPtr baseMaterial = mm.getByName(AssetAPI::SanitateAssetRef(baseMaterialName));
            if (baseMaterial.isNull())
                return Ogre::MaterialPtr();
            material = baseMaterial->clone(AssetAPI::SanitateAssetRef(materialName));
        }

        assert(material.get());
        return material;
    }

    Ogre::MaterialPtr GetOrCreateLegacyMaterial(const std::string& texture_name, const std::string& suffix)
    {
        uint variation = GetMaterialVariation(suffix);
        return GetOrCreateLegacyMaterial(texture_name, variation);
    }

    Ogre::MaterialPtr GetOrCreateLegacyMaterial(const std::string& texture_name, uint variation)
    {
        if (variation >= MAX_MATERIAL_VARIATIONS)
        {
            ::LogWarning("Requested suffix for non-existing material variation " + QString::number(variation));
            variation = 0;
        }
        const std::string& suffix = MaterialSuffix[variation];

        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();

        std::string material_name = sanitatedtexname + suffix;
        Ogre::MaterialPtr material = mm.getByName(material_name);

        if (!material.get())
        {
            material = mm.create(material_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
            assert(material.get());
        }
        else
            return material;

        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);
        bool has_alpha = false;
        if (!tex.isNull())
        {
            // As far as the legacy materials are concerned, DXT1 is not alpha
            if (tex->getFormat() == Ogre::PF_DXT1)
                has_alpha = false;
            else if (Ogre::PixelUtil::hasAlpha(tex->getFormat()))
                has_alpha = true;
        }

        Ogre::MaterialPtr base_material;
        if (!has_alpha)
            base_material = mm.getByName(BaseMaterials[variation]);
        else
            base_material = mm.getByName(AlphaBaseMaterials[variation]);
        if (!base_material.get())
        {
            ::LogError("Could not find " + MaterialSuffix[variation] + " base material for " + texture_name);
            return Ogre::MaterialPtr();
        }

        base_material->copyDetailsTo(material);
        SetTextureUnitOnMaterial(material, texture_name, 0);

        return material;
    }

    void UpdateLegacyMaterials(const std::string& texture_name)
    {
        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::MaterialManager &mm = Ogre::MaterialManager::getSingleton();

        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);
        bool has_alpha = false;
        if (!tex.isNull())
            if (Ogre::PixelUtil::hasAlpha(tex->getFormat()))
                has_alpha = true;

        for(uint i = 0; i < MAX_MATERIAL_VARIATIONS; ++i)
        {
            std::string material_name = sanitatedtexname + MaterialSuffix[i];
            Ogre::MaterialPtr material = mm.getByName(material_name);

            if (!material.get())
                continue;

            Ogre::MaterialPtr base_material;
            if (!has_alpha)
                base_material = mm.getByName(BaseMaterials[i]);
            else
                base_material = mm.getByName(AlphaBaseMaterials[i]);
            if (!base_material.get())
            {
                ::LogError("Could not find " + MaterialSuffix[i] + " base material for " + texture_name);
                continue;
            }

            base_material->copyDetailsTo(material);
            SetTextureUnitOnMaterial(material, texture_name, 0);
        }
    }

    void SetTextureUnitOnMaterial(Ogre::MaterialPtr material, const std::string& texture_name, uint index)
    {
        if (material.isNull())
            return;

        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);

        Ogre::Material::TechniqueIterator iter = material->getTechniqueIterator();
        while(iter.hasMoreElements())
        {
            Ogre::Technique *tech = iter.getNext();
            assert(tech);
            Ogre::Technique::PassIterator passIter = tech->getPassIterator();
            while(passIter.hasMoreElements())
            {
                Ogre::Pass *pass = passIter.getNext();

                Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();
                uint cmp_index = 0;

                while(texIter.hasMoreElements())
                {
                    Ogre::TextureUnitState *texUnit = texIter.getNext();
                    if (index == cmp_index)
                    {
                        if (tex.get())
                            texUnit->setTextureName(sanitatedtexname);
                        else
                            texUnit->setTextureName("TextureMissing.png");

                        return; // We found and replaced the index we wanted to - can early-out return without looping the rest of the indices for nothing.
                    }
                    cmp_index++;
                }
            }
        }
    }

    void ReplaceTextureOnMaterial(Ogre::MaterialPtr material, const std::string& original_name, const std::string& texture_name)
    {
        if (material.isNull())
            return;

        std::string sanitatedorgname = AssetAPI::SanitateAssetRef(original_name);
        std::string sanitatedtexname = AssetAPI::SanitateAssetRef(texture_name);

        Ogre::TextureManager &tm = Ogre::TextureManager::getSingleton();
        Ogre::TexturePtr tex = tm.getByName(sanitatedtexname);

        Ogre::Material::TechniqueIterator iter = material->getTechniqueIterator();
        while(iter.hasMoreElements())
        {
            Ogre::Technique *tech = iter.getNext();
            assert(tech);
            Ogre::Technique::PassIterator passIter = tech->getPassIterator();
            while(passIter.hasMoreElements())
            {
                Ogre::Pass *pass = passIter.getNext();

                Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();

                while(texIter.hasMoreElements())
                {
                    Ogre::TextureUnitState *texUnit = texIter.getNext();
                    if (texUnit->getTextureName() == sanitatedorgname)
                    {
                        if (tex.get())
                            texUnit->setTextureName(sanitatedtexname);
                        else
                            texUnit->setTextureName("TextureMissing.png");
                    }
                }
            }
        }
    }

    void GetTextureNamesFromMaterial(Ogre::MaterialPtr material, StringVector& textures)
    {
        textures.clear();
        if (material.isNull())
            return;

        // Use a set internally to avoid duplicates
        std::set<std::string> textures_set;

        Ogre::Material::TechniqueIterator iter = material->getTechniqueIterator();
        while(iter.hasMoreElements())
        {
            Ogre::Technique *tech = iter.getNext();
            assert(tech);
            Ogre::Technique::PassIterator passIter = tech->getPassIterator();
            while(passIter.hasMoreElements())
            {
                Ogre::Pass *pass = passIter.getNext();

                Ogre::Pass::TextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();

                while(texIter.hasMoreElements())
                {
                    Ogre::TextureUnitState *texUnit = texIter.getNext();
                    const std::string& texname = texUnit->getTextureName();

                    if (!texname.empty())
                        textures_set.insert(texname);
                }
            }
        }

        std::set<std::string>::iterator i = textures_set.begin();

        while(i != textures_set.end())
        {
            textures.push_back(*i);
            ++i;
        }
    }

    void RemoveMaterial(Ogre::MaterialPtr& material)
    {
        if (!material.isNull())
        {
            std::string material_name = material->getName();
            material.setNull();

            try
            {
                Ogre::MaterialManager::getSingleton().remove(material_name);
            }
            catch(Ogre::Exception& e)
            {
                ::LogDebug("Failed to remove Ogre material:" + std::string(e.what()));
            }
        }
    }

    bool ProcessBraces(const std::string& line, int& braceLevel)
    {
        if (line == "{")
        {
            ++braceLevel;
            return true;
        }
        else if (line == "}")
        {
            --braceLevel;
            return true;
        }
        else return false;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013, "Kira"
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "precompiled_headers.hpp"

#include "connection.hpp"
#include "logging.hpp"
#include "ferror.hpp"
#include "fjson.hpp"
#include "flua.hpp"
#include "server.hpp"
#include "lua_constants.hpp"
#include "channel.hpp"

#define MAX_SEND_QUEUE_ITEMS 150
// This sets the size at which long messages are split into multiple pieces.
// No more than this amount will ever be sent to a single send() call at once.
#define MAX_SEND_QUEUE_ITEM_SIZE 8192

ConnectionInstance::ConnectionInstance()
:
LBase(),
accountID(0),
identified(false),
admin(false),
globalModerator(false),
protocol(PROTOCOL_UNKNOWN),
closed(false),
delayClose(false),
status("online"),
gender("None"),
writePosition(0),
loop(0),
pingEvent(0),
timerEvent(0),
readEvent(0),
writeEvent(0),
refCount(0),
debugL(0) {
}

ConnectionInstance::~ConnectionInstance() {
    if (debugL) {
        lua_close(debugL);
    }
}

void intrusive_ptr_release(ConnectionInstance* p) {
    if ((--p->refCount) <= 0) {
        delete p;
    }
}

void intrusive_ptr_add_ref(ConnectionInstance* p) {
    ++p->refCount;
}

bool ConnectionInstance::send(MessagePtr message) {
    // This will disconnect the client as a side effect.
    if (closed || writeQueue.size() > MAX_SEND_QUEUE_ITEMS)
        return false;

    writeQueue.push_back(message);
    ev_io_start(loop, writeEvent);
    return true;
}

bool ConnectionInstance::sendRaw(string& message) {
    if (closed)
        return false;

    MessageBuffer* buffer = new MessageBuffer();
    MessagePtr outMessage(buffer);
    buffer->Set(message.data(), message.length());

    writeQueue.push_back(outMessage);
    ev_io_start(loop, writeEvent);
    return true;
}

void ConnectionInstance::sendError(int error) {
    string outstr("ERR ");
    json_t* topnode = json_object();
    json_object_set_new_nocheck(topnode, "number",
            json_integer(error)
            );
    json_object_set_new_nocheck(topnode, "message",
            json_string_nocheck(LuaConstants::getErrorMessage(error).c_str())
            );
    const char* errstr = json_dumps(topnode, JSON_COMPACT);
    outstr += errstr;
    MessagePtr message(MessageBuffer::FromString(outstr));
    send(message);
    free((void*) errstr);
    json_decref(topnode);
    DLOG(INFO) << "Sending error to connection: " << outstr;
}

void ConnectionInstance::sendError(int error, string message) {
    string outstr("ERR ");
    json_t* topnode = json_object();
    json_object_set_new_nocheck(topnode, "number",
            json_integer(error)
            );
    json_t* messagenode = json_string(message.c_str());
    if (!messagenode)
        messagenode = json_string_nocheck("There was an error encoding this error message. Please report this to Kira.");
    json_object_set_new_nocheck(topnode, "message", messagenode);
    const char* errstr = json_dumps(topnode, JSON_COMPACT);
    outstr += errstr;
    MessagePtr outMessage(MessageBuffer::FromString(outstr));
    send(outMessage);
    free((void*) errstr);
    json_decref(topnode);
    DLOG(INFO) << "Sending custom error to connection: " << outstr;
}

void ConnectionInstance::sendDebugReply(string message) {
    string outstr("ZZZ ");
    json_t* topnode = json_object();
    json_t* messagenode = json_string(message.c_str());
    if (!messagenode)
        messagenode = json_string_nocheck("Failed to parse the debug reply as a valid UTF-8 string.");
    json_object_set_new_nocheck(topnode, "message", messagenode);
    const char* replystr = json_dumps(topnode, JSON_COMPACT);
    outstr += replystr;
    free((void*) replystr);
    json_decref(topnode);
    MessagePtr outMessage(MessageBuffer::FromString(outstr));
    send(outMessage);
}

void ConnectionInstance::setDelayClose() {
    delayClose = true;
    ev_io_stop(loop, readEvent);
    ev_timer_stop(loop, timerEvent);
    ev_timer_set(timerEvent, 1., 1.);
    ev_timer_start(loop, timerEvent);
}

void ConnectionInstance::joinChannel(Channel* channel) {
    ChannelPtr chan(channel);
    channelList.push_back(chan);
}

void ConnectionInstance::leaveChannel(Channel* channel) {
    ChannelPtr chan(channel);
    channelList.remove(chan);
}

FReturnCode ConnectionInstance::reloadIsolation(string& output) {
    lua_State* newstate = luaL_newstate();
    FReturnCode ret = Server::loadLuaIntoState(newstate, output, true);
    if (ret == FERR_OK) {
        lua_close(debugL);
        debugL = newstate;
    } else {
        lua_close(newstate);
    }

    return ret;
}

FReturnCode ConnectionInstance::isolateLua(string& output) {
    lua_State* newstate = luaL_newstate();
    FReturnCode ret = Server::loadLuaIntoState(newstate, output, true);
    if (ret == FERR_OK)
        debugL = newstate;
    else
        lua_close(newstate);

    return ret;
}

void ConnectionInstance::deisolateLua() {
    lua_close(debugL);
    debugL = 0;
}
<commit_msg>[BUG #29] Debug code to assist in finding the cause of premature connection deletion.<commit_after>/*
 * Copyright (c) 2011-2013, "Kira"
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "precompiled_headers.hpp"

#include "connection.hpp"
#include "logging.hpp"
#include "ferror.hpp"
#include "fjson.hpp"
#include "flua.hpp"
#include "server.hpp"
#include "lua_constants.hpp"
#include "channel.hpp"

#define MAX_SEND_QUEUE_ITEMS 150
// This sets the size at which long messages are split into multiple pieces.
// No more than this amount will ever be sent to a single send() call at once.
#define MAX_SEND_QUEUE_ITEM_SIZE 8192

ConnectionInstance::ConnectionInstance()
:
LBase(),
accountID(0),
identified(false),
admin(false),
globalModerator(false),
protocol(PROTOCOL_UNKNOWN),
closed(false),
delayClose(false),
status("online"),
gender("None"),
writePosition(0),
loop(0),
pingEvent(0),
timerEvent(0),
readEvent(0),
writeEvent(0),
refCount(0),
debugL(0) {
}

ConnectionInstance::~ConnectionInstance() {
    if (closed != true) {
        LOG(FATAL) << "[BUG] Deleting a connection not marked as closed.";
    }
    if (debugL) {
        lua_close(debugL);
    }
}

void intrusive_ptr_release(ConnectionInstance* p) {
    if ((--p->refCount) <= 0) {
        if (p->closed != true) {
            LOG(FATAL) << "[BUG] Deleting a connection not marked as closed.";
        }
        delete p;
    }
}

void intrusive_ptr_add_ref(ConnectionInstance* p) {
    ++p->refCount;
}

bool ConnectionInstance::send(MessagePtr message) {
    // This will disconnect the client as a side effect.
    if (closed || writeQueue.size() > MAX_SEND_QUEUE_ITEMS)
        return false;

    writeQueue.push_back(message);
    ev_io_start(loop, writeEvent);
    return true;
}

bool ConnectionInstance::sendRaw(string& message) {
    if (closed)
        return false;

    MessageBuffer* buffer = new MessageBuffer();
    MessagePtr outMessage(buffer);
    buffer->Set(message.data(), message.length());

    writeQueue.push_back(outMessage);
    ev_io_start(loop, writeEvent);
    return true;
}

void ConnectionInstance::sendError(int error) {
    string outstr("ERR ");
    json_t* topnode = json_object();
    json_object_set_new_nocheck(topnode, "number",
            json_integer(error)
            );
    json_object_set_new_nocheck(topnode, "message",
            json_string_nocheck(LuaConstants::getErrorMessage(error).c_str())
            );
    const char* errstr = json_dumps(topnode, JSON_COMPACT);
    outstr += errstr;
    MessagePtr message(MessageBuffer::FromString(outstr));
    send(message);
    free((void*) errstr);
    json_decref(topnode);
    DLOG(INFO) << "Sending error to connection: " << outstr;
}

void ConnectionInstance::sendError(int error, string message) {
    string outstr("ERR ");
    json_t* topnode = json_object();
    json_object_set_new_nocheck(topnode, "number",
            json_integer(error)
            );
    json_t* messagenode = json_string(message.c_str());
    if (!messagenode)
        messagenode = json_string_nocheck("There was an error encoding this error message. Please report this to Kira.");
    json_object_set_new_nocheck(topnode, "message", messagenode);
    const char* errstr = json_dumps(topnode, JSON_COMPACT);
    outstr += errstr;
    MessagePtr outMessage(MessageBuffer::FromString(outstr));
    send(outMessage);
    free((void*) errstr);
    json_decref(topnode);
    DLOG(INFO) << "Sending custom error to connection: " << outstr;
}

void ConnectionInstance::sendDebugReply(string message) {
    string outstr("ZZZ ");
    json_t* topnode = json_object();
    json_t* messagenode = json_string(message.c_str());
    if (!messagenode)
        messagenode = json_string_nocheck("Failed to parse the debug reply as a valid UTF-8 string.");
    json_object_set_new_nocheck(topnode, "message", messagenode);
    const char* replystr = json_dumps(topnode, JSON_COMPACT);
    outstr += replystr;
    free((void*) replystr);
    json_decref(topnode);
    MessagePtr outMessage(MessageBuffer::FromString(outstr));
    send(outMessage);
}

void ConnectionInstance::setDelayClose() {
    delayClose = true;
    ev_io_stop(loop, readEvent);
    ev_timer_stop(loop, timerEvent);
    ev_timer_set(timerEvent, 1., 1.);
    ev_timer_start(loop, timerEvent);
}

void ConnectionInstance::joinChannel(Channel* channel) {
    ChannelPtr chan(channel);
    channelList.push_back(chan);
}

void ConnectionInstance::leaveChannel(Channel* channel) {
    ChannelPtr chan(channel);
    channelList.remove(chan);
}

FReturnCode ConnectionInstance::reloadIsolation(string& output) {
    lua_State* newstate = luaL_newstate();
    FReturnCode ret = Server::loadLuaIntoState(newstate, output, true);
    if (ret == FERR_OK) {
        lua_close(debugL);
        debugL = newstate;
    } else {
        lua_close(newstate);
    }

    return ret;
}

FReturnCode ConnectionInstance::isolateLua(string& output) {
    lua_State* newstate = luaL_newstate();
    FReturnCode ret = Server::loadLuaIntoState(newstate, output, true);
    if (ret == FERR_OK)
        debugL = newstate;
    else
        lua_close(newstate);

    return ret;
}

void ConnectionInstance::deisolateLua() {
    lua_close(debugL);
    debugL = 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

const float pi = M_PI;

// chain of oscillators
class osc {
private:
	int n;
	float dt, dx;
	float* xi;
	float* v;
public:
	osc(float Dt, float L, int mode, float Dx = 0) {
		dt = Dt;
		if (Dx == 0)
			dx = Dt;
		else
			dx = Dx;
		n = int(L / dx) + 1;
		xi = new float[n];
		v = new float[n];
		// set xi and v at the same time instance
		if (mode == 0) {
			// peak-like xi(x)
			for (int i = 0; i < n; ++i) {
				float k = pi / ((n - 1) * dx);
				xi[i] = 6.0 / (20 * k) * pow(sin(k * i * dx), 20);
				v[i] = -6 * pow(sin(k * i * dx), 19) * cos(k * i * dx);
			}
		} else {
			// n-th mode
			for (int i = 0; i < n; ++i) {
				v[i] = sin(pi * mode * i / (n - 1));
				xi[i] = 0;
			}
		}
		// halfstep back for xi
		for (int i = 1; i < n - 1; ++i)
			xi[i] -= v[i] * 0.5 * dt;
	}
	~osc() {
		delete xi;
		delete v;
	}
	void advance() {
		// main loop
		for (int i = 1; i < n - 1; ++i)
			xi[i] += v[i] * dt;
		for (int i = 1; i < n - 1; ++i)
			v[i] += dt / (dx * dx) * (xi[i + 1] - 2 * xi[i] + xi[i - 1]);
	}
	// displays v by pseudographics
	void show() {
		const char c[] = { '.', ':', '=', '?', '%', '$', '@', '#' };
		const char s[] = { ' ', '-' };
		for (int i = 0; i < n; ++i) {
			int j = (int) (8 * fabs(v[i]));
			if (j < 8)
				cout << setw(1) << s[v[i] < 0] << setw(1) << c[j];
			else
				cout << setw(1) << s[v[i] < 0] << setw(1) << c[7];
		}
		cout << '\n';
	}
};

int main() {
	// 1-st mode
	osc u(0.1, 2, 1);
	// 2-nd mode
	osc v(0.1, 2, 2);
	// (n-1)/2 mode
	osc y(0.1, 2.1, 10);
	// wave travelling from left to right
	osc w(0.1, 2, 0);
	// computes and plots the evolution
	for (int i = 0; i < 40; ++i) {
		u.advance();
		u.show();
	}
	/*
	 // 1-st mode, dt>dx
	 osc us(0.107, 2, 1, 0.1);
	 // computes and plots the evolution
	 for (int i = 0; i < 40; ++i) {
	 us.advance();
	 us.show();
	 }
	 */
	/*
	 // wave travelling from left to right, dt<dx
	 osc ws(0.05, 2, 0, 0.1);
	 // computes and plots the evolution
	 for (int i = 0; i < 80; ++i) {
	 ws.advance();
	 ws.show();
	 }
	 */
	return 0;
}
<commit_msg>add [] to delete in destructor<commit_after>#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

const float pi = M_PI;

// chain of oscillators
class osc {
private:
	int n;
	float dt, dx;
	float* xi;
	float* v;
public:
	osc(float Dt, float L, int mode, float Dx = 0) {
		dt = Dt;
		if (Dx == 0)
			dx = Dt;
		else
			dx = Dx;
		n = int(L / dx) + 1;
		xi = new float[n];
		v = new float[n];
		// set xi and v at the same time instance
		if (mode == 0) {
			// peak-like xi(x)
			for (int i = 0; i < n; ++i) {
				float k = pi / ((n - 1) * dx);
				xi[i] = 6.0 / (20 * k) * pow(sin(k * i * dx), 20);
				v[i] = -6 * pow(sin(k * i * dx), 19) * cos(k * i * dx);
			}
		} else {
			// n-th mode
			for (int i = 0; i < n; ++i) {
				v[i] = sin(pi * mode * i / (n - 1));
				xi[i] = 0;
			}
		}
		// halfstep back for xi
		for (int i = 1; i < n - 1; ++i)
			xi[i] -= v[i] * 0.5 * dt;
	}
	~osc() {
		delete[] xi;
		delete[] v;
	}
	void advance() {
		// main loop
		for (int i = 1; i < n - 1; ++i)
			xi[i] += v[i] * dt;
		for (int i = 1; i < n - 1; ++i)
			v[i] += dt / (dx * dx) * (xi[i + 1] - 2 * xi[i] + xi[i - 1]);
	}
	// displays v by pseudographics
	void show() {
		const char c[] = { '.', ':', '=', '?', '%', '$', '@', '#' };
		const char s[] = { ' ', '-' };
		for (int i = 0; i < n; ++i) {
			int j = (int) (8 * fabs(v[i]));
			if (j < 8)
				cout << setw(1) << s[v[i] < 0] << setw(1) << c[j];
			else
				cout << setw(1) << s[v[i] < 0] << setw(1) << c[7];
		}
		cout << '\n';
	}
};

int main() {
	// 1-st mode
	osc u(0.1, 2, 1);
	// 2-nd mode
	osc v(0.1, 2, 2);
	// (n-1)/2 mode
	osc y(0.1, 2.1, 10);
	// wave travelling from left to right
	osc w(0.1, 2, 0);
	// computes and plots the evolution
	for (int i = 0; i < 40; ++i) {
		u.advance();
		u.show();
	}
	/*
	 // 1-st mode, dt>dx
	 osc us(0.107, 2, 1, 0.1);
	 // computes and plots the evolution
	 for (int i = 0; i < 40; ++i) {
	 us.advance();
	 us.show();
	 }
	 */
	/*
	 // wave travelling from left to right, dt<dx
	 osc ws(0.05, 2, 0, 0.1);
	 // computes and plots the evolution
	 for (int i = 0; i < 80; ++i) {
	 ws.advance();
	 ws.show();
	 }
	 */
	return 0;
}
<|endoftext|>


<commit_before>#include "downloader.h"

#include <QDebug>
#include <QtNetwork>
#include <QDir>
#include <QFile>

#include "uivalues.h"

#define COOKIE_CREATOR_URL "http://www.goear.com/listen/"
#define TARGET_URL "http://www.goear.com/"
#define SEARCH_URL "http://www.goear.com/search/"

QString Downloader::DownloadUrl("http://www.goear.com/action/sound/get/");

Downloader::Downloader(QObject *parent) :
    QObject(parent),
    m_downloading(false)
{
    m_netAccess = new QNetworkAccessManager(this);
    connect(m_netAccess, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
}

Downloader::~Downloader()
{
    delete m_netAccess;
}

void Downloader::downloadSong(const QString &name, const QString &url)
{
#ifdef Q_OS_ANDROID
    mAdm.downloadFile(url, name.simplified());
#else
    m_songsToDownload.insert(url, name);
    download(url);
    setDownloading(true);
#endif
}

void Downloader::getDownloadLink(const QString &code)
{
    //    qDebug() << Q_FUNC_INFO << " - " << code;
    //    QString newUrl = url;
    //    newUrl.replace(DownloadUrl, COOKIE_CREATOR_URL);

    download(COOKIE_CREATOR_URL + code);
    //    setDownloading(true);
}

void Downloader::download(const QString &urlString)
{
    QUrl url(urlString);
    QNetworkRequest request(url);

    if (!mCookies.isEmpty()) {
        QVariant var;
        var.setValue(mCookies);
        request.setHeader(QNetworkRequest::CookieHeader, var);
    }

    request.setRawHeader("User-Agent", " Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0");
    m_nreply = m_netAccess->get(request);
    connect(m_nreply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgressChanged(qint64, qint64)));
}

void Downloader::search(const QString &term)
{
    // qDebug() << Q_FUNC_INFO << " " + term;
    download(SEARCH_URL + term);
}

void Downloader::downloadFinished(QNetworkReply *reply)
{
    if (reply->url().toString().startsWith(COOKIE_CREATOR_URL)) {
        mCookies = m_netAccess->cookieJar()->cookiesForUrl(reply->url());

        download(reply->url().toString().replace(COOKIE_CREATOR_URL, DownloadUrl));
        reply->deleteLater();
        return;
    }

    if (reply->error() != QNetworkReply::NoError) {
        setDownloading(false);

        qDebug() << Q_FUNC_INFO << " error downloading "
                 << reply->url().toString() << ":" << reply->errorString();

        emit serverError();

        reply->deleteLater();
        return;
    }

    // if (!reply->url().toString().startsWith("http://www.goear.com/action/sound/get/"))
       // qDebug() << reply->url().toString() << "Downloaded";

    QVariant redir = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

    if (redir.isValid()) {
        QUrl url = redir.toUrl();
        QString name = m_songsToDownload.value(reply->url().toString()).toString();
        m_songsToDownload.remove(reply->url().toString());
        m_songsToDownload.insert(url.toString(), name);

        if (url.toString().endsWith(".mp3")) {
            emit decodedUrl(reply->url().toString().remove(DownloadUrl), url.toString());
            reply->deleteLater();
            return;
        }

        qDebug() << reply->url().toString() << " was redirected to:" << url.toString();

        if (url.isRelative())
            url.setScheme(reply->url().scheme());

        download(url.toString());
        reply->deleteLater();
        return;
    }

    QString mimeType(reply->header(QNetworkRequest::ContentTypeHeader).toString());

    if (mimeType.contains("text/html")) {
        QString songs(reply->readAll());

        int count = qMin(songs.count("listen/") / 2, 10);

        QString hasMore = "";
        QString searchTerm = "
";
        QString closingTerm = "
";

        int termBegins = songs.indexOf(searchTerm);
        int termEnds = songs.indexOf(closingTerm, termBegins);

        if (termBegins != -1) {
            hasMore = songs.mid(termBegins + searchTerm.length(), termEnds - termBegins
                                - searchTerm.length());
        }

        QStringList list = hasMore.simplified().split("<li", QString::SkipEmptyParts);

        bool foundMore = false;
        for (int i = 0; i < list.length() - 1; ++i) {
            if (list.at(i).simplified().startsWith("class=\"active\">")) {
                QString number = reply->url().toString().mid(reply->url().toString().lastIndexOf("/") + 1);
                bool isNumber = false;
                int index = number.toInt(&isNumber);
                //                reply->url().toString().mid(reply->url().toString().length() - 1).toInt(isANumber);
                if (isNumber)
                    emit searchHasMoreResults(reply->url().toString().mid(0, reply->url().toString().lastIndexOf("/")) + "/" + QString::number(index + 1));
                else
                    emit searchHasMoreResults(reply->url().toString() + "/" + QString::number(++i));

                foundMore = true;
                break;
            }
        }

        if (!foundMore)
            emit searchHasNoMoreResults();

        searchTerm = "
";
        closingTerm = "
";

        termBegins = songs.indexOf(searchTerm);
        termEnds = songs.indexOf(closingTerm, termBegins);

        songs = songs.mid(termBegins + searchTerm.length(),
                          termEnds - termBegins);

        songs = decodeHtml(songs);

        for (int i = 0; i < count; ++i) {
            searchTerm = "listen/";
            closingTerm = "/";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString code = songs.mid(termBegins, termEnds - termBegins);

            searchTerm = "src=\"http://www.goear.com/band/picture/";
            closingTerm = "\"";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString picture = songs.mid(termBegins, termEnds - termBegins);

            songs = songs.mid(termEnds);

            searchTerm = "\">";
            closingTerm = "
";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString tmp = songs.mid(termBegins, termEnds - termBegins);
            QString group = tmp.mid(0, tmp.indexOf(" -"));
            QString title = tmp.mid(tmp.indexOf("- ") + 2);

            if (group == "")
                group = tmp;

            if (title == "")
                title = tmp;

            searchTerm = "") + 1);

            searchTerm = "title=\"Kbps\">";
            closingTerm = "";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString kbps = songs.mid(termBegins, termEnds - termBegins).remove("").remove("kbps");

            searchTerm = "title=\"Plays\">";
            closingTerm = "
";

            if (songs.indexOf(searchTerm) == -1)
                searchTerm = "class=\"total_hits\" >";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString hits = songs.mid(termBegins, termEnds - termBegins);

            searchTerm = "
";
            closingTerm = "
";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString comment = songs.mid(termBegins, termEnds - termBegins);

            // qDebug() << "ADDDING SONG:";
            // qDebug() << "TITLE:" << title << "GROUP:" << group << "LENGTH:" << length
            //          << "COMMENT:" << comment << "KBPS:" << kbps << "CODE:" << code
            //          << "PICTURE:" << picture;

            songs = songs.mid(songs.indexOf("
"));

            emit songFound(title, group, length, comment, kbps.toInt(), code, picture, hits.replace(",", "").toLong());
            getDownloadLink(code);
        }
    }  else if (mimeType == "audio/mpeg") {
        qDebug() << "Writing file";
        QString name(m_songsToDownload.value(reply->url().toString()).toString());
        m_songsToDownload.remove(reply->url().toString());

        name.replace("/", "-");

#ifdef Q_OS_BLACKBERRY
        name = "shared/music/" + name;
#endif

#ifdef Q_OS_ANDROID
        QDir musicDir("/sdcard/Music");
        if (!musicDir.exists())
            musicDir.mkdir("/sdcard/Music");

        name = "/sdcard/Music/" + name;
#endif

        bool permission;
        QFile file(name + reply->url().toString().mid(reply->url().toString().lastIndexOf(".")));
        permission = file.open(QIODevice::WriteOnly);

        if (!permission) {
            UIValues uiValues;
            uiValues.showMessage("Unable to create file, no permission");
        }

        file.write(reply->readAll());
        file.close();
    } else {
        qDebug() << reply->url().toString() << " type is:" << mimeType;
    }

    if (reply->url().toString().endsWith(".mp3"))
        setDownloading(false);

    if (reply->url().toString().startsWith(SEARCH_URL))
        emit searchEnded();

    reply->deleteLater();
}

QString Downloader::decodeHtml(const QString &html)
{
    QString decodedHtml(html);

    decodedHtml.replace("&", "&");

    decodedHtml.replace("á", "á");
    decodedHtml.replace("é", "é");
    decodedHtml.replace("í", "í");
    decodedHtml.replace("ó", "ó");
    decodedHtml.replace("ú", "ú");

    decodedHtml.replace("Á", "Á");
    decodedHtml.replace("É", "É");
    decodedHtml.replace("Í", "Í");
    decodedHtml.replace("Ó", "Ó");
    decodedHtml.replace("Ú", "Ú");

    decodedHtml.replace("Ñ", "Ñ");
    decodedHtml.replace("ñ", "ñ");

    decodedHtml.replace("Ë", "Ë");
    decodedHtml.replace("ë", "ë");
    decodedHtml.replace("Ü", "Ü");
    decodedHtml.replace("ü", "ü");

    decodedHtml.replace("Ç", "Ç");
    decodedHtml.replace("ç", "ç");

    return decodedHtml;
}

void Downloader::downloadProgressChanged(qint64 bytesReceived, qint64 bytesTotal)
{
    if (bytesTotal == 0 || bytesTotal == -1)
        return;

    float i = bytesReceived / (double)bytesTotal;

    QNetworkReply *net = (QNetworkReply *)sender();
    // qDebug() << "Progress for: "<< net->url().toString() << " " <url().toString()).toString());
}

bool Downloader::isDownloading() const
{
    return m_downloading;
}

void Downloader::setDownloading(bool downloading)
{
    if (m_downloading == downloading)
        return;

    m_downloading = downloading;
    emit downloadingChanged();
}
<commit_msg>Emit searchEnded if theres an error<commit_after>#include "downloader.h"

#include <QDebug>
#include <QtNetwork>
#include <QDir>
#include <QFile>

#include "uivalues.h"

#define COOKIE_CREATOR_URL "http://www.goear.com/listen/"
#define TARGET_URL "http://www.goear.com/"
#define SEARCH_URL "http://www.goear.com/search/"

QString Downloader::DownloadUrl("http://www.goear.com/action/sound/get/");

Downloader::Downloader(QObject *parent) :
    QObject(parent),
    m_downloading(false)
{
    m_netAccess = new QNetworkAccessManager(this);
    connect(m_netAccess, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
}

Downloader::~Downloader()
{
    delete m_netAccess;
}

void Downloader::downloadSong(const QString &name, const QString &url)
{
#ifdef Q_OS_ANDROID
    mAdm.downloadFile(url, name.simplified());
#else
    m_songsToDownload.insert(url, name);
    download(url);
    setDownloading(true);
#endif
}

void Downloader::getDownloadLink(const QString &code)
{
    //    qDebug() << Q_FUNC_INFO << " - " << code;
    //    QString newUrl = url;
    //    newUrl.replace(DownloadUrl, COOKIE_CREATOR_URL);

    download(COOKIE_CREATOR_URL + code);
    //    setDownloading(true);
}

void Downloader::download(const QString &urlString)
{
    QUrl url(urlString);
    QNetworkRequest request(url);

    if (!mCookies.isEmpty()) {
        QVariant var;
        var.setValue(mCookies);
        request.setHeader(QNetworkRequest::CookieHeader, var);
    }

    request.setRawHeader("User-Agent", " Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0");
    m_nreply = m_netAccess->get(request);
    connect(m_nreply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgressChanged(qint64, qint64)));
}

void Downloader::search(const QString &term)
{
    // qDebug() << Q_FUNC_INFO << " " + term;
    download(SEARCH_URL + term);
}

void Downloader::downloadFinished(QNetworkReply *reply)
{
    if (reply->url().toString().startsWith(COOKIE_CREATOR_URL)) {
        mCookies = m_netAccess->cookieJar()->cookiesForUrl(reply->url());

        download(reply->url().toString().replace(COOKIE_CREATOR_URL, DownloadUrl));
        reply->deleteLater();
        return;
    }

    if (reply->error() != QNetworkReply::NoError) {
        setDownloading(false);
        emit searchEnded();

        qDebug() << Q_FUNC_INFO << " error downloading "
                 << reply->url().toString() << ":" << reply->errorString();

        emit serverError();

        reply->deleteLater();
        return;
    }

    // if (!reply->url().toString().startsWith("http://www.goear.com/action/sound/get/"))
       // qDebug() << reply->url().toString() << "Downloaded";

    QVariant redir = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

    if (redir.isValid()) {
        QUrl url = redir.toUrl();
        QString name = m_songsToDownload.value(reply->url().toString()).toString();
        m_songsToDownload.remove(reply->url().toString());
        m_songsToDownload.insert(url.toString(), name);

        if (url.toString().endsWith(".mp3")) {
            emit decodedUrl(reply->url().toString().remove(DownloadUrl), url.toString());
            reply->deleteLater();
            return;
        }

        qDebug() << reply->url().toString() << " was redirected to:" << url.toString();

        if (url.isRelative())
            url.setScheme(reply->url().scheme());

        download(url.toString());
        reply->deleteLater();
        return;
    }

    QString mimeType(reply->header(QNetworkRequest::ContentTypeHeader).toString());

    if (mimeType.contains("text/html")) {
        QString songs(reply->readAll());

        int count = qMin(songs.count("listen/") / 2, 10);

        QString hasMore = "";
        QString searchTerm = "
";
        QString closingTerm = "
";

        int termBegins = songs.indexOf(searchTerm);
        int termEnds = songs.indexOf(closingTerm, termBegins);

        if (termBegins != -1) {
            hasMore = songs.mid(termBegins + searchTerm.length(), termEnds - termBegins
                                - searchTerm.length());
        }

        QStringList list = hasMore.simplified().split("<li", QString::SkipEmptyParts);

        bool foundMore = false;
        for (int i = 0; i < list.length() - 1; ++i) {
            if (list.at(i).simplified().startsWith("class=\"active\">")) {
                QString number = reply->url().toString().mid(reply->url().toString().lastIndexOf("/") + 1);
                bool isNumber = false;
                int index = number.toInt(&isNumber);
                //                reply->url().toString().mid(reply->url().toString().length() - 1).toInt(isANumber);
                if (isNumber)
                    emit searchHasMoreResults(reply->url().toString().mid(0, reply->url().toString().lastIndexOf("/")) + "/" + QString::number(index + 1));
                else
                    emit searchHasMoreResults(reply->url().toString() + "/" + QString::number(++i));

                foundMore = true;
                break;
            }
        }

        if (!foundMore)
            emit searchHasNoMoreResults();

        searchTerm = "
";
        closingTerm = "
";

        termBegins = songs.indexOf(searchTerm);
        termEnds = songs.indexOf(closingTerm, termBegins);

        songs = songs.mid(termBegins + searchTerm.length(),
                          termEnds - termBegins);

        songs = decodeHtml(songs);

        for (int i = 0; i < count; ++i) {
            searchTerm = "listen/";
            closingTerm = "/";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString code = songs.mid(termBegins, termEnds - termBegins);

            searchTerm = "src=\"http://www.goear.com/band/picture/";
            closingTerm = "\"";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString picture = songs.mid(termBegins, termEnds - termBegins);

            songs = songs.mid(termEnds);

            searchTerm = "\">";
            closingTerm = "
";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString tmp = songs.mid(termBegins, termEnds - termBegins);
            QString group = tmp.mid(0, tmp.indexOf(" -"));
            QString title = tmp.mid(tmp.indexOf("- ") + 2);

            if (group == "")
                group = tmp;

            if (title == "")
                title = tmp;

            searchTerm = "") + 1);

            searchTerm = "title=\"Kbps\">";
            closingTerm = "";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString kbps = songs.mid(termBegins, termEnds - termBegins).remove("").remove("kbps");

            searchTerm = "title=\"Plays\">";
            closingTerm = "
";

            if (songs.indexOf(searchTerm) == -1)
                searchTerm = "class=\"total_hits\" >";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString hits = songs.mid(termBegins, termEnds - termBegins);

            searchTerm = "
";
            closingTerm = "
";

            termBegins = songs.indexOf(searchTerm) + searchTerm.length();
            termEnds = songs.indexOf(closingTerm, termBegins);

            QString comment = songs.mid(termBegins, termEnds - termBegins);

            // qDebug() << "ADDDING SONG:";
            // qDebug() << "TITLE:" << title << "GROUP:" << group << "LENGTH:" << length
            //          << "COMMENT:" << comment << "KBPS:" << kbps << "CODE:" << code
            //          << "PICTURE:" << picture;

            songs = songs.mid(songs.indexOf("
"));

            emit songFound(title, group, length, comment, kbps.toInt(), code, picture, hits.replace(",", "").toLong());
            getDownloadLink(code);
        }
    }  else if (mimeType == "audio/mpeg") {
        qDebug() << "Writing file";
        QString name(m_songsToDownload.value(reply->url().toString()).toString());
        m_songsToDownload.remove(reply->url().toString());

        name.replace("/", "-");

#ifdef Q_OS_BLACKBERRY
        name = "shared/music/" + name;
#endif

#ifdef Q_OS_ANDROID
        QDir musicDir("/sdcard/Music");
        if (!musicDir.exists())
            musicDir.mkdir("/sdcard/Music");

        name = "/sdcard/Music/" + name;
#endif

        bool permission;
        QFile file(name + reply->url().toString().mid(reply->url().toString().lastIndexOf(".")));
        permission = file.open(QIODevice::WriteOnly);

        if (!permission) {
            UIValues uiValues;
            uiValues.showMessage("Unable to create file, no permission");
        }

        file.write(reply->readAll());
        file.close();
    } else {
        qDebug() << reply->url().toString() << " type is:" << mimeType;
    }

    if (reply->url().toString().endsWith(".mp3"))
        setDownloading(false);

    if (reply->url().toString().startsWith(SEARCH_URL))
        emit searchEnded();

    reply->deleteLater();
}

QString Downloader::decodeHtml(const QString &html)
{
    QString decodedHtml(html);

    decodedHtml.replace("&", "&");

    decodedHtml.replace("á", "á");
    decodedHtml.replace("é", "é");
    decodedHtml.replace("í", "í");
    decodedHtml.replace("ó", "ó");
    decodedHtml.replace("ú", "ú");

    decodedHtml.replace("Á", "Á");
    decodedHtml.replace("É", "É");
    decodedHtml.replace("Í", "Í");
    decodedHtml.replace("Ó", "Ó");
    decodedHtml.replace("Ú", "Ú");

    decodedHtml.replace("Ñ", "Ñ");
    decodedHtml.replace("ñ", "ñ");

    decodedHtml.replace("Ë", "Ë");
    decodedHtml.replace("ë", "ë");
    decodedHtml.replace("Ü", "Ü");
    decodedHtml.replace("ü", "ü");

    decodedHtml.replace("Ç", "Ç");
    decodedHtml.replace("ç", "ç");

    return decodedHtml;
}

void Downloader::downloadProgressChanged(qint64 bytesReceived, qint64 bytesTotal)
{
    if (bytesTotal == 0 || bytesTotal == -1)
        return;

    float i = bytesReceived / (double)bytesTotal;

    QNetworkReply *net = (QNetworkReply *)sender();
    // qDebug() << "Progress for: "<< net->url().toString() << " " <url().toString()).toString());
}

bool Downloader::isDownloading() const
{
    return m_downloading;
}

void Downloader::setDownloading(bool downloading)
{
    if (m_downloading == downloading)
        return;

    m_downloading = downloading;
    emit downloadingChanged();
}
<|endoftext|>