forked from KolibriOS/kolibrios
WebView: autodetect encoding, fix crash on "dd" tag overflow, write ipfame link
git-svn-id: svn://kolibrios.org@7762 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
41f0cf93f5
commit
1ae3511fb7
@ -36,15 +36,16 @@ struct TWebBrowser {
|
|||||||
dword bufpointer;
|
dword bufpointer;
|
||||||
dword bufsize;
|
dword bufsize;
|
||||||
|
|
||||||
|
void DrawStyle();
|
||||||
void SetPageDefaults();
|
void SetPageDefaults();
|
||||||
void AddCharToTheLine();
|
void AddCharToTheLine();
|
||||||
void ParseHtml();
|
void ParseHtml();
|
||||||
void SetStyle();
|
void SetStyle();
|
||||||
void DrawStyle();
|
|
||||||
void DrawPage();
|
|
||||||
void DrawScroller();
|
|
||||||
void NewLine();
|
|
||||||
bool CheckForLineBreak();
|
bool CheckForLineBreak();
|
||||||
|
void NewLine();
|
||||||
|
void DrawScroller();
|
||||||
|
void ChangeEncoding();
|
||||||
|
void DrawPage();
|
||||||
char line[500];
|
char line[500];
|
||||||
char header[150];
|
char header[150];
|
||||||
};
|
};
|
||||||
@ -55,6 +56,7 @@ scroll_bar scroll_wv = { 15,NULL,NULL,NULL,0,2,NULL,0,0,0xeeeeee,0xBBBbbb,0xeeee
|
|||||||
void TWebBrowser::DrawStyle()
|
void TWebBrowser::DrawStyle()
|
||||||
{
|
{
|
||||||
dword start_x, line_length, stolbec_len;
|
dword start_x, line_length, stolbec_len;
|
||||||
|
dword text_color__;
|
||||||
|
|
||||||
if (style.tag_title)
|
if (style.tag_title)
|
||||||
{
|
{
|
||||||
@ -91,10 +93,14 @@ void TWebBrowser::DrawStyle()
|
|||||||
DrawBuf.DrawBar(start_x, draw_y + list.item_h - calc(zoom*2), line_length, zoom, 0x999999);
|
DrawBuf.DrawBar(start_x, draw_y + list.item_h - calc(zoom*2), line_length, zoom, 0x999999);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawBuf.WriteText(start_x, draw_y, list.font_type, text_colors[text_color_index], #line);
|
text_color__ = text_colors[text_color_index];
|
||||||
if (style.b) DrawBuf.WriteText(start_x+1, draw_y, list.font_type, text_colors[text_color_index], #line);
|
if (link) && (text_colors[text_color_index]==text_colors[0]) text_color__ = link_color_default;
|
||||||
if (style.s) DrawBuf.DrawBar(start_x, list.item_h / 2 - zoom + draw_y, line_length, zoom, text_colors[text_color_index]);
|
|
||||||
if (style.u) DrawBuf.DrawBar(start_x, list.item_h - zoom - zoom + draw_y, line_length, zoom, text_colors[text_color_index]);
|
|
||||||
|
DrawBuf.WriteText(start_x, draw_y, list.font_type, text_color__, #line);
|
||||||
|
if (style.b) DrawBuf.WriteText(start_x+1, draw_y, list.font_type, text_color__, #line);
|
||||||
|
if (style.s) DrawBuf.DrawBar(start_x, list.item_h / 2 - zoom + draw_y, line_length, zoom, text_color__);
|
||||||
|
if (style.u) DrawBuf.DrawBar(start_x, list.item_h - zoom - zoom + draw_y, line_length, zoom, text_color__);
|
||||||
if (link) {
|
if (link) {
|
||||||
if (line[0]==' ') && (line[1]==NULL) {} else {
|
if (line[0]==' ') && (line[1]==NULL) {} else {
|
||||||
DrawBuf.DrawBar(start_x, draw_y + list.item_h - calc(zoom*2)-1, line_length, zoom, link_color_default);
|
DrawBuf.DrawBar(start_x, draw_y + list.item_h - calc(zoom*2)-1, line_length, zoom, link_color_default);
|
||||||
@ -222,7 +228,7 @@ void TWebBrowser::ParseHtml(dword _bufpointer, _bufsize){
|
|||||||
while (ESBYTE[bufpos] !='>') && (bufpos < bufpointer + bufsize) //ïîëó÷àåì òåã è åãî ïàðàìåòðû
|
while (ESBYTE[bufpos] !='>') && (bufpos < bufpointer + bufsize) //ïîëó÷àåì òåã è åãî ïàðàìåòðû
|
||||||
{
|
{
|
||||||
bukva = ESBYTE[bufpos];
|
bukva = ESBYTE[bufpos];
|
||||||
if (bukva == '\9') || (bukva == '\x0a') || (bukva == '\x0d') bukva = ' ';
|
if (bukva == '\x9') || (bukva == '\x0a') || (bukva == '\x0d') bukva = ' ';
|
||||||
if (!ignor_param) && (bukva <>' ')
|
if (!ignor_param) && (bukva <>' ')
|
||||||
{
|
{
|
||||||
if (strlen(#tag.name)+1<sizeof(tag.name)) chrcat(#tag.name, bukva);
|
if (strlen(#tag.name)+1<sizeof(tag.name)) chrcat(#tag.name, bukva);
|
||||||
@ -294,13 +300,12 @@ bool TWebBrowser::CheckForLineBreak()
|
|||||||
|
|
||||||
strcpy(#line, #new_line_text);
|
strcpy(#line, #new_line_text);
|
||||||
NewLine();
|
NewLine();
|
||||||
//if (strlen(#line)*zoom + stolbec > list.column_max)CheckForLineBreak();
|
//while (CheckForLineBreak()==true) {};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//============================================================================================
|
//============================================================================================
|
||||||
void TWebBrowser::SetStyle() {
|
void TWebBrowser::SetStyle() {
|
||||||
char img_path[4096]=0;
|
char img_path[4096]=0;
|
||||||
int meta_encoding;
|
|
||||||
|
|
||||||
dword value;
|
dword value;
|
||||||
|
|
||||||
@ -315,16 +320,6 @@ void TWebBrowser::SetStyle() {
|
|||||||
t_html = tag.opened;
|
t_html = tag.opened;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tag.is("q"))
|
|
||||||
{
|
|
||||||
if (tag.opened) {
|
|
||||||
meta_encoding = strlen(#line);
|
|
||||||
if (line[meta_encoding-1] != ' ') chrcat(#line, ' ');
|
|
||||||
chrcat(#line, '\"');
|
|
||||||
}
|
|
||||||
if (!tag.opened) strcat(#line, "\" ");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tag.is("title")) {
|
if (tag.is("title")) {
|
||||||
style.tag_title = tag.opened;
|
style.tag_title = tag.opened;
|
||||||
if (!tag.opened) DrawTitle(#header);
|
if (!tag.opened) DrawTitle(#header);
|
||||||
@ -339,26 +334,40 @@ void TWebBrowser::SetStyle() {
|
|||||||
style.bg_color = page_bg = GetColor(value);
|
style.bg_color = page_bg = GetColor(value);
|
||||||
DrawBuf.Fill(0, page_bg);
|
DrawBuf.Fill(0, page_bg);
|
||||||
}
|
}
|
||||||
|
// Autodetecting encoding if no encoding was set
|
||||||
|
if (tag.opened) && (custom_encoding==-1) && (cur_encoding == CH_CP866) {
|
||||||
|
if (strstr(bufpointer, "\208\190")) ChangeEncoding(CH_UTF8);
|
||||||
|
else if (chrnum(bufpointer, '\x246')>5) ChangeEncoding(CH_CP1251);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (tag.is("br")) { NewLine(); return; }
|
||||||
|
if (tag.is("b")) || (tag.is("strong")) || (tag.is("big")) { style.b = tag.opened; return; }
|
||||||
if (tag.is("a")) {
|
if (tag.is("a")) {
|
||||||
if (tag.opened)
|
if (tag.opened)
|
||||||
{
|
{
|
||||||
if (link) IF(text_color_index > 0) text_color_index--; //åñëè ïðåäûäóùèé òåã à íå áûë çàêðûò
|
|
||||||
if (value = tag.get_value_of("href=")) && (!strstr(value,"javascript:"))
|
if (value = tag.get_value_of("href=")) && (!strstr(value,"javascript:"))
|
||||||
{
|
{
|
||||||
text_color_index++;
|
link = true;
|
||||||
text_colors[text_color_index] = text_colors[text_color_index-1];
|
|
||||||
link = 1;
|
|
||||||
text_colors[text_color_index] = link_color_default;
|
|
||||||
PageLinks.AddLink(value);
|
PageLinks.AddLink(value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
link = 0;
|
link = false;
|
||||||
IF(text_color_index > 0) text_color_index--;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (tag.is("iframe")) && (value = tag.get_value_of("src=")) {
|
||||||
|
NewLine();
|
||||||
|
strcpy(#line, "IFRAME: ");
|
||||||
|
DrawStyle();
|
||||||
|
link=true;
|
||||||
|
PageLinks.AddLink(value);
|
||||||
|
strncpy(#line, value, sizeof(TWebBrowser.line)-1);
|
||||||
|
while (CheckForLineBreak()) {};
|
||||||
|
DrawStyle();
|
||||||
|
link=false;
|
||||||
|
NewLine();
|
||||||
|
}
|
||||||
if (tag.is("font")) {
|
if (tag.is("font")) {
|
||||||
style.bg_color = page_bg;
|
style.bg_color = page_bg;
|
||||||
if (tag.opened)
|
if (tag.opened)
|
||||||
@ -385,16 +394,14 @@ void TWebBrowser::SetStyle() {
|
|||||||
NewLine();
|
NewLine();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tag.is("br")) { NewLine(); return; }
|
if (tag.is("pre")) { style.pre = tag.opened; return; }
|
||||||
if (tag.is("td")) { if (tag.opened) AddCharToTheLine(' '); return; }
|
if (tag.is("td")) { if (tag.opened) AddCharToTheLine(' '); return; }
|
||||||
if (tag.is("tr")) { if (tag.opened) NewLine(); return; }
|
if (tag.is("tr")) { if (tag.opened) NewLine(); return; }
|
||||||
if (tag.is("b")) || (tag.is("strong")) || (tag.is("big")) { style.b = tag.opened; return; }
|
|
||||||
if (tag.is("button")) { style.button = tag.opened; stolbec++; return; }
|
if (tag.is("button")) { style.button = tag.opened; stolbec++; return; }
|
||||||
if (tag.is("u")) || (tag.is("ins")) { style.u=tag.opened; return;}
|
if (tag.is("u")) || (tag.is("ins")) { style.u=tag.opened; return;}
|
||||||
if (tag.is("s")) || (tag.is("strike")) || (tag.is("del")) { style.s=tag.opened; return; }
|
if (tag.is("s")) || (tag.is("strike")) || (tag.is("del")) { style.s=tag.opened; return; }
|
||||||
if (tag.is("dd")) { stolbec += 5; return; }
|
//if (tag.is("dd")) { stolbec += 5; return; } //stolbec overflow!
|
||||||
if (tag.is("blockquote")) { style.blq = tag.opened; return; }
|
if (tag.is("blockquote")) { style.blq = tag.opened; return; }
|
||||||
if (tag.is("pre")) { style.pre = tag.opened; return; }
|
|
||||||
if (tag.is("code")) {
|
if (tag.is("code")) {
|
||||||
if (tag.opened) style.bg_color = 0xe4ffcb; else style.bg_color = page_bg;
|
if (tag.opened) style.bg_color = 0xe4ffcb; else style.bg_color = page_bg;
|
||||||
style.pre = tag.opened; return;
|
style.pre = tag.opened; return;
|
||||||
@ -473,6 +480,16 @@ void TWebBrowser::SetStyle() {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (tag.is("q"))
|
||||||
|
{
|
||||||
|
if (tag.opened) {
|
||||||
|
EAX = strlen(#line);
|
||||||
|
if (line[EAX-1] != ' ') chrcat(#line, ' ');
|
||||||
|
chrcat(#line, '\"');
|
||||||
|
}
|
||||||
|
if (!tag.opened) strcat(#line, "\" ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (tag.is("hr")) {
|
if (tag.is("hr")) {
|
||||||
if (value = tag.get_value_of("color=")) EDI = GetColor(value); else EDI = 0x999999;
|
if (value = tag.get_value_of("color=")) EDI = GetColor(value); else EDI = 0x999999;
|
||||||
$push edi;
|
$push edi;
|
||||||
@ -485,24 +502,15 @@ void TWebBrowser::SetStyle() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (custom_encoding == -1) && (tag.is("meta")) || (tag.is("?xml")) {
|
if (custom_encoding == -1) && (tag.is("meta")) || (tag.is("?xml")) {
|
||||||
meta_encoding = CH_CP866;
|
|
||||||
if (value = tag.get_value_of("charset=")) || (value = tag.get_value_of("content=")) || (value = tag.get_value_of("encoding="))
|
if (value = tag.get_value_of("charset=")) || (value = tag.get_value_of("content=")) || (value = tag.get_value_of("encoding="))
|
||||||
{
|
{
|
||||||
value += strrchr(value, '='); //search in content=
|
value += strrchr(value, '='); //search in content=
|
||||||
strlwr(value);
|
strlwr(value);
|
||||||
if (streq(value,"utf-8")) || (streq(value,"utf8")) meta_encoding = CH_UTF8;
|
if (streq(value,"utf-8")) || (streq(value,"utf8")) ChangeEncoding(CH_UTF8);
|
||||||
else if (streq(value,"windows-1251")) || (streq(value,"windows1251")) meta_encoding = CH_CP1251;
|
else if (streq(value,"windows-1251")) || (streq(value,"windows1251")) ChangeEncoding(CH_CP1251);
|
||||||
else if (streq(value,"dos")) || (streq(value,"cp-866")) meta_encoding = CH_CP866;
|
else if (streq(value,"dos")) || (streq(value,"cp-866")) ChangeEncoding(CH_CP866);
|
||||||
else if (streq(value,"iso-8859-5")) || (streq(value,"iso8859-5")) meta_encoding = CH_ISO8859_5;
|
else if (streq(value,"iso-8859-5")) || (streq(value,"iso8859-5")) ChangeEncoding(CH_ISO8859_5);
|
||||||
else if (streq(value,"koi8-r")) || (streq(value,"koi8-u")) meta_encoding = CH_KOI8;
|
else if (streq(value,"koi8-r")) || (streq(value,"koi8-u")) ChangeEncoding(CH_KOI8);
|
||||||
}
|
|
||||||
if (meta_encoding != CH_CP866) && (cur_encoding != meta_encoding) {
|
|
||||||
cur_encoding = meta_encoding;
|
|
||||||
bufpointer = ChangeCharset(cur_encoding*10+#charsets, "CP866", bufpointer);
|
|
||||||
if (header) {
|
|
||||||
ChangeCharset(cur_encoding*10+#charsets, "CP866", #header);
|
|
||||||
DrawTitle(#header);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -520,6 +528,17 @@ void TWebBrowser::DrawScroller()
|
|||||||
scrollbar_v_draw(#scroll_wv);
|
scrollbar_v_draw(#scroll_wv);
|
||||||
}
|
}
|
||||||
//============================================================================================
|
//============================================================================================
|
||||||
|
void TWebBrowser::ChangeEncoding(int _new_encoding)
|
||||||
|
{
|
||||||
|
if (cur_encoding == _new_encoding) return;
|
||||||
|
cur_encoding = _new_encoding;
|
||||||
|
bufpointer = ChangeCharset(cur_encoding*10+#charsets, "CP866", bufpointer);
|
||||||
|
if (header) {
|
||||||
|
ChangeCharset(cur_encoding*10+#charsets, "CP866", #header);
|
||||||
|
DrawTitle(#header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//============================================================================================
|
||||||
void TWebBrowser::NewLine()
|
void TWebBrowser::NewLine()
|
||||||
{
|
{
|
||||||
dword onleft, ontop;
|
dword onleft, ontop;
|
||||||
|
@ -35,53 +35,12 @@ _history history;
|
|||||||
#include "history.h"
|
#include "history.h"
|
||||||
bool debug_mode = false;
|
bool debug_mode = false;
|
||||||
#include "..\TWB\TWB.c" //HTML Parser, a core component
|
#include "..\TWB\TWB.c" //HTML Parser, a core component
|
||||||
|
#include "texts.h"
|
||||||
|
|
||||||
TWebBrowser WB1;
|
TWebBrowser WB1;
|
||||||
|
|
||||||
char version[]="WebView 2.1";
|
|
||||||
|
|
||||||
#ifdef LANG_RUS
|
|
||||||
char page_not_found[] = FROM "html\\page_not_found_ru.htm""\0";
|
|
||||||
char homepage[] = FROM "html\\homepage_ru.htm""\0";
|
|
||||||
char help[] = FROM "html\\help_ru.htm""\0";
|
|
||||||
char accept_language[]= "Accept-Language: ru\n";
|
|
||||||
char rmb_menu[] =
|
|
||||||
"<EFBFBD>®á¬®âà¥âì ¨á室¨ª
|
|
||||||
<EFBFBD>¥¤ ªâ¨à®¢ âì ¨á室¨ª";
|
|
||||||
char main_menu[] =
|
|
||||||
"Žâªàëâì ä ©«
|
|
||||||
<EFBFBD>®¢®¥ ®ª®
|
|
||||||
ˆáâ®à¨ï
|
|
||||||
Œ¥¥¤¦¥à § £à㧮ª";
|
|
||||||
char link_menu[] =
|
|
||||||
"Š®¯¨à®¢ âì áá뫪ã
|
|
||||||
‘ª ç âì ᮤ¥à¦¨¬®¥ áá뫪¨";
|
|
||||||
char loading_text[] = "‡ £à㧪 ...";
|
|
||||||
#else
|
|
||||||
char page_not_found[] = FROM "html\\page_not_found_en.htm""\0";
|
|
||||||
char homepage[] = FROM "html\\homepage_en.htm""\0";
|
|
||||||
char help[] = FROM "html\\help_en.htm""\0";
|
|
||||||
char accept_language[]= "Accept-Language: en\n";
|
|
||||||
char rmb_menu[] =
|
|
||||||
"View source
|
|
||||||
Edit source";
|
|
||||||
char main_menu[] =
|
|
||||||
"Open local file
|
|
||||||
New window
|
|
||||||
History
|
|
||||||
Download Manager";
|
|
||||||
char link_menu[] =
|
|
||||||
"Copy link
|
|
||||||
Download link contents";
|
|
||||||
char loading_text[] = "Loading...";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define URL_SIZE 4000
|
#define URL_SIZE 4000
|
||||||
|
|
||||||
#define URL_SERVICE_HISTORY "WebView:history"
|
|
||||||
#define URL_SERVICE_HOMEPAGE "WebView:home"
|
|
||||||
#define URL_SERVICE_HELP "WebView:help"
|
|
||||||
|
|
||||||
#define PADDING 9
|
#define PADDING 9
|
||||||
#define SKIN_Y 24
|
#define SKIN_Y 24
|
||||||
#define TSZE 25
|
#define TSZE 25
|
||||||
@ -157,7 +116,8 @@ void main()
|
|||||||
{
|
{
|
||||||
int i, btn, redirect_count=0;
|
int i, btn, redirect_count=0;
|
||||||
LoadLibraries();
|
LoadLibraries();
|
||||||
CreateDir("/tmp0/1/downloads");
|
CreateDir("/tmp0/1/Downloads");
|
||||||
|
CreateDir("/tmp0/1/WebView_Cache");
|
||||||
Libimg_LoadImage(#skin, "/sys/toolbar.png");
|
Libimg_LoadImage(#skin, "/sys/toolbar.png");
|
||||||
HandleParam();
|
HandleParam();
|
||||||
skin.h = 26;
|
skin.h = 26;
|
||||||
@ -490,7 +450,10 @@ void OpenPage(dword _open_URL)
|
|||||||
|
|
||||||
history.add(#new_url);
|
history.add(#new_url);
|
||||||
|
|
||||||
if (!strncmp(#new_url,"WebView:",8)) {
|
if (pages_cache.have(#new_url)) {
|
||||||
|
LoadInternalPage(pages_cache.current_page_buf, pages_cache.pages_cache.current_page_size);
|
||||||
|
}
|
||||||
|
else if (!strncmp(#new_url,"WebView:",8)) {
|
||||||
//INTERNAL PAGE
|
//INTERNAL PAGE
|
||||||
if (!strcmp(#new_url, URL_SERVICE_HOMEPAGE)) LoadInternalPage(#homepage, sizeof(homepage));
|
if (!strcmp(#new_url, URL_SERVICE_HOMEPAGE)) LoadInternalPage(#homepage, sizeof(homepage));
|
||||||
else if (!strcmp(#new_url, URL_SERVICE_HELP)) LoadInternalPage(#help, sizeof(help));
|
else if (!strcmp(#new_url, URL_SERVICE_HELP)) LoadInternalPage(#help, sizeof(help));
|
||||||
|
42
programs/cmm/browser/texts.h
Normal file
42
programs/cmm/browser/texts.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
char version[]="WebView 2.15";
|
||||||
|
|
||||||
|
#ifdef LANG_RUS
|
||||||
|
char page_not_found[] = FROM "html\\page_not_found_ru.htm""\0";
|
||||||
|
char homepage[] = FROM "html\\homepage_ru.htm""\0";
|
||||||
|
char help[] = FROM "html\\help_ru.htm""\0";
|
||||||
|
char accept_language[]= "Accept-Language: ru\n";
|
||||||
|
char rmb_menu[] =
|
||||||
|
"<EFBFBD>®á¬®âà¥âì ¨á室¨ª
|
||||||
|
<EFBFBD>¥¤ ªâ¨à®¢ âì ¨á室¨ª";
|
||||||
|
char main_menu[] =
|
||||||
|
"Žâªàëâì ä ©«
|
||||||
|
<EFBFBD>®¢®¥ ®ª®
|
||||||
|
ˆáâ®à¨ï
|
||||||
|
Œ¥¥¤¦¥à § £à㧮ª";
|
||||||
|
char link_menu[] =
|
||||||
|
"Š®¯¨à®¢ âì áá뫪ã
|
||||||
|
‘ª ç âì ᮤ¥à¦¨¬®¥ áá뫪¨";
|
||||||
|
char loading_text[] = "‡ £à㧪 ...";
|
||||||
|
#else
|
||||||
|
char page_not_found[] = FROM "html\\page_not_found_en.htm""\0";
|
||||||
|
char homepage[] = FROM "html\\homepage_en.htm""\0";
|
||||||
|
char help[] = FROM "html\\help_en.htm""\0";
|
||||||
|
char accept_language[]= "Accept-Language: en\n";
|
||||||
|
char rmb_menu[] =
|
||||||
|
"View source
|
||||||
|
Edit source";
|
||||||
|
char main_menu[] =
|
||||||
|
"Open local file
|
||||||
|
New window
|
||||||
|
History
|
||||||
|
Download Manager";
|
||||||
|
char link_menu[] =
|
||||||
|
"Copy link
|
||||||
|
Download link contents";
|
||||||
|
char loading_text[] = "Loading...";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define URL_SERVICE_HISTORY "WebView:history"
|
||||||
|
#define URL_SERVICE_HOMEPAGE "WebView:home"
|
||||||
|
#define URL_SERVICE_HELP "WebView:help"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user