浏览代码

- Better mysql URL parser

Jan Janak 22 年之前
父节点
当前提交
e3a64d8b5b
共有 4 个文件被更改,包括 128 次插入87 次删除
  1. 0 1
      modules/db_mysql/Makefile
  2. 2 2
      modules/db_mysql/dbase.c
  3. 120 78
      modules/db_mysql/utils.c
  4. 6 6
      modules/db_mysql/utils.h

+ 0 - 1
modules/db_mysql/Makefile

@@ -6,7 +6,6 @@ include ../../Makefile.defs
 auto_gen=
 NAME=mysql.so
 
-
 # mysql.h locations (freebsd,openbsd  solaris)
 DEFS +=-I$(LOCALBASE)/include -I$(LOCALBASE)/include/mysql \
 		-I$(LOCALBASE)/mysql/include -I/usr/pkg/include \

+ 2 - 2
modules/db_mysql/dbase.c

@@ -73,8 +73,8 @@ static inline int connect_db(db_con_t* _h, const char* _db_url)
 	}
 	memcpy(buf, _db_url, l + 1);
 
-	res = parse_sql_url(buf, &user, &password, &host, &port, &database);
-	if (port) {
+	res = parse_mysql_url(buf, &user, &password, &host, &port, &database);
+	if (port && *port) {
 		p = atoi(port);
 	} else {
 		p = 0;

+ 120 - 78
modules/db_mysql/utils.c

@@ -34,40 +34,11 @@
 
 #define _XOPEN_SOURCE
 
+#include <strings.h>
 #include <string.h>
 #include "defs.h"
 #include "utils.h"
 
-/* FIXME: to be removed */
-
-/*
- * Remove any tabs and spaces from the begining and the end of
- * a string
- */
-char* trim(char* _s)
-{
-	int len;
-	char* end;
-
-	     /* Null pointer, there is nothing to do */
-	if (!_s) return _s;
-
-	     /* Remove spaces and tabs from the begining of string */
-	while ((*_s == ' ') || (*_s == '\t')) _s++;
-
-	len = strlen(_s);
-
-        end = _s + len - 1;
-
-	     /* Remove trailing spaces and tabs */
-	while ((*end == ' ') || (*end == '\t')) end--;
-	if (end != (_s + len - 1)) {
-		*(end+1) = '\0';
-	}
-
-	return _s;
-}
-
 
 /*
  * Convert time_t structure to format accepted by MySQL database
@@ -108,70 +79,141 @@ time_t mysql2time(const char* _str)
 }
 
 
-/* FIXME */
 /*
- * SQL URL parser
+ * Parse a mysql database URL of form 
+ * mysql://[username[:password]@]hostname[:port]/database
+ *
+ * Returns 0 if parsing was sucessful and -1 otherwise
  */
-int parse_sql_url(char* _url, char** _user, char** _pass, 
-		  char** _host, char** _port, char** _db)
+int parse_mysql_url(char* _url, char** _user, char** _pass,
+		    char** _host, char** _port, char** _db)
 {
-	char* slash, *dcolon, *at, *db_slash;
+#define SHORTEST_MYSQL_URL "mysql://a/b"
+#define SHORTEST_MYSQL_URL_LEN (sizeof(SHORTEST_MYSQL_URL) - 1)
+
+#define MYSQL_URL_PREFIX "mysql://"
+#define MYSQL_URL_PREFIX_LEN (sizeof(MYSQL_URL_PREFIX) - 1)
+
+	enum state {
+		ST_USER_HOST,  /* Username or hostname */
+		ST_PASS_PORT,  /* Password or port part */
+		ST_HOST,       /* Hostname part */
+		ST_PORT,       /* Port part */
+		ST_DB          /* Database part */
+	};
+
+	enum state st;
+	int len, i;
+	char* begin, *prev_begin;
+
+	if (!_url || !_user || !_pass || !_host || !_port || !_db) {
+		return -1;
+	}
+	
+	len = strlen(_url);
+	if (len < SHORTEST_MYSQL_URL_LEN) {
+		return -1;
+	}
+	
+	if (strncasecmp(_url, MYSQL_URL_PREFIX, MYSQL_URL_PREFIX_LEN)) {
+		return -1;
+	}
 
+	     /* Skip the prefix part */
+	_url += MYSQL_URL_PREFIX_LEN;
+	len -= MYSQL_URL_PREFIX_LEN;
+	
+	     /* Initialize all variables */
 	*_user = '\0';
 	*_pass = '\0';
 	*_host = '\0';
 	*_port = '\0';
 	*_db   = '\0';
 
-	     /* Remove any leading and trailing spaces and tab */
-	_url = trim(_url);
-
-	if (strlen(_url) < 6) return -1;
-
-	if (*_url == '\0') return -2; /* Empty string */
-
-	slash = strchr(_url, '/');
-	if (!slash) return -3;   /* Invalid string, slashes not found */
-
-	if ((*(++slash)) != '/') {  /* Invalid URL, 2nd slash not found */
-		return -4;
-	}
+	st = ST_USER_HOST;
+	begin = _url;
+	prev_begin = 0;
+
+	for(i = 0; i < len; i++) {
+		switch(st) {
+		case ST_USER_HOST:
+			switch(_url[i]) {
+			case '@':
+				st = ST_HOST;
+				*_user = begin;
+				begin = _url + i + 1;
+				_url[i] = '\0';
+				break;
+
+			case ':':
+				st = ST_PASS_PORT;
+				prev_begin = begin;
+				begin = _url + i + 1;
+				_url[i] = '\0';
+				break;
+
+			case '/':
+				*_host = begin;
+				_url[i] = '\0';
+
+				*_db = _url + i + 1;
+				return 0;
+			}
 
-	slash++;
+		case ST_PASS_PORT:
+			switch(_url[i]) {
+			case '@':
+				st = ST_HOST;
+				*_user = prev_begin;
+				*_pass = begin;
+				begin = _url + i + 1;
+				_url[i] = '\0';
+				break;
+
+			case '/':
+				*_host = prev_begin;
+				*_port = begin;
+				_url[i] = '\0';
+
+				*_db = _url + i + 1;
+				return 0;
+			}
 
-	at = strchr(slash, '@');
+		case ST_HOST:
+			switch(_url[i]) {
+			case ':':
+				st = ST_PORT;
+				*_host = begin;
+				begin = _url + i + 1;
+				_url[i] = '\0';
+				break;
+
+			case '/':
+				*_host = begin;
+				_url[i] = '\0';
+
+				*_db = _url + i + 1;
+				return 0;
+			}
 
-	db_slash = strchr(slash, '/');
-	if (db_slash) {
-		*db_slash++ = '\0';
-		*_db = trim(db_slash);
-	}
+		case ST_PORT:
+			switch(_url[i]) {
+			case '/':
+				*_port = begin;
+				_url[i] = '\0';
 
-	if (!at) {
-		dcolon = strchr(slash, ':');
-		if (dcolon) {
-			*dcolon++ = '\0';
-			*_port = trim(dcolon);
-		}
-		*_host = trim(slash);
-	} else {
-		dcolon = strchr(slash, ':');
-	        *at++ = '\0';
-		if (dcolon) {
-			*dcolon++ = '\0';
-			if (dcolon < at) {   /* user:passwd */
-				*_pass = trim(dcolon);
-				dcolon = strchr(at, ':');
-				if (dcolon) {  /* host:port */
-					*dcolon++ = '\0';
-					*_port = trim(dcolon);
-				}
-			} else {            /* host:port */
-				*_port = trim(dcolon);
+				*_db = _url + i + 1;
+				return 0;
 			}
+			break;
+			
+		case ST_DB:
+			break;
 		}
-		*_host = trim(at);
-		*_user = trim(slash);
+	}
+
+	if (st != ST_DB) {
+		return -1;
 	}
 
 	return 0;

+ 6 - 6
modules/db_mysql/utils.h

@@ -34,9 +34,6 @@
 #include <time.h>
 
 
-char* trim(char* _s);
-
-
 /*
  * Convert time_t structure to format accepted by MySQL database
  */
@@ -50,10 +47,13 @@ time_t mysql2time(const char* _str);
 
 
 /*
- * SQL URL parser
+ * Parse a mysql database URL of form 
+ * mysql://[username[:password]@]hostname[:port]/database
+ *
+ * Returns 0 if parsing was sucessful and -1 otherwise
  */
-int parse_sql_url(char* _url, char** _user, char** _pass, 
-		  char** _host, char** _port, char** _db);
+int parse_mysql_url(char* _url, char** _user, char** _pass,
+		    char** _host, char** _port, char** _db);
 
 
 #endif /* UTILS_H */