Ejemplo n.º 1
0
/**********************************************************************
 * public interface dict_mysql_lookup
 * find database entry return 0 if no alias found, set dict_errno
 * on errors to DICT_ERRBO_RETRY and set dict_errno to 0 on success
 *********************************************************************/
static const char *dict_mysql_lookup(DICT *dict, const char *name)
{
    MYSQL_RES *query_res;
    MYSQL_ROW row;
    DICT_MYSQL *dict_mysql;
    PLMYSQL *pldb;
    static VSTRING *result;
    static VSTRING *query = 0;
    int     i,
            j,
            numrows;
    char   *name_escaped = 0;

    dict_mysql = (DICT_MYSQL *) dict;
    pldb = dict_mysql->pldb;
    /* initialization  for query */
    query = vstring_alloc(24);
    vstring_strcpy(query, "");
    if ((name_escaped = (char *) mymalloc((sizeof(char) * (strlen(name) * 2) +1))) == NULL) {
        msg_fatal("dict_mysql_lookup: out of memory.");
    }
    /* prepare the query */
    mysql_escape_string(name_escaped, name, (unsigned int) strlen(name));
    vstring_sprintf(query, "select %s from %s where %s = '%s' %s", dict_mysql->name->select_field,
                    dict_mysql->name->table, dict_mysql->name->where_field, name_escaped,
                    dict_mysql->name->additional_conditions);
    if (msg_verbose)
        msg_info("dict_mysql_lookup using sql query: %s", vstring_str(query));
    /* free mem associated with preparing the query */
    myfree(name_escaped);
    /* do the query - set dict_errno & cleanup if there's an error */
    if ((query_res = plmysql_query(pldb,
                                   vstring_str(query),
                                   dict_mysql->name->dbname,
                                   dict_mysql->name->username,
                                   dict_mysql->name->password)) == 0) {
        dict_errno = DICT_ERR_RETRY;
        vstring_free(query);
        return 0;
    }
    dict_errno = 0;
    /* free the vstring query */
    vstring_free(query);
    numrows = mysql_num_rows(query_res);
    if (msg_verbose)
        msg_info("dict_mysql_lookup: retrieved %d rows", numrows);
    if (numrows == 0) {
        mysql_free_result(query_res);
        return 0;
    }
    if (result == 0)
        result = vstring_alloc(10);
    vstring_strcpy(result, "");
    for (i = 0; i < numrows; i++) {
        row = mysql_fetch_row(query_res);
        if (i > 0)
            vstring_strcat(result, ",");
        for (j = 0; j < mysql_num_fields(query_res); j++) {
            if (row[j] == 0) {
                if (msg_verbose > 1)
                    msg_info("dict_mysql_lookup: null field #%d row #%d", j, i);
                mysql_free_result(query_res);
                return (0);
            }
            if (j > 0)
                vstring_strcat(result, ",");
            vstring_strcat(result, row[j]);
            if (msg_verbose > 1)
                msg_info("dict_mysql_lookup: retrieved field: %d: %s", j, row[j]);
        }
    }
    mysql_free_result(query_res);
    return vstring_str(result);
}
Ejemplo n.º 2
0
static const char *dict_mysql_lookup(DICT *dict, const char *name)
{
    const char *myname = "dict_mysql_lookup";
    DICT_MYSQL *dict_mysql = (DICT_MYSQL *) dict;
    MYSQL_RES *query_res;
    MYSQL_ROW row;
    static VSTRING *result;
    static VSTRING *query;
    int     i;
    int     j;
    int     numrows;
    int     expansion;
    const char *r;
    db_quote_callback_t quote_func = dict_mysql_quote;
    int     domain_rc;

    dict->error = 0;

    /*
     * Optionally fold the key.
     */
    if (dict->flags & DICT_FLAG_FOLD_FIX) {
	if (dict->fold_buf == 0)
	    dict->fold_buf = vstring_alloc(10);
	vstring_strcpy(dict->fold_buf, name);
	name = lowercase(vstring_str(dict->fold_buf));
    }

    /*
     * If there is a domain list for this map, then only search for addresses
     * in domains on the list. This can significantly reduce the load on the
     * server.
     */
    if ((domain_rc = db_common_check_domain(dict_mysql->ctx, name)) == 0) {
	if (msg_verbose)
	    msg_info("%s: Skipping lookup of '%s'", myname, name);
	return (0);
    }
    if (domain_rc < 0)
	DICT_ERR_VAL_RETURN(dict, domain_rc, (char *) 0);

#define INIT_VSTR(buf, len) do { \
	if (buf == 0) \
	    buf = vstring_alloc(len); \
	VSTRING_RESET(buf); \
	VSTRING_TERMINATE(buf); \
    } while (0)

    INIT_VSTR(query, 10);

    /*
     * Suppress the lookup if the query expansion is empty
     * 
     * This initial expansion is outside the context of any specific host
     * connection, we just want to check the key pre-requisites, so when
     * quoting happens separately for each connection, we don't bother with
     * quoting...
     */
#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
    quote_func = 0;
#endif
    if (!db_common_expand(dict_mysql->ctx, dict_mysql->query,
			  name, 0, query, quote_func))
	return (0);

    /* do the query - set dict->error & cleanup if there's an error */
    if ((query_res = plmysql_query(dict_mysql, name, query)) == 0) {
	dict->error = DICT_ERR_RETRY;
	return (0);
    }
    numrows = mysql_num_rows(query_res);
    if (msg_verbose)
	msg_info("%s: retrieved %d rows", myname, numrows);
    if (numrows == 0) {
	mysql_free_result(query_res);
	return 0;
    }
    INIT_VSTR(result, 10);

    for (expansion = i = 0; i < numrows && dict->error == 0; i++) {
	row = mysql_fetch_row(query_res);
	for (j = 0; j < mysql_num_fields(query_res); j++) {
	    if (db_common_expand(dict_mysql->ctx, dict_mysql->result_format,
				 row[j], name, result, 0)
		&& dict_mysql->expansion_limit > 0
		&& ++expansion > dict_mysql->expansion_limit) {
		msg_warn("%s: %s: Expansion limit exceeded for key: '%s'",
			 myname, dict_mysql->parser->name, name);
		dict->error = DICT_ERR_RETRY;
		break;
	    }
	}
    }
    mysql_free_result(query_res);
    r = vstring_str(result);
    return ((dict->error == 0 && *r) ? r : 0);
}