mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
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:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
hba_getauthmethod(SockAddr *raddr, char *database, char *auth_arg,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
@@ -203,6 +203,10 @@ static void readStartupPacket(char *arg, PacketLen len, char *pkt);
|
||||
static int initMasks(fd_set *rmask, fd_set *wmask);
|
||||
static void RandomSalt(char* salt);
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
void GetCharSetByHost(char *,int,char *);
|
||||
#endif
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind,
|
||||
opterr;
|
||||
@@ -974,7 +978,14 @@ BackendStartup(Port *port)
|
||||
Backend *bn; /* for backend cleanup */
|
||||
int pid,
|
||||
i;
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
#define NR_ENVIRONMENT_VBL 6
|
||||
char ChTable[80];
|
||||
#else
|
||||
#define NR_ENVIRONMENT_VBL 5
|
||||
#endif
|
||||
|
||||
static char envEntry[NR_ENVIRONMENT_VBL][2 * ARGV_SIZE];
|
||||
|
||||
for (i = 0; i < NR_ENVIRONMENT_VBL; ++i)
|
||||
@@ -1000,6 +1011,15 @@ BackendStartup(Port *port)
|
||||
sprintf(envEntry[4], "IPC_KEY=%d", ipc_key);
|
||||
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)
|
||||
{
|
||||
char **p;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* this is the "main" module of the postgres backend and
|
||||
@@ -1168,6 +1168,10 @@ PostgresMain(int argc, char *argv[])
|
||||
SetPgUserName();
|
||||
userName = GetPgUserName();
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
SetCharSet();
|
||||
#endif
|
||||
|
||||
if (FindBackend(pg_pathname, argv[0]) < 0)
|
||||
elog(FATAL, "%s: could not locate executable, bailing out...",
|
||||
argv[0]);
|
||||
@@ -1293,7 +1297,7 @@ PostgresMain(int argc, char *argv[])
|
||||
if (IsUnderPostmaster == false)
|
||||
{
|
||||
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
|
||||
* $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 "utils/builtins.h"
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
char *convertstr(char *,int,int);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
|
||||
* 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')
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
convertstr(result + VARHDRSZ,len,0);
|
||||
#endif
|
||||
|
||||
/* blank pad the string if necessary */
|
||||
for (; i < len; i++)
|
||||
{
|
||||
@@ -110,6 +119,11 @@ bpcharout(char *s)
|
||||
result = (char *) palloc(len + 1);
|
||||
StrNCpy(result, VARDATA(s), len+1); /* these are blank-padded */
|
||||
}
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
convertstr(result,len,1);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -143,6 +157,10 @@ varcharin(char *s, int dummy, int16 atttypmod)
|
||||
VARSIZE(result) = len;
|
||||
strncpy(VARDATA(result), s, len - VARHDRSZ);
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
convertstr(result + VARHDRSZ,len,0);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -164,6 +182,11 @@ varcharout(char *s)
|
||||
result = (char *) palloc(len + 1);
|
||||
StrNCpy(result, VARDATA(s), len+1);
|
||||
}
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
convertstr(result,len,1);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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;
|
||||
|
||||
memmove(VARDATA(result), inputText, len - VARHDRSZ);
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
convertstr(VARDATA(result),len-VARHDRSZ,0);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -180,6 +185,11 @@ textout(text *vlena)
|
||||
result = (char *) palloc(len + 1);
|
||||
memmove(result, VARDATA(vlena), len);
|
||||
result[len] = '\0';
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
convertstr(result,len,1);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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 *DatabasePath;
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
unsigned char RecodeForwTable[128];
|
||||
unsigned char RecodeBackTable[128];
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Define USE_ENVIRONMENT to get PGDATA, etc. from environment variables.
|
||||
@@ -258,6 +263,145 @@ SetDatabaseName(char *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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user