/* * Copyright (C) 2015-2018 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ #pragma once #include #include #include class CHttpRange { public: CHttpRange() = default; CHttpRange(uint64_t firstPosition, uint64_t lastPosition); virtual ~CHttpRange() = default; bool operator<(const CHttpRange &other) const; bool operator==(const CHttpRange &other) const; bool operator!=(const CHttpRange &other) const; virtual uint64_t GetFirstPosition() const { return m_first; } virtual void SetFirstPosition(uint64_t firstPosition) { m_first = firstPosition; } virtual uint64_t GetLastPosition() const { return m_last; } virtual void SetLastPosition(uint64_t lastPosition) { m_last = lastPosition; } virtual uint64_t GetLength() const; virtual void SetLength(uint64_t length); virtual bool IsValid() const; protected: uint64_t m_first = 1; uint64_t m_last = 0; }; typedef std::vector HttpRanges; class CHttpResponseRange : public CHttpRange { public: CHttpResponseRange(); CHttpResponseRange(uint64_t firstPosition, uint64_t lastPosition); CHttpResponseRange(const void* data, uint64_t firstPosition, uint64_t lastPosition); CHttpResponseRange(const void* data, uint64_t length); ~CHttpResponseRange() override = default; bool operator==(const CHttpResponseRange &other) const; bool operator!=(const CHttpResponseRange &other) const; const void* GetData() const { return m_data; } void SetData(const void* data) { m_data = data; } void SetData(const void* data, uint64_t length); void SetData(const void* data, uint64_t firstPosition, uint64_t lastPosition); bool IsValid() const override; protected: const void* m_data; }; typedef std::vector HttpResponseRanges; class CHttpRanges final { public: CHttpRanges(); explicit CHttpRanges(const HttpRanges& httpRanges); const HttpRanges& Get() const { return m_ranges; } bool Get(size_t index, CHttpRange& range) const; bool GetFirst(CHttpRange& range) const; bool GetLast(CHttpRange& range) const; size_t Size() const { return m_ranges.size(); } bool IsEmpty() const { return m_ranges.empty(); } bool GetFirstPosition(uint64_t& position) const; bool GetLastPosition(uint64_t& position) const; uint64_t GetLength() const; bool GetTotalRange(CHttpRange& range) const; void Add(const CHttpRange& range); void Remove(size_t index); void Clear(); HttpRanges::const_iterator Begin() const { return m_ranges.begin(); } HttpRanges::const_iterator End() const { return m_ranges.end(); } bool Parse(const std::string& header); bool Parse(const std::string& header, uint64_t totalLength); protected: void SortAndCleanup(); HttpRanges m_ranges; }; class HttpRangeUtils { public: /*! * \brief Generates a valid Content-Range HTTP header value for the given HTTP * range definition. * * \param range HTTP range definition used to generate the Content-Range HTTP header * \return Content-Range HTTP header value */ static std::string GenerateContentRangeHeaderValue(const CHttpRange* range); /*! * \brief Generates a valid Content-Range HTTP header value for the given HTTP * range properties. * * \param start Start position of the HTTP range * \param end Last/End position of the HTTP range * \param total Total length of original content (not just the range) * \return Content-Range HTTP header value */ static std::string GenerateContentRangeHeaderValue(uint64_t start, uint64_t end, uint64_t total); #ifdef HAS_WEB_SERVER /*! * \brief Generates a multipart boundary that can be used in ranged HTTP * responses. * * \return Multipart boundary that can be used in ranged HTTP responses */ static std::string GenerateMultipartBoundary(); /*! * \brief Generates the multipart/byteranges Content-Type HTTP header value * containing the given multipart boundary for a ranged HTTP response. * * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response * \return multipart/byteranges Content-Type HTTP header value */ static std::string GenerateMultipartBoundaryContentType(const std::string& multipartBoundary); /*! * \brief Generates a multipart boundary including the Content-Type HTTP * header value with the (actual) given content type of the original * content. * * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response * \param contentType (Actual) Content type of the original content * \return Multipart boundary (including the Content-Type HTTP header) value that can be used in ranged HTTP responses */ static std::string GenerateMultipartBoundaryWithHeader(const std::string& multipartBoundary, const std::string& contentType); /*! * \brief Generates a multipart boundary including the Content-Type HTTP * header value with the (actual) given content type of the original * content and the Content-Range HTTP header value for the given range. * * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response * \param contentType (Actual) Content type of the original content * \param range HTTP range definition used to generate the Content-Range HTTP header * \return Multipart boundary (including the Content-Type and Content-Range HTTP headers) value that can be used in ranged HTTP responses */ static std::string GenerateMultipartBoundaryWithHeader(const std::string& multipartBoundary, const std::string& contentType, const CHttpRange* range); /*! * \brief Generates a multipart boundary including the Content-Type HTTP * header value with the (actual) given content type of the original * content and the Content-Range HTTP header value for the given range. * * \param multipartBoundaryWithContentType Multipart boundary (already including the Content-Type HTTP header value) to be used in the ranged HTTP response * \param range HTTP range definition used to generate the Content-Range HTTP header * \return Multipart boundary (including the Content-Type and Content-Range HTTP headers) value that can be used in ranged HTTP responses */ static std::string GenerateMultipartBoundaryWithHeader(const std::string& multipartBoundaryWithContentType, const CHttpRange* range); /*! * \brief Generates a multipart boundary end that can be used in ranged HTTP * responses. * * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response * \return Multipart boundary end that can be used in a ranged HTTP response */ static std::string GenerateMultipartBoundaryEnd(const std::string& multipartBoundary); #endif // HAS_WEB_SERVER };