⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdb_sql.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	/* insert the result */	log_debug2(ZONE, LOGT_STORAGE, "the row results in: %s", xmlnode2str(new_instance));	xmlnode_insert_node(result, xmlnode_get_firstchild(new_instance));    }    PQclear(res);    return 0;#else    log_debug2(ZONE, LOGT_STRANGE, "xdb_sql_execute_postgresql called, but not compiled in.");    return 1;#endif}/** * execute a sql query * * @param i the instance we are running in * @param xq instance internal data * @param query the SQL query to execute * @param template template to construct the result * @param result where to add the results * @return 0 on success, non zero on failure */int xdb_sql_execute(instance i, xdbsql xq, char *query, xmlnode template, xmlnode result) {#ifdef HAVE_MYSQL    if (xq->use_mysql) {	return xdb_sql_execute_mysql(i, xq, query, template, result);    }#endif#ifdef HAVE_POSTGRESQL    if (xq->use_postgresql) {	return xdb_sql_execute_postgresql(i, xq, query, template, result);    }#endif    log_error(i->id, "SQL query %s has not been handled by any sql driver", query);    return 1;}/** * modify xdb query to be a result, that can be sent back * * @param p the packet that should be modified */void xdb_sql_makeresult(dpacket p) {    xmlnode_put_attrib(p->x, "type", "result");    xmlnode_put_attrib(p->x, "to", xmlnode_get_attrib(p->x, "from"));    xmlnode_put_attrib(p->x, "from", jid_full(p->id));}/** * callback function that is called by jabberd to handle xdb requests * * @param i the instance we are for jabberd * @param p the packet containing the xdb query * @param arg pointer to our own internal data * @return r_DONE if we could handle the request, r_ERR otherwise */result xdb_sql_phandler(instance i, dpacket p, void *arg) {    xdbsql xq = (xdbsql)arg;	/* xdb_sql internal data */    char *ns = NULL;		/* namespace of the query */    xdbsql_ns_def ns_def = NULL; /* pointer to the namespace definitions */    int is_set_request = 0;	/* if this is a set request */    char *action = NULL;	/* xdb-set action */    char *match = NULL;		/* xdb-set match */    log_debug2(ZONE, LOGT_STORAGE|LOGT_DELIVER, "handling xdb request %s", xmlnode2str(p->x));    /* get the namespace of the request */    ns = xmlnode_get_attrib(p->x, "ns");    if (ns == NULL) {	log_debug2(ZONE, LOGT_STORAGE|LOGT_STRANGE, "xdb_sql got a xdb request without namespace");	return r_ERR;    }    /* check if we know how to handle this namespace */    ns_def = xhash_get(xq->namespace_defs, ns);    if (ns_def == NULL) {	log_error(i->id, "xdb_sql got a xdb request for an unconfigured namespace %s, use this handler only for selected namespaces.", ns);	return r_ERR;    }    /* check the type of xdb request */    is_set_request = (j_strcmp(xmlnode_get_attrib(p->x, "type"), "set") == 0);    if (is_set_request) {	/* set request */	action = xmlnode_get_attrib(p->x, "action");	match = xmlnode_get_attrib(p->x, "match");	if (action == NULL) {	    char *query = NULL;	    	    /* just a boring set */	    /* start the transaction */	    xdb_sql_execute(i, xq, "BEGIN", NULL, NULL);	    /* delete old values */	    query = xdb_sql_construct_query(ns_def->delete, p->x);	    log_debug2(ZONE, LOGT_STORAGE, "using the following SQL statement for deletion: %s", query);	    if (xdb_sql_execute(i, xq, query, NULL, NULL)) {		/* SQL query failed */		xdb_sql_execute(i, xq, "ROLLBACK", NULL, NULL);		return r_ERR;	    }	    /* insert new values (if there are any) */	    if (xmlnode_get_firstchild(p->x) != NULL) {		query = xdb_sql_construct_query(ns_def->set, p->x);		log_debug2(ZONE, LOGT_STORAGE, "using the following SQL statement for insertion: %s", query);		if (xdb_sql_execute(i, xq, query, NULL, NULL)) {		    /* SQL query failed */		    xdb_sql_execute(i, xq, "ROLLBACK", NULL, NULL);		    return r_ERR;		}	    }	    /* commit the transaction */	    xdb_sql_execute(i, xq, "COMMIT", NULL, NULL);	    /* send result back */	    xdb_sql_makeresult(p);	    deliver(dpacket_new(p->x), NULL);	    return r_DONE;	} else if (j_strcmp(action, "insert") == 0) {	    char *query = NULL;	    /* start the transaction */	    xdb_sql_execute(i, xq, "BEGIN", NULL, NULL);	    /* insert new values */	    query = xdb_sql_construct_query(ns_def->set, p->x);	    log_debug2(ZONE, LOGT_STORAGE, "using the following SQL statement for insertion: %s", query);	    if (xdb_sql_execute(i, xq, query, NULL, NULL)) {		/* SQL query failed */		xdb_sql_execute(i, xq, "ROLLBACK", NULL, NULL);		return r_ERR;	    }	    /* commit the transaction */	    xdb_sql_execute(i, xq, "COMMIT", NULL, NULL);	    /* send result back */	    xdb_sql_makeresult(p);	    deliver(dpacket_new(p->x), NULL);	    return r_DONE;	} else {	    /* not supported action, probably check */	    log_warn(i->id, "unable to handle unsupported xdb-set action '%s'", action);	    return r_ERR;	}    } else {	char *query = NULL;	char *group_element = NULL;	xmlnode result_element = p->x;	/* get request */	/* start the transaction */	xdb_sql_execute(i, xq, "BEGIN", NULL, NULL);	/* get the record(s) */	query = xdb_sql_construct_query(ns_def->get_query, p->x);	group_element = xmlnode_get_attrib(ns_def->get_result, "group");	if (group_element != NULL) {	    result_element = xmlnode_insert_tag(result_element, group_element);	    xmlnode_put_attrib(result_element, "ns", ns);	}	log_debug2(ZONE, LOGT_STORAGE, "using the following SQL statement for selection: %s", query);	if (xdb_sql_execute(i, xq, query, ns_def->get_result, result_element)) {	    /* SQL query failed */	    xdb_sql_execute(i, xq, "ROLLBACK", NULL, NULL);	    return r_ERR;	}	/* commit the transaction */	xdb_sql_execute(i, xq, "COMMIT", NULL, NULL);	/* construct the result */	xdb_sql_makeresult(p);	deliver(dpacket_new(p->x), NULL);	return r_DONE;    }}/** * init the mysql driver * * @param i the instance we are (jabberd's view) * @param xq our internal instance data * @param config the configuration node of this instance */void xdb_sql_mysql_init(instance i, xdbsql xq, xmlnode config) {#ifdef HAVE_MYSQL    /* create a MYSQL handle */    if (xq->mysql == NULL) {	xq->mysql = mysql_init(NULL);    }    /* process our own configuration */    xq->mysql_user = pstrdup(i->p, xmlnode_get_tag_data(config, "mysql/user"));    xq->mysql_password = pstrdup(i->p, xmlnode_get_tag_data(config, "mysql/password"));    xq->mysql_host = pstrdup(i->p, xmlnode_get_tag_data(config, "mysql/host"));    xq->mysql_database = pstrdup(i->p, xmlnode_get_tag_data(config, "mysql/database"));    xq->mysql_port = j_atoi(xmlnode_get_tag_data(config, "mysql/port"), 0);    xq->mysql_socket = pstrdup(i->p, xmlnode_get_tag_data(config, "mysql/socket"));    xq->mysql_flag = j_atoi(xmlnode_get_tag_data(config, "mysql/flag"), 0);    /* connect to the database server */    xdb_sql_mysql_connect(i, xq);#else    log_debug2(ZONE, LOGT_STRANGE, "xdb_sql_mysql_init called, but not compiled in.");#endif}/** * init the postgresql driver * * @param i the instance we are (jabberd's view) * @param xq our internal instance data * @param config the configuration node of this instance */void xdb_sql_postgresql_init(instance i, xdbsql xq, xmlnode config) {#ifdef HAVE_POSTGRESQL    /* process our own configuration */    xq->postgresql_conninfo = pstrdup(i->p, xmlnode_get_tag_data(config, "postgresql/conninfo"));    /* connect to the database server */    xq->postgresql = PQconnectdb(xq->postgresql_conninfo);    /* did we connect? */    if (PQstatus(xq->postgresql) != CONNECTION_OK) {	log_error(i->id, "failed to connect to postgresql server: %s", PQerrorMessage(xq->postgresql));    }#else    log_debug2(ZONE, LOGT_STRANGE, "xdb_sql_postgresql_init called, but not compiled in.");#endif}/** * preprocess a SQL query definition * * @param i the instance we are running in * @param query the SQL query definition * @return array of preprocessed query, contains array of strings, odd entries are literals, even entries are variables */char **xdb_sql_query_preprocess(instance i, char *query) {    int count = 0;    char *pos = NULL;    char *next = NULL;    char **result = NULL;    /* check provieded parameters */    if (i == NULL || query == NULL) {	return NULL;    }    /* make a copy of the query that we can tokenize */    query = pstrdup(i->p, query);    /* go to the start of the query */    pos = query;    /* estimate the number of variables in the string */    while ( (pos = strstr(pos, "{")) != NULL ) {	/* don't find this variable again */	pos++;	/* count the number of variables */	count++;    }    /* allocate memory for the array */    result = pmalloco(i->p, (count+1)*2*sizeof(char*));    /* tokenize the query */    count = 0;    pos = query;    while (pos != NULL) {	/* find start or end of variable	 * if count is odd we search for end of variable	 * if count is even we search for the begin of a variable	 */	next = (count % 2) ? strstr(pos, "}") : strstr(pos, "{");	/* tokenize */	if (next != NULL) {	    *next = 0;	}	/* store the pointer to this token */	result[count] = pos;	/* skip the token separator { or } */	if (next != NULL) {	    next++;	}	/* next search starts where next points to */	pos = next;	count++;    }    return result;}/** * process a handler definition * * @param i the instance we are running as * @param xq our instance internal data * @param handler the handler definition */void xdb_sql_handler_process(instance i, xdbsql xq, xmlnode handler) {    char *handled_ns = NULL;	/* which namespace this definition is for */    xdbsql_ns_def nsdef = NULL;	/* where to store the processed information */    int count = 0;    char *temp = NULL;        log_debug2(ZONE, LOGT_INIT, "processing handler definition: %s", xmlnode2str(handler));    nsdef = pmalloco(i->p, sizeof(_xdbsql_ns_def));    /* query the relevant tags from this handler */    handled_ns = pstrdup(i->p, xmlnode_get_attrib(handler, "ns"));    temp = xmlnode_get_tag_data(handler, "get/query");    nsdef->get_query = xdb_sql_query_preprocess(i, temp);    nsdef->get_result = xmlnode_dup_pool(i->p, xmlnode_get_tag(handler, "get/result"));    temp = xmlnode_get_tag_data(handler, "set");    nsdef->set = xdb_sql_query_preprocess(i, temp);    temp = xmlnode_get_tag_data(handler, "delete");    nsdef->delete = xdb_sql_query_preprocess(i, temp);    /* store the read definition */    log_debug2(ZONE, LOGT_INIT|LOGT_STORAGE, "registering namespace handler for %s", handled_ns);    xhash_put(xq->namespace_defs, handled_ns, nsdef);}/** * read the handler configuration and generate their internal representation * * @param i the instance we are running as * @param xq our instance internal data * @param config the configuration data for this xdb_sql instance */void xdb_sql_handler_read(instance i, xdbsql xq, xmlnode config) {    xmlnode cur = NULL;		/* used to iterate through <handler/> elements */        if (i == NULL || xq == NULL || config == NULL) {	log_debug2(ZONE, LOGT_STRANGE|LOGT_INIT|LOGT_STORAGE, "called xdb_sql_handler_read with i, xq, or config as NULL");	return;    }    for (cur = xmlnode_get_firstchild(config); cur != NULL; cur = xmlnode_get_nextsibling(cur)) {	/* we only care for <handler/> elements */	char *element_name = xmlnode_get_name(cur);	if (j_strcmp(element_name, "handler") != 0) {	    continue;	}	/* process this handler definition */	xdb_sql_handler_process(i, xq, cur);    }}/** * init the xdb_sql module, called by the jabberd module loader * * @param i jabberd's data about our instance * @param x the <load/> xmlnode that instructed the moduleloader to load us */void xdb_sql(instance i, xmlnode x) {    xdbcache xc;		/* to fetch our configuration */    xmlnode config = NULL;	/* our configuration */    xdbsql xq = NULL;		/* pointer to instance internal data */    char *driver = NULL;	/* database driver to use */    /* output a first sign of life ... :) */    log_debug2(ZONE, LOGT_INIT, "xdb_sql loading");    /* fetch our own configuration */    xc = xdb_cache(i);    if (xc != NULL) {	config = xdb_get(xc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:xdb_sql");    }    if (config == NULL) {	log_error(i->id, "xdb_sql failed to load its configuration");	return;    }    /* create our internal data */    xq = pmalloco(i->p, sizeof(_xdbsql));    xq->namespace_defs = xhash_new(j_atoi(xmlnode_get_tag_data(config, "maxns"), XDBSQL_MAXNS_PRIME));    /* use which driver? */    driver = xmlnode_get_tag_data(config, "driver");    if (driver == NULL) {	log_error(i->id, "you have to configure which driver xdb_sql should use");	xmlnode_free(config);	return;#ifdef HAVE_MYSQL    } else if (j_strcmp(driver, "mysql") == 0) {	xq->use_mysql = 1;		/* use mysql for the queries */	xdb_sql_mysql_init(i, xq, config);#endif#ifdef HAVE_POSTGRESQL    } else if (j_strcmp(driver, "postgresql") == 0) {	xq->use_postgresql = 1;		/* use postgresql for the queries */	xdb_sql_postgresql_init(i, xq, config);#endif    } else {	log_error(i->id, "Your xdb_sql is compiled without support for the selected database driver '%s'.", driver);    }    /* read the handler defintions */    xdb_sql_handler_read(i, xq, config);    /* register our packet handler */    register_phandler(i, o_DELIVER, xdb_sql_phandler, (void *)xq);    /* free the configuration we have processed */    xmlnode_free(config);}

⌨️ 快捷键说明

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