mirror of
https://github.com/matrix-construct/construct
synced 2024-09-11 11:09:12 +02:00
267 lines
7.9 KiB
C++
267 lines
7.9 KiB
C++
/*
|
|
* charybdis: 21st Century IRC++d
|
|
*
|
|
* Copyright (C) 2016 Charybdis Development Team
|
|
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice is present in all copies.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
#define HAVE_IRCD_M_ID_H
|
|
|
|
namespace ircd::m
|
|
{
|
|
struct id;
|
|
|
|
IRCD_M_EXCEPTION(error, INVALID_MXID, http::BAD_REQUEST)
|
|
IRCD_M_EXCEPTION(INVALID_MXID, BAD_SIGIL, http::BAD_REQUEST)
|
|
|
|
bool my(const id &);
|
|
}
|
|
|
|
/// (Appendix 4.2) Common Identifier Format
|
|
///
|
|
/// The Matrix protocol uses a common format to assign unique identifiers to
|
|
/// a number of entities, including users, events and rooms. Each identifier
|
|
/// takes the form: `&localpart:domain` where & represents a 'sigil' character;
|
|
/// domain is the server name of the homeserver which allocated the identifier,
|
|
/// and localpart is an identifier allocated by that homeserver. The precise
|
|
/// grammar defining the allowable format of an identifier depends on the type
|
|
/// of identifier.
|
|
///
|
|
/// This structure is an interface to a string representing an mxid. The m::id
|
|
/// itself is just a string_view over some existing data. m::id::buf is an
|
|
/// m::id with an internal array providing the buffer.
|
|
///
|
|
struct ircd::m::id
|
|
:string_view
|
|
{
|
|
struct event;
|
|
struct user;
|
|
struct room;
|
|
struct room_alias;
|
|
struct group;
|
|
struct origin;
|
|
|
|
enum sigil :char;
|
|
template<class T, size_t SIZE = 256> struct buf;
|
|
template<class it> struct input;
|
|
template<class it> struct output;
|
|
struct parser;
|
|
struct printer;
|
|
struct validator;
|
|
|
|
struct parser static const parser;
|
|
struct printer static const printer;
|
|
struct validator static const validator;
|
|
|
|
public:
|
|
// Extract elements
|
|
string_view local() const;
|
|
string_view host() const;
|
|
string_view name() const;
|
|
string_view hostname() const;
|
|
uint16_t hostport() const;
|
|
|
|
IRCD_USING_OVERLOAD(generate, m::generate);
|
|
|
|
id(const enum sigil &, const mutable_buffer &, const generate_t &, const string_view &host);
|
|
id(const enum sigil &, const mutable_buffer &, const string_view &name, const string_view &host);
|
|
id(const enum sigil &, const mutable_buffer &, const string_view &id);
|
|
id(const enum sigil &, const string_view &id);
|
|
id(const string_view &id);
|
|
id() = default;
|
|
};
|
|
|
|
/// (4.2) The sigil characters
|
|
enum ircd::m::id::sigil
|
|
:char
|
|
{
|
|
USER = '@', ///< User ID (4.2.1)
|
|
EVENT = '$', ///< Event ID (4.2.2)
|
|
ROOM = '!', ///< Room ID (4.2.2)
|
|
ROOM_ALIAS = '#', ///< Room alias (4.2.3)
|
|
GROUP = '+', ///< Group ID (experimental)
|
|
ORIGIN = ':', ///< Origin ID (experimental)
|
|
};
|
|
|
|
/// (Appendix 4.2.1) User Identifiers
|
|
///
|
|
/// Users within Matrix are uniquely identified by their Matrix user ID. The
|
|
/// user ID is namespaced to the homeserver which allocated the account and
|
|
/// has the form: `@localpart:domain` The localpart of a user ID is an opaque
|
|
/// identifier for that user. It MUST NOT be empty, and MUST contain only the
|
|
/// characters a-z, 0-9, ., _, =, -, and /. The domain of a user ID is the
|
|
/// server name of the homeserver which allocated the account. The length of
|
|
/// a user ID, including the @ sigil and the domain, MUST NOT exceed 255
|
|
/// characters.
|
|
///
|
|
struct ircd::m::id::user
|
|
:ircd::m::id
|
|
{
|
|
using buf = m::id::buf<user>;
|
|
template<class... args> user(args&&... a) :m::id{USER, std::forward<args>(a)...} {}
|
|
user() = default;
|
|
};
|
|
|
|
/// (Appendix 4.2.2) Room IDs and Event IDs
|
|
///
|
|
/// An event has exactly one event ID. An event ID has the format:
|
|
/// `$opaque_id:domain` The domain of an event ID is the server name of the
|
|
/// homeserver which created the event. The domain is used only for namespacing
|
|
/// to avoid the risk of clashes of identifiers between different homeservers.
|
|
/// There is no implication that the event in question is still available at
|
|
/// the corresponding homeserver. Event IDs are case-sensitive. They are not
|
|
/// meant to be human readable.
|
|
///
|
|
struct ircd::m::id::event
|
|
:ircd::m::id
|
|
{
|
|
using buf = m::id::buf<event>;
|
|
template<class... args> event(args&&... a) :m::id{EVENT, std::forward<args>(a)...} {}
|
|
event() = default;
|
|
};
|
|
|
|
/// (Appendix 4.2.2) Room IDs and Event IDs
|
|
///
|
|
/// A room has exactly one room ID. A room ID has the format:
|
|
/// `!opaque_id:domain` The domain of a room ID is the server name of the
|
|
/// homeserver which created the room. The domain is used only for namespacing
|
|
/// to avoid the risk of clashes of identifiers between different homeservers.
|
|
/// There is no implication that the room in question is still available at
|
|
/// the corresponding homeserver. Room IDs are case-sensitive. They are not
|
|
/// meant to be human readable.
|
|
///
|
|
struct ircd::m::id::room
|
|
:ircd::m::id
|
|
{
|
|
using buf = m::id::buf<room>;
|
|
template<class... args> room(args&&... a) :m::id{ROOM, std::forward<args>(a)...} {}
|
|
room() = default;
|
|
};
|
|
|
|
/// (Appendix 4.2.3) Room Aliases
|
|
/// A room may have zero or more aliases. A room alias has the format:
|
|
/// `#room_alias:domain` The domain of a room alias is the server name of the
|
|
/// homeserver which created the alias. Other servers may contact this
|
|
/// homeserver to look up the alias. Room aliases MUST NOT exceed 255 bytes
|
|
/// (including the # sigil and the domain).
|
|
///
|
|
struct ircd::m::id::room_alias
|
|
:ircd::m::id
|
|
{
|
|
using buf = m::id::buf<room_alias>;
|
|
template<class... args> room_alias(args&&... a) :m::id{ROOM_ALIAS, std::forward<args>(a)...} {}
|
|
room_alias() = default;
|
|
};
|
|
|
|
/// Group ID (EXPERIMENTAL)
|
|
///
|
|
struct ircd::m::id::group
|
|
:ircd::m::id
|
|
{
|
|
using buf = m::id::buf<group>;
|
|
template<class... args> group(args&&... a) :m::id{GROUP, std::forward<args>(a)...} {}
|
|
group() = default;
|
|
};
|
|
|
|
/// Group ID (EXPERIMENTAL)
|
|
///
|
|
struct ircd::m::id::origin
|
|
:ircd::m::id
|
|
{
|
|
using buf = m::id::buf<origin>;
|
|
template<class... args> origin(args&&... a) :m::id{ORIGIN, std::forward<args>(a)...} {}
|
|
origin() = default;
|
|
};
|
|
|
|
// Utilities
|
|
namespace ircd::m
|
|
{
|
|
id::sigil sigil(const char &c);
|
|
id::sigil sigil(const string_view &id);
|
|
const char *reflect(const id::sigil &);
|
|
|
|
// Checks
|
|
bool valid_sigil(const char &c);
|
|
bool valid_sigil(const string_view &id);
|
|
bool valid(const id::sigil &, const string_view &) noexcept;
|
|
bool valid_local(const id::sigil &, const string_view &); // Local part is valid
|
|
void validate(const id::sigil &, const string_view &); // valid() | throws
|
|
}
|
|
|
|
/// ID object backed by an internal buffer of default worst-case size.
|
|
///
|
|
template<class T,
|
|
size_t MAX = 256>
|
|
struct ircd::m::id::buf
|
|
:T
|
|
{
|
|
static constexpr const size_t SIZE
|
|
{
|
|
MAX
|
|
};
|
|
|
|
private:
|
|
fixed_buffer<mutable_buffer, SIZE> b;
|
|
|
|
public:
|
|
operator const fixed_buffer<mutable_buffer, SIZE> &() const
|
|
{
|
|
return b;
|
|
}
|
|
|
|
operator mutable_buffer()
|
|
{
|
|
return b;
|
|
}
|
|
|
|
template<class... args>
|
|
buf(args&&... a)
|
|
:T{b, std::forward<args>(a)...}
|
|
{}
|
|
|
|
buf() = default;
|
|
|
|
buf(buf &&other) noexcept
|
|
:T{b, std::move(other)}
|
|
{}
|
|
|
|
buf(const buf &other)
|
|
:T{b, other}
|
|
{}
|
|
|
|
buf &operator=(const buf &other)
|
|
{
|
|
static_cast<T &>(*this) = T{b, other};
|
|
return *this;
|
|
}
|
|
|
|
buf &operator=(buf &&other) noexcept
|
|
{
|
|
static_cast<T &>(*this) = T{b, std::move(other)};
|
|
return *this;
|
|
}
|
|
|
|
buf &operator=(const string_view &s)
|
|
{
|
|
static_cast<T &>(*this) = T{b, s};
|
|
return *this;
|
|
}
|
|
};
|