#include <mysql/mysql.h>
#include "stralloc.h"
#include "qsutil.h"
#include "mysql_queries.h"
extern int connect_mysql();
extern int disconnect_mysql();
extern MYSQL dbh, *mysql;
extern MYSQL_RES *result;
/* simulate reading a .qmail file from ye olde database */
int dotqmail_mysql(char *username, char *ext, stralloc *sa, int bufsize) {
int i, len, num;
MYSQL_ROW row;
stralloc query = { 0 };
stralloc user = { 0 };
stralloc real_ext = { 0 };
#ifdef FUNKY_ALIAS_QUERIES
#ifdef OIL_AND_WATER
stralloc last1 = { 0 };
stralloc last2 = { 0 };
#endif
#endif
/* initialise database handle or signal trouble */
if (! connect_mysql()) return -1;
i = str_len(username);
if (! stralloc_ready(&user, 2 * i + 1)) return zoiks(-1);
mysql_escape_string(user.s, username, i);
i = str_len(ext);
if (! stralloc_ready(&real_ext, 2 * i + 1)) return zoiks(-1);
mysql_escape_string(real_ext.s, ext, i);
/* make the query or signal an out of memory exception */
len = str_len(ALIAS) + real_ext.len + user.len - 3;
if (! stralloc_ready(&query, len)) return zoiks(-1);
if (! stralloc_cats(&query, ALIAS1)) return zoiks(-1);
if (! stralloc_cats(&query, user.s)) return zoiks(-1);
if (! stralloc_cats(&query, ALIAS2)) return zoiks(-1);
if (! stralloc_cats(&query, real_ext.s)) return zoiks(-1);
if (! stralloc_cats(&query, ALIAS3)) return zoiks(-1);
if (! stralloc_0(&query)) return zoiks(-1);
#ifndef O_NOT_LOG
tcplog("query: ", query.s, ";\n");
#endif
/* do the query or signal to use .qmail */
if (mysql_real_query(mysql, query.s, query.len) < 0) {
/* bad => log it anyway */
tcplog("error: ", mysql_error(&dbh), "\n");
disconnect_mysql();
return 0;
}
result = mysql_store_result(mysql);
if (!result) return zoiks(-1);
num = mysql_num_rows(result);
/* no rows: let's try the default alias - but not if extension was blank */
if (num == 0 && *ext) {
mysql_free_result(result);
query.len = 0;
len = str_len(ALIAS) + user.len - 2;
if (! stralloc_ready(&query, len)) return zoiks(-1);
if (! stralloc_cats(&query, ALIAS1)) return zoiks(-1);
if (! stralloc_cats(&query, user.s)) return zoiks(-1);
if (! stralloc_cats(&query, ALIAS2)) return zoiks(-1);
if (! stralloc_append(&query, "@")) return zoiks(-1);
if (! stralloc_cats(&query, ALIAS3)) return zoiks(-1);
if (! stralloc_0(&query)) return zoiks(-1);
#ifndef O_NOT_LOG
tcplog("query: ", query.s, ";\n");
#endif
/* hmm, a function would have been nice here */
if (mysql_real_query(mysql, query.s, query.len) < 0) {
/* bad => log it anyway */
tcplog("error: ", mysql_error(&dbh), "\n");
disconnect_mysql();
return 0;
}
result = mysql_store_result(mysql);
if (!result) return zoiks(0);
num = mysql_num_rows(result);
}
/* well it looks like there's really no match */
if (num == 0) return zoiks(0);
#ifdef FUNKY_ALIAS_QUERIES
#ifdef OIL_AND_WATER
if (! stralloc_ready(&last1, 2)) return zoiks(-1);
if (! stralloc_append(&last1, "0")) return zoiks(-1);
if (! stralloc_0(&last1)) return zoiks(-1);
if (! stralloc_ready(&last2, 2)) return zoiks(-1);
if (! stralloc_append(&last2, "0")) return zoiks(-1);
if (! stralloc_0(&last2)) return zoiks(-1);
#endif
#endif
for (i = 0; i < num; i++) {
row = mysql_fetch_row(result);
if (! *(row[0])) {
tcplog("MySQL misconfiguration: alias_username is blank for username '", user.s, "' in alias table!\n");
continue;
}
#ifdef FUNKY_ALIAS_QUERIES
#ifdef OIL_AND_WATER
/* discard wildcard matches if we already had explicit matches */
if (i && (str_diff(row[2], last1.s) || str_diff(row[3], last2.s))) break;
if (! stralloc_ready(&last1, str_len(row[2]) + 1)) return zoiks(-1);
if (! stralloc_cats(&last1, row[2])) return zoiks(-1);
if (! stralloc_0(&last1)) return zoiks(-1);
if (! stralloc_ready(&last2, str_len(row[3]) + 1)) return zoiks(-1);
if (! stralloc_cats(&last2, row[3])) return zoiks(-1);
if (! stralloc_0(&last2)) return zoiks(-1);
#endif
#endif
/* we need space for &blabla@crap\n\0 */
len = str_len(row[0]) + str_len(row[1]) + 4;
if (! stralloc_readyplus(sa, len)) return zoiks(-1);
/* if the result is too big for the buffer we skip it */
if (len > bufsize) continue;
/* if the alias username is a | we use the alias host value as the target */
if (*row[0] == '|') {
/* skip if the pipe would break */
if (str_len(row[1]) == 0) continue;
if (! stralloc_cats(sa, "| ")) return zoiks(-1);
}
/* . or / means delivery to a mailbox or maildir */
else if (*row[0] == '/' || *row[0] == '.') {
*(row[0] + 1) = '\0';
if (str_len(row[1]) == 0) continue;
if (! stralloc_cats(sa, row[0])) return zoiks(-1);
}
else {
if (! stralloc_cats(sa, "&")) return zoiks(-1);
if (! stralloc_cats(sa, row[0])) return zoiks(-1);
if (strcmp(row[1], "") && ! stralloc_cats(sa, "@")) return zoiks(-1);
}
if (! stralloc_cats(sa, row[1])) return zoiks(-1);
if (! stralloc_cats(sa, "\n")) return zoiks(-1);
}
return zoiks(num);
}
/* free memory used by query, disconnect from database and return */
int zoiks(int ret) {
mysql_free_result(result);
disconnect_mysql();
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1