apr_dbd_freetds.c

来自「linux网络服务器工具」· C语言 代码 · 共 796 行 · 第 1/2 页

C
796
字号
        stmt->sz = apr_palloc(pool, n*sizeof(int));        ret = 0;    }    else {        int i;        int sz = 0;        int len = matches[1].rm_eo - matches[1].rm_so - 2;        if (len > 255) {            return 9999;        }        ret = recurse_args(pool, n+1, query+matches[0].rm_eo,                           stmt, offs+matches[0].rm_eo);        memmove(stmt->fmt + offs + matches[1].rm_so,                stmt->fmt + offs + matches[0].rm_eo-1,                strlen(stmt->fmt+offs+matches[0].rm_eo)+2);        /* compile untaint to a regex if found */        if (matches[1].rm_so == -1) {            stmt->taint[n] = NULL;        }        else {            strncpy(arg, query+matches[1].rm_so+1,                    matches[1].rm_eo - matches[1].rm_so - 2);            arg[matches[1].rm_eo - matches[1].rm_so - 2] = '\0';            stmt->taint[n] = apr_palloc(pool, sizeof(regex_t));            if (regcomp(stmt->taint[n], arg, REG_ICASE|REG_EXTENDED) != 0) {                ++ret;            }            else {                apr_pool_cleanup_register(pool, stmt->taint[n], freetds_regfree,                                          apr_pool_cleanup_null);            }        }        /* record length if specified */        for (i=matches[2].rm_so; i<matches[2].rm_eo; ++i) {            sz = 10*sz + (query[i]-'\0');        }    }    return ret;}static int dbd_freetds_prepare(apr_pool_t *pool, apr_dbd_t *sql,                             const char *query, const char *label,                             apr_dbd_prepared_t **statement){    apr_dbd_prepared_t *stmt;    if (label == NULL) {        label = apr_psprintf(pool, "%d", labelnum++);    }    if (!*statement) {        *statement = apr_palloc(pool, sizeof(apr_dbd_prepared_t));    }    stmt = *statement;#if 0    /* count args */    stmt->fmt = apr_pstrdup(pool, query);    stmt->fmt = recurse_args(pool, 0, query, stmt, stmt->fmt);    /* overestimate by a byte or two to simplify */    len = strlen("CREATE PROC apr.")            + strlen(label)            + stmt->nargs * strlen(" @arg1 varchar(len1),")            + strlen(" AS begin ")            + strlen(stmt->fmt)            + strlen(" end "); /* extra byte for terminator */    pquery = apr_pcalloc(pool, len);    sprintf(pquery, "CREATE PROC apr.%s", label);    for (i=0; i<stmt->nargs; ++i) {        sprintf(pquery+strlen(pquery), " @arg%d varchar(%d)", i, stmt->sz[i]);        if (i < stmt->nargs-1) {            pquery[strlen(pquery)] = ',';        }    }    strcat(pquery, " AS BEGIN ");    strcat(pquery, stmt->fmt);    strcat(pquery, " END");    return (freetds_exec(sql->proc, pquery, 0, &i) == SUCCEED) ? 0 : 1;#else    stmt->fmt = apr_pstrdup(pool, query);    return recurse_args(pool, 0, query, stmt, 0);#endif}static int dbd_freetds_start_transaction(apr_pool_t *pool, apr_dbd_t *handle,                                         apr_dbd_transaction_t **trans){    int dummy;    /* XXX handle recursive transactions here */    handle->err = freetds_exec(handle->proc, "BEGIN TRANSACTION", 0, &dummy);    if (dbd_freetds_is_success(handle->err)) {        if (!*trans) {            *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));        }        (*trans)->handle = handle;        handle->trans = *trans;        return 0;    }    return 1;}static int dbd_freetds_end_transaction(apr_dbd_transaction_t *trans){    int dummy;    if (trans) {        /* rollback on error or explicit rollback request */        if (trans->errnum) {            trans->errnum = 0;            trans->handle->err = freetds_exec(trans->handle->proc,                                              "ROLLBACK", 0, &dummy);        }        else {            trans->handle->err = freetds_exec(trans->handle->proc,                                              "COMMIT", 0, &dummy);        }        trans->handle->trans = NULL;    }    return (trans->handle->err == SUCCEED) ? 0 : 1;}static DBPROCESS *freetds_open(apr_pool_t *pool, const char *params,                               const char **error){    char *server = NULL;    DBPROCESS *process;    LOGINREC *login;    static const char *delims = " \r\n\t;|,";    char *ptr;    char *key;    char *value;    int vlen;    int klen;    char *buf;    char *databaseName = NULL;    /* FIXME - this uses malloc */    /* FIXME - pass error message back to the caller in case of failure */    login = dblogin();    if (login == NULL) {        return NULL;    }    /* now set login properties */    for (ptr = strchr(params, '='); ptr; ptr = strchr(ptr, '=')) {        /* don't dereference memory that may not belong to us */        if (ptr == params) {            ++ptr;            continue;        }        for (key = ptr-1; isspace(*key); --key);        klen = 0;        while (isalpha(*key)) {            --key;            ++klen;        }        ++key;        for (value = ptr+1; isspace(*value); ++value);        vlen = strcspn(value, delims);        buf = apr_pstrndup(pool, value, vlen);        /* NULL-terminated copy */        if (!strncasecmp(key, "username", klen)) {            DBSETLUSER(login, buf);        }        else if (!strncasecmp(key, "password", klen)) {            DBSETLPWD(login, buf);        }        else if (!strncasecmp(key, "appname", klen)) {            DBSETLAPP(login, buf);        }        else if (!strncasecmp(key, "dbname", klen)) {            databaseName = buf;        }        else if (!strncasecmp(key, "host", klen)) {            DBSETLHOST(login, buf);        }        else if (!strncasecmp(key, "charset", klen)) {            DBSETLCHARSET(login, buf);        }        else if (!strncasecmp(key, "lang", klen)) {            DBSETLNATLANG(login, buf);        }        else if (!strncasecmp(key, "server", klen)) {            server = buf;        }        else {            /* unknown param */        }        ptr = value+vlen;    }    process = dbopen(login, server);    fprintf(stderr, "databaseName [%s]\n", databaseName);    if (databaseName != NULL)    {        dbuse(process, databaseName);    }     dbloginfree(login);    if (process == NULL) {        return NULL;    }    return process;}static apr_dbd_t *dbd_freetds_open(apr_pool_t *pool, const char *params,                                   const char **error){    apr_dbd_t *sql;    /* FIXME - pass error message back to the caller in case of failure */    DBPROCESS *process = freetds_open(pool, params, error);    if (process == NULL) {        return NULL;    }    sql = apr_palloc (pool, sizeof (apr_dbd_t));    sql->pool = pool;    sql->proc = process;    sql->params = params;    return sql;}static apr_status_t dbd_freetds_close(apr_dbd_t *handle){    dbclose(handle->proc);    return APR_SUCCESS;}static apr_status_t dbd_freetds_check_conn(apr_pool_t *pool,                                           apr_dbd_t *handle){    if (dbdead(handle->proc)) {        /* try again */        dbclose(handle->proc);        handle->proc = freetds_open(handle->pool, handle->params);        if (!handle->proc || dbdead(handle->proc)) {            return APR_EGENERAL;        }    }    /* clear it, in case this is called in error handling */    dbcancel(handle->proc);    return APR_SUCCESS;}static int dbd_freetds_select_db(apr_pool_t *pool, apr_dbd_t *handle,                               const char *name){    /* ouch, it's declared int.  But we can use APR 0/nonzero */    return (dbuse(handle->proc, (char*)name) == SUCCEED) ? APR_SUCCESS : APR_EGENERAL;}static void *dbd_freetds_native(apr_dbd_t *handle){    return handle->proc;}static int dbd_freetds_num_cols(apr_dbd_results_t* res){    return res->sz;}static int dbd_freetds_num_tuples(apr_dbd_results_t* res){    if (res->random) {        return res->ntuples;    }    else {        return -1;    }}static apr_status_t freetds_term(void *dummy){    dbexit();    regfree(&dbd_freetds_find_arg);    return APR_SUCCESS;}static void dbd_freetds_init(apr_pool_t *pool){    int rv = regcomp(&dbd_freetds_find_arg,                     "%(\\{[^}]*\\})?([0-9]*)[A-Za-z]", REG_EXTENDED);    if (rv != 0) {        char errmsg[256];        regerror(rv, &dbd_freetds_find_arg, errmsg, 256);        fprintf(stderr, "regcomp failed: %s\n", errmsg);    }    dbinit();    apr_pool_cleanup_register(pool, NULL, freetds_term, apr_pool_cleanup_null);}#ifdef COMPILE_STUBS/* get_name is the only one of these that is implemented */static const char *dbd_freetds_get_name(const apr_dbd_results_t *res, int n){    return (const char*) dbcolname(res->proc, n+1); /* numbering starts at 1 */}/* These are stubs: transaction modes not implemented here */#define DBD_NOTIMPL APR_ENOTIMPL;static int dbd_freetds_transaction_mode_get(apr_dbd_transaction_t *trans){    return trans ? trans->mode : APR_DBD_TRANSACTION_COMMIT;}static int dbd_freetds_transaction_mode_set(apr_dbd_transaction_t *trans,                                            int mode){    if (trans) {        trans->mode = mode & TXN_MODE_BITS;        return trans->mode;    }    return APR_DBD_TRANSACTION_COMMIT;}static int dbd_freetds_pvbquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,                                apr_dbd_prepared_t *statement, va_list args){    return DBD_NOTIMPL;}static int dbd_freetds_pbquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows,                               apr_dbd_prepared_t * statement,                               const void **values){    return DBD_NOTIMPL;}static int dbd_freetds_pvbselect(apr_pool_t *pool, apr_dbd_t *sql,                                 apr_dbd_results_t **results,                                 apr_dbd_prepared_t *statement,                                 int seek, va_list args){    return DBD_NOTIMPL;}static int dbd_freetds_pbselect(apr_pool_t *pool, apr_dbd_t *sql,                                apr_dbd_results_t **results,                                apr_dbd_prepared_t *statement,                                int seek, const void **values){    return DBD_NOTIMPL;}static apr_status_t dbd_freetds_datum_get(const apr_dbd_row_t *row, int n,                                          apr_dbd_type_e type, void *data){    return APR_ENOTIMPL;}#endifAPU_MODULE_DECLARE_DATA const apr_dbd_driver_t apr_dbd_freetds_driver = {    "freetds",    dbd_freetds_init,    dbd_freetds_native,    dbd_freetds_open,    dbd_freetds_check_conn,    dbd_freetds_close,    dbd_freetds_select_db,    dbd_freetds_start_transaction,    dbd_freetds_end_transaction,    dbd_freetds_query,    dbd_freetds_select,    dbd_freetds_num_cols,    dbd_freetds_num_tuples,    dbd_freetds_get_row,    dbd_freetds_get_entry,    dbd_freetds_error,    dbd_freetds_escape,    dbd_freetds_prepare,    dbd_freetds_pvquery,    dbd_freetds_pvselect,    dbd_freetds_pquery,    dbd_freetds_pselect,    /* this is only implemented to support httpd/2.2 standard usage,     * as in the original DBD implementation.  Everything else is NOTIMPL.     */#ifdef COMPILE_STUBS    dbd_freetds_get_name,    dbd_freetds_transaction_mode_get,    dbd_freetds_transaction_mode_set,    "",    dbd_freetds_pvbquery,    dbd_freetds_pvbselect,    dbd_freetds_pbquery,    dbd_freetds_pbselect,    dbd_freetds_datum_get#endif};#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?