forked from wolfSSL/wolfssl
begin BIO gets functions
This commit is contained in:
149
src/bio.c
149
src/bio.c
@@ -36,6 +36,130 @@ WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* helper function for wolfSSL_BIO_gets
|
||||||
|
* size till a newline is hit
|
||||||
|
* returns the number of bytes
|
||||||
|
*/
|
||||||
|
static int wolfSSL_getLineLength(char* in, int inSz)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < inSz; i++) {
|
||||||
|
if (in[i] == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i + 1; /* +1 to return number of bytes not index */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
|
||||||
|
{
|
||||||
|
int ret = WOLFSSL_BIO_UNSET;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_BIO_gets");
|
||||||
|
|
||||||
|
if (bio == NULL || buf == NULL) {
|
||||||
|
return SSL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not enough space for character plus terminator */
|
||||||
|
if (sz <= 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (bio->type) {
|
||||||
|
case WOLFSSL_BIO_FILE:
|
||||||
|
#if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET)
|
||||||
|
WOLFSSL_MSG("XFGETS not ported for this system yet");
|
||||||
|
ret = XFGETS(buf, sz, bio->file);
|
||||||
|
#else
|
||||||
|
if (XFGETS(buf, sz, bio->file) != NULL) {
|
||||||
|
ret = (int)XSTRLEN(buf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = WOLFSSL_BIO_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WOLFSSL_BIO_MEMORY:
|
||||||
|
case WOLFSSL_BIO_BIO:
|
||||||
|
{
|
||||||
|
char* c;
|
||||||
|
int cSz;
|
||||||
|
cSz = wolfSSL_BIO_nread0(bio, &c);
|
||||||
|
if (cSz < 0) {
|
||||||
|
ret = cSz;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cSz = wolfSSL_getLineLength(c, cSz);
|
||||||
|
/* check case where line was bigger then buffer and buffer
|
||||||
|
* needs end terminator */
|
||||||
|
if (cSz > sz) {
|
||||||
|
cSz = sz - 1;
|
||||||
|
buf[cSz] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wolfSSL_BIO_nread(bio, &c, cSz);
|
||||||
|
if (ret > 0 && ret < sz) {
|
||||||
|
XMEMCPY(buf, c, ret);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("BIO type not supported yet with wolfSSL_BIO_gets");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* searches through bio list for a BIO of type "type"
|
||||||
|
* returns NULL on failure to find a given type */
|
||||||
|
WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type)
|
||||||
|
{
|
||||||
|
WOLFSSL_BIO* local = NULL;
|
||||||
|
WOLFSSL_BIO* current;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("wolfSSL_BIO_find_type");
|
||||||
|
|
||||||
|
if (bio == NULL) {
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = bio;
|
||||||
|
while (current != NULL) {
|
||||||
|
if (current->type == type) {
|
||||||
|
WOLFSSL_MSG("Found matching WOLFSSL_BIO type");
|
||||||
|
local = current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* returns a pointer to the next WOLFSSL_BIO in the chain on success.
|
||||||
|
* If a failure case then NULL is returned */
|
||||||
|
WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio)
|
||||||
|
{
|
||||||
|
WOLFSSL_ENTER("wolfSSL_BIO_next");
|
||||||
|
|
||||||
|
if (bio == NULL) {
|
||||||
|
WOLFSSL_MSG("Bad argument passed in");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bio->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return the number of pending bytes in read and write buffers */
|
/* Return the number of pending bytes in read and write buffers */
|
||||||
size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
|
size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
|
||||||
{
|
{
|
||||||
@@ -48,12 +172,12 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
|
|||||||
return (long)wolfSSL_pending(bio->ssl);
|
return (long)wolfSSL_pending(bio->ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio->type == BIO_MEMORY) {
|
if (bio->type == WOLFSSL_BIO_MEMORY) {
|
||||||
return bio->memLen;
|
return bio->memLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* type BIO_BIO then check paired buffer */
|
/* type BIO_BIO then check paired buffer */
|
||||||
if (bio->type == BIO_BIO && bio->pair != NULL) {
|
if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) {
|
||||||
WOLFSSL_BIO* pair = bio->pair;
|
WOLFSSL_BIO* pair = bio->pair;
|
||||||
if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) {
|
if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) {
|
||||||
/* in wrap around state where begining of buffer is being
|
/* in wrap around state where begining of buffer is being
|
||||||
@@ -98,8 +222,8 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
|
|||||||
{
|
{
|
||||||
WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size");
|
WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size");
|
||||||
|
|
||||||
if (bio == NULL || bio->type != BIO_BIO || size < 0) {
|
if (bio == NULL || bio->type != WOLFSSL_BIO_BIO || size < 0) {
|
||||||
return WOLFSSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if already in pair then do not change size */
|
/* if already in pair then do not change size */
|
||||||
@@ -144,7 +268,7 @@ int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* both are expected to be of type BIO and not already paired */
|
/* both are expected to be of type BIO and not already paired */
|
||||||
if (b1->type != BIO_BIO || b2->type != BIO_BIO ||
|
if (b1->type != WOLFSSL_BIO_BIO || b2->type != WOLFSSL_BIO_BIO ||
|
||||||
b1->pair != NULL || b2->pair != NULL) {
|
b1->pair != NULL || b2->pair != NULL) {
|
||||||
WOLFSSL_MSG("Expected type BIO and not already paired");
|
WOLFSSL_MSG("Expected type BIO and not already paired");
|
||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
@@ -338,12 +462,12 @@ int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
|
|||||||
|
|
||||||
switch (bio->type) {
|
switch (bio->type) {
|
||||||
#ifndef NO_FILESYSTEM
|
#ifndef NO_FILESYSTEM
|
||||||
case BIO_FILE:
|
case WOLFSSL_BIO_FILE:
|
||||||
XREWIND(bio->file);
|
XREWIND(bio->file);
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case BIO_BIO:
|
case WOLFSSL_BIO_BIO:
|
||||||
bio->rdIdx = 0;
|
bio->rdIdx = 0;
|
||||||
bio->wrIdx = 0;
|
bio->wrIdx = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -365,7 +489,7 @@ long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c)
|
|||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio->type != BIO_FILE) {
|
if (bio->type != WOLFSSL_BIO_FILE) {
|
||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,8 +508,8 @@ long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp)
|
|||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio->type != BIO_FILE) {
|
if (bio->type != WOLFSSL_BIO_FILE) {
|
||||||
return WOLFSSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*fp = bio->file;
|
*fp = bio->file;
|
||||||
@@ -402,7 +526,7 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name)
|
|||||||
return WOLFSSL_FAILURE;
|
return WOLFSSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio->type == BIO_FILE) {
|
if (bio->type == WOLFSSL_BIO_FILE) {
|
||||||
if (bio->file != NULL && bio->close == BIO_CLOSE) {
|
if (bio->file != NULL && bio->close == BIO_CLOSE) {
|
||||||
XFCLOSE(bio->file);
|
XFCLOSE(bio->file);
|
||||||
}
|
}
|
||||||
@@ -429,7 +553,8 @@ int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* offset ofs from begining of file */
|
/* offset ofs from begining of file */
|
||||||
if (bio->type == BIO_FILE && XFSEEK(bio->file, ofs, SEEK_SET) < 0) {
|
if (bio->type == WOLFSSL_BIO_FILE &&
|
||||||
|
XFSEEK(bio->file, ofs, SEEK_SET) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/ssl.c
24
src/ssl.c
@@ -11606,7 +11606,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
static WOLFSSL_BIO_METHOD meth;
|
static WOLFSSL_BIO_METHOD meth;
|
||||||
|
|
||||||
WOLFSSL_ENTER("BIO_f_buffer");
|
WOLFSSL_ENTER("BIO_f_buffer");
|
||||||
meth.type = BIO_BUFFER;
|
meth.type = WOLFSSL_BIO_BUFFER;
|
||||||
|
|
||||||
return &meth;
|
return &meth;
|
||||||
}
|
}
|
||||||
@@ -11626,7 +11626,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
static WOLFSSL_BIO_METHOD bio_meth;
|
static WOLFSSL_BIO_METHOD bio_meth;
|
||||||
|
|
||||||
WOLFSSL_ENTER("wolfSSL_BIO_f_bio");
|
WOLFSSL_ENTER("wolfSSL_BIO_f_bio");
|
||||||
bio_meth.type = BIO_BIO;
|
bio_meth.type = WOLFSSL_BIO_BIO;
|
||||||
|
|
||||||
return &bio_meth;
|
return &bio_meth;
|
||||||
}
|
}
|
||||||
@@ -11638,7 +11638,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
static WOLFSSL_BIO_METHOD file_meth;
|
static WOLFSSL_BIO_METHOD file_meth;
|
||||||
|
|
||||||
WOLFSSL_ENTER("wolfSSL_BIO_f_file");
|
WOLFSSL_ENTER("wolfSSL_BIO_f_file");
|
||||||
file_meth.type = BIO_FILE;
|
file_meth.type = WOLFSSL_BIO_FILE;
|
||||||
|
|
||||||
return &file_meth;
|
return &file_meth;
|
||||||
}
|
}
|
||||||
@@ -11650,7 +11650,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
static WOLFSSL_BIO_METHOD meth;
|
static WOLFSSL_BIO_METHOD meth;
|
||||||
|
|
||||||
WOLFSSL_ENTER("BIO_f_ssl");
|
WOLFSSL_ENTER("BIO_f_ssl");
|
||||||
meth.type = BIO_SSL;
|
meth.type = WOLFSSL_BIO_SSL;
|
||||||
|
|
||||||
return &meth;
|
return &meth;
|
||||||
}
|
}
|
||||||
@@ -11661,7 +11661,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
static WOLFSSL_BIO_METHOD meth;
|
static WOLFSSL_BIO_METHOD meth;
|
||||||
|
|
||||||
WOLFSSL_ENTER("BIO_s_socket");
|
WOLFSSL_ENTER("BIO_s_socket");
|
||||||
meth.type = BIO_SOCKET;
|
meth.type = WOLFSSL_BIO_SOCKET;
|
||||||
|
|
||||||
return &meth;
|
return &meth;
|
||||||
}
|
}
|
||||||
@@ -11675,7 +11675,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
WOLFSSL_ENTER("BIO_new_socket");
|
WOLFSSL_ENTER("BIO_new_socket");
|
||||||
if (bio) {
|
if (bio) {
|
||||||
XMEMSET(bio, 0, sizeof(WOLFSSL_BIO));
|
XMEMSET(bio, 0, sizeof(WOLFSSL_BIO));
|
||||||
bio->type = BIO_SOCKET;
|
bio->type = WOLFSSL_BIO_SOCKET;
|
||||||
bio->close = (byte)closeF;
|
bio->close = (byte)closeF;
|
||||||
bio->fd = sfd;
|
bio->fd = sfd;
|
||||||
bio->mem = NULL;
|
bio->mem = NULL;
|
||||||
@@ -11801,7 +11801,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_FILESYSTEM
|
#ifndef NO_FILESYSTEM
|
||||||
if (bio->type == BIO_FILE && bio->close == BIO_CLOSE) {
|
if (bio->type == WOLFSSL_BIO_FILE && bio->close == BIO_CLOSE) {
|
||||||
if (bio->file) {
|
if (bio->file) {
|
||||||
XFCLOSE(bio->file);
|
XFCLOSE(bio->file);
|
||||||
}
|
}
|
||||||
@@ -11905,12 +11905,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
|
|
||||||
WOLFSSL_ENTER("wolfSSL_BIO_read");
|
WOLFSSL_ENTER("wolfSSL_BIO_read");
|
||||||
|
|
||||||
if (bio && bio->type == BIO_BIO) {
|
if (bio && bio->type == WOLFSSL_BIO_BIO) {
|
||||||
return wolfSSL_BIO_BIO_read(bio, buf, len);
|
return wolfSSL_BIO_BIO_read(bio, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_FILESYSTEM
|
#ifndef NO_FILESYSTEM
|
||||||
if (bio && bio->type == BIO_FILE) {
|
if (bio && bio->type == WOLFSSL_BIO_FILE) {
|
||||||
return (int)XFREAD(buf, 1, len, bio->file);
|
return (int)XFREAD(buf, 1, len, bio->file);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -11969,12 +11969,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
|
|
||||||
WOLFSSL_ENTER("wolfSSL_BIO_write");
|
WOLFSSL_ENTER("wolfSSL_BIO_write");
|
||||||
|
|
||||||
if (bio && bio->type == BIO_BIO) {
|
if (bio && bio->type == WOLFSSL_BIO_BIO) {
|
||||||
return wolfSSL_BIO_BIO_write(bio, data, len);
|
return wolfSSL_BIO_BIO_write(bio, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_FILESYSTEM
|
#ifndef NO_FILESYSTEM
|
||||||
if (bio && bio->type == BIO_FILE) {
|
if (bio && bio->type == WOLFSSL_BIO_FILE) {
|
||||||
return (int)XFWRITE(data, 1, len, bio->file);
|
return (int)XFWRITE(data, 1, len, bio->file);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -15942,7 +15942,7 @@ WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void)
|
|||||||
static WOLFSSL_BIO_METHOD meth;
|
static WOLFSSL_BIO_METHOD meth;
|
||||||
|
|
||||||
WOLFSSL_ENTER("BIO_s_mem");
|
WOLFSSL_ENTER("BIO_s_mem");
|
||||||
meth.type = BIO_MEMORY;
|
meth.type = WOLFSSL_BIO_MEMORY;
|
||||||
|
|
||||||
return &meth;
|
return &meth;
|
||||||
}
|
}
|
||||||
|
@@ -1346,16 +1346,6 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
enum BIO_TYPE {
|
|
||||||
BIO_BUFFER = 1,
|
|
||||||
BIO_SOCKET = 2,
|
|
||||||
BIO_SSL = 3,
|
|
||||||
BIO_MEMORY = 4,
|
|
||||||
BIO_BIO = 5,
|
|
||||||
BIO_FILE = 6
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* wolfSSL BIO_METHOD type */
|
/* wolfSSL BIO_METHOD type */
|
||||||
struct WOLFSSL_BIO_METHOD {
|
struct WOLFSSL_BIO_METHOD {
|
||||||
byte type; /* method type */
|
byte type; /* method type */
|
||||||
|
@@ -32,8 +32,14 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BIO_find_type wolfSSL_BIO_find_type
|
||||||
|
#define BIO_next wolfSSL_BIO_next
|
||||||
|
#define BIO_gets wolfSSL_BIO_gets
|
||||||
|
|
||||||
|
|
||||||
|
#define BIO_TYPE_FILE WOLFSSL_BIO_FILE
|
||||||
|
#define BIO_TYPE_BIO WOLFSSL_BIO_BIO
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@@ -203,6 +203,15 @@ typedef struct WOLFSSL_MD4_CTX {
|
|||||||
} WOLFSSL_MD4_CTX;
|
} WOLFSSL_MD4_CTX;
|
||||||
|
|
||||||
|
|
||||||
|
enum BIO_TYPE {
|
||||||
|
WOLFSSL_BIO_BUFFER = 1,
|
||||||
|
WOLFSSL_BIO_SOCKET = 2,
|
||||||
|
WOLFSSL_BIO_SSL = 3,
|
||||||
|
WOLFSSL_BIO_MEMORY = 4,
|
||||||
|
WOLFSSL_BIO_BIO = 5,
|
||||||
|
WOLFSSL_BIO_FILE = 6
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct WOLFSSL_COMP_METHOD {
|
typedef struct WOLFSSL_COMP_METHOD {
|
||||||
int type; /* stunnel dereference */
|
int type; /* stunnel dereference */
|
||||||
} WOLFSSL_COMP_METHOD;
|
} WOLFSSL_COMP_METHOD;
|
||||||
@@ -656,6 +665,9 @@ WOLFSSL_API void wolfSSL_MD4_Final(unsigned char*, WOLFSSL_MD4_CTX*);
|
|||||||
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*);
|
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*);
|
||||||
WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*);
|
WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*);
|
||||||
WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*);
|
WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*);
|
||||||
|
WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz);
|
||||||
|
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio);
|
||||||
|
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type);
|
||||||
WOLFSSL_API int wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int);
|
WOLFSSL_API int wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int);
|
||||||
WOLFSSL_API int wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int);
|
WOLFSSL_API int wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int);
|
||||||
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append);
|
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append);
|
||||||
|
Reference in New Issue
Block a user