Esempio n. 1
0
    bool inflate_gzip(char const* in, int size, std::vector<char>& buffer, int maximum_size, std::string& error)
    {
        LIBED2K_ASSERT(maximum_size > 0);

        int header_len = gzip_header(in, size);
        if (header_len < 0)
        {
            error = "invalid gzip header";
            return true;
        }

        // start off with one kilobyte and grow
        // if needed
        buffer.resize(maximum_size);

        boost::uint32_t destlen = buffer.size();
        boost::uint32_t srclen = size - header_len;
        in += header_len;
        int ret = puff((unsigned char*)&buffer[0], &destlen, (unsigned char*)in, &srclen);

        if (ret == -1)
        {
            error = "inflated data too big";
            return true;
        }

        buffer.resize(destlen);

        if (ret != 0)
        {
            error = "error while inflating data";
            return true;
        }
        return false;
    }
Esempio n. 2
0
	TORRENT_EXTRA_EXPORT void inflate_gzip(
		char const* in
		, int size
		, std::vector<char>& buffer
		, int maximum_size
		, error_code& ec)
	{
		ec.clear();
		TORRENT_ASSERT(maximum_size > 0);

		int header_len = gzip_header(in, size);
		if (header_len < 0)
		{
			ec = gzip_errors::invalid_gzip_header;
			return;
		}

		// start off with 4 kilobytes and grow
		// if needed
		boost::uint32_t destlen = 4096;
		int ret = 0;
		boost::uint32_t srclen = size - header_len;
		in += header_len;

		do
		{
			TORRENT_TRY {
				buffer.resize(destlen);
			} TORRENT_CATCH(std::exception&) {
				ec = errors::no_memory;
				return;
			}

			ret = puff(reinterpret_cast<unsigned char*>(&buffer[0]), &destlen
				, reinterpret_cast<const unsigned char*>(in), &srclen);

			// if the destination buffer wasn't large enough, double its
			// size and try again. Unless it's already at its max, in which
			// case we fail
			if (ret == 1) // 1:  output space exhausted before completing inflate
			{
				if (destlen == boost::uint32_t(maximum_size))
				{
					ec = gzip_errors::inflated_data_too_large;
					return;
				}

				destlen *= 2;
				if (destlen > boost::uint32_t(maximum_size))
					destlen = maximum_size;
			}
		} while (ret == 1);
Esempio n. 3
0
	// TODO: 2 it would be nice to use proper error handling here
	TORRENT_EXTRA_EXPORT bool inflate_gzip(
		char const* in
		, int size
		, std::vector<char>& buffer
		, int maximum_size
		, std::string& error)
	{
		TORRENT_ASSERT(maximum_size > 0);

		int header_len = gzip_header(in, size);
		if (header_len < 0)
		{
			error = "invalid gzip header";
			return true;
		}

		// start off with 4 kilobytes and grow
		// if needed
		boost::uint32_t destlen = 4096;
		int ret = 0;
		boost::uint32_t srclen = size - header_len;
		in += header_len;

		do
		{
			TORRENT_TRY {
				buffer.resize(destlen);
			} TORRENT_CATCH(std::exception& e) {
				error = "out of memory: ";
				error += e.what();
				return true;
			}

			ret = puff((unsigned char*)&buffer[0], &destlen, (unsigned char*)in, &srclen);

			// if the destination buffer wasn't large enough, double its
			// size and try again. Unless it's already at its max, in which
			// case we fail
			if (ret == 1) // 1:  output space exhausted before completing inflate
			{
				if (destlen == boost::uint32_t(maximum_size))
				{
					error = "inflated data too big";
					return true;
				}

				destlen *= 2;
				if (destlen > (unsigned int)maximum_size)
					destlen = maximum_size;
			}
		} while (ret == 1);
Esempio n. 4
0
	bool inflate_gzip(
		char const* in
		, int size
		, std::vector<char>& buffer
		, int maximum_size
		, std::string& error)
	{
		TORRENT_ASSERT(maximum_size > 0);

		int header_len = gzip_header(in, size);
		if (header_len < 0)
		{
			error = "invalid gzip header in tracker response";
			return true;
		}

		// start off with one kilobyte and grow
		// if needed
		buffer.resize(1024);

		// initialize the zlib-stream
		z_stream str;

		// subtract 8 from the end of the buffer since that's CRC32 and input size
		// and those belong to the gzip file
		str.avail_in = (int)size - header_len - 8;
		str.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in + header_len));
		str.next_out = reinterpret_cast<Bytef*>(&buffer[0]);
		str.avail_out = (int)buffer.size();
		str.zalloc = Z_NULL;
		str.zfree = Z_NULL;
		str.opaque = 0;
		// -15 is really important. It will make inflate() not look for a zlib header
		// and just deflate the buffer
		if (inflateInit2(&str, -15) != Z_OK)
		{
			error = "gzip out of memory";
			return true;
		}

		// inflate and grow inflate_buffer as needed
		int ret = inflate(&str, Z_SYNC_FLUSH);
		while (ret == Z_OK)
		{
			if (str.avail_out == 0)
			{
				if (buffer.size() >= (unsigned)maximum_size)
				{
					inflateEnd(&str);
					error = "response too large";
					return true;
				}
				int new_size = (int)buffer.size() * 2;
				if (new_size > maximum_size)
					new_size = maximum_size;
				int old_size = (int)buffer.size();

				buffer.resize(new_size);
				str.next_out = reinterpret_cast<Bytef*>(&buffer[old_size]);
				str.avail_out = new_size - old_size;
			}

			ret = inflate(&str, Z_SYNC_FLUSH);
		}

		buffer.resize(buffer.size() - str.avail_out);
		inflateEnd(&str);

		if (ret != Z_STREAM_END)
		{
			error = "gzip error";
			return true;
		}

		// commit the resulting buffer
		return false;
	}