00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "db_id.h"
00031 #include "../dprint.h"
00032 #include "../mem/mem.h"
00033 #include "../ut.h"
00034 #include <stdlib.h>
00035 #include <string.h>
00036
00037
00038
00039
00040
00041
00042
00043
00044 static int dupl_string(char** dst, const char* begin, const char* end)
00045 {
00046 if (*dst) pkg_free(*dst);
00047
00048 *dst = pkg_malloc(end - begin + 1);
00049 if ((*dst) == NULL) {
00050 return -1;
00051 }
00052
00053 memcpy(*dst, begin, end - begin);
00054 (*dst)[end - begin] = '\0';
00055 return 0;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 static int parse_db_url(struct db_id* id, const str* url)
00068 {
00069 #define SHORTEST_DB_URL "s://a/b"
00070 #define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1)
00071
00072 enum state {
00073 ST_SCHEME,
00074 ST_SLASH1,
00075 ST_SLASH2,
00076 ST_USER_HOST,
00077 ST_PASS_PORT,
00078 ST_HOST,
00079 ST_PORT,
00080 ST_DB
00081 };
00082
00083 enum state st;
00084 unsigned int len, i;
00085 const char* begin;
00086 char* prev_token;
00087
00088 prev_token = 0;
00089
00090 if (!id || !url || !url->s) {
00091 goto err;
00092 }
00093
00094 len = url->len;
00095 if (len < SHORTEST_DB_URL_LEN) {
00096 goto err;
00097 }
00098
00099
00100 memset(id, 0, sizeof(struct db_id));
00101 st = ST_SCHEME;
00102 begin = url->s;
00103
00104 for(i = 0; i < len; i++) {
00105 switch(st) {
00106 case ST_SCHEME:
00107 switch(url->s[i]) {
00108 case ':':
00109 st = ST_SLASH1;
00110 if (dupl_string(&id->scheme, begin, url->s + i) < 0) goto err;
00111 break;
00112 }
00113 break;
00114
00115 case ST_SLASH1:
00116 switch(url->s[i]) {
00117 case '/':
00118 st = ST_SLASH2;
00119 break;
00120
00121 default:
00122 goto err;
00123 }
00124 break;
00125
00126 case ST_SLASH2:
00127 switch(url->s[i]) {
00128 case '/':
00129 st = ST_USER_HOST;
00130 begin = url->s + i + 1;
00131 break;
00132
00133 default:
00134 goto err;
00135 }
00136 break;
00137
00138 case ST_USER_HOST:
00139 switch(url->s[i]) {
00140 case '@':
00141 st = ST_HOST;
00142 if (dupl_string(&id->username, begin, url->s + i) < 0) goto err;
00143 begin = url->s + i + 1;
00144 break;
00145
00146 case ':':
00147 st = ST_PASS_PORT;
00148 if (dupl_string(&prev_token, begin, url->s + i) < 0) goto err;
00149 begin = url->s + i + 1;
00150 break;
00151
00152 case '/':
00153 if (dupl_string(&id->host, begin, url->s + i) < 0) goto err;
00154 if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;
00155 return 0;
00156 }
00157 break;
00158
00159 case ST_PASS_PORT:
00160 switch(url->s[i]) {
00161 case '@':
00162 st = ST_HOST;
00163 id->username = prev_token;
00164 if (dupl_string(&id->password, begin, url->s + i) < 0) goto err;
00165 begin = url->s + i + 1;
00166 break;
00167
00168 case '/':
00169 id->host = prev_token;
00170 id->port = str2s(begin, url->s + i - begin, 0);
00171 if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;
00172 return 0;
00173 }
00174 break;
00175
00176 case ST_HOST:
00177 switch(url->s[i]) {
00178 case ':':
00179 st = ST_PORT;
00180 if (dupl_string(&id->host, begin, url->s + i) < 0) goto err;
00181 begin = url->s + i + 1;
00182 break;
00183
00184 case '/':
00185 if (dupl_string(&id->host, begin, url->s + i) < 0) goto err;
00186 if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;
00187 return 0;
00188 }
00189 break;
00190
00191 case ST_PORT:
00192 switch(url->s[i]) {
00193 case '/':
00194 id->port = str2s(begin, url->s + i - begin, 0);
00195 if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err;
00196 return 0;
00197 }
00198 break;
00199
00200 case ST_DB:
00201 break;
00202 }
00203 }
00204
00205 if (st != ST_DB) goto err;
00206 return 0;
00207
00208 err:
00209 if (id->scheme) pkg_free(id->scheme);
00210 if (id->username) pkg_free(id->username);
00211 if (id->password) pkg_free(id->password);
00212 if (id->host) pkg_free(id->host);
00213 if (id->database) pkg_free(id->database);
00214 if (prev_token) pkg_free(prev_token);
00215 return -1;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 struct db_id* new_db_id(const str* url)
00225 {
00226 struct db_id* ptr;
00227
00228 if (!url || !url->s) {
00229 LM_ERR("invalid parameter\n");
00230 return 0;
00231 }
00232
00233 ptr = (struct db_id*)pkg_malloc(sizeof(struct db_id));
00234 if (!ptr) {
00235 LM_ERR("no private memory left\n");
00236 goto err;
00237 }
00238 memset(ptr, 0, sizeof(struct db_id));
00239
00240 if (parse_db_url(ptr, url) < 0) {
00241 LM_ERR("error while parsing database URL: '%.*s' \n", url->len, url->s);
00242 goto err;
00243 }
00244
00245 return ptr;
00246
00247 err:
00248 if (ptr) pkg_free(ptr);
00249 return 0;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 unsigned char cmp_db_id(const struct db_id* id1, const struct db_id* id2)
00260 {
00261 if (!id1 || !id2) return 0;
00262 if (id1->port != id2->port) return 0;
00263
00264 if (strcmp(id1->scheme, id2->scheme)) return 0;
00265 if (id1->username!=0 && id2->username!=0) {
00266 if (strcmp(id1->username, id2->username)) return 0;
00267 } else {
00268 if (id1->username!=0 || id2->username!=0) return 0;
00269 }
00270 if (id1->password!=0 && id2->password!=0) {
00271 if(strcmp(id1->password, id2->password)) return 0;
00272 } else {
00273 if (id1->password!=0 || id2->password!=0) return 0;
00274 }
00275 if (strcasecmp(id1->host, id2->host)) return 0;
00276 if (strcmp(id1->database, id2->database)) return 0;
00277 return 1;
00278 }
00279
00280
00281
00282
00283
00284
00285 void free_db_id(struct db_id* id)
00286 {
00287 if (!id) return;
00288
00289 if (id->scheme) pkg_free(id->scheme);
00290 if (id->username) pkg_free(id->username);
00291 if (id->password) pkg_free(id->password);
00292 if (id->host) pkg_free(id->host);
00293 if (id->database) pkg_free(id->database);
00294 pkg_free(id);
00295 }