Initialize cdtext to NULL and other add some initializations that should
have been done.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: bincue.c,v 1.31 2004/07/10 11:06:00 rocky Exp $
|
$Id: bincue.c,v 1.32 2004/07/11 02:28:06 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
(*.cue).
|
(*.cue).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char _rcsid[] = "$Id: bincue.c,v 1.31 2004/07/10 11:06:00 rocky Exp $";
|
static const char _rcsid[] = "$Id: bincue.c,v 1.32 2004/07/11 02:28:06 rocky Exp $";
|
||||||
|
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "cdio_assert.h"
|
#include "cdio_assert.h"
|
||||||
@@ -87,9 +87,6 @@ typedef struct {
|
|||||||
track_format_t mode;
|
track_format_t mode;
|
||||||
} _img_private_t;
|
} _img_private_t;
|
||||||
|
|
||||||
#if 0
|
|
||||||
static bool _bincue_image_read_cue (_img_private_t *env);
|
|
||||||
#endif
|
|
||||||
static uint32_t _stat_size_bincue (void *user_data);
|
static uint32_t _stat_size_bincue (void *user_data);
|
||||||
static bool parse_cuefile (_img_private_t *cd, const char *toc_name);
|
static bool parse_cuefile (_img_private_t *cd, const char *toc_name);
|
||||||
|
|
||||||
@@ -117,6 +114,7 @@ _bincue_init (_img_private_t *env)
|
|||||||
env->gen.init = true;
|
env->gen.init = true;
|
||||||
env->i_first_track = 1;
|
env->i_first_track = 1;
|
||||||
env->psz_mcn = NULL;
|
env->psz_mcn = NULL;
|
||||||
|
env->cdtext = NULL;
|
||||||
|
|
||||||
lead_lsn = _stat_size_bincue( (_img_private_t *) env);
|
lead_lsn = _stat_size_bincue( (_img_private_t *) env);
|
||||||
|
|
||||||
@@ -125,11 +123,7 @@ _bincue_init (_img_private_t *env)
|
|||||||
if ((env->psz_cue_name == NULL)) return false;
|
if ((env->psz_cue_name == NULL)) return false;
|
||||||
|
|
||||||
/* Read in CUE sheet. */
|
/* Read in CUE sheet. */
|
||||||
#if 0
|
|
||||||
if ( !_bincue_image_read_cue(env) ) return false;
|
|
||||||
#else
|
|
||||||
if ( !parse_cuefile(env, env->psz_cue_name) ) return false;
|
if ( !parse_cuefile(env, env->psz_cue_name) ) return false;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fake out leadout track and sector count for last track*/
|
/* Fake out leadout track and sector count for last track*/
|
||||||
cdio_lsn_to_msf (lead_lsn, &env->tocent[env->i_tracks].start_msf);
|
cdio_lsn_to_msf (lead_lsn, &env->tocent[env->i_tracks].start_msf);
|
||||||
@@ -660,167 +654,6 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static bool
|
|
||||||
_bincue_image_read_cue (_img_private_t *env)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char line[MAXLINE];
|
|
||||||
|
|
||||||
int i_track;
|
|
||||||
int min,sec,frame;
|
|
||||||
int blocksize;
|
|
||||||
int start_index;
|
|
||||||
bool b_first_index_for_track=false;
|
|
||||||
|
|
||||||
if ( env == NULL || env->psz_cue_name == NULL ) return false;
|
|
||||||
|
|
||||||
fp = fopen (env->psz_cue_name, "r");
|
|
||||||
if (fp == NULL) return false;
|
|
||||||
|
|
||||||
env->i_tracks=0;
|
|
||||||
env->i_first_track=1;
|
|
||||||
env->psz_mcn=NULL;
|
|
||||||
|
|
||||||
while ((fgets(line, MAXLINE, fp)) != NULL) {
|
|
||||||
char s[80];
|
|
||||||
char *p;
|
|
||||||
/*printf("Retrieved line of length %zu :\n", read);
|
|
||||||
printf("%s", line); */
|
|
||||||
for (p=line; isspace(*p); p++) ;
|
|
||||||
if (1==sscanf(p, "FILE \"%80s[^\"]", s)) {
|
|
||||||
/* Should expand file name based on cue file basename.
|
|
||||||
free(env->bin_file);
|
|
||||||
env->bin_file = strdup(s);
|
|
||||||
*/
|
|
||||||
/* printf("Found file name %s\n", s); */
|
|
||||||
} else if (1==sscanf(p, "CATALOG %80s", s)) {
|
|
||||||
env->psz_mcn = strdup(s);
|
|
||||||
} else if (2==sscanf(p, "TRACK %d MODE2/%d", &i_track, &blocksize)) {
|
|
||||||
track_info_t *this_track=&(env->tocent[env->i_tracks]);
|
|
||||||
this_track->track_num = i_track;
|
|
||||||
this_track->num_indices = 0;
|
|
||||||
this_track->track_format= TRACK_FORMAT_XA;
|
|
||||||
this_track->track_green = true;
|
|
||||||
b_first_index_for_track = false;
|
|
||||||
env->i_tracks++;
|
|
||||||
/*printf("Added track %d with blocksize %d\n", i_track, blocksize);*/
|
|
||||||
|
|
||||||
this_track->blocksize = blocksize;
|
|
||||||
switch(blocksize) {
|
|
||||||
case 2336:
|
|
||||||
this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;
|
|
||||||
this_track->datasize = M2RAW_SECTOR_SIZE;
|
|
||||||
this_track->endsize = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cdio_warn ("Unknown MODE2 size %d. Assuming 2352", blocksize);
|
|
||||||
case 2352:
|
|
||||||
this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE +
|
|
||||||
CDIO_CD_SUBHEADER_SIZE;
|
|
||||||
this_track->datasize = CDIO_CD_FRAMESIZE;
|
|
||||||
this_track->endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (2==sscanf(p, "TRACK %d MODE1/%d", &i_track, &blocksize)) {
|
|
||||||
track_info_t *this_track=&(env->tocent[env->i_tracks]);
|
|
||||||
this_track->blocksize = blocksize;
|
|
||||||
switch(blocksize) {
|
|
||||||
case 2048:
|
|
||||||
/* Is the below correct? */
|
|
||||||
this_track->datastart = 0;
|
|
||||||
this_track->datasize = CDIO_CD_FRAMESIZE;
|
|
||||||
this_track->endsize = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cdio_warn ("Unknown MODE1 size %d. Assuming 2352", blocksize);
|
|
||||||
case 2352:
|
|
||||||
this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;
|
|
||||||
this_track->datasize = CDIO_CD_FRAMESIZE;
|
|
||||||
this_track->endsize = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE
|
|
||||||
+ CDIO_CD_ECC_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
this_track->track_num = i_track;
|
|
||||||
this_track->num_indices = 0;
|
|
||||||
this_track->track_format = TRACK_FORMAT_DATA;
|
|
||||||
this_track->track_green = false;
|
|
||||||
b_first_index_for_track = false;
|
|
||||||
env->i_tracks++;
|
|
||||||
/*printf("Added track %d with blocksize %d\n", i_track, blocksize);*/
|
|
||||||
|
|
||||||
} else if (1==sscanf(p, "TRACK %d AUDIO", &i_track)) {
|
|
||||||
track_info_t *this_track=&(env->tocent[env->i_tracks]);
|
|
||||||
this_track->blocksize = CDIO_CD_FRAMESIZE_RAW;
|
|
||||||
this_track->datasize = CDIO_CD_FRAMESIZE_RAW;
|
|
||||||
this_track->datastart = 0;
|
|
||||||
this_track->endsize = 0;
|
|
||||||
this_track->track_num = i_track;
|
|
||||||
this_track->num_indices = 0;
|
|
||||||
this_track->track_format = TRACK_FORMAT_AUDIO;
|
|
||||||
this_track->track_green = false;
|
|
||||||
b_first_index_for_track = false;
|
|
||||||
env->i_tracks++;
|
|
||||||
|
|
||||||
} else if (4==sscanf(p, "INDEX %d %d:%d:%d",
|
|
||||||
&start_index, &min, &sec, &frame)) {
|
|
||||||
track_info_t *this_track=&(env->tocent[env->i_tracks - env->i_first_track]);
|
|
||||||
/* FIXME! all of this is a big hack.
|
|
||||||
If start_index == 0, then this is the "last_cue" information.
|
|
||||||
The +2 below seconds is to adjust for the 150 pregap.
|
|
||||||
*/
|
|
||||||
if (start_index != 0) {
|
|
||||||
if (!b_first_index_for_track) {
|
|
||||||
this_track->start_index = start_index;
|
|
||||||
sec += 2;
|
|
||||||
if (sec >= 60) {
|
|
||||||
min++;
|
|
||||||
sec -= 60;
|
|
||||||
}
|
|
||||||
this_track->start_msf.m = to_bcd8 (min);
|
|
||||||
this_track->start_msf.s = to_bcd8 (sec);
|
|
||||||
this_track->start_msf.f = to_bcd8 (frame);
|
|
||||||
b_first_index_for_track = true;
|
|
||||||
this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env->i_tracks > 1) {
|
|
||||||
/* Figure out number of sectors for previous track */
|
|
||||||
track_info_t *prev_track=&(env->tocent[env->i_tracks-2]);
|
|
||||||
if ( this_track->start_lba < prev_track->start_lba ) {
|
|
||||||
cdio_warn("track %d at LBA %lu starts before track %d at LBA %lu",
|
|
||||||
env->i_tracks,
|
|
||||||
(unsigned long int) this_track->start_lba,
|
|
||||||
env->i_tracks,
|
|
||||||
(unsigned long int) prev_track->start_lba);
|
|
||||||
prev_track->sec_count = 0;
|
|
||||||
} else if ( this_track->start_lba >= prev_track->start_lba
|
|
||||||
+ CDIO_PREGAP_SECTORS ) {
|
|
||||||
prev_track->sec_count = this_track->start_lba -
|
|
||||||
prev_track->start_lba - CDIO_PREGAP_SECTORS ;
|
|
||||||
} else {
|
|
||||||
cdio_warn ("%lu fewer than pregap (%d) sectors in track %d",
|
|
||||||
(long unsigned int)
|
|
||||||
this_track->start_lba - prev_track->start_lba,
|
|
||||||
CDIO_PREGAP_SECTORS,
|
|
||||||
env->i_tracks);
|
|
||||||
/* Include pregap portion in sec_count. Maybe the pregap
|
|
||||||
was omitted. */
|
|
||||||
prev_track->sec_count = this_track->start_lba -
|
|
||||||
prev_track->start_lba;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this_track->num_indices++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose (fp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Reads a single audio sector from CD device into data starting
|
Reads a single audio sector from CD device into data starting
|
||||||
from lsn. Returns 0 if no error.
|
from lsn. Returns 0 if no error.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: cdrdao.c,v 1.17 2004/07/10 11:06:00 rocky Exp $
|
$Id: cdrdao.c,v 1.18 2004/07/11 02:28:07 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||||
toc reading routine adapted from cuetools
|
toc reading routine adapted from cuetools
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
(*.cue).
|
(*.cue).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char _rcsid[] = "$Id: cdrdao.c,v 1.17 2004/07/10 11:06:00 rocky Exp $";
|
static const char _rcsid[] = "$Id: cdrdao.c,v 1.18 2004/07/11 02:28:07 rocky Exp $";
|
||||||
|
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "cdio_assert.h"
|
#include "cdio_assert.h"
|
||||||
@@ -109,6 +109,7 @@ _init_cdrdao (_img_private_t *env)
|
|||||||
env->gen.init = true;
|
env->gen.init = true;
|
||||||
env->i_first_track = 1;
|
env->i_first_track = 1;
|
||||||
env->psz_mcn = NULL;
|
env->psz_mcn = NULL;
|
||||||
|
env->cdtext = NULL;
|
||||||
|
|
||||||
/* Read in TOC sheet. */
|
/* Read in TOC sheet. */
|
||||||
if ( !parse_tocfile(env, env->psz_cue_name) ) return false;
|
if ( !parse_tocfile(env, env->psz_cue_name) ) return false;
|
||||||
@@ -264,7 +265,8 @@ _stat_size_cdrdao (void *user_data)
|
|||||||
static bool
|
static bool
|
||||||
parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
||||||
{
|
{
|
||||||
char line[MAXLINE];
|
char psz_line[MAXLINE];
|
||||||
|
unsigned int i_cdtext_nest = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
unsigned int i_line=0;
|
unsigned int i_line=0;
|
||||||
char *keyword, *psz_field;
|
char *keyword, *psz_field;
|
||||||
@@ -281,17 +283,17 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((fgets(line, MAXLINE, fp)) != NULL) {
|
while ((fgets(psz_line, MAXLINE, fp)) != NULL) {
|
||||||
|
|
||||||
i_line++;
|
i_line++;
|
||||||
|
|
||||||
/* strip comment from line */
|
/* strip comment from line */
|
||||||
/* todo: // in quoted strings? */
|
/* todo: // in quoted strings? */
|
||||||
/* //comment */
|
/* //comment */
|
||||||
if (NULL != (psz_field = strstr (line, "//")))
|
if (NULL != (psz_field = strstr (psz_line, "//")))
|
||||||
*psz_field = '\0';
|
*psz_field = '\0';
|
||||||
|
|
||||||
if (NULL != (keyword = strtok (line, " \t\n\r"))) {
|
if (NULL != (keyword = strtok (psz_line, " \t\n\r"))) {
|
||||||
/* CATALOG "ddddddddddddd" */
|
/* CATALOG "ddddddddddddd" */
|
||||||
if (0 == strcmp ("CATALOG", keyword)) {
|
if (0 == strcmp ("CATALOG", keyword)) {
|
||||||
if (-1 == i) {
|
if (-1 == i) {
|
||||||
@@ -360,7 +362,7 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
|||||||
/* TRACK <track-mode> [<sub-channel-mode>] */
|
/* TRACK <track-mode> [<sub-channel-mode>] */
|
||||||
} else if (0 == strcmp ("TRACK", keyword)) {
|
} else if (0 == strcmp ("TRACK", keyword)) {
|
||||||
i++;
|
i++;
|
||||||
/* cd->tocent[i].cdtext = NULL; */
|
if (NULL != cd) cd->tocent[i].cdtext = NULL;
|
||||||
if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
|
if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
|
||||||
if (0 == strcmp ("AUDIO", psz_field)) {
|
if (0 == strcmp ("AUDIO", psz_field)) {
|
||||||
if (NULL != cd) {
|
if (NULL != cd) {
|
||||||
@@ -513,7 +515,8 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
|||||||
cd->tocent[i].filename = strdup (psz_field);
|
cd->tocent[i].filename = strdup (psz_field);
|
||||||
/* Todo: do something about reusing existing files. */
|
/* Todo: do something about reusing existing files. */
|
||||||
if (!(cd->tocent[i].data_source = cdio_stdio_new (psz_field))) {
|
if (!(cd->tocent[i].data_source = cdio_stdio_new (psz_field))) {
|
||||||
cdio_warn ("%s line %d: can't open file `%s' for reading",
|
cdio_log (log_level,
|
||||||
|
"%s line %d: can't open file `%s' for reading",
|
||||||
psz_cue_name, i_line, psz_field);
|
psz_cue_name, i_line, psz_field);
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
@@ -616,32 +619,48 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
|||||||
/* CD_TEXT { ... } */
|
/* CD_TEXT { ... } */
|
||||||
/* todo: opening { must be on same line as CD_TEXT */
|
/* todo: opening { must be on same line as CD_TEXT */
|
||||||
} else if (0 == strcmp ("CD_TEXT", keyword)) {
|
} else if (0 == strcmp ("CD_TEXT", keyword)) {
|
||||||
|
if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) {
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
if ( 0 == strcmp( "{", psz_field ) ) {
|
||||||
|
i_cdtext_nest++;
|
||||||
|
} else {
|
||||||
|
cdio_log (log_level,
|
||||||
|
"%s line %d: expecting '{'", psz_cue_name, i_line);
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (0 == strcmp ("LANGUAGE_MAP", keyword)) {
|
} else if (0 == strcmp ("LANGUAGE_MAP", keyword)) {
|
||||||
} else if (0 == strcmp ("LANGUAGE", keyword)) {
|
} else if (0 == strcmp ("LANGUAGE", keyword)) {
|
||||||
|
if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) {
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
/* Language number */
|
||||||
|
if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) {
|
||||||
|
goto format_error;
|
||||||
|
}
|
||||||
|
if ( 0 == strcmp( "{", psz_field ) ) {
|
||||||
|
i_cdtext_nest++;
|
||||||
|
} else {
|
||||||
|
cdio_log (log_level,
|
||||||
|
"%s line %d: expecting '{'", psz_cue_name, i_line);
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
} else if (0 == strcmp ("}", keyword)) {
|
} else if (0 == strcmp ("}", keyword)) {
|
||||||
|
if (i_cdtext_nest > 0) i_cdtext_nest--;
|
||||||
} else if (0 == cdtext_is_keyword (keyword)) {
|
} else if (0 == cdtext_is_keyword (keyword)) {
|
||||||
if (-1 == i) {
|
if (-1 == i) {
|
||||||
if (NULL != cd) {
|
if (NULL != cd) {
|
||||||
#if 0
|
|
||||||
if (NULL == cd->cdtext)
|
if (NULL == cd->cdtext)
|
||||||
cd->cdtext = cdtext_init ();
|
cd->cdtext = cdtext_init ();
|
||||||
cdtext_set (keyword, strtok (NULL, "\"\t\n\r"), cd->cdtext);
|
cdtext_set (keyword, strtok (NULL, "\"\t\n\r"), cd->cdtext);
|
||||||
#else
|
|
||||||
;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (NULL != cd) {
|
if (NULL != cd) {
|
||||||
#if 0
|
|
||||||
if (NULL == cd->tocent[i].cdtext)
|
if (NULL == cd->tocent[i].cdtext)
|
||||||
cd->tocent[i].cdtext = cdtext_init ();
|
cd->tocent[i].cdtext = cdtext_init ();
|
||||||
cdtext_set (keyword, strtok (NULL, "\"\t\n\r"),
|
cdtext_set (keyword, strtok (NULL, "\"\t\n\r"),
|
||||||
cd->tocent[i].cdtext);
|
cd->tocent[i].cdtext);
|
||||||
#else
|
|
||||||
;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: nrg.c,v 1.29 2004/07/10 11:31:42 rocky Exp $
|
$Id: nrg.c,v 1.30 2004/07/11 02:28:07 rocky Exp $
|
||||||
|
|
||||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||||
Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>
|
Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
#include "_cdio_stdio.h"
|
#include "_cdio_stdio.h"
|
||||||
#include "nrg.h"
|
#include "nrg.h"
|
||||||
|
|
||||||
static const char _rcsid[] = "$Id: nrg.c,v 1.29 2004/07/10 11:31:42 rocky Exp $";
|
static const char _rcsid[] = "$Id: nrg.c,v 1.30 2004/07/11 02:28:07 rocky Exp $";
|
||||||
|
|
||||||
|
|
||||||
/* reader */
|
/* reader */
|
||||||
@@ -755,6 +755,9 @@ _init_nrg (_img_private_t *env)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->psz_mcn = NULL;
|
||||||
|
env->cdtext = NULL;
|
||||||
|
|
||||||
if ( !parse_nrg (env, env->gen.source_name) ) {
|
if ( !parse_nrg (env, env->gen.source_name) ) {
|
||||||
cdio_warn ("image file %s is not a Nero image",
|
cdio_warn ("image file %s is not a Nero image",
|
||||||
env->gen.source_name);
|
env->gen.source_name);
|
||||||
|
|||||||
Reference in New Issue
Block a user