1 /*$Id: issub.c,v 1.16 1999/12/11 03:04:19 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
14 #include "subscribe.h"
18 static void die_nomem(fatal
)
21 strerr_die2x(111,fatal
,ERR_NOMEM
);
24 static stralloc addr
= {0};
25 static stralloc lcaddr
= {0};
26 static stralloc line
= {0};
27 static stralloc quoted
= {0};
28 static stralloc fn
= {0};
30 static char ssbuf
[512];
31 static char szh
[FMT_ULONG
];
33 char *issub(dbname
,userhost
,tab
,fatal
)
34 /* Returns (char *) to match if userhost is in the subscriber database */
35 /* dbname, 0 otherwise. dbname is a base directory for a list and may NOT */
37 /* NOTE: The returned pointer is NOT VALID after a subsequent call to issub!*/
39 char *dbname
; /* directory to basedir */
41 char *tab
; /* override table name */
49 unsigned long *lengths
;
58 if ((ret
= opensql(dbname
,&table
))) {
59 if (*ret
) strerr_die2x(111,fatal
,ret
);
60 /* fallback to local db */
62 if (!stralloc_copys(&addr
,"T")) die_nomem(fatal
);
63 if (!stralloc_cats(&addr
,userhost
)) die_nomem(fatal
);
65 j
= byte_rchr(addr
.s
,addr
.len
,'@');
66 if (j
== addr
.len
) return 0;
67 case_lowerb(addr
.s
+ j
+ 1,addr
.len
- j
- 1);
68 if (!stralloc_copy(&lcaddr
,&addr
)) die_nomem(fatal
);
69 case_lowerb(lcaddr
.s
+ 1,j
- 1); /* totally lc version of addr */
72 lch
= h
; /* make hash for both for backwards comp */
73 for (j
= 0;j
< addr
.len
;++j
) { /* (lcaddr.len == addr.len) */
74 h
= (h
+ (h
<< 5)) ^ (uint32
) (unsigned char) addr
.s
[j
];
75 lch
= (lch
+ (lch
<< 5)) ^ (uint32
) (unsigned char) lcaddr
.s
[j
];
78 lcch
= 64 + (lch
% 53);
80 if (!stralloc_0(&addr
)) die_nomem(fatal
);
81 if (!stralloc_0(&lcaddr
)) die_nomem(fatal
);
82 if (!stralloc_copys(&fn
,dbname
)) die_nomem(fatal
);
83 if (!stralloc_cats(&fn
,"/subscribers/")) die_nomem(fatal
);
84 if (!stralloc_catb(&fn
,&lcch
,1)) die_nomem(fatal
);
85 if (!stralloc_0(&fn
)) die_nomem(fatal
);
89 if (errno
!= error_noent
)
90 strerr_die4sys(111,fatal
,ERR_OPEN
,fn
.s
,": ");
92 substdio_fdbuf(&ss
,read
,fd
,ssbuf
,sizeof(ssbuf
));
95 if (getln(&ss
,&line
,&match
,'\0') == -1)
96 strerr_die4sys(111,fatal
,ERR_READ
,fn
.s
,": ");
98 if (line
.len
== lcaddr
.len
)
99 if (!case_diffb(line
.s
,line
.len
,lcaddr
.s
))
100 { close(fd
); return line
.s
+1; }
105 /* here if file not found or (file found && addr not there) */
107 if (ch
== lcch
) return 0;
109 /* try case sensitive hash for backwards compatibility */
110 fn
.s
[fn
.len
- 2] = ch
;
111 fd
= open_read(fn
.s
);
113 if (errno
!= error_noent
)
114 strerr_die4sys(111,fatal
,ERR_OPEN
,fn
.s
,": ");
117 substdio_fdbuf(&ss
,read
,fd
,ssbuf
,sizeof(ssbuf
));
120 if (getln(&ss
,&line
,&match
,'\0') == -1)
121 strerr_die4sys(111,fatal
,ERR_READ
,fn
.s
,": ");
123 if (line
.len
== addr
.len
)
124 if (!case_diffb(line
.s
,line
.len
,addr
.s
))
125 { close(fd
); return line
.s
+1; }
131 } else { /* SQL version */
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 ...". */
138 if (!stralloc_copys(&addr
,userhost
)) die_nomem(fatal
);
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);
143 if (!stralloc_copys(&line
,"SELECT address FROM ")) die_nomem(fatal
);
144 if (!stralloc_cats(&line
,table
)) die_nomem(fatal
);
145 if (!stralloc_cats(&line
," WHERE address = '")) die_nomem(fatal
);
146 if (!stralloc_ready("ed
,2 * addr
.len
+ 1)) die_nomem(fatal
);
147 if (!stralloc_catb(&line
,quoted
.s
,
148 mysql_escape_string(quoted
.s
,userhost
,addr
.len
))) die_nomem(fatal
);
149 if (!stralloc_cats(&line
,"'"))
151 if (mysql_real_query((MYSQL
*) psql
,line
.s
,line
.len
)) /* query */
152 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
153 if (!(result
= mysql_use_result((MYSQL
*) psql
)))
154 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
155 row
= mysql_fetch_row(result
);
157 if (!row
) { /* we need to return the actual address as other */
158 /* dbs may accept user-*@host, but we still want */
159 /* to make sure to send to e.g the correct moderator*/
161 if (!mysql_eof(result
))
162 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
164 if (!(lengths
= mysql_fetch_lengths(result
)))
165 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
166 if (!stralloc_copyb(&line
,row
[0],lengths
[0])) die_nomem(fatal
);
167 if (!stralloc_0(&line
)) die_nomem(fatal
);
169 while ((row
= mysql_fetch_row(result
))); /* maybe not necessary */
170 mysql_free_result(result
);