From: "Denis V. Dmitrienko" <denis@null.net>
What it does: It solves stupid problem with cyrillic charsets IP-based on-fly recoding. take a look at /data/charset.conf for details. You can use any tables for any charset. Tables are from Russian Apache project. Tables in this patch contains also Ukrainian characters. Then run ./configure --enable-recode
This commit is contained in:
parent
96316211c3
commit
0227a4e114
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.27 1998/01/27 03:24:56 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.28 1998/02/24 15:18:41 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -846,6 +846,192 @@ authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
#define CHARSET_FILE "charset.conf"
|
||||||
|
#define MAX_CHARSETS 10
|
||||||
|
#define KEY_HOST 1
|
||||||
|
#define KEY_BASE 2
|
||||||
|
#define KEY_TABLE 3
|
||||||
|
|
||||||
|
struct CharsetItem
|
||||||
|
{
|
||||||
|
char Orig[MAX_TOKEN];
|
||||||
|
char Dest[MAX_TOKEN];
|
||||||
|
char Table[MAX_TOKEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
int InRange(char *buf,int host)
|
||||||
|
{
|
||||||
|
int valid,i,FromAddr,ToAddr,tmp;
|
||||||
|
struct in_addr file_ip_addr;
|
||||||
|
char *p;
|
||||||
|
unsigned int one=0x80000000,NetMask=0;
|
||||||
|
unsigned char mask;
|
||||||
|
p = strchr(buf,'/');
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
*p++ = '\0';
|
||||||
|
valid = inet_aton(buf, &file_ip_addr);
|
||||||
|
if(valid)
|
||||||
|
{
|
||||||
|
mask = strtoul(p,0,0);
|
||||||
|
FromAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
ToAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
for(i=0;i<mask;i++)
|
||||||
|
{
|
||||||
|
NetMask |= one;
|
||||||
|
one >>= 1;
|
||||||
|
}
|
||||||
|
FromAddr &= NetMask;
|
||||||
|
ToAddr = ToAddr | ~NetMask;
|
||||||
|
tmp = ntohl(host);
|
||||||
|
return ((unsigned)tmp>=(unsigned)FromAddr &&
|
||||||
|
(unsigned)tmp<=(unsigned)ToAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = strchr(buf,'-');
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
*p++ = '\0';
|
||||||
|
valid = inet_aton(buf, &file_ip_addr);
|
||||||
|
if(valid)
|
||||||
|
{
|
||||||
|
FromAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
valid = inet_aton(p, &file_ip_addr);
|
||||||
|
if(valid)
|
||||||
|
{
|
||||||
|
ToAddr = ntohl(file_ip_addr.s_addr);
|
||||||
|
tmp = ntohl(host);
|
||||||
|
return ((unsigned)tmp>=(unsigned)FromAddr &&
|
||||||
|
(unsigned)tmp<=(unsigned)ToAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = inet_aton(buf, &file_ip_addr);
|
||||||
|
if(valid)
|
||||||
|
{
|
||||||
|
FromAddr = file_ip_addr.s_addr;
|
||||||
|
return ((unsigned)FromAddr == (unsigned)host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetCharSetByHost(char TableName[],int host, const char DataDir[])
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char buf[MAX_TOKEN],BaseCharset[MAX_TOKEN],
|
||||||
|
OrigCharset[MAX_TOKEN],DestCharset[MAX_TOKEN],HostCharset[MAX_TOKEN];
|
||||||
|
char c,eof=false;
|
||||||
|
char *map_file;
|
||||||
|
int key=0,i;
|
||||||
|
struct CharsetItem* ChArray[MAX_CHARSETS];
|
||||||
|
int ChIndex=0;
|
||||||
|
|
||||||
|
*TableName = '\0';
|
||||||
|
map_file = (char *) malloc((strlen(DataDir) +
|
||||||
|
strlen(CHARSET_FILE)+2)*sizeof(char));
|
||||||
|
sprintf(map_file, "%s/%s", DataDir, CHARSET_FILE);
|
||||||
|
file = fopen(map_file, "r");
|
||||||
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
while (!eof)
|
||||||
|
{
|
||||||
|
c = getc(file);
|
||||||
|
ungetc(c, file);
|
||||||
|
if (c == EOF)
|
||||||
|
eof = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c == '#')
|
||||||
|
read_through_eol(file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Read the key */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
if (strcasecmp(buf, "HostCharset") == 0)
|
||||||
|
key = KEY_HOST;
|
||||||
|
if (strcasecmp(buf, "BaseCharset") == 0)
|
||||||
|
key = KEY_BASE;
|
||||||
|
if (strcasecmp(buf, "RecodeTable") == 0)
|
||||||
|
key = KEY_TABLE;
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case KEY_HOST:
|
||||||
|
/* Read the host */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
if (InRange(buf,host))
|
||||||
|
{
|
||||||
|
/* Read the charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
strcpy(HostCharset,buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BASE:
|
||||||
|
/* Read the base charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
strcpy(BaseCharset,buf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_TABLE:
|
||||||
|
/* Read the original charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
strcpy(OrigCharset,buf);
|
||||||
|
/* Read the destination charset */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
strcpy(DestCharset,buf);
|
||||||
|
/* Read the table filename */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
ChArray[ChIndex] = (struct CharsetItem *) malloc(sizeof(struct CharsetItem));
|
||||||
|
strcpy(ChArray[ChIndex]->Orig,OrigCharset);
|
||||||
|
strcpy(ChArray[ChIndex]->Dest,DestCharset);
|
||||||
|
strcpy(ChArray[ChIndex]->Table,buf);
|
||||||
|
ChIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
read_through_eol(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
free(map_file);
|
||||||
|
|
||||||
|
for(i=0; i<ChIndex; i++)
|
||||||
|
{
|
||||||
|
if(!strcasecmp(BaseCharset,ChArray[i]->Orig) &&
|
||||||
|
!strcasecmp(HostCharset,ChArray[i]->Dest))
|
||||||
|
{
|
||||||
|
strncpy(TableName,ChArray[i]->Table,79);
|
||||||
|
}
|
||||||
|
free((struct CharsetItem *) ChArray[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
hba_getauthmethod(SockAddr *raddr, char *database, char *auth_arg,
|
hba_getauthmethod(SockAddr *raddr, char *database, char *auth_arg,
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.73 1998/01/31 20:14:15 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.74 1998/02/24 15:19:00 scrappy Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -203,6 +203,10 @@ static void readStartupPacket(char *arg, PacketLen len, char *pkt);
|
|||||||
static int initMasks(fd_set *rmask, fd_set *wmask);
|
static int initMasks(fd_set *rmask, fd_set *wmask);
|
||||||
static void RandomSalt(char* salt);
|
static void RandomSalt(char* salt);
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
void GetCharSetByHost(char *,int,char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind,
|
extern int optind,
|
||||||
opterr;
|
opterr;
|
||||||
@ -974,7 +978,14 @@ BackendStartup(Port *port)
|
|||||||
Backend *bn; /* for backend cleanup */
|
Backend *bn; /* for backend cleanup */
|
||||||
int pid,
|
int pid,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
#define NR_ENVIRONMENT_VBL 6
|
||||||
|
char ChTable[80];
|
||||||
|
#else
|
||||||
#define NR_ENVIRONMENT_VBL 5
|
#define NR_ENVIRONMENT_VBL 5
|
||||||
|
#endif
|
||||||
|
|
||||||
static char envEntry[NR_ENVIRONMENT_VBL][2 * ARGV_SIZE];
|
static char envEntry[NR_ENVIRONMENT_VBL][2 * ARGV_SIZE];
|
||||||
|
|
||||||
for (i = 0; i < NR_ENVIRONMENT_VBL; ++i)
|
for (i = 0; i < NR_ENVIRONMENT_VBL; ++i)
|
||||||
@ -1000,6 +1011,15 @@ BackendStartup(Port *port)
|
|||||||
sprintf(envEntry[4], "IPC_KEY=%d", ipc_key);
|
sprintf(envEntry[4], "IPC_KEY=%d", ipc_key);
|
||||||
putenv(envEntry[4]);
|
putenv(envEntry[4]);
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
GetCharSetByHost(ChTable,port->raddr.in.sin_addr.s_addr,DataDir);
|
||||||
|
if(*ChTable != '\0')
|
||||||
|
{
|
||||||
|
sprintf(envEntry[5], "PG_RECODETABLE=%s", ChTable);
|
||||||
|
putenv(envEntry[5]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (DebugLvl > 2)
|
if (DebugLvl > 2)
|
||||||
{
|
{
|
||||||
char **p;
|
char **p;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.65 1998/02/02 00:05:03 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.66 1998/02/24 15:19:23 scrappy Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -1168,6 +1168,10 @@ PostgresMain(int argc, char *argv[])
|
|||||||
SetPgUserName();
|
SetPgUserName();
|
||||||
userName = GetPgUserName();
|
userName = GetPgUserName();
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
SetCharSet();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (FindBackend(pg_pathname, argv[0]) < 0)
|
if (FindBackend(pg_pathname, argv[0]) < 0)
|
||||||
elog(FATAL, "%s: could not locate executable, bailing out...",
|
elog(FATAL, "%s: could not locate executable, bailing out...",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
@ -1293,7 +1297,7 @@ PostgresMain(int argc, char *argv[])
|
|||||||
if (IsUnderPostmaster == false)
|
if (IsUnderPostmaster == false)
|
||||||
{
|
{
|
||||||
puts("\nPOSTGRES backend interactive interface");
|
puts("\nPOSTGRES backend interactive interface");
|
||||||
puts("$Revision: 1.65 $ $Date: 1998/02/02 00:05:03 $");
|
puts("$Revision: 1.66 $ $Date: 1998/02/24 15:19:23 $");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.27 1998/02/10 16:03:46 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.28 1998/02/24 15:19:44 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -16,6 +16,10 @@
|
|||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
char *convertstr(char *,int,int);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
|
* CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
|
||||||
* is for blank-padded string whose length is specified in CREATE TABLE.
|
* is for blank-padded string whose length is specified in CREATE TABLE.
|
||||||
@ -84,6 +88,11 @@ bpcharin(char *s, int dummy, int16 atttypmod)
|
|||||||
if (*r == '\0')
|
if (*r == '\0')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
convertstr(result + VARHDRSZ,len,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* blank pad the string if necessary */
|
/* blank pad the string if necessary */
|
||||||
for (; i < len; i++)
|
for (; i < len; i++)
|
||||||
{
|
{
|
||||||
@ -110,6 +119,11 @@ bpcharout(char *s)
|
|||||||
result = (char *) palloc(len + 1);
|
result = (char *) palloc(len + 1);
|
||||||
StrNCpy(result, VARDATA(s), len+1); /* these are blank-padded */
|
StrNCpy(result, VARDATA(s), len+1); /* these are blank-padded */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
convertstr(result,len,1);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +157,10 @@ varcharin(char *s, int dummy, int16 atttypmod)
|
|||||||
VARSIZE(result) = len;
|
VARSIZE(result) = len;
|
||||||
strncpy(VARDATA(result), s, len - VARHDRSZ);
|
strncpy(VARDATA(result), s, len - VARHDRSZ);
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
convertstr(result + VARHDRSZ,len,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +182,11 @@ varcharout(char *s)
|
|||||||
result = (char *) palloc(len + 1);
|
result = (char *) palloc(len + 1);
|
||||||
StrNCpy(result, VARDATA(s), len+1);
|
StrNCpy(result, VARDATA(s), len+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
convertstr(result,len,1);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.29 1998/01/07 18:46:54 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.30 1998/02/24 15:19:45 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -157,6 +157,11 @@ textin(char *inputText)
|
|||||||
VARSIZE(result) = len;
|
VARSIZE(result) = len;
|
||||||
|
|
||||||
memmove(VARDATA(result), inputText, len - VARHDRSZ);
|
memmove(VARDATA(result), inputText, len - VARHDRSZ);
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
convertstr(VARDATA(result),len-VARHDRSZ,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,6 +185,11 @@ textout(text *vlena)
|
|||||||
result = (char *) palloc(len + 1);
|
result = (char *) palloc(len + 1);
|
||||||
memmove(result, VARDATA(vlena), len);
|
memmove(result, VARDATA(vlena), len);
|
||||||
result[len] = '\0';
|
result[len] = '\0';
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
convertstr(result,len,1);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.9 1998/01/25 04:07:00 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.10 1998/02/24 15:20:16 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -51,6 +51,11 @@ extern char *DatabaseName;
|
|||||||
extern char *UserName;
|
extern char *UserName;
|
||||||
extern char *DatabasePath;
|
extern char *DatabasePath;
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
unsigned char RecodeForwTable[128];
|
||||||
|
unsigned char RecodeBackTable[128];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define USE_ENVIRONMENT to get PGDATA, etc. from environment variables.
|
* Define USE_ENVIRONMENT to get PGDATA, etc. from environment variables.
|
||||||
@ -258,6 +263,145 @@ SetDatabaseName(char *name)
|
|||||||
strcpy(DatabaseName, name);
|
strcpy(DatabaseName, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
#define MAX_TOKEN 80
|
||||||
|
|
||||||
|
/* Some standard C libraries, including GNU, have an isblank() function.
|
||||||
|
Others, including Solaris, do not. So we have our own.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
isblank(const char c)
|
||||||
|
{
|
||||||
|
return (c == ' ' || c == 9 /* tab */ );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
next_token(FILE *fp, char *buf, const int bufsz)
|
||||||
|
{
|
||||||
|
/*--------------------------------------------------------------------------
|
||||||
|
Grab one token out of fp. Tokens are strings of non-blank
|
||||||
|
characters bounded by blank characters, beginning of line, and end
|
||||||
|
of line. Blank means space or tab. Return the token as *buf.
|
||||||
|
Leave file positioned to character immediately after the token or
|
||||||
|
EOF, whichever comes first. If no more tokens on line, return null
|
||||||
|
string as *buf and position file to beginning of next line or EOF,
|
||||||
|
whichever comes first.
|
||||||
|
--------------------------------------------------------------------------*/
|
||||||
|
int c;
|
||||||
|
char *eb = buf + (bufsz - 1);
|
||||||
|
|
||||||
|
/* Move over inital token-delimiting blanks */
|
||||||
|
while (isblank(c = getc(fp)));
|
||||||
|
|
||||||
|
if (c != '\n')
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* build a token in buf of next characters up to EOF, eol, or
|
||||||
|
* blank.
|
||||||
|
*/
|
||||||
|
while (c != EOF && c != '\n' && !isblank(c))
|
||||||
|
{
|
||||||
|
if (buf < eb)
|
||||||
|
*buf++ = c;
|
||||||
|
c = getc(fp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put back the char right after the token (putting back EOF
|
||||||
|
* is ok)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
ungetc(c, fp);
|
||||||
|
}
|
||||||
|
*buf = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_through_eol(FILE *file)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
do
|
||||||
|
c = getc(file);
|
||||||
|
while (c != '\n' && c != EOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCharSet()
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char *p,c,eof=false;
|
||||||
|
char *map_file;
|
||||||
|
char buf[MAX_TOKEN];
|
||||||
|
int i;
|
||||||
|
unsigned char FromChar,ToChar;
|
||||||
|
|
||||||
|
for(i=0; i<128; i++)
|
||||||
|
{
|
||||||
|
RecodeForwTable[i] = i+128;
|
||||||
|
RecodeBackTable[i] = i+128;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = getenv("PG_RECODETABLE");
|
||||||
|
if (p && *p != '\0')
|
||||||
|
{
|
||||||
|
map_file = (char *) malloc((strlen(DataDir) +
|
||||||
|
strlen(p)+2)*sizeof(char));
|
||||||
|
sprintf(map_file, "%s/%s", DataDir, p);
|
||||||
|
file = fopen(map_file, "r");
|
||||||
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
eof=false;
|
||||||
|
while (!eof)
|
||||||
|
{
|
||||||
|
c = getc(file);
|
||||||
|
ungetc(c, file);
|
||||||
|
if (c == EOF)
|
||||||
|
eof = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c == '#')
|
||||||
|
read_through_eol(file);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Read the FromChar */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
FromChar = strtoul(buf,0,0);
|
||||||
|
/* Read the ToChar */
|
||||||
|
next_token(file, buf, sizeof(buf));
|
||||||
|
if (buf[0] != '\0')
|
||||||
|
{
|
||||||
|
ToChar = strtoul(buf,0,0);
|
||||||
|
RecodeForwTable[FromChar-128] = ToChar;
|
||||||
|
RecodeBackTable[ToChar-128] = FromChar;
|
||||||
|
}
|
||||||
|
read_through_eol(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
free(map_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* convertstr(unsigned char *buff,int len,int dest)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *ch=buff;
|
||||||
|
for (i = 0; i < len; i++,buff++)
|
||||||
|
{
|
||||||
|
if (*buff >127)
|
||||||
|
if (dest)
|
||||||
|
*buff = RecodeForwTable[*buff-128];
|
||||||
|
else
|
||||||
|
*buff = RecodeBackTable[*buff-128];
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* GetPgUserName and SetPgUserName
|
* GetPgUserName and SetPgUserName
|
||||||
*
|
*
|
||||||
|
@ -211,6 +211,19 @@ else
|
|||||||
fi
|
fi
|
||||||
export USE_LOCALE
|
export USE_LOCALE
|
||||||
|
|
||||||
|
dnl We exclude cyrillic recode support unless we override it with
|
||||||
|
dnl --enable-recode
|
||||||
|
dnl --disable-recode to explicitly disable it
|
||||||
|
dnl --enable-recode to explicitly enable it
|
||||||
|
dnl It defaults to disabled
|
||||||
|
if test "$enable_recode" = "yes" -o "$enable_recode" = "no"
|
||||||
|
then
|
||||||
|
CYR_RECODE=$enable_recode
|
||||||
|
else
|
||||||
|
CYR_RECODE=no
|
||||||
|
fi
|
||||||
|
export CYR_RECODE
|
||||||
|
|
||||||
dnl We use the default value of 5432 for the DEF_PGPORT value. If
|
dnl We use the default value of 5432 for the DEF_PGPORT value. If
|
||||||
dnl we over-ride it with --with-pgport=port then we bypass this piece
|
dnl we over-ride it with --with-pgport=port then we bypass this piece
|
||||||
if test "X$with_pgport" != "X"
|
if test "X$with_pgport" != "X"
|
||||||
@ -518,6 +531,14 @@ then
|
|||||||
else
|
else
|
||||||
AC_MSG_RESULT(disabled)
|
AC_MSG_RESULT(disabled)
|
||||||
fi
|
fi
|
||||||
|
AC_MSG_CHECKING(setting CYR_RECODE)
|
||||||
|
if test "$CYR_RECODE" = "yes"
|
||||||
|
then
|
||||||
|
AC_MSG_RESULT(enabled)
|
||||||
|
AC_DEFINE(CYR_RECODE)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(disabled)
|
||||||
|
fi
|
||||||
AC_MSG_CHECKING(setting DEF_PGPORT)
|
AC_MSG_CHECKING(setting DEF_PGPORT)
|
||||||
AC_DEFINE_UNQUOTED(DEF_PGPORT, "${DEF_PGPORT}")
|
AC_DEFINE_UNQUOTED(DEF_PGPORT, "${DEF_PGPORT}")
|
||||||
AC_MSG_RESULT($DEF_PGPORT)
|
AC_MSG_RESULT($DEF_PGPORT)
|
||||||
|
40
src/data/charset.conf
Normal file
40
src/data/charset.conf
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# Example PostgreSQL charsets control file.
|
||||||
|
#
|
||||||
|
# Should be placed in $PG_DATA directory.
|
||||||
|
#
|
||||||
|
# On the fly recoding charsets, based on client's IP address.
|
||||||
|
# For example: koi8-u (koi) <-> cp1251 (win) <-> cp866 (alt)
|
||||||
|
#
|
||||||
|
|
||||||
|
# Base charset for backend
|
||||||
|
# Most Unices use koi8-r(u) as base charset. But Solaris
|
||||||
|
# use iso8859-5 and some networkless workstations use cp866.
|
||||||
|
BaseCharset koi
|
||||||
|
|
||||||
|
# There are recode table definitions from base charset to
|
||||||
|
# other. Table names are relative to $PG_DATA directory.
|
||||||
|
# Tables are taken from Russian Apache <http://apache.lexa.ru>.
|
||||||
|
RecodeTable koi alt koi-alt.tab
|
||||||
|
RecodeTable koi win koi-win.tab
|
||||||
|
RecodeTable koi iso koi-iso.tab
|
||||||
|
RecodeTable koi koi koi-koi.tab
|
||||||
|
RecodeTable alt win othertabs/alt-win.tab
|
||||||
|
RecodeTable alt koi othertabs/alt-koi.tab
|
||||||
|
RecodeTable iso koi othertabs/iso-koi.tab
|
||||||
|
|
||||||
|
# Local loopback
|
||||||
|
HostCharset 127.0.0.1 koi
|
||||||
|
|
||||||
|
# Yet another Unix (maybe ;)
|
||||||
|
HostCharset 192.168.0.1 koi
|
||||||
|
|
||||||
|
# There are Windows on 192.168.1.64 through 192.168.1.95
|
||||||
|
HostCharset 192.168.1.64/27 win
|
||||||
|
|
||||||
|
# There are cp866 (alt) systems on 192.168.2.3 through
|
||||||
|
# 192.168.2.7 (exept 192.168.2.4 - see below)
|
||||||
|
HostCharset 192.168.2.3-192.168.2.7 alt
|
||||||
|
|
||||||
|
# This is exeption from previous rule!
|
||||||
|
HostCharset 192.168.2.4 win
|
0
src/data/charset.conf.orig
Normal file
0
src/data/charset.conf.orig
Normal file
85
src/data/koi-alt.tab
Normal file
85
src/data/koi-alt.tab
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# Line with '#' at the begin is comment
|
||||||
|
# table file may contain number of line as you wana
|
||||||
|
# first - code of symbol, second translate code of symbol
|
||||||
|
# codes may be in two forms: decimal and hex
|
||||||
|
# examples:
|
||||||
|
# 192 225
|
||||||
|
# 0x81 226
|
||||||
|
# 226 0x81
|
||||||
|
# 0x90 0xfe
|
||||||
|
# patch for Russia by Dm.Kryukov (dvk@stack.serpukhov.su)
|
||||||
|
#
|
||||||
|
163 241
|
||||||
|
164 243
|
||||||
|
166 249
|
||||||
|
167 245
|
||||||
|
173 173
|
||||||
|
179 240
|
||||||
|
180 242
|
||||||
|
182 248
|
||||||
|
183 244
|
||||||
|
189 189
|
||||||
|
192 238
|
||||||
|
193 160
|
||||||
|
194 161
|
||||||
|
195 230
|
||||||
|
196 164
|
||||||
|
197 165
|
||||||
|
198 228
|
||||||
|
199 163
|
||||||
|
200 229
|
||||||
|
201 168
|
||||||
|
202 169
|
||||||
|
203 170
|
||||||
|
204 171
|
||||||
|
205 172
|
||||||
|
206 173
|
||||||
|
207 174
|
||||||
|
208 175
|
||||||
|
209 239
|
||||||
|
210 224
|
||||||
|
211 225
|
||||||
|
212 226
|
||||||
|
213 227
|
||||||
|
214 166
|
||||||
|
215 162
|
||||||
|
216 236
|
||||||
|
217 235
|
||||||
|
218 167
|
||||||
|
219 232
|
||||||
|
220 237
|
||||||
|
221 233
|
||||||
|
222 231
|
||||||
|
223 234
|
||||||
|
224 158
|
||||||
|
225 128
|
||||||
|
226 129
|
||||||
|
227 150
|
||||||
|
228 132
|
||||||
|
229 133
|
||||||
|
230 148
|
||||||
|
231 131
|
||||||
|
232 149
|
||||||
|
233 136
|
||||||
|
234 137
|
||||||
|
235 138
|
||||||
|
236 139
|
||||||
|
237 140
|
||||||
|
238 141
|
||||||
|
239 142
|
||||||
|
240 143
|
||||||
|
241 159
|
||||||
|
242 144
|
||||||
|
243 145
|
||||||
|
244 146
|
||||||
|
245 147
|
||||||
|
246 134
|
||||||
|
247 130
|
||||||
|
248 156
|
||||||
|
249 155
|
||||||
|
250 135
|
||||||
|
251 152
|
||||||
|
252 157
|
||||||
|
253 153
|
||||||
|
254 151
|
||||||
|
255 154
|
0
src/data/koi-alt.tab.orig
Normal file
0
src/data/koi-alt.tab.orig
Normal file
75
src/data/koi-iso.tab
Normal file
75
src/data/koi-iso.tab
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Line with '#' at the begin is comment
|
||||||
|
# table file may contain number of line as you wana
|
||||||
|
# first - code of symbol, second translate code of symbol
|
||||||
|
# codes may be in two forms: decimal and hex
|
||||||
|
# examples:
|
||||||
|
# 192 225
|
||||||
|
# 0x81 226
|
||||||
|
# 226 0x81
|
||||||
|
# 0x90 0xfe
|
||||||
|
# patch for Russia by Dm.Kryukov (dvk@stack.serpukhov.su)
|
||||||
|
#
|
||||||
|
192 0xee
|
||||||
|
193 0xd0
|
||||||
|
194 0xd1
|
||||||
|
195 0xe6
|
||||||
|
196 0xd4
|
||||||
|
197 0xd5
|
||||||
|
198 0xe4
|
||||||
|
199 0xd3
|
||||||
|
200 0xe5
|
||||||
|
201 0xd8
|
||||||
|
202 0xd9
|
||||||
|
203 0xda
|
||||||
|
204 0xdb
|
||||||
|
205 0xdc
|
||||||
|
206 0xdd
|
||||||
|
207 0xde
|
||||||
|
208 0xdf
|
||||||
|
209 0xef
|
||||||
|
210 0xe0
|
||||||
|
211 0xe1
|
||||||
|
212 0xe2
|
||||||
|
213 0xe3
|
||||||
|
214 0xd6
|
||||||
|
215 0xd2
|
||||||
|
216 0xec
|
||||||
|
217 0xeb
|
||||||
|
218 0xd7
|
||||||
|
219 0xe8
|
||||||
|
220 0xed
|
||||||
|
221 0xe9
|
||||||
|
222 0xe7
|
||||||
|
223 0xea
|
||||||
|
224 0xce
|
||||||
|
225 0xb0
|
||||||
|
226 0xb1
|
||||||
|
227 0xc6
|
||||||
|
228 0xb4
|
||||||
|
229 0xb5
|
||||||
|
230 0xc4
|
||||||
|
231 0xb3
|
||||||
|
232 0xc5
|
||||||
|
233 0xb8
|
||||||
|
234 0xb9
|
||||||
|
235 0xba
|
||||||
|
236 0xbb
|
||||||
|
237 0xbc
|
||||||
|
238 0xbd
|
||||||
|
239 0xbe
|
||||||
|
240 0xbf
|
||||||
|
241 0xcf
|
||||||
|
242 0xc0
|
||||||
|
243 0xc1
|
||||||
|
244 0xc2
|
||||||
|
245 0xc3
|
||||||
|
246 0xb6
|
||||||
|
247 0xb2
|
||||||
|
248 0xcc
|
||||||
|
249 0xcb
|
||||||
|
250 0xb7
|
||||||
|
251 0xc8
|
||||||
|
252 0xcd
|
||||||
|
253 0xc9
|
||||||
|
254 0xc7
|
||||||
|
255 0xca
|
0
src/data/koi-iso.tab.orig
Normal file
0
src/data/koi-iso.tab.orig
Normal file
2
src/data/koi-koi.tab
Normal file
2
src/data/koi-koi.tab
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Hmm ...
|
||||||
|
#
|
0
src/data/koi-koi.tab.orig
Normal file
0
src/data/koi-koi.tab.orig
Normal file
130
src/data/koi-mac.tab
Normal file
130
src/data/koi-mac.tab
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# Hmm ...
|
||||||
|
#
|
||||||
|
128 0xc0
|
||||||
|
129 0xc1
|
||||||
|
130 0xc2
|
||||||
|
131 0xc3
|
||||||
|
132 0xc4
|
||||||
|
133 0xc5
|
||||||
|
134 0xc6
|
||||||
|
135 0xc7
|
||||||
|
136 0xc8
|
||||||
|
137 0xc9
|
||||||
|
138 0xca
|
||||||
|
139 0xcb
|
||||||
|
140 0xcc
|
||||||
|
141 0xcd
|
||||||
|
142 0xce
|
||||||
|
143 0xcf
|
||||||
|
144 0xd0
|
||||||
|
145 0xd1
|
||||||
|
146 0xd2
|
||||||
|
147 0xd3
|
||||||
|
148 0xd4
|
||||||
|
149 0xd5
|
||||||
|
150 0xd6
|
||||||
|
151 0xd7
|
||||||
|
152 0xd8
|
||||||
|
153 0xd9
|
||||||
|
154 0xda
|
||||||
|
155 0xdb
|
||||||
|
156 0xdc
|
||||||
|
157 0xdd
|
||||||
|
158 0xde
|
||||||
|
159 0xdf
|
||||||
|
160 0xa0
|
||||||
|
161 0xa1
|
||||||
|
162 0xa2
|
||||||
|
163 0xa3
|
||||||
|
164 0xa4
|
||||||
|
165 0xa5
|
||||||
|
166 0xa6
|
||||||
|
167 0xa7
|
||||||
|
168 0xa8
|
||||||
|
169 0xa9
|
||||||
|
170 0xaa
|
||||||
|
171 0xab
|
||||||
|
172 0xac
|
||||||
|
173 0xad
|
||||||
|
174 0xae
|
||||||
|
175 0xaf
|
||||||
|
176 0xb0
|
||||||
|
177 0xb1
|
||||||
|
178 0xb2
|
||||||
|
179 0xb3
|
||||||
|
180 0xb4
|
||||||
|
181 0xb5
|
||||||
|
182 0xb6
|
||||||
|
183 0xb7
|
||||||
|
184 0xb8
|
||||||
|
185 0xb9
|
||||||
|
186 0xba
|
||||||
|
187 0xbb
|
||||||
|
188 0xbc
|
||||||
|
189 0xbd
|
||||||
|
190 0xbe
|
||||||
|
191 0xbf
|
||||||
|
192 0xfe
|
||||||
|
193 0xe0
|
||||||
|
194 0xe1
|
||||||
|
195 0xf6
|
||||||
|
196 0xe4
|
||||||
|
197 0xe5
|
||||||
|
198 0xf4
|
||||||
|
199 0xe3
|
||||||
|
200 0xf5
|
||||||
|
201 0xe8
|
||||||
|
202 0xe9
|
||||||
|
203 0xea
|
||||||
|
204 0xeb
|
||||||
|
205 0xec
|
||||||
|
206 0xed
|
||||||
|
207 0xee
|
||||||
|
208 0xef
|
||||||
|
209 0xdf
|
||||||
|
210 0xf0
|
||||||
|
211 0xf1
|
||||||
|
212 0xf2
|
||||||
|
213 0xf3
|
||||||
|
214 0xe6
|
||||||
|
215 0xe2
|
||||||
|
216 0xfc
|
||||||
|
217 0xfb
|
||||||
|
218 0xe7
|
||||||
|
219 0xf8
|
||||||
|
220 0xfd
|
||||||
|
221 0xf9
|
||||||
|
222 0xf7
|
||||||
|
223 0xfa
|
||||||
|
224 0x9e
|
||||||
|
225 0x80
|
||||||
|
226 0x81
|
||||||
|
227 0x96
|
||||||
|
228 0x84
|
||||||
|
229 0x85
|
||||||
|
230 0x94
|
||||||
|
231 0x83
|
||||||
|
232 0x95
|
||||||
|
233 0x88
|
||||||
|
234 0x89
|
||||||
|
235 0x8a
|
||||||
|
236 0x8b
|
||||||
|
237 0x8c
|
||||||
|
238 0x8d
|
||||||
|
239 0x8e
|
||||||
|
240 0x8f
|
||||||
|
241 0x9f
|
||||||
|
242 0x90
|
||||||
|
243 0x91
|
||||||
|
244 0x92
|
||||||
|
245 0x93
|
||||||
|
246 0x86
|
||||||
|
247 0x82
|
||||||
|
248 0x9c
|
||||||
|
249 0x9b
|
||||||
|
250 0x87
|
||||||
|
251 0x98
|
||||||
|
252 0x9d
|
||||||
|
253 0x99
|
||||||
|
254 0x97
|
||||||
|
255 0x9a
|
0
src/data/koi-mac.tab.orig
Normal file
0
src/data/koi-mac.tab.orig
Normal file
85
src/data/koi-win.tab
Normal file
85
src/data/koi-win.tab
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# Line with '#' at the begin is comment
|
||||||
|
# table file may contain number of line as you wana
|
||||||
|
# first - code of symbol, second translate code of symbol
|
||||||
|
# codes may be in two forms: decimal and hex
|
||||||
|
# examples:
|
||||||
|
# 192 225
|
||||||
|
# 0x81 226
|
||||||
|
# 226 0x81
|
||||||
|
# 0x90 0xfe
|
||||||
|
# patch for Russia by Dm.Kryukov (dvk@stack.serpukhov.su)
|
||||||
|
#
|
||||||
|
163 184
|
||||||
|
164 186
|
||||||
|
166 179
|
||||||
|
167 191
|
||||||
|
173 180
|
||||||
|
179 168
|
||||||
|
180 170
|
||||||
|
182 178
|
||||||
|
183 175
|
||||||
|
189 165
|
||||||
|
192 254
|
||||||
|
193 224
|
||||||
|
194 225
|
||||||
|
195 246
|
||||||
|
196 228
|
||||||
|
197 229
|
||||||
|
198 244
|
||||||
|
199 227
|
||||||
|
200 245
|
||||||
|
201 232
|
||||||
|
202 233
|
||||||
|
203 234
|
||||||
|
204 235
|
||||||
|
205 236
|
||||||
|
206 237
|
||||||
|
207 238
|
||||||
|
208 239
|
||||||
|
209 255
|
||||||
|
210 240
|
||||||
|
211 241
|
||||||
|
212 242
|
||||||
|
213 243
|
||||||
|
214 230
|
||||||
|
215 226
|
||||||
|
216 252
|
||||||
|
217 251
|
||||||
|
218 231
|
||||||
|
219 248
|
||||||
|
220 253
|
||||||
|
221 249
|
||||||
|
222 247
|
||||||
|
223 250
|
||||||
|
224 222
|
||||||
|
225 192
|
||||||
|
226 193
|
||||||
|
227 214
|
||||||
|
228 196
|
||||||
|
229 197
|
||||||
|
230 212
|
||||||
|
231 195
|
||||||
|
232 213
|
||||||
|
233 200
|
||||||
|
234 201
|
||||||
|
235 202
|
||||||
|
236 203
|
||||||
|
237 204
|
||||||
|
238 205
|
||||||
|
239 206
|
||||||
|
240 207
|
||||||
|
241 223
|
||||||
|
242 208
|
||||||
|
243 209
|
||||||
|
244 210
|
||||||
|
245 211
|
||||||
|
246 198
|
||||||
|
247 194
|
||||||
|
248 220
|
||||||
|
249 219
|
||||||
|
250 199
|
||||||
|
251 216
|
||||||
|
252 221
|
||||||
|
253 217
|
||||||
|
254 215
|
||||||
|
255 218
|
0
src/data/koi-win.tab.orig
Normal file
0
src/data/koi-win.tab.orig
Normal file
@ -195,6 +195,9 @@ extern void srandom(int seed);
|
|||||||
/* Set to 1 if you want to USE_LOCALE */
|
/* Set to 1 if you want to USE_LOCALE */
|
||||||
#undef USE_LOCALE
|
#undef USE_LOCALE
|
||||||
|
|
||||||
|
/* Set to 1 if you want CYR_RECODE (cyrillic recode) */
|
||||||
|
#undef CYR_RECODE
|
||||||
|
|
||||||
/* Set to 1 if you want to Disable ASSERT CHECKING */
|
/* Set to 1 if you want to Disable ASSERT CHECKING */
|
||||||
#undef NO_ASSERT_CHECKING
|
#undef NO_ASSERT_CHECKING
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1995, Regents of the University of California
|
* Copyright (c) 1995, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: postgres.h,v 1.11 1997/11/13 03:22:46 momjian Exp $
|
* $Id: postgres.h,v 1.12 1998/02/24 15:27:04 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -214,4 +214,12 @@ typedef uint32 CommandId;
|
|||||||
#define STATUS_BAD_PACKET (-7)
|
#define STATUS_BAD_PACKET (-7)
|
||||||
#define STATUS_FOUND (1)
|
#define STATUS_FOUND (1)
|
||||||
|
|
||||||
|
/* ---------------
|
||||||
|
* Cyrillic on the fly charsets recode
|
||||||
|
* ---------------
|
||||||
|
*/
|
||||||
|
#ifdef CYR_RECODE
|
||||||
|
void SetCharSet();
|
||||||
|
#endif /* CYR_RECODE */
|
||||||
|
|
||||||
#endif /* POSTGRES_H */
|
#endif /* POSTGRES_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user