ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
issub.c
Go to the documentation of this file.
1#include "stralloc.h"
2#include "getln.h"
3#include "readwrite.h"
4#include "buffer.h"
5#include "open.h"
6#include "byte.h"
7#include "case.h"
8#include "strerr.h"
9#include "error.h"
10#include "uint32.h"
11#include "fmt.h"
12#include "subscribe.h"
13#include "errtxt.h"
14#include "idx.h"
15#include <unistd.h>
16#include <libpq-fe.h>
17
18#define WHO "issub"
19
25
26extern PGconn *pgsql;
27
28static stralloc addr = {0};
29static stralloc lcaddr = {0};
30static stralloc line = {0};
31static stralloc fn = {0};
32static buffer bi;
33static char inbuf[512];
34
44
45const char *issub(const char *dbname,const char *userhost,const char *tab)
46{
47 PGresult *result;
48 const char *ret;
49 const char *table;
50
51 int fd;
52 unsigned int j;
53 uint32 h,lch;
54 char ch,lcch;
55 int match;
56
57 table = tab;
58 if ((ret = opensql(dbname,&table))) {
59 if (*ret) logmsg(WHO,111,FATAL,ret); /* fallback to local db */
60
61 if (!stralloc_copys(&addr,"T")) die_nomem();
62 if (!stralloc_cats(&addr,userhost)) die_nomem();
63
64 j = byte_rchr(addr.s,addr.len,'@');
65 if (j == addr.len) return 0;
66 case_lowerb(addr.s + j + 1,addr.len - j - 1);
67 if (!stralloc_copy(&lcaddr,&addr)) die_nomem();
68 case_lowerb(lcaddr.s + 1,j - 1); /* totally lc version of addr */
69
70 h = 5381;
71 lch = h; /* make hash for both for backwards comp */
72 for (j = 0;j < addr.len;++j) { /* (lcaddr.len == addr.len) */
73 h = (h + (h << 5)) ^ (uint32) (unsigned char) addr.s[j];
74 lch = (lch + (lch << 5)) ^ (uint32) (unsigned char) lcaddr.s[j];
75 }
76 ch = 64 + (h % 53);
77 lcch = 64 + (lch % 53);
78
79 if (!stralloc_0(&addr)) die_nomem();
80 if (!stralloc_0(&lcaddr)) die_nomem();
81 if (!stralloc_copys(&fn,dbname)) die_nomem();
82 if (!stralloc_cats(&fn,"/subscribers/")) die_nomem();
83 if (!stralloc_catb(&fn,&lcch,1)) die_nomem();
84 if (!stralloc_0(&fn)) die_nomem();
85
86 fd = open_read(fn.s);
87 if (fd == -1) {
88 if (errno != ENOENT)
89 logmsg(WHO,111,FATAL,B("ERR_OPEN :",fn.s));
90 } else {
91 buffer_init(&bi,buffer_unixread,fd,inbuf,sizeof(inbuf));
92
93 for (;;) {
94 if (getln(&bi,&line,&match,'\0') == -1)
95 logmsg(WHO,111,FATAL,B("ERR_READ :",fn.s));
96 if (!match) break;
97 if (line.len == lcaddr.len)
98 if (!case_diffb(line.s,line.len,lcaddr.s))
99 { close(fd); return line.s+1; }
100 }
101
102 close(fd);
103 }
104 /* here if file not found or (file found && addr not there) */
105
106 if (ch == lcch) return 0;
107
108 /* try case sensitive hash for backwards compatibility */
109 fn.s[fn.len - 2] = ch;
110 fd = open_read(fn.s);
111 if (fd == -1) {
112 if (errno != ENOENT)
113 logmsg(WHO,111,FATAL,B("ERR_OPEN :",fn.s));
114 return 0;
115 }
116 buffer_init(&bi,buffer_unixread,fd,inbuf,sizeof(inbuf));
117
118 for (;;) {
119 if (getln(&bi,&line,&match,'\0') == -1)
120 logmsg(WHO,111,FATAL,B("ERR_READ :",fn.s));
121 if (!match) break;
122 if (line.len == addr.len)
123 if (!case_diffb(line.s,line.len,addr.s))
124 { close(fd); return line.s+1; }
125 }
126
127 close(fd);
128
129 return 0;
130 } else { /* SQL version */
131
132 /* SELECT address FROM list WHERE address = 'userhost' AND hash */
133 /* BETWEEN 0 AND 52. Without the hash restriction, we'd make it */
134 /* even easier to defeat. Just faking sender to the list name would*/
135 /* work. Since sender checks for posts are bogus anyway, I don't */
136 /* know if it's worth the cost of the "WHERE ...". */
137
138 if (!stralloc_copys(&addr,userhost)) die_nomem();
139 j = byte_rchr(addr.s,addr.len,'@');
140 if (j == addr.len) return 0;
141 case_lowerb(addr.s + j + 1,addr.len - j - 1);
142
143 if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem();
144 if (!stralloc_cats(&line,table)) die_nomem();
145 if (!stralloc_cats(&line," WHERE address ~* '^")) die_nomem();
146 if (!stralloc_cat(&line,&addr)) die_nomem();
147 if (!stralloc_cats(&line,"$'")) die_nomem();
148 if (!stralloc_0(&line)) die_nomem();
149
150 result = PQexec(pgsql,line.s);
151 if (result == NULL)
152 logmsg(WHO,111,FATAL,PQerrorMessage(pgsql));
153 if (PQresultStatus(result) != PGRES_TUPLES_OK )
154 logmsg(WHO,111,FATAL,PQresultErrorMessage(result));
155
156 /* No data returned in QUERY */
157
158 if (PQntuples(result) < 1)
159 return (char *)0;
160
161 if (!stralloc_copyb(&line,PQgetvalue(result,0,0),PQgetlength(result,0,0))) die_nomem();
162 if (!stralloc_0(&line)) die_nomem();
163
164 PQclear(result);
165 return line.s;
166 }
167}
int issub()
Returns (char *) to match if userhost is in the subscriber database dbname, 0 otherwise....
Error messages. If you translate these, I would urge you to keep the English version as well....
const char * opensql(const char *dir, const char **table)
Definition opensql.c:13
void die_nomem()
Definition getconf.c:17
#define WHO
Definition author.c:1
stralloc fn
char inbuf[1024]
buffer bi
char * userhost
stralloc addr
Definition ezmlm-cron.c:45
int fd
Definition ezmlm-cgi.c:141
int match
Definition ezmlm-cgi.c:140
PGconn * pgsql
Definition opensql.c:22
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32