mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
librpc: Introduce cab.idl
This allows processing of Windows Cabinet files (required for the MS-PAR print protocol implementation) Guenther Signed-off-by: Guenther Deschner <gd@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
parent
20eadb5f9a
commit
88e1c4dc44
135
librpc/idl/cab.idl
Normal file
135
librpc/idl/cab.idl
Normal file
@ -0,0 +1,135 @@
|
||||
#include "idl_types.h"
|
||||
|
||||
import "misc.idl";
|
||||
|
||||
/*
|
||||
IDL structures defining Cabinet files
|
||||
|
||||
more info can be found at:
|
||||
https://msdn.microsoft.com/en-us/library/bb267310.aspx#cabinet_format
|
||||
*/
|
||||
|
||||
[
|
||||
pointer_default(unique),
|
||||
helper("../librpc/ndr/ndr_cab.h"),
|
||||
helpstring("Cabinet structure"),
|
||||
uuid("12345678-0000-0000-0000-00000000")
|
||||
]
|
||||
interface cab
|
||||
{
|
||||
|
||||
/*
|
||||
* flags.cfhdrPREV_CABINET is set if this cabinet file is not the first in
|
||||
* a set of cabinet files. When this bit is set, the szCabinetPrev and
|
||||
* szDiskPrev fields are present in this CFHEADER.
|
||||
*
|
||||
* flags.cfhdrNEXT_CABINET is set if this cabinet file is not the last in a
|
||||
* set of cabinet files. When this bit is set, the szCabinetNext and
|
||||
* szDiskNext fields are present in this CFHEADER.
|
||||
*
|
||||
* flags.cfhdrRESERVE_PRESENT is set if this cabinet file contains any
|
||||
* reserved fields. When this bit is set, the cbCFHeader, cbCFFolder, and
|
||||
* cbCFData fields are present in this CFHEADER.
|
||||
*/
|
||||
|
||||
typedef [bitmap16bit] bitmap {
|
||||
cfhdrPREV_CABINET = 0x0001,
|
||||
cfhdrNEXT_CABINET = 0x0002,
|
||||
cfhdrRESERVE_PRESENT = 0x0004
|
||||
} cf_flags;
|
||||
|
||||
typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
|
||||
[charset(DOS),value("MSCF")] uint8 signature[4];
|
||||
[value(0)] uint32 reserved1; /* reserved */
|
||||
uint32 cbCabinet; /* size of this cabinet file in bytes */
|
||||
[value(0)] uint32 reserved2; /* reserved */
|
||||
[value(cFolders*8+36)] uint32 coffFiles; /* offset of the first CFFILE entry */
|
||||
[value(0)] uint32 reserved3; /* reserved */
|
||||
[value(3)] uint8 versionMinor; /* cabinet file format version, minor */
|
||||
[value(1)] uint8 versionMajor; /* cabinet file format version, major */
|
||||
uint16 cFolders; /* number of CFFOLDER entries in this cabinet */
|
||||
uint16 cFiles; /* number of CFFILE entries in this cabinet */
|
||||
cf_flags flags; /* cabinet file option indicators */
|
||||
uint16 setID; /* must be the same for all cabinets in a set */
|
||||
uint16 iCabinet; /* number of this cabinet file in a set */
|
||||
#if 0
|
||||
[range(0,60000)] uint16 cbCFHeader; /* (optional) size of per-cabinet reserved area */
|
||||
[range(0,255)] uint8 cbCFFolder; /* (optional) size of per-folder reserved area */
|
||||
[range(0,255)] uint8 cbCFData; /* (optional) size of per-datablock reserved area */
|
||||
uint8 abReserve[]; /* (optional) per-cabinet reserved area */
|
||||
uint8 szCabinetPrev[]; /* (optional) name of previous cabinet file */
|
||||
uint8 szDiskPrev[]; /* (optional) name of previous disk */
|
||||
uint8 szCabinetNext[]; /* (optional) name of next cabinet file */
|
||||
uint8 szDiskNext[]; /* (optional) name of next disk */
|
||||
#endif
|
||||
} CFHEADER;
|
||||
|
||||
typedef enum {
|
||||
CF_COMPRESS_NONE = 0,
|
||||
CF_COMPRESS_MSZIP = 1,
|
||||
CF_COMPRESS_LZX = 4611
|
||||
} cf_compress_type;
|
||||
|
||||
typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
|
||||
uint32 coffCabStart; /* offset of the first CFDATA block in this folder */
|
||||
uint16 cCFData; /* number of CFDATA blocks in this folder */
|
||||
cf_compress_type typeCompress; /* compression type indicator */
|
||||
#if 0
|
||||
uint8 abReserve[]; /* (optional) per-folder reserved area */
|
||||
#endif
|
||||
} CFFOLDER;
|
||||
|
||||
const int ifoldCONTINUED_FROM_PREV = 0xFFFD;
|
||||
const int ifoldCONTINUED_TO_NEXT = 0xFFFE;
|
||||
const int ifoldCONTINUED_PREV_AND_NEXT = 0xFFFF;
|
||||
|
||||
typedef [bitmap16bit] bitmap {
|
||||
_A_RDONLY = 0x01, /* file is read-only */
|
||||
_A_HIDDEN = 0x02, /* file is hidden */
|
||||
_A_SYSTEM = 0x04, /* file is a system file */
|
||||
_A_ARCH = 0x20, /* file modified since last backup */
|
||||
_A_EXEC = 0x40, /* run after extraction */
|
||||
_A_NAME_IS_UTF = 0x80 /* szName[] contains UTF */
|
||||
} cf_attributes;
|
||||
|
||||
typedef [noprint,flag(NDR_NOALIGN)] struct {
|
||||
uint16 date;
|
||||
} cf_date;
|
||||
|
||||
typedef [noprint,flag(NDR_NOALIGN)] struct {
|
||||
uint16 time;
|
||||
} cf_time;
|
||||
|
||||
typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN),gensize] struct {
|
||||
uint32 cbFile; /* uncompressed size of this file in bytes */
|
||||
uint32 uoffFolderStart; /* uncompressed offset of this file in the folder */
|
||||
uint16 iFolder; /* index into the CFFOLDER area */
|
||||
cf_date date; /* date stamp for this file */
|
||||
cf_time time; /* time stamp for this file */
|
||||
cf_attributes attribs; /* attribute flags for this file */
|
||||
[flag(r->attribs & _A_NAME_IS_UTF ? STR_UTF8|STR_NULLTERM : STR_ASCII|STR_NULLTERM)] string szName;
|
||||
} CFFILE;
|
||||
|
||||
typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
|
||||
uint32 csum; /* checksum of this CFDATA entry */
|
||||
uint16 cbData; /* number of compressed bytes in this block */
|
||||
uint16 cbUncomp; /* number of uncompressed bytes in this block */
|
||||
#if 0
|
||||
uint8 abReserve[]; /* (optional) per-datablock reserved area */
|
||||
#endif
|
||||
uint8 ab[cbData]; /* compressed data bytes */
|
||||
} CFDATA;
|
||||
|
||||
typedef [nopush,nopull,public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
|
||||
CFHEADER cfheader;
|
||||
CFFOLDER cffolders[cfheader.cFolders];
|
||||
CFFILE cffiles[cfheader.cFiles];
|
||||
[noprint,value(ndr_count_cfdata(r))] uint32 cfdata_count;
|
||||
CFDATA cfdata[cfdata_count];
|
||||
} cab_file;
|
||||
|
||||
void decode_cab_file(
|
||||
[in] cab_file file
|
||||
);
|
||||
|
||||
}
|
@ -34,8 +34,15 @@ bld.SAMBA_PIDL_LIST('PIDL',
|
||||
output_dir='../gen_ndr')
|
||||
|
||||
bld.SAMBA_PIDL_LIST('PIDL',
|
||||
'''rap.idl ntprinting.idl preg.idl ioctl.idl printcap.idl
|
||||
fsrvp_state.idl''',
|
||||
'''
|
||||
rap.idl
|
||||
ntprinting.idl
|
||||
preg.idl
|
||||
ioctl.idl
|
||||
printcap.idl
|
||||
fsrvp_state.idl
|
||||
cab.idl
|
||||
''',
|
||||
options='--header --ndr-parser',
|
||||
output_dir='../gen_ndr')
|
||||
|
||||
|
153
librpc/ndr/ndr_cab.c
Normal file
153
librpc/ndr/ndr_cab.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
routines for marshalling/unmarshalling cab structures
|
||||
|
||||
Copyright (C) Guenther Deschner 2016
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "librpc/gen_ndr/ndr_cab.h"
|
||||
|
||||
_PUBLIC_ void ndr_print_cf_time(struct ndr_print *ndr, const char *name, const struct cf_time *r)
|
||||
{
|
||||
uint8_t hour = 0, minute = 0, seconds = 0;
|
||||
char *s;
|
||||
if (r == NULL) { ndr_print_null(ndr); return; }
|
||||
hour = r->time >> 11;
|
||||
minute = (r->time >> 5) & 0x3f;
|
||||
seconds = (r->time << 1) & 0x3e;
|
||||
s = talloc_asprintf(ndr, "%02d:%02d:%02d", hour, minute, seconds);
|
||||
if (s == NULL) { return; }
|
||||
ndr_print_string(ndr, "time", s);
|
||||
talloc_free(s);
|
||||
}
|
||||
|
||||
_PUBLIC_ void ndr_print_cf_date(struct ndr_print *ndr, const char *name, const struct cf_date *r)
|
||||
{
|
||||
uint16_t year = 0;
|
||||
uint8_t month = 0, day = 0;
|
||||
char *s;
|
||||
if (r == NULL) { ndr_print_null(ndr); return; }
|
||||
year = (r->date >> 9);
|
||||
year += 1980;
|
||||
month = (r->date >> 5 & 0xf);
|
||||
day = (r->date & 0x1f);
|
||||
s = talloc_asprintf(ndr, "%02d/%02d/%04d", day, month, year);
|
||||
if (s == NULL) { return; }
|
||||
ndr_print_string(ndr, "date", s);
|
||||
talloc_free(s);
|
||||
}
|
||||
|
||||
uint32_t ndr_count_cfdata(const struct cab_file *r)
|
||||
{
|
||||
uint32_t count = 0, i;
|
||||
|
||||
for (i = 0; i < r->cfheader.cFolders; i++) {
|
||||
count += r->cffolders[i].cCFData;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
_PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r)
|
||||
{
|
||||
uint32_t cntr_cffolders_0;
|
||||
uint32_t cntr_cffiles_0;
|
||||
uint32_t cntr_cfdata_0;
|
||||
{
|
||||
uint32_t _flags_save_STRUCT = ndr->flags;
|
||||
ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
|
||||
NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
|
||||
if (ndr_flags & NDR_SCALARS) {
|
||||
NDR_CHECK(ndr_push_align(ndr, 4));
|
||||
NDR_CHECK(ndr_push_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
|
||||
for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (r->cfheader.cFolders); cntr_cffolders_0++) {
|
||||
NDR_CHECK(ndr_push_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
|
||||
}
|
||||
for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (r->cfheader.cFiles); cntr_cffiles_0++) {
|
||||
NDR_CHECK(ndr_push_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
|
||||
}
|
||||
#if 0
|
||||
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
|
||||
#endif
|
||||
for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (ndr_count_cfdata(r)); cntr_cfdata_0++) {
|
||||
NDR_CHECK(ndr_push_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
|
||||
}
|
||||
NDR_CHECK(ndr_push_trailer_align(ndr, 4));
|
||||
}
|
||||
if (ndr_flags & NDR_BUFFERS) {
|
||||
}
|
||||
ndr->flags = _flags_save_STRUCT;
|
||||
}
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
_PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags, struct cab_file *r)
|
||||
{
|
||||
uint32_t size_cffolders_0 = 0;
|
||||
uint32_t cntr_cffolders_0;
|
||||
TALLOC_CTX *_mem_save_cffolders_0 = NULL;
|
||||
uint32_t size_cffiles_0 = 0;
|
||||
uint32_t cntr_cffiles_0;
|
||||
TALLOC_CTX *_mem_save_cffiles_0 = NULL;
|
||||
uint32_t size_cfdata_0 = 0;
|
||||
uint32_t cntr_cfdata_0;
|
||||
TALLOC_CTX *_mem_save_cfdata_0 = NULL;
|
||||
{
|
||||
uint32_t _flags_save_STRUCT = ndr->flags;
|
||||
ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
|
||||
NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
|
||||
if (ndr_flags & NDR_SCALARS) {
|
||||
NDR_CHECK(ndr_pull_align(ndr, 4));
|
||||
NDR_CHECK(ndr_pull_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
|
||||
size_cffolders_0 = r->cfheader.cFolders;
|
||||
NDR_PULL_ALLOC_N(ndr, r->cffolders, size_cffolders_0);
|
||||
_mem_save_cffolders_0 = NDR_PULL_GET_MEM_CTX(ndr);
|
||||
NDR_PULL_SET_MEM_CTX(ndr, r->cffolders, 0);
|
||||
for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
|
||||
NDR_CHECK(ndr_pull_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
|
||||
}
|
||||
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffolders_0, 0);
|
||||
size_cffiles_0 = r->cfheader.cFiles;
|
||||
NDR_PULL_ALLOC_N(ndr, r->cffiles, size_cffiles_0);
|
||||
_mem_save_cffiles_0 = NDR_PULL_GET_MEM_CTX(ndr);
|
||||
NDR_PULL_SET_MEM_CTX(ndr, r->cffiles, 0);
|
||||
for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (size_cffiles_0); cntr_cffiles_0++) {
|
||||
NDR_CHECK(ndr_pull_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
|
||||
}
|
||||
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffiles_0, 0);
|
||||
#if 0
|
||||
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->cfdata_count));
|
||||
#else
|
||||
r->cfdata_count = ndr_count_cfdata(r);
|
||||
#endif
|
||||
size_cfdata_0 = r->cfdata_count;
|
||||
NDR_PULL_ALLOC_N(ndr, r->cfdata, size_cfdata_0);
|
||||
_mem_save_cfdata_0 = NDR_PULL_GET_MEM_CTX(ndr);
|
||||
NDR_PULL_SET_MEM_CTX(ndr, r->cfdata, 0);
|
||||
for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (size_cfdata_0); cntr_cfdata_0++) {
|
||||
NDR_CHECK(ndr_pull_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
|
||||
}
|
||||
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cfdata_0, 0);
|
||||
NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
|
||||
}
|
||||
if (ndr_flags & NDR_BUFFERS) {
|
||||
}
|
||||
ndr->flags = _flags_save_STRUCT;
|
||||
}
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
22
librpc/ndr/ndr_cab.h
Normal file
22
librpc/ndr/ndr_cab.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
routines for marshalling/unmarshalling cab structures
|
||||
|
||||
Copyright (C) Guenther Deschner 2016
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
uint32_t ndr_count_cfdata(const struct cab_file *r);
|
@ -423,6 +423,13 @@ bld.SAMBA_SUBSYSTEM('NDR_PREG',
|
||||
public_deps='ndr'
|
||||
)
|
||||
|
||||
bld.SAMBA_SUBSYSTEM('NDR_CAB',
|
||||
source='''
|
||||
gen_ndr/ndr_cab.c
|
||||
ndr/ndr_cab.c
|
||||
''',
|
||||
public_deps='ndr')
|
||||
|
||||
bld.SAMBA_SUBSYSTEM('NDR_FILE_ID',
|
||||
source='gen_ndr/ndr_file_id.c',
|
||||
public_deps='ndr'
|
||||
|
@ -69,18 +69,66 @@ bld.SAMBA_PIDL_TABLES('GEN_NDR_TABLES', 'gen_ndr/tables.c')
|
||||
|
||||
bld.SAMBA_SUBSYSTEM('ndr-table',
|
||||
source='../../librpc/ndr/ndr_table.c gen_ndr/tables.c',
|
||||
public_deps='''ndr-standard NDR_AUDIOSRV NDR_DSBACKUP NDR_EFS
|
||||
NDR_DRSUAPI NDR_POLICYAGENT NDR_UNIXINFO NDR_SPOOLSS NDR_EPMAPPER
|
||||
NDR_DBGIDL NDR_DSSETUP NDR_MSGSVC NDR_WINSIF NDR_MGMT
|
||||
NDR_OXIDRESOLVER NDR_REMACT NDR_WZCSVC
|
||||
NDR_BROWSER NDR_W32TIME NDR_SCERPC NDR_TRKWKS NDR_KEYSVC ndr-krb5pac
|
||||
NDR_XATTR NDR_SCHANNEL NDR_ROT NDR_DRSBLOBS ndr_nbt NDR_WINSREPL
|
||||
NDR_SECURITY NDR_DNSSERVER NDR_WINSTATION NDR_IRPC NDR_OPENDB
|
||||
NDR_SASL_HELPERS NDR_NOTIFY NDR_WINBIND NDR_FRSRPC NDR_FRSAPI
|
||||
NDR_FRSTRANS NDR_NFS4ACL NDR_NTP_SIGND NDR_DCOM NDR_WMI
|
||||
NDR_NAMED_PIPE_AUTH NDR_NTLMSSP NDR_DFSBLOBS NDR_DNSP
|
||||
NDR_NTPRINTING NDR_DNS NDR_BACKUPKEY NDR_PREG NDR_BKUPBLOBS NDR_FSCC
|
||||
NDR_FRSBLOBS NDR_CLUSAPI NDR_WINSPOOL''',
|
||||
public_deps='''
|
||||
ndr-standard
|
||||
NDR_AUDIOSRV
|
||||
NDR_DSBACKUP
|
||||
NDR_EFS
|
||||
NDR_DRSUAPI
|
||||
NDR_POLICYAGENT
|
||||
NDR_UNIXINFO
|
||||
NDR_SPOOLSS
|
||||
NDR_EPMAPPER
|
||||
NDR_DBGIDL
|
||||
NDR_DSSETUP
|
||||
NDR_MSGSVC
|
||||
NDR_WINSIF
|
||||
NDR_MGMT
|
||||
NDR_OXIDRESOLVER
|
||||
NDR_REMACT
|
||||
NDR_WZCSVC
|
||||
NDR_BROWSER
|
||||
NDR_W32TIME
|
||||
NDR_SCERPC
|
||||
NDR_TRKWKS
|
||||
NDR_KEYSVC
|
||||
ndr-krb5pac
|
||||
NDR_XATTR
|
||||
NDR_SCHANNEL
|
||||
NDR_ROT
|
||||
NDR_DRSBLOBS
|
||||
ndr_nbt
|
||||
NDR_WINSREPL
|
||||
NDR_SECURITY
|
||||
NDR_DNSSERVER
|
||||
NDR_WINSTATION
|
||||
NDR_IRPC
|
||||
NDR_OPENDB
|
||||
NDR_SASL_HELPERS
|
||||
NDR_NOTIFY
|
||||
NDR_WINBIND
|
||||
NDR_FRSRPC
|
||||
NDR_FRSAPI
|
||||
NDR_FRSTRANS
|
||||
NDR_NFS4ACL
|
||||
NDR_NTP_SIGND
|
||||
NDR_DCOM
|
||||
NDR_WMI
|
||||
NDR_NAMED_PIPE_AUTH
|
||||
NDR_NTLMSSP
|
||||
NDR_DFSBLOBS
|
||||
NDR_DNSP
|
||||
NDR_NTPRINTING
|
||||
NDR_DNS
|
||||
NDR_BACKUPKEY
|
||||
NDR_PREG
|
||||
NDR_BKUPBLOBS
|
||||
NDR_FSCC
|
||||
NDR_FRSBLOBS
|
||||
NDR_CLUSAPI
|
||||
NDR_WINSPOOL
|
||||
NDR_CAB
|
||||
''',
|
||||
depends_on='GEN_NDR_TABLES'
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user