2020-01-18 03:38:21 -05:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
2021-05-23 17:31:16 -04:00
* Copyright ( c ) 2021 , Max Wipfli < mail @ maxwipfli . ch >
2020-01-18 03:38:21 -05:00
*
2021-04-22 04:24:48 -04:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 03:38:21 -05:00
*/
2019-08-10 11:27:56 -04:00
# pragma once
2022-12-04 13:02:33 -05:00
# include <AK/DeprecatedString.h>
2023-02-28 15:35:41 -05:00
# include <AK/String.h>
2019-08-10 11:27:56 -04:00
# include <AK/StringView.h>
2021-11-10 05:05:21 -05:00
# include <AK/Vector.h>
2019-08-10 11:27:56 -04:00
2022-09-25 14:54:06 -04:00
// On Linux distros that use mlibc `basename` is defined as a macro that expands to `__mlibc_gnu_basename` or `__mlibc_gnu_basename_c`, so we undefine it.
# if defined(AK_OS_LINUX) && defined(basename)
# undef basename
# endif
2019-08-10 11:27:56 -04:00
namespace AK {
class URL {
2021-05-25 16:13:15 -04:00
friend class URLParser ;
2019-08-10 11:27:56 -04:00
public :
2021-05-25 07:50:03 -04:00
enum class PercentEncodeSet {
C0Control ,
Fragment ,
Query ,
SpecialQuery ,
Path ,
Userinfo ,
Component ,
ApplicationXWWWFormUrlencoded ,
EncodeURI
} ;
2021-05-25 16:32:39 -04:00
enum class ExcludeFragment {
No ,
Yes
} ;
2021-01-10 18:29:28 -05:00
URL ( ) = default ;
2021-11-10 18:55:02 -05:00
URL ( StringView ) ;
2022-12-04 13:02:33 -05:00
URL ( DeprecatedString const & string )
2019-08-10 13:31:37 -04:00
: URL ( string . view ( ) )
{
}
2023-02-28 15:35:41 -05:00
URL ( String const & string )
: URL ( string . bytes_as_string_view ( ) )
{
}
2019-08-10 11:27:56 -04:00
2021-09-13 15:42:48 -04:00
bool is_valid ( ) const { return m_valid ; }
2021-05-23 17:31:16 -04:00
2023-04-13 18:06:58 -04:00
enum class ApplyPercentDecoding {
Yes ,
No
} ;
2022-12-04 13:02:33 -05:00
DeprecatedString const & scheme ( ) const { return m_scheme ; }
2023-04-13 18:06:58 -04:00
DeprecatedString username ( ApplyPercentDecoding = ApplyPercentDecoding : : Yes ) const ;
DeprecatedString password ( ApplyPercentDecoding = ApplyPercentDecoding : : Yes ) const ;
2022-12-04 13:02:33 -05:00
DeprecatedString const & host ( ) const { return m_host ; }
2023-04-13 18:06:58 -04:00
DeprecatedString basename ( ApplyPercentDecoding = ApplyPercentDecoding : : Yes ) const ;
DeprecatedString query ( ApplyPercentDecoding = ApplyPercentDecoding : : No ) const ;
DeprecatedString fragment ( ApplyPercentDecoding = ApplyPercentDecoding : : Yes ) const ;
2021-09-13 16:12:16 -04:00
Optional < u16 > port ( ) const { return m_port ; }
2023-04-13 18:29:51 -04:00
DeprecatedString path_segment_at_index ( size_t index , ApplyPercentDecoding = ApplyPercentDecoding : : Yes ) const ;
size_t path_segment_count ( ) const { return m_paths . size ( ) ; }
2023-04-13 18:06:58 -04:00
2021-09-13 16:12:16 -04:00
u16 port_or_default ( ) const { return m_port . value_or ( default_port_for_scheme ( m_scheme ) ) ; }
2021-09-13 15:42:48 -04:00
bool cannot_be_a_base_url ( ) const { return m_cannot_be_a_base_url ; }
2021-09-13 15:46:31 -04:00
bool cannot_have_a_username_or_password_or_port ( ) const { return m_host . is_null ( ) | | m_host . is_empty ( ) | | m_cannot_be_a_base_url | | m_scheme = = " file " sv ; }
2019-08-10 11:27:56 -04:00
2021-05-25 16:05:01 -04:00
bool includes_credentials ( ) const { return ! m_username . is_empty ( ) | | ! m_password . is_empty ( ) ; }
bool is_special ( ) const { return is_special_scheme ( m_scheme ) ; }
2023-04-09 09:21:00 -04:00
enum class ApplyPercentEncoding {
Yes ,
No
} ;
2022-12-04 13:02:33 -05:00
void set_scheme ( DeprecatedString ) ;
2023-04-14 15:12:20 -04:00
void set_username ( DeprecatedString , ApplyPercentEncoding = ApplyPercentEncoding : : Yes ) ;
void set_password ( DeprecatedString , ApplyPercentEncoding = ApplyPercentEncoding : : Yes ) ;
2022-12-04 13:02:33 -05:00
void set_host ( DeprecatedString ) ;
2021-09-13 16:12:16 -04:00
void set_port ( Optional < u16 > ) ;
2023-04-14 15:12:20 -04:00
void set_paths ( Vector < DeprecatedString > , ApplyPercentEncoding = ApplyPercentEncoding : : Yes ) ;
void set_query ( DeprecatedString , ApplyPercentEncoding = ApplyPercentEncoding : : Yes ) ;
void set_fragment ( DeprecatedString fragment , ApplyPercentEncoding = ApplyPercentEncoding : : Yes ) ;
2021-06-01 04:58:27 -04:00
void set_cannot_be_a_base_url ( bool value ) { m_cannot_be_a_base_url = value ; }
2023-04-14 15:12:20 -04:00
void append_path ( DeprecatedString , ApplyPercentEncoding = ApplyPercentEncoding : : Yes ) ;
2023-04-09 09:21:00 -04:00
void append_slash ( )
{
// NOTE: To indicate that we want to end the path with a slash, we have to append an empty path segment.
append_path ( " " , ApplyPercentEncoding : : No ) ;
}
2019-10-05 04:14:42 -04:00
2023-04-14 15:12:03 -04:00
DeprecatedString serialize_path ( ApplyPercentDecoding = ApplyPercentDecoding : : Yes ) const ;
2022-12-04 13:02:33 -05:00
DeprecatedString serialize ( ExcludeFragment = ExcludeFragment : : No ) const ;
DeprecatedString serialize_for_display ( ) const ;
2022-12-05 20:12:49 -05:00
DeprecatedString to_deprecated_string ( ) const { return serialize ( ) ; }
2021-05-27 15:38:16 -04:00
2021-09-13 15:18:14 -04:00
// HTML origin
2022-12-04 13:02:33 -05:00
DeprecatedString serialize_origin ( ) const ;
2021-09-13 15:18:14 -04:00
2021-06-01 04:58:27 -04:00
bool equals ( URL const & other , ExcludeFragment = ExcludeFragment : : No ) const ;
2021-05-27 15:38:16 -04:00
2023-02-13 12:42:27 -05:00
URL complete_url ( StringView ) const ;
2019-11-18 16:04:39 -05:00
2020-04-26 16:48:54 -04:00
bool data_payload_is_base64 ( ) const { return m_data_payload_is_base64 ; }
2022-12-04 13:02:33 -05:00
DeprecatedString const & data_mime_type ( ) const { return m_data_mime_type ; }
DeprecatedString const & data_payload ( ) const { return m_data_payload ; }
2020-04-26 16:48:54 -04:00
2022-12-04 13:02:33 -05:00
static URL create_with_url_or_path ( DeprecatedString const & ) ;
static URL create_with_file_scheme ( DeprecatedString const & path , DeprecatedString const & fragment = { } , DeprecatedString const & hostname = { } ) ;
static URL create_with_help_scheme ( DeprecatedString const & path , DeprecatedString const & fragment = { } , DeprecatedString const & hostname = { } ) ;
static URL create_with_data ( DeprecatedString mime_type , DeprecatedString payload , bool is_base64 = false ) { return URL ( move ( mime_type ) , move ( payload ) , is_base64 ) ; } ;
2021-05-25 16:05:01 -04:00
2021-11-10 18:55:02 -05:00
static bool scheme_requires_port ( StringView ) ;
static u16 default_port_for_scheme ( StringView ) ;
static bool is_special_scheme ( StringView ) ;
2020-04-18 16:02:04 -04:00
2022-04-09 12:34:49 -04:00
enum class SpaceAsPlus {
No ,
Yes ,
} ;
2022-12-04 13:02:33 -05:00
static DeprecatedString percent_encode ( StringView input , PercentEncodeSet set = PercentEncodeSet : : Userinfo , SpaceAsPlus = SpaceAsPlus : : No ) ;
static DeprecatedString percent_decode ( StringView input ) ;
2021-05-25 07:50:03 -04:00
2021-06-01 05:14:30 -04:00
bool operator = = ( URL const & other ) const { return equals ( other , ExcludeFragment : : No ) ; }
2020-06-01 15:50:07 -04:00
2022-04-09 18:48:15 -04:00
static bool code_point_is_in_percent_encode_set ( u32 code_point , URL : : PercentEncodeSet ) ;
2019-08-10 11:27:56 -04:00
private :
2022-12-04 13:02:33 -05:00
URL ( DeprecatedString & & data_mime_type , DeprecatedString & & data_payload , bool payload_is_base64 )
2021-05-25 16:05:01 -04:00
: m_valid ( true )
, m_scheme ( " data " )
, m_data_payload_is_base64 ( payload_is_base64 )
, m_data_mime_type ( move ( data_mime_type ) )
, m_data_payload ( move ( data_payload ) )
{
}
2020-04-11 17:07:23 -04:00
bool compute_validity ( ) const ;
2022-12-04 13:02:33 -05:00
DeprecatedString serialize_data_url ( ) const ;
2019-08-10 11:27:56 -04:00
2022-04-08 09:20:30 -04:00
static void append_percent_encoded_if_necessary ( StringBuilder & , u32 code_point , PercentEncodeSet set = PercentEncodeSet : : Userinfo ) ;
2021-05-25 07:50:03 -04:00
static void append_percent_encoded ( StringBuilder & , u32 code_point ) ;
2019-08-10 11:27:56 -04:00
bool m_valid { false } ;
2021-05-25 15:32:20 -04:00
2022-12-04 13:02:33 -05:00
DeprecatedString m_scheme ;
DeprecatedString m_username ;
DeprecatedString m_password ;
DeprecatedString m_host ;
2021-09-13 16:12:16 -04:00
// NOTE: If the port is the default port for the scheme, m_port should be empty.
Optional < u16 > m_port ;
2022-12-04 13:02:33 -05:00
DeprecatedString m_path ;
Vector < DeprecatedString > m_paths ;
DeprecatedString m_query ;
DeprecatedString m_fragment ;
2021-05-25 15:32:20 -04:00
bool m_cannot_be_a_base_url { false } ;
bool m_data_payload_is_base64 { false } ;
2022-12-04 13:02:33 -05:00
DeprecatedString m_data_mime_type ;
DeprecatedString m_data_payload ;
2019-08-10 11:27:56 -04:00
} ;
2020-10-04 07:29:47 -04:00
template < >
struct Formatter < URL > : Formatter < StringView > {
2021-11-15 19:15:21 -05:00
ErrorOr < void > format ( FormatBuilder & builder , URL const & value )
2020-10-04 07:29:47 -04:00
{
2021-11-15 19:15:21 -05:00
return Formatter < StringView > : : format ( builder , value . serialize ( ) ) ;
2020-10-04 07:29:47 -04:00
}
} ;
2020-06-01 15:50:07 -04:00
template < >
struct Traits < URL > : public GenericTraits < URL > {
2022-12-05 20:12:49 -05:00
static unsigned hash ( URL const & url ) { return url . to_deprecated_string ( ) . hash ( ) ; }
2020-06-01 15:50:07 -04:00
} ;
2020-05-16 13:35:39 -04:00
}