00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "asterisk.h"
00023
00024 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 351618 $")
00025
00026 #include "include/sip.h"
00027 #include "include/sip_utils.h"
00028 #include "include/reqresp_parser.h"
00029
00030 #ifdef HAVE_XLOCALE_H
00031 locale_t c_locale;
00032 #endif
00033
00034
00035 int parse_uri_full(char *uri, const char *scheme, char **user, char **pass,
00036 char **hostport, struct uriparams *params, char **headers,
00037 char **residue)
00038 {
00039 char *userinfo = NULL;
00040 char *parameters = NULL;
00041 char *endparams = NULL;
00042 char *c = NULL;
00043 int error = 0;
00044
00045
00046
00047
00048
00049
00050 if (user) {
00051 *user = "";
00052 }
00053 if (pass) {
00054 *pass = "";
00055 }
00056 if (hostport) {
00057 *hostport = "";
00058 }
00059 if (headers) {
00060 *headers = "";
00061 }
00062 if (residue) {
00063 *residue = "";
00064 }
00065
00066
00067 if (ast_strlen_zero(uri)) {
00068 return -1;
00069 }
00070
00071 if (scheme) {
00072 int l;
00073 char *scheme2 = ast_strdupa(scheme);
00074 char *cur = strsep(&scheme2, ",");
00075 for (; !ast_strlen_zero(cur); cur = strsep(&scheme2, ",")) {
00076 l = strlen(cur);
00077 if (!strncasecmp(uri, cur, l)) {
00078 uri += l;
00079 break;
00080 }
00081 }
00082 if (ast_strlen_zero(cur)) {
00083 ast_debug(1, "No supported scheme found in '%s' using the scheme[s] %s\n", uri, scheme);
00084 error = -1;
00085 }
00086 }
00087
00088 if (!hostport) {
00089
00090
00091 userinfo = uri;
00092 } else {
00093 char *dom = "";
00094 if ((c = strchr(uri, '@'))) {
00095 *c++ = '\0';
00096 dom = c;
00097 userinfo = uri;
00098 uri = c;
00099 } else {
00100
00101 dom = uri;
00102 userinfo = "";
00103 }
00104
00105 *hostport = dom;
00106 }
00107
00108 if (pass && (c = strchr(userinfo, ':'))) {
00109 *c++ = '\0';
00110 *pass = c;
00111 } else if (pass) {
00112 *pass = "";
00113 }
00114
00115 if (user) {
00116 *user = userinfo;
00117 }
00118
00119 parameters = uri;
00120
00121 if ((c = strrchr(uri, '?'))) {
00122 *c++ = '\0';
00123 uri = c;
00124 if (headers) {
00125 *headers = c;
00126 }
00127 if ((c = strrchr(uri, ';'))) {
00128 *c++ = '\0';
00129 } else {
00130 c = strrchr(uri, '\0');
00131 }
00132 uri = c;
00133
00134
00135 } else if (headers) {
00136 *headers = "";
00137 }
00138
00139
00140 endparams = strchr(parameters,'\0');
00141 if ((c = strchr(parameters, ';'))) {
00142 *c++ = '\0';
00143 parameters = c;
00144 } else {
00145 parameters = endparams;
00146 }
00147
00148 if (params) {
00149 char *rem = parameters;
00150 char *label;
00151 char *value;
00152 int lr = 0;
00153
00154 params->transport = "";
00155 params->user = "";
00156 params->method = "";
00157 params->ttl = "";
00158 params->maddr = "";
00159 params->lr = 0;
00160
00161 rem = parameters;
00162
00163 while ((value = strchr(parameters, '=')) || (lr = !strncmp(parameters, "lr", 2))) {
00164
00165 if (lr) {
00166 value = parameters;
00167 } else {
00168 *value++ = '\0';
00169 }
00170 label = parameters;
00171 if ((c = strchr(value, ';'))) {
00172 *c++ = '\0';
00173 parameters = c;
00174 } else {
00175 parameters = endparams;
00176 }
00177
00178 if (!strcmp(label, "transport")) {
00179 params->transport = value;
00180 rem = parameters;
00181 } else if (!strcmp(label, "user")) {
00182 params->user = value;
00183 rem = parameters;
00184 } else if (!strcmp(label, "method")) {
00185 params->method = value;
00186 rem = parameters;
00187 } else if (!strcmp(label, "ttl")) {
00188 params->ttl = value;
00189 rem = parameters;
00190 } else if (!strcmp(label, "maddr")) {
00191 params->maddr = value;
00192 rem = parameters;
00193
00194 } else if ((!strcmp(label, "lr") && strcmp(value, "no") && strcmp(value, "off") && strcmp(value, "0") && strcmp(value, "")) || ((lr) && strcmp(value, "lr"))) {
00195 params->lr = 1;
00196 rem = parameters;
00197 } else {
00198 value--;
00199 *value = '=';
00200 if (c) {
00201 c--;
00202 *c = ';';
00203 }
00204 }
00205 }
00206 if (rem > uri) {
00207 uri = rem;
00208 }
00209
00210 }
00211
00212 if (residue) {
00213 *residue = uri;
00214 }
00215
00216 return error;
00217 }
00218
00219
00220 AST_TEST_DEFINE(sip_parse_uri_fully_test)
00221 {
00222 int res = AST_TEST_PASS;
00223 char uri[1024];
00224 char *user, *pass, *hostport, *headers, *residue;
00225 struct uriparams params;
00226
00227 struct testdata {
00228 char *desc;
00229 char *uri;
00230 char **userptr;
00231 char **passptr;
00232 char **hostportptr;
00233 char **headersptr;
00234 char **residueptr;
00235 struct uriparams *paramsptr;
00236 char *user;
00237 char *pass;
00238 char *hostport;
00239 char *headers;
00240 char *residue;
00241 struct uriparams params;
00242 AST_LIST_ENTRY(testdata) list;
00243 };
00244
00245
00246 struct testdata *testdataptr;
00247
00248 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
00249
00250 struct testdata td1 = {
00251 .desc = "no headers",
00252 .uri = "sip:user:secret@host:5060;param=discard;transport=tcp;param2=residue",
00253 .userptr = &user,
00254 .passptr = &pass,
00255 .hostportptr = &hostport,
00256 .headersptr = &headers,
00257 .residueptr = &residue,
00258 .paramsptr = ¶ms,
00259 .user = "user",
00260 .pass = "secret",
00261 .hostport = "host:5060",
00262 .headers = "",
00263 .residue = "param2=residue",
00264 .params.transport = "tcp",
00265 .params.lr = 0,
00266 .params.user = ""
00267 };
00268
00269 struct testdata td2 = {
00270 .desc = "with headers",
00271 .uri = "sip:user:secret@host:5060;param=discard;transport=tcp;param2=discard2?header=blah&header2=blah2;param3=residue",
00272 .userptr = &user,
00273 .passptr = &pass,
00274 .hostportptr = &hostport,
00275 .headersptr = &headers,
00276 .residueptr = &residue,
00277 .paramsptr = ¶ms,
00278 .user = "user",
00279 .pass = "secret",
00280 .hostport = "host:5060",
00281 .headers = "header=blah&header2=blah2",
00282 .residue = "param3=residue",
00283 .params.transport = "tcp",
00284 .params.lr = 0,
00285 .params.user = ""
00286 };
00287
00288 struct testdata td3 = {
00289 .desc = "difficult user",
00290 .uri = "sip:-_.!~*'()&=+$,;?/:secret@host:5060;transport=tcp",
00291 .userptr = &user,
00292 .passptr = &pass,
00293 .hostportptr = &hostport,
00294 .headersptr = &headers,
00295 .residueptr = &residue,
00296 .paramsptr = ¶ms,
00297 .user = "-_.!~*'()&=+$,;?/",
00298 .pass = "secret",
00299 .hostport = "host:5060",
00300 .headers = "",
00301 .residue = "",
00302 .params.transport = "tcp",
00303 .params.lr = 0,
00304 .params.user = ""
00305 };
00306
00307 struct testdata td4 = {
00308 .desc = "difficult pass",
00309 .uri = "sip:user:-_.!~*'()&=+$,@host:5060;transport=tcp",
00310 .userptr = &user,
00311 .passptr = &pass,
00312 .hostportptr = &hostport,
00313 .headersptr = &headers,
00314 .residueptr = &residue,
00315 .paramsptr = ¶ms,
00316 .user = "user",
00317 .pass = "-_.!~*'()&=+$,",
00318 .hostport = "host:5060",
00319 .headers = "",
00320 .residue = "",
00321 .params.transport = "tcp",
00322 .params.lr = 0,
00323 .params.user = ""
00324 };
00325
00326 struct testdata td5 = {
00327 .desc = "difficult host",
00328 .uri = "sip:user:secret@1-1.a-1.:5060;transport=tcp",
00329 .userptr = &user,
00330 .passptr = &pass,
00331 .hostportptr = &hostport,
00332 .headersptr = &headers,
00333 .residueptr = &residue,
00334 .paramsptr = ¶ms,
00335 .user = "user",
00336 .pass = "secret",
00337 .hostport = "1-1.a-1.:5060",
00338 .headers = "",
00339 .residue = "",
00340 .params.transport = "tcp",
00341 .params.lr = 0,
00342 .params.user = ""
00343 };
00344
00345 struct testdata td6 = {
00346 .desc = "difficult params near transport",
00347 .uri = "sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$;transport=tcp",
00348 .userptr = &user,
00349 .passptr = &pass,
00350 .hostportptr = &hostport,
00351 .headersptr = &headers,
00352 .residueptr = &residue,
00353 .paramsptr = ¶ms,
00354 .user = "user",
00355 .pass = "secret",
00356 .hostport = "host:5060",
00357 .headers = "",
00358 .residue = "",
00359 .params.transport = "tcp",
00360 .params.lr = 0,
00361 .params.user = ""
00362 };
00363
00364 struct testdata td7 = {
00365 .desc = "difficult params near headers",
00366 .uri = "sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$?header=blah&header2=blah2;-_.!~*'()[]/:&+$=residue",
00367 .userptr = &user,
00368 .passptr = &pass,
00369 .hostportptr = &hostport,
00370 .headersptr = &headers,
00371 .residueptr = &residue,
00372 .paramsptr = ¶ms,
00373 .user = "user",
00374 .pass = "secret",
00375 .hostport = "host:5060",
00376 .headers = "header=blah&header2=blah2",
00377 .residue = "-_.!~*'()[]/:&+$=residue",
00378 .params.transport = "",
00379 .params.lr = 0,
00380 .params.user = ""
00381 };
00382
00383 struct testdata td8 = {
00384 .desc = "lr parameter",
00385 .uri = "sip:user:secret@host:5060;param=discard;lr?header=blah",
00386 .userptr = &user,
00387 .passptr = &pass,
00388 .hostportptr = &hostport,
00389 .headersptr = &headers,
00390 .residueptr = &residue,
00391 .paramsptr = ¶ms,
00392 .user = "user",
00393 .pass = "secret",
00394 .hostport = "host:5060",
00395 .headers = "header=blah",
00396 .residue = "",
00397 .params.transport = "",
00398 .params.lr = 1,
00399 .params.user = ""
00400 };
00401
00402 struct testdata td9 = {
00403 .desc = "alternative lr parameter",
00404 .uri = "sip:user:secret@host:5060;param=discard;lr=yes?header=blah",
00405 .userptr = &user,
00406 .passptr = &pass,
00407 .hostportptr = &hostport,
00408 .headersptr = &headers,
00409 .residueptr = &residue,
00410 .paramsptr = ¶ms,
00411 .user = "user",
00412 .pass = "secret",
00413 .hostport = "host:5060",
00414 .headers = "header=blah",
00415 .residue = "",
00416 .params.transport = "",
00417 .params.lr = 1,
00418 .params.user = ""
00419 };
00420
00421 struct testdata td10 = {
00422 .desc = "no lr parameter",
00423 .uri = "sip:user:secret@host:5060;paramlr=lr;lr=no;lr=off;lr=0;lr=;=lr;lrextra;lrparam2=lr?header=blah",
00424 .userptr = &user,
00425 .passptr = &pass,
00426 .hostportptr = &hostport,
00427 .headersptr = &headers,
00428 .residueptr = &residue,
00429 .paramsptr = ¶ms,
00430 .user = "user",
00431 .pass = "secret",
00432 .hostport = "host:5060",
00433 .headers = "header=blah",
00434 .residue = "",
00435 .params.transport = "",
00436 .params.lr = 0,
00437 .params.user = ""
00438 };
00439
00440
00441 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &td1);
00442 AST_LIST_INSERT_TAIL(&testdatalist, &td2, list);
00443 AST_LIST_INSERT_TAIL(&testdatalist, &td3, list);
00444 AST_LIST_INSERT_TAIL(&testdatalist, &td4, list);
00445 AST_LIST_INSERT_TAIL(&testdatalist, &td5, list);
00446 AST_LIST_INSERT_TAIL(&testdatalist, &td6, list);
00447 AST_LIST_INSERT_TAIL(&testdatalist, &td7, list);
00448 AST_LIST_INSERT_TAIL(&testdatalist, &td8, list);
00449 AST_LIST_INSERT_TAIL(&testdatalist, &td9, list);
00450 AST_LIST_INSERT_TAIL(&testdatalist, &td10, list);
00451
00452
00453 switch (cmd) {
00454 case TEST_INIT:
00455 info->name = "sip_uri_full_parse_test";
00456 info->category = "/channels/chan_sip/";
00457 info->summary = "tests sip full uri parsing";
00458 info->description =
00459 "Tests full parsing of various URIs "
00460 "Verifies output matches expected behavior.";
00461 return AST_TEST_NOT_RUN;
00462 case TEST_EXECUTE:
00463 break;
00464 }
00465
00466 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
00467 user = pass = hostport = headers = residue = NULL;
00468 params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
00469 params.lr = 0;
00470
00471 ast_copy_string(uri,testdataptr->uri,sizeof(uri));
00472 if (parse_uri_full(uri, "sip:,sips:", testdataptr->userptr,
00473 testdataptr->passptr, testdataptr->hostportptr,
00474 testdataptr->paramsptr,
00475 testdataptr->headersptr,
00476 testdataptr->residueptr) ||
00477 ((testdataptr->userptr) && strcmp(testdataptr->user, user)) ||
00478 ((testdataptr->passptr) && strcmp(testdataptr->pass, pass)) ||
00479 ((testdataptr->hostportptr) && strcmp(testdataptr->hostport, hostport)) ||
00480 ((testdataptr->headersptr) && strcmp(testdataptr->headers, headers)) ||
00481 ((testdataptr->residueptr) && strcmp(testdataptr->residue, residue)) ||
00482 ((testdataptr->paramsptr) && strcmp(testdataptr->params.transport,params.transport)) ||
00483 ((testdataptr->paramsptr) && (testdataptr->params.lr != params.lr)) ||
00484 ((testdataptr->paramsptr) && strcmp(testdataptr->params.user,params.user))
00485 ) {
00486 ast_test_status_update(test, "Sub-Test: %s, failed.\n", testdataptr->desc);
00487 res = AST_TEST_FAIL;
00488 }
00489 }
00490
00491
00492 return res;
00493 }
00494
00495
00496 int parse_uri(char *uri, const char *scheme, char **user, char **pass,
00497 char **hostport, char **transport) {
00498 int ret;
00499 char *headers;
00500 struct uriparams params;
00501
00502 headers = NULL;
00503 ret = parse_uri_full(uri, scheme, user, pass, hostport, ¶ms, &headers, NULL);
00504 if (transport) {
00505 *transport=params.transport;
00506 }
00507 return ret;
00508 }
00509
00510 AST_TEST_DEFINE(sip_parse_uri_test)
00511 {
00512 int res = AST_TEST_PASS;
00513 char *name, *pass, *hostport, *transport;
00514 char uri1[] = "sip:name@host";
00515 char uri2[] = "sip:name@host;transport=tcp";
00516 char uri3[] = "sip:name:secret@host;transport=tcp";
00517 char uri4[] = "sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00518
00519 char uri6[] = "sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00520 char uri7[] = "sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00521 char uri8[] = "sip:host";
00522 char uri9[] = "sip:host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00523 char uri10[] = "host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00524 char uri11[] = "host";
00525
00526 switch (cmd) {
00527 case TEST_INIT:
00528 info->name = "sip_uri_parse_test";
00529 info->category = "/channels/chan_sip/";
00530 info->summary = "tests sip uri parsing";
00531 info->description =
00532 "Tests parsing of various URIs "
00533 "Verifies output matches expected behavior.";
00534 return AST_TEST_NOT_RUN;
00535 case TEST_EXECUTE:
00536 break;
00537 }
00538
00539
00540 name = pass = hostport = transport = NULL;
00541 if (parse_uri(uri1, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00542 strcmp(name, "name") ||
00543 !ast_strlen_zero(pass) ||
00544 strcmp(hostport, "host") ||
00545 !ast_strlen_zero(transport)) {
00546 ast_test_status_update(test, "Test 1: simple uri failed. \n");
00547 res = AST_TEST_FAIL;
00548 }
00549
00550
00551 name = pass = hostport = transport = NULL;
00552 if (parse_uri(uri2, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00553 strcmp(name, "name") ||
00554 !ast_strlen_zero(pass) ||
00555 strcmp(hostport, "host") ||
00556 strcmp(transport, "tcp")) {
00557 ast_test_status_update(test, "Test 2: uri with addtion of tcp transport failed. \n");
00558 res = AST_TEST_FAIL;
00559 }
00560
00561
00562 name = pass = hostport = transport = NULL;
00563 if (parse_uri(uri3, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00564 strcmp(name, "name") ||
00565 strcmp(pass, "secret") ||
00566 strcmp(hostport, "host") ||
00567 strcmp(transport, "tcp")) {
00568 ast_test_status_update(test, "Test 3: uri with addition of secret failed.\n");
00569 res = AST_TEST_FAIL;
00570 }
00571
00572
00573 name = pass = hostport = transport = NULL;
00574 if (parse_uri(uri4, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00575 strcmp(name, "name") ||
00576 strcmp(pass, "secret") ||
00577 strcmp(hostport, "host:port") ||
00578 strcmp(transport, "tcp")) {
00579 ast_test_status_update(test, "Test 4: add port and unparsed header field failed.\n");
00580 res = AST_TEST_FAIL;
00581 }
00582
00583
00584 name = pass = hostport = transport = NULL;
00585 if (!parse_uri(NULL, "sip:,sips:", &name, &pass, &hostport, &transport)) {
00586 ast_test_status_update(test, "Test 5: passing a NULL uri failed.\n");
00587 res = AST_TEST_FAIL;
00588 }
00589
00590
00591 name = pass = hostport = transport = NULL;
00592 if (parse_uri(uri6, "sip:,sips:", NULL, NULL, NULL, NULL)) {
00593 ast_test_status_update(test, "Test 6: passing NULL output parameters failed.\n");
00594 res = AST_TEST_FAIL;
00595 }
00596
00597
00598 name = pass = hostport = transport = NULL;
00599 if (parse_uri(uri7, "sip:,sips:", &name, NULL, &hostport, NULL) ||
00600 strcmp(name, "name:secret") ||
00601 strcmp(hostport, "host:port")) {
00602
00603 ast_test_status_update(test, "Test 7: providing no port and secret output parameters failed.\n");
00604 res = AST_TEST_FAIL;
00605 }
00606
00607
00608 name = pass = hostport = transport = NULL;
00609 if (parse_uri(uri8, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00610 strcmp(hostport, "host") ||
00611 !ast_strlen_zero(name)) {
00612 ast_test_status_update(test, "Test 8: add port and unparsed header field failed.\n");
00613 res = AST_TEST_FAIL;
00614 }
00615
00616
00617 name = pass = hostport = transport = NULL;
00618 if (parse_uri(uri9, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00619 !ast_strlen_zero(name) ||
00620 !ast_strlen_zero(pass) ||
00621 strcmp(hostport, "host:port") ||
00622 strcmp(transport, "tcp")) {
00623 ast_test_status_update(test, "Test 9: hostport only uri failed \n");
00624 res = AST_TEST_FAIL;
00625 }
00626
00627
00628
00629
00630 name = pass = hostport = transport = NULL;
00631 if (!parse_uri(uri10, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00632 !ast_strlen_zero(name) ||
00633 !ast_strlen_zero(pass) ||
00634 strcmp(hostport, "host:port") ||
00635 strcmp(transport, "tcp")) {
00636 ast_test_status_update(test, "Test 10: missing \"sip:sips:\" scheme failed\n");
00637 res = AST_TEST_FAIL;
00638 }
00639
00640
00641
00642
00643 name = pass = hostport = transport = NULL;
00644 if (!parse_uri(uri11, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00645 !ast_strlen_zero(name) ||
00646 !ast_strlen_zero(pass) ||
00647 strcmp(hostport, "host") ||
00648 !ast_strlen_zero(transport)) {
00649 ast_test_status_update(test, "Test 11: simple uri with missing scheme failed. \n");
00650 res = AST_TEST_FAIL;
00651 }
00652
00653 return res;
00654 }
00655
00656
00657
00658
00659
00660 const char *get_calleridname(const char *input, char *output, size_t outputsize)
00661 {
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 char *orig_output = output;
00686 const char *orig_input = input;
00687
00688 if (!output || !outputsize) {
00689
00690 return input;
00691 }
00692
00693
00694 input = ast_skip_blanks(input);
00695
00696
00697 *orig_output = '\0';
00698
00699
00700 --outputsize;
00701
00702
00703 if (!input || *input == '<') {
00704 return input;
00705 }
00706
00707
00708 if (input[0] == '"') {
00709 input++;
00710
00711 for (; *input; ++input) {
00712 if (*input == '"') {
00713 break;
00714 } else if (*input == 0x5c) {
00715 ++input;
00716 if (!*input) {
00717 break;
00718 }
00719 if ((unsigned char) *input > 0x7f || *input == 0xa || *input == 0xd) {
00720 continue;
00721 }
00722 } else if ((*input != 0x9 && (unsigned char) *input < 0x20)
00723 || *input == 0x7f) {
00724 continue;
00725 }
00726
00727 if (0 < outputsize) {
00728
00729 *output++ = *input;
00730 --outputsize;
00731 }
00732 }
00733
00734
00735 if (*input != '"') {
00736 ast_log(LOG_WARNING, "No ending quote for display-name was found\n");
00737 *orig_output = '\0';
00738 return orig_input;
00739 }
00740
00741
00742 ++input;
00743
00744
00745 *output = '\0';
00746 } else {
00747 for (; *input; ++input) {
00748
00749 if ((*input >= '0' && *input <= '9') || (*input >= 'A' && *input <= 'Z')
00750 || (*input >= 'a' && *input <= 'z') || *input == '-' || *input == '.'
00751 || *input == '!' || *input == '%' || *input == '*' || *input == '_'
00752 || *input == '+' || *input == '`' || *input == '\'' || *input == '~'
00753 || *input == 0x9 || *input == ' ') {
00754 if (0 < outputsize) {
00755
00756 *output++ = *input;
00757 --outputsize;
00758 }
00759 } else if (*input == '<') {
00760
00761 break;
00762 } else if (*input == ':') {
00763
00764 *orig_output = '\0';
00765 return orig_input;
00766 } else {
00767 continue;
00768 }
00769 }
00770
00771 if (*input != '<') {
00772 *orig_output = '\0';
00773 return orig_input;
00774 }
00775
00776
00777 do {
00778 *output-- = '\0';
00779 } while (orig_output <= output && (*output == 0x9 || *output == ' '));
00780 }
00781
00782 return input;
00783 }
00784
00785 AST_TEST_DEFINE(get_calleridname_test)
00786 {
00787 int res = AST_TEST_PASS;
00788 const char *in1 = " \" quoted-text internal \\\" quote \"<stuff>";
00789 const char *in2 = " token text with no quotes <stuff>";
00790 const char *overflow1 = " \"quoted-text overflow 1234567890123456789012345678901234567890\" <stuff>";
00791 const char *overflow2 = " non-quoted text overflow 1234567890123456789012345678901234567890 <stuff>";
00792 const char *noendquote = " \"quoted-text no end <stuff>";
00793 const char *addrspec = " sip:blah@blah";
00794 const char *no_quotes_no_brackets = "blah@blah";
00795 const char *after_dname;
00796 char dname[40];
00797
00798 switch (cmd) {
00799 case TEST_INIT:
00800 info->name = "sip_get_calleridname_test";
00801 info->category = "/channels/chan_sip/";
00802 info->summary = "decodes callerid name from sip header";
00803 info->description = "Decodes display-name field of sip header. Checks for valid output and expected failure cases.";
00804 return AST_TEST_NOT_RUN;
00805 case TEST_EXECUTE:
00806 break;
00807 }
00808
00809
00810 after_dname = get_calleridname(in1, dname, sizeof(dname));
00811 ast_test_status_update(test, "display-name1: %s\nafter: %s\n", dname, after_dname);
00812 if (strcmp(dname, " quoted-text internal \" quote ")) {
00813 ast_test_status_update(test, "display-name1 test failed\n");
00814 res = AST_TEST_FAIL;
00815 }
00816
00817
00818 after_dname = get_calleridname(in2, dname, sizeof(dname));
00819 ast_test_status_update(test, "display-name2: %s\nafter: %s\n", dname, after_dname);
00820 if (strcmp(dname, "token text with no quotes")) {
00821 ast_test_status_update(test, "display-name2 test failed\n");
00822 res = AST_TEST_FAIL;
00823 }
00824
00825
00826 after_dname = get_calleridname(overflow1, dname, sizeof(dname));
00827 ast_test_status_update(test, "overflow display-name1: %s\nafter: %s\n", dname, after_dname);
00828 if (strcmp(dname, "quoted-text overflow 123456789012345678")) {
00829 ast_test_status_update(test, "overflow display-name1 test failed\n");
00830 res = AST_TEST_FAIL;
00831 }
00832
00833
00834 after_dname = get_calleridname(overflow2, dname, sizeof(dname));
00835 ast_test_status_update(test, "overflow display-name2: %s\nafter: %s\n", dname, after_dname);
00836 if (strcmp(dname, "non-quoted text overflow 12345678901234")) {
00837 ast_test_status_update(test, "overflow display-name2 test failed\n");
00838 res = AST_TEST_FAIL;
00839 }
00840
00841
00842 after_dname = get_calleridname(noendquote, dname, sizeof(dname));
00843 ast_test_status_update(test, "noendquote display-name1: %s\nafter: %s\n", dname, after_dname);
00844 if (*dname != '\0' && after_dname != noendquote) {
00845 ast_test_status_update(test, "no end quote for quoted-text display-name failed\n");
00846 res = AST_TEST_FAIL;
00847 }
00848
00849
00850 after_dname = get_calleridname(addrspec, dname, sizeof(dname));
00851 ast_test_status_update(test, "addr-spec display-name1: %s\nafter: %s\n", dname, after_dname);
00852 if (*dname != '\0' && after_dname != addrspec) {
00853 ast_test_status_update(test, "detection of addr-spec failed\n");
00854 res = AST_TEST_FAIL;
00855 }
00856
00857
00858 after_dname = get_calleridname(no_quotes_no_brackets, dname, sizeof(dname));
00859 ast_test_status_update(test, "no_quotes_no_brackets display-name1: %s\nafter: %s\n", dname, after_dname);
00860 if (*dname != '\0' && after_dname != no_quotes_no_brackets) {
00861 ast_test_status_update(test, "detection of addr-spec failed\n");
00862 res = AST_TEST_FAIL;
00863 }
00864
00865 return res;
00866 }
00867
00868 int get_name_and_number(const char *hdr, char **name, char **number)
00869 {
00870 char header[256];
00871 char tmp_name[50];
00872 char *tmp_number = NULL;
00873 char *hostport = NULL;
00874 char *dummy = NULL;
00875
00876 if (!name || !number || ast_strlen_zero(hdr)) {
00877 return -1;
00878 }
00879
00880 *number = NULL;
00881 *name = NULL;
00882 ast_copy_string(header, hdr, sizeof(header));
00883
00884
00885 get_calleridname(header, tmp_name, sizeof(tmp_name));
00886
00887
00888 tmp_number = get_in_brackets(header);
00889
00890
00891 if (parse_uri(tmp_number, "sip:,sips:", &tmp_number, &dummy, &hostport, NULL) || ast_strlen_zero(tmp_number)) {
00892 ast_log(LOG_ERROR, "can not parse name and number from sip header.\n");
00893 return -1;
00894 }
00895
00896
00897 *number = ast_strdup(tmp_number);
00898 ast_uri_decode(*number);
00899
00900
00901 if (!ast_strlen_zero(tmp_name)) {
00902 *name = ast_strdup(tmp_name);
00903 }
00904
00905 return 0;
00906 }
00907
00908 AST_TEST_DEFINE(get_name_and_number_test)
00909 {
00910 int res = AST_TEST_PASS;
00911 char *name = NULL;
00912 char *number = NULL;
00913 const char *in1 = "NAME <sip:NUMBER@place>";
00914 const char *in2 = "\"NA><ME\" <sip:NUMBER@place>";
00915 const char *in3 = "NAME";
00916 const char *in4 = "<sip:NUMBER@place>";
00917 const char *in5 = "This is a screwed up string <sip:LOLCLOWNS<sip:>@place>";
00918
00919 switch (cmd) {
00920 case TEST_INIT:
00921 info->name = "sip_get_name_and_number_test";
00922 info->category = "/channels/chan_sip/";
00923 info->summary = "Tests getting name and number from sip header";
00924 info->description =
00925 "Runs through various test situations in which a name and "
00926 "and number can be retrieved from a sip header.";
00927 return AST_TEST_NOT_RUN;
00928 case TEST_EXECUTE:
00929 break;
00930 }
00931
00932
00933 number = name = NULL;
00934 if ((get_name_and_number(in1, &name, &number)) ||
00935 strcmp(name, "NAME") ||
00936 strcmp(number, "NUMBER")) {
00937
00938 ast_test_status_update(test, "Test 1, simple get name and number failed.\n");
00939 res = AST_TEST_FAIL;
00940 }
00941 ast_free(name);
00942 ast_free(number);
00943
00944
00945 number = name = NULL;
00946 if ((get_name_and_number(in2, &name, &number)) ||
00947 strcmp(name, "NA><ME") ||
00948 strcmp(number, "NUMBER")) {
00949
00950 ast_test_status_update(test, "Test 2, get quoted name and number failed.\n");
00951 res = AST_TEST_FAIL;
00952 }
00953 ast_free(name);
00954 ast_free(number);
00955
00956
00957 number = name = NULL;
00958 if (!(get_name_and_number(in3, &name, &number))) {
00959
00960 ast_test_status_update(test, "Test 3, get name only was expected to fail but did not.\n");
00961 res = AST_TEST_FAIL;
00962 }
00963 ast_free(name);
00964 ast_free(number);
00965
00966
00967 number = name = NULL;
00968 if ((get_name_and_number(in4, &name, &number)) ||
00969 !ast_strlen_zero(name) ||
00970 strcmp(number, "NUMBER")) {
00971
00972 ast_test_status_update(test, "Test 4, get number with no name present failed.\n");
00973 res = AST_TEST_FAIL;
00974 }
00975 ast_free(name);
00976 ast_free(number);
00977
00978
00979 number = name = NULL;
00980 if (!(get_name_and_number(in5, &name, &number)) ||
00981 !ast_strlen_zero(name) ||
00982 !ast_strlen_zero(number)) {
00983
00984 ast_test_status_update(test, "Test 5, processing malformed string failed.\n");
00985 res = AST_TEST_FAIL;
00986 }
00987 ast_free(name);
00988 ast_free(number);
00989
00990
00991 number = name = NULL;
00992 if (!(get_name_and_number(in5, NULL, NULL))) {
00993
00994 ast_test_status_update(test, "Test 6, NULL output parameters failed.\n");
00995 res = AST_TEST_FAIL;
00996 }
00997
00998
00999 number = name = NULL;
01000 if (!(get_name_and_number(NULL, &name, &number)) ||
01001 !ast_strlen_zero(name) ||
01002 !ast_strlen_zero(number)) {
01003
01004 ast_test_status_update(test, "Test 7, NULL input parameter failed.\n");
01005 res = AST_TEST_FAIL;
01006 }
01007 ast_free(name);
01008 ast_free(number);
01009
01010 return res;
01011 }
01012
01013 int get_in_brackets_full(char *tmp,char **out,char **residue)
01014 {
01015 const char *parse = tmp;
01016 char *first_bracket;
01017 char *second_bracket;
01018
01019 if (out) {
01020 *out = "";
01021 }
01022 if (residue) {
01023 *residue = "";
01024 }
01025
01026 if (ast_strlen_zero(tmp)) {
01027 return 1;
01028 }
01029
01030
01031
01032
01033
01034 while ( (first_bracket = strchr(parse, '<')) ) {
01035 char *first_quote = strchr(parse, '"');
01036 first_bracket++;
01037 if (!first_quote || first_quote >= first_bracket) {
01038 break;
01039 }
01040
01041 parse = find_closing_quote(first_quote + 1, NULL);
01042 if (!*parse) {
01043 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp);
01044 return -1;
01045 }
01046 parse++;
01047 }
01048
01049
01050
01051
01052 if (first_bracket) {
01053 parse = first_bracket;
01054 } else {
01055 parse = tmp;
01056 }
01057
01058 if ((second_bracket = strchr(parse, '>'))) {
01059 *second_bracket++ = '\0';
01060 if (out) {
01061 *out = (char *) parse;
01062 }
01063 if (residue) {
01064 *residue = second_bracket;
01065 }
01066 return 0;
01067 }
01068
01069 if ((first_bracket)) {
01070 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp);
01071 return -1;
01072 }
01073
01074 if (out) {
01075 *out = tmp;
01076 }
01077
01078 return 1;
01079 }
01080
01081 char *get_in_brackets(char *tmp)
01082 {
01083 char *out;
01084
01085 if ((get_in_brackets_full(tmp, &out, NULL))) {
01086 return tmp;
01087 }
01088 return out;
01089 }
01090
01091 AST_TEST_DEFINE(get_in_brackets_test)
01092 {
01093 int res = AST_TEST_PASS;
01094 char in_brackets[] = "sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah";
01095 char no_name[] = "<sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01096 char quoted_string[] = "\"I'm a quote stri><ng\" <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01097 char missing_end_quote[] = "\"I'm a quote string <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01098 char name_no_quotes[] = "name not in quotes <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01099 char no_end_bracket[] = "name not in quotes <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah";
01100 char no_name_no_brackets[] = "sip:name@host";
01101 char missing_start_bracket[] = "sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01102 char *uri = NULL;
01103
01104 switch (cmd) {
01105 case TEST_INIT:
01106 info->name = "sip_get_in_brackets_test";
01107 info->category = "/channels/chan_sip/";
01108 info->summary = "Tests getting a sip uri in <> brackets within a sip header.";
01109 info->description =
01110 "Runs through various test situations in which a sip uri "
01111 "in angle brackets needs to be retrieved";
01112 return AST_TEST_NOT_RUN;
01113 case TEST_EXECUTE:
01114 break;
01115 }
01116
01117
01118 if (!(uri = get_in_brackets(no_name)) || strcmp(uri, in_brackets)) {
01119 ast_test_status_update(test, "Test 1, simple get in brackets failed. %s\n", uri);
01120 res = AST_TEST_FAIL;
01121 }
01122
01123
01124 if (!(uri = get_in_brackets(quoted_string)) || strcmp(uri, in_brackets)) {
01125 ast_test_status_update(test, "Test 2, get in brackets with quoted string in front failed. %s\n", uri);
01126 res = AST_TEST_FAIL;
01127 }
01128
01129
01130 if (!(uri = get_in_brackets(missing_end_quote)) || !strcmp(uri, in_brackets)) {
01131 ast_test_status_update(test, "Test 3, missing end quote failed. %s\n", uri);
01132 res = AST_TEST_FAIL;
01133 }
01134
01135
01136 if (!(uri = get_in_brackets(name_no_quotes)) || strcmp(uri, in_brackets)) {
01137 ast_test_status_update(test, "Test 4, passing name not in quotes failed. %s\n", uri);
01138 res = AST_TEST_FAIL;
01139 }
01140
01141
01142 if (!(uri = get_in_brackets(no_end_bracket)) || !strcmp(uri, in_brackets)) {
01143 ast_test_status_update(test, "Test 5, no end bracket failed. %s\n", uri);
01144 res = AST_TEST_FAIL;
01145 }
01146
01147
01148 if ((uri = get_in_brackets(NULL))) {
01149 ast_test_status_update(test, "Test 6, NULL input failed.\n");
01150 res = AST_TEST_FAIL;
01151 }
01152
01153
01154 if (!(uri = get_in_brackets(no_name_no_brackets)) || strcmp(uri, "sip:name@host")) {
01155 ast_test_status_update(test, "Test 7 failed. %s\n", uri);
01156 res = AST_TEST_FAIL;
01157 }
01158
01159
01160 if (!(uri = get_in_brackets(missing_start_bracket)) || strcmp(uri, in_brackets)) {
01161 ast_test_status_update(test, "Test 8 failed. %s\n", uri);
01162 res = AST_TEST_FAIL;
01163 }
01164
01165 return res;
01166 }
01167
01168
01169 int parse_name_andor_addr(char *uri, const char *scheme, char **name,
01170 char **user, char **pass, char **hostport,
01171 struct uriparams *params, char **headers,
01172 char **residue)
01173 {
01174 char buf[1024];
01175 char **residue2 = residue;
01176 char *orig_uri = uri;
01177 int ret;
01178
01179 buf[0] = '\0';
01180 if (name) {
01181 uri = (char *) get_calleridname(uri, buf, sizeof(buf));
01182 }
01183 ret = get_in_brackets_full(uri, &uri, residue);
01184 if (ret == 0) {
01185
01186
01187
01188
01189 if (residue && **residue) {
01190
01191 *residue = *residue + 1;
01192 }
01193 residue2 = NULL;
01194 }
01195
01196 if (name) {
01197 if (buf[0]) {
01198
01199
01200
01201
01202
01203 strcpy(orig_uri, buf);
01204 *name = orig_uri;
01205 } else {
01206 *name = "";
01207 }
01208 }
01209
01210 return parse_uri_full(uri, scheme, user, pass, hostport, params, headers, residue2);
01211 }
01212
01213 AST_TEST_DEFINE(parse_name_andor_addr_test)
01214 {
01215 int res = AST_TEST_PASS;
01216 char uri[1024];
01217 char *name, *user, *pass, *hostport, *headers, *residue;
01218 struct uriparams params;
01219
01220 struct testdata {
01221 char *desc;
01222 char *uri;
01223 char **nameptr;
01224 char **userptr;
01225 char **passptr;
01226 char **hostportptr;
01227 char **headersptr;
01228 char **residueptr;
01229 struct uriparams *paramsptr;
01230 char *name;
01231 char *user;
01232 char *pass;
01233 char *hostport;
01234 char *headers;
01235 char *residue;
01236 struct uriparams params;
01237 AST_LIST_ENTRY(testdata) list;
01238 };
01239
01240 struct testdata *testdataptr;
01241
01242 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
01243
01244 struct testdata td1 = {
01245 .desc = "quotes and brackets",
01246 .uri = "\"name :@ \" <sip:user:secret@host:5060;param=discard;transport=tcp>;tag=tag",
01247 .nameptr = &name,
01248 .userptr = &user,
01249 .passptr = &pass,
01250 .hostportptr = &hostport,
01251 .headersptr = &headers,
01252 .residueptr = &residue,
01253 .paramsptr = ¶ms,
01254 .name = "name :@ ",
01255 .user = "user",
01256 .pass = "secret",
01257 .hostport = "host:5060",
01258 .headers = "",
01259 .residue = "tag=tag",
01260 .params.transport = "tcp",
01261 .params.lr = 0,
01262 .params.user = ""
01263 };
01264
01265 struct testdata td2 = {
01266 .desc = "no quotes",
01267 .uri = "givenname familyname <sip:user:secret@host:5060;param=discard;transport=tcp>;expires=3600",
01268 .nameptr = &name,
01269 .userptr = &user,
01270 .passptr = &pass,
01271 .hostportptr = &hostport,
01272 .headersptr = &headers,
01273 .residueptr = &residue,
01274 .paramsptr = ¶ms,
01275 .name = "givenname familyname",
01276 .user = "user",
01277 .pass = "secret",
01278 .hostport = "host:5060",
01279 .headers = "",
01280 .residue = "expires=3600",
01281 .params.transport = "tcp",
01282 .params.lr = 0,
01283 .params.user = ""
01284 };
01285
01286 struct testdata td3 = {
01287 .desc = "no brackets",
01288 .uri = "sip:user:secret@host:5060;param=discard;transport=tcp;q=1",
01289 .nameptr = &name,
01290 .userptr = &user,
01291 .passptr = &pass,
01292 .hostportptr = &hostport,
01293 .headersptr = &headers,
01294 .residueptr = &residue,
01295 .paramsptr = ¶ms,
01296 .name = "",
01297 .user = "user",
01298 .pass = "secret",
01299 .hostport = "host:5060",
01300 .headers = "",
01301 .residue = "q=1",
01302 .params.transport = "tcp",
01303 .params.lr = 0,
01304 .params.user = ""
01305 };
01306
01307 struct testdata td4 = {
01308 .desc = "just host",
01309 .uri = "sips:host",
01310 .nameptr = &name,
01311 .userptr = &user,
01312 .passptr = &pass,
01313 .hostportptr = &hostport,
01314 .headersptr = &headers,
01315 .residueptr = &residue,
01316 .paramsptr = ¶ms,
01317 .name = "",
01318 .user = "",
01319 .pass = "",
01320 .hostport = "host",
01321 .headers = "",
01322 .residue = "",
01323 .params.transport = "",
01324 .params.lr = 0,
01325 .params.user = ""
01326 };
01327
01328
01329 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &td1);
01330 AST_LIST_INSERT_TAIL(&testdatalist, &td2, list);
01331 AST_LIST_INSERT_TAIL(&testdatalist, &td3, list);
01332 AST_LIST_INSERT_TAIL(&testdatalist, &td4, list);
01333
01334
01335 switch (cmd) {
01336 case TEST_INIT:
01337 info->name = "parse_name_andor_addr_test";
01338 info->category = "/channels/chan_sip/";
01339 info->summary = "tests parsing of name_andor_addr abnf structure";
01340 info->description =
01341 "Tests parsing of abnf name-andor-addr = name-addr / addr-spec "
01342 "Verifies output matches expected behavior.";
01343 return AST_TEST_NOT_RUN;
01344 case TEST_EXECUTE:
01345 break;
01346 }
01347
01348 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
01349 name = user = pass = hostport = headers = residue = NULL;
01350 params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
01351 params.lr = 0;
01352 ast_copy_string(uri,testdataptr->uri,sizeof(uri));
01353 if (parse_name_andor_addr(uri, "sip:,sips:",
01354 testdataptr->nameptr,
01355 testdataptr->userptr,
01356 testdataptr->passptr,
01357 testdataptr->hostportptr,
01358 testdataptr->paramsptr,
01359 testdataptr->headersptr,
01360 testdataptr->residueptr) ||
01361 ((testdataptr->nameptr) && strcmp(testdataptr->name, name)) ||
01362 ((testdataptr->userptr) && strcmp(testdataptr->user, user)) ||
01363 ((testdataptr->passptr) && strcmp(testdataptr->pass, pass)) ||
01364 ((testdataptr->hostportptr) && strcmp(testdataptr->hostport, hostport)) ||
01365 ((testdataptr->headersptr) && strcmp(testdataptr->headers, headers)) ||
01366 ((testdataptr->residueptr) && strcmp(testdataptr->residue, residue)) ||
01367 ((testdataptr->paramsptr) && strcmp(testdataptr->params.transport,params.transport)) ||
01368 ((testdataptr->paramsptr) && strcmp(testdataptr->params.user,params.user))
01369 ) {
01370 ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
01371 res = AST_TEST_FAIL;
01372 }
01373 }
01374
01375 return res;
01376 }
01377
01378 int get_comma(char *in, char **out)
01379 {
01380 char *c;
01381 char *parse = in;
01382 if (out) {
01383 *out = in;
01384 }
01385
01386
01387 while (*parse) {
01388 if ((c = strchr(parse, '"'))) {
01389 in = (char *)find_closing_quote((const char *)c + 1, NULL);
01390 if (!*in) {
01391 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", c);
01392 return -1;
01393 } else {
01394 break;
01395 }
01396 } else {
01397 break;
01398 }
01399 parse++;
01400 }
01401 parse = in;
01402
01403
01404 if ((c = strchr(parse,'@'))) {
01405 parse = c+1;
01406 }
01407 if ((out) && (c = strchr(parse,','))) {
01408 *c++ = '\0';
01409 *out = c;
01410 return 0;
01411 }
01412 return 1;
01413 }
01414
01415 int parse_contact_header(char *contactheader, struct contactliststruct *contactlist)
01416 {
01417 int res;
01418 int last;
01419 char *comma;
01420 char *residue;
01421 char *param;
01422 char *value;
01423 struct contact *split_contact = NULL;
01424
01425 if (*contactheader == '*') {
01426 return 1;
01427 }
01428
01429 split_contact = ast_calloc(1, sizeof(*split_contact));
01430
01431 AST_LIST_HEAD_SET_NOLOCK(contactlist, split_contact);
01432 while ((last = get_comma(contactheader, &comma)) != -1) {
01433 res = parse_name_andor_addr(contactheader, "sip:,sips:",
01434 &split_contact->name, &split_contact->user,
01435 &split_contact->pass, &split_contact->hostport,
01436 &split_contact->params, &split_contact->headers,
01437 &residue);
01438 if (res == -1) {
01439 return res;
01440 }
01441
01442
01443 split_contact->expires = split_contact->q = "";
01444
01445 while ((value = strchr(residue,'='))) {
01446 *value++ = '\0';
01447
01448 param = residue;
01449 if ((residue = strchr(value,';'))) {
01450 *residue++ = '\0';
01451 } else {
01452 residue = "";
01453 }
01454
01455 if (!strcmp(param,"expires")) {
01456 split_contact->expires = value;
01457 } else if (!strcmp(param,"q")) {
01458 split_contact->q = value;
01459 }
01460 }
01461
01462 if (last) {
01463 return 0;
01464 }
01465 contactheader = comma;
01466
01467 split_contact = ast_calloc(1, sizeof(*split_contact));
01468 AST_LIST_INSERT_TAIL(contactlist, split_contact, list);
01469 }
01470 return last;
01471 }
01472
01473 AST_TEST_DEFINE(parse_contact_header_test)
01474 {
01475 int res = AST_TEST_PASS;
01476 char contactheader[1024];
01477 int star;
01478 struct contactliststruct contactlist;
01479 struct contactliststruct *contactlistptr=&contactlist;
01480
01481 struct testdata {
01482 char *desc;
01483 char *contactheader;
01484 int star;
01485 struct contactliststruct *contactlist;
01486
01487 AST_LIST_ENTRY(testdata) list;
01488 };
01489
01490 struct testdata *testdataptr;
01491 struct contact *tdcontactptr;
01492 struct contact *contactptr;
01493
01494 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
01495 struct contactliststruct contactlist1, contactlist2;
01496
01497 struct testdata td1 = {
01498 .desc = "single contact",
01499 .contactheader = "\"name :@;?&,\" <sip:user:secret@host:5082;param=discard;transport=tcp>;expires=3600",
01500 .contactlist = &contactlist1,
01501 .star = 0
01502 };
01503 struct contact contact11 = {
01504 .name = "name :@;?&,",
01505 .user = "user",
01506 .pass = "secret",
01507 .hostport = "host:5082",
01508 .params.transport = "tcp",
01509 .params.ttl = "",
01510 .params.lr = 0,
01511 .headers = "",
01512 .expires = "3600",
01513 .q = ""
01514 };
01515
01516 struct testdata td2 = {
01517 .desc = "multiple contacts",
01518 .contactheader = "sip:,user1,:,secret1,@host1;ttl=7;q=1;expires=3600,sips:host2",
01519 .contactlist = &contactlist2,
01520 .star = 0,
01521 };
01522 struct contact contact21 = {
01523 .name = "",
01524 .user = ",user1,",
01525 .pass = ",secret1,",
01526 .hostport = "host1",
01527 .params.transport = "",
01528 .params.ttl = "7",
01529 .params.lr = 0,
01530 .headers = "",
01531 .expires = "3600",
01532 .q = "1"
01533 };
01534 struct contact contact22 = {
01535 .name = "",
01536 .user = "",
01537 .pass = "",
01538 .hostport = "host2",
01539 .params.transport = "",
01540 .params.ttl = "",
01541 .params.lr = 0,
01542 .headers = "",
01543 .expires = "",
01544 .q = ""
01545 };
01546
01547 struct testdata td3 = {
01548 .desc = "star - all contacts",
01549 .contactheader = "*",
01550 .star = 1,
01551 .contactlist = NULL
01552 };
01553
01554 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &td1);
01555 AST_LIST_INSERT_TAIL(&testdatalist, &td2, list);
01556 AST_LIST_INSERT_TAIL(&testdatalist, &td3, list);
01557
01558 AST_LIST_HEAD_SET_NOLOCK(&contactlist1, &contact11);
01559
01560 AST_LIST_HEAD_SET_NOLOCK(&contactlist2, &contact21);
01561 AST_LIST_INSERT_TAIL(&contactlist2, &contact22, list);
01562
01563
01564 switch (cmd) {
01565 case TEST_INIT:
01566 info->name = "parse_contact_header_test";
01567 info->category = "/channels/chan_sip/";
01568 info->summary = "tests parsing of sip contact header";
01569 info->description =
01570 "Tests parsing of a contact header including those with multiple contacts "
01571 "Verifies output matches expected behavior.";
01572 return AST_TEST_NOT_RUN;
01573 case TEST_EXECUTE:
01574 break;
01575 }
01576
01577 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
01578 ast_copy_string(contactheader,testdataptr->contactheader,sizeof(contactheader));
01579 star = parse_contact_header(contactheader,contactlistptr);
01580 if (testdataptr->star) {
01581
01582 if (!star) {
01583 ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
01584 res = AST_TEST_FAIL;
01585 break;
01586 }
01587 } else {
01588 contactptr = AST_LIST_FIRST(contactlistptr);
01589 AST_LIST_TRAVERSE(testdataptr->contactlist, tdcontactptr, list) {
01590 if (!contactptr ||
01591 strcmp(tdcontactptr->name, contactptr->name) ||
01592 strcmp(tdcontactptr->user, contactptr->user) ||
01593 strcmp(tdcontactptr->pass, contactptr->pass) ||
01594 strcmp(tdcontactptr->hostport, contactptr->hostport) ||
01595 strcmp(tdcontactptr->headers, contactptr->headers) ||
01596 strcmp(tdcontactptr->expires, contactptr->expires) ||
01597 strcmp(tdcontactptr->q, contactptr->q) ||
01598 strcmp(tdcontactptr->params.transport, contactptr->params.transport) ||
01599 strcmp(tdcontactptr->params.ttl, contactptr->params.ttl) ||
01600 (tdcontactptr->params.lr != contactptr->params.lr)
01601 ) {
01602 ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
01603 res = AST_TEST_FAIL;
01604 break;
01605 }
01606
01607 contactptr = AST_LIST_NEXT(contactptr,list);
01608 }
01609 }
01610 }
01611
01612 return res;
01613 }
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 unsigned int parse_sip_options(const char *options, char *unsupported, size_t unsupported_len)
01628 {
01629 char *next, *sep;
01630 char *temp;
01631 int i, found, supported;
01632 unsigned int profile = 0;
01633
01634 char *out = unsupported;
01635 size_t outlen = unsupported_len;
01636 char *cur_out = out;
01637
01638 if (out && (outlen > 0)) {
01639 memset(out, 0, outlen);
01640 }
01641
01642 if (ast_strlen_zero(options) )
01643 return 0;
01644
01645 temp = ast_strdupa(options);
01646
01647 ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", options);
01648
01649 for (next = temp; next; next = sep) {
01650 found = FALSE;
01651 supported = FALSE;
01652 if ((sep = strchr(next, ',')) != NULL) {
01653 *sep++ = '\0';
01654 }
01655
01656
01657 next = ast_strip(next);
01658
01659 if (ast_strlen_zero(next)) {
01660 continue;
01661 }
01662
01663 ast_debug(3, "Found SIP option: -%s-\n", next);
01664 for (i = 0; i < ARRAY_LEN(sip_options); i++) {
01665 if (!strcasecmp(next, sip_options[i].text)) {
01666 profile |= sip_options[i].id;
01667 if (sip_options[i].supported == SUPPORTED) {
01668 supported = TRUE;
01669 }
01670 found = TRUE;
01671 ast_debug(3, "Matched SIP option: %s\n", next);
01672 break;
01673 }
01674 }
01675
01676
01677 if (!supported && out && outlen) {
01678 size_t copylen = strlen(next);
01679 size_t cur_outlen = strlen(out);
01680
01681
01682 if ((cur_outlen + copylen + 2) < outlen) {
01683
01684 if (cur_outlen) {
01685 *cur_out = ',';
01686 cur_out++;
01687 cur_outlen++;
01688 }
01689 ast_copy_string(cur_out, next, (outlen - cur_outlen));
01690 cur_out += copylen;
01691 }
01692 }
01693
01694 if (!found) {
01695 profile |= SIP_OPT_UNKNOWN;
01696 if (!strncasecmp(next, "x-", 2))
01697 ast_debug(3, "Found private SIP option, not supported: %s\n", next);
01698 else
01699 ast_debug(3, "Found no match for SIP option: %s (Please file bug report!)\n", next);
01700 }
01701 }
01702
01703 return profile;
01704 }
01705
01706 AST_TEST_DEFINE(sip_parse_options_test)
01707 {
01708 int res = AST_TEST_PASS;
01709 char unsupported[64];
01710 unsigned int option_profile = 0;
01711 struct testdata {
01712 char *name;
01713 char *input_options;
01714 char *expected_unsupported;
01715 unsigned int expected_profile;
01716 AST_LIST_ENTRY(testdata) list;
01717 };
01718
01719 struct testdata *testdataptr;
01720 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
01721
01722 struct testdata test1 = {
01723 .name = "test_all_unsupported",
01724 .input_options = "unsupported1,,, ,unsupported2,unsupported3,unsupported4",
01725 .expected_unsupported = "unsupported1,unsupported2,unsupported3,unsupported4",
01726 .expected_profile = SIP_OPT_UNKNOWN,
01727 };
01728 struct testdata test2 = {
01729 .name = "test_all_unsupported_one_supported",
01730 .input_options = " unsupported1, replaces, unsupported3 , , , ,unsupported4",
01731 .expected_unsupported = "unsupported1,unsupported3,unsupported4",
01732 .expected_profile = SIP_OPT_UNKNOWN | SIP_OPT_REPLACES
01733 };
01734 struct testdata test3 = {
01735 .name = "test_two_supported_two_unsupported",
01736 .input_options = ",, timer ,replaces ,unsupported3,unsupported4",
01737 .expected_unsupported = "unsupported3,unsupported4",
01738 .expected_profile = SIP_OPT_UNKNOWN | SIP_OPT_REPLACES | SIP_OPT_TIMER,
01739 };
01740
01741 struct testdata test4 = {
01742 .name = "test_all_supported",
01743 .input_options = "timer,replaces",
01744 .expected_unsupported = "",
01745 .expected_profile = SIP_OPT_REPLACES | SIP_OPT_TIMER,
01746 };
01747
01748 struct testdata test5 = {
01749 .name = "test_all_supported_redundant",
01750 .input_options = "timer,replaces,timer,replace,timer,replaces",
01751 .expected_unsupported = "",
01752 .expected_profile = SIP_OPT_REPLACES | SIP_OPT_TIMER,
01753 };
01754 struct testdata test6 = {
01755 .name = "test_buffer_overflow",
01756 .input_options = "unsupported1,replaces,timer,unsupported4,unsupported_huge____"
01757 "____________________________________,__________________________________________"
01758 "________________________________________________",
01759 .expected_unsupported = "unsupported1,unsupported4",
01760 .expected_profile = SIP_OPT_UNKNOWN | SIP_OPT_REPLACES | SIP_OPT_TIMER,
01761 };
01762 struct testdata test7 = {
01763 .name = "test_null_input",
01764 .input_options = NULL,
01765 .expected_unsupported = "",
01766 .expected_profile = 0,
01767 };
01768 struct testdata test8 = {
01769 .name = "test_whitespace_input",
01770 .input_options = " ",
01771 .expected_unsupported = "",
01772 .expected_profile = 0,
01773 };
01774 struct testdata test9 = {
01775 .name = "test_whitespace_plus_option_input",
01776 .input_options = " , , ,timer , , , , , ",
01777 .expected_unsupported = "",
01778 .expected_profile = SIP_OPT_TIMER,
01779 };
01780
01781 switch (cmd) {
01782 case TEST_INIT:
01783 info->name = "sip_parse_options_test";
01784 info->category = "/channels/chan_sip/";
01785 info->summary = "Tests parsing of sip options";
01786 info->description =
01787 "Tests parsing of SIP options from supported and required "
01788 "header fields. Verifies when unsupported options are encountered "
01789 "that they are appended to the unsupported out buffer and that the "
01790 "correct bit field representnig the option profile is returned.";
01791 return AST_TEST_NOT_RUN;
01792 case TEST_EXECUTE:
01793 break;
01794 }
01795
01796 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &test1);
01797 AST_LIST_INSERT_TAIL(&testdatalist, &test2, list);
01798 AST_LIST_INSERT_TAIL(&testdatalist, &test3, list);
01799 AST_LIST_INSERT_TAIL(&testdatalist, &test4, list);
01800 AST_LIST_INSERT_TAIL(&testdatalist, &test5, list);
01801 AST_LIST_INSERT_TAIL(&testdatalist, &test6, list);
01802 AST_LIST_INSERT_TAIL(&testdatalist, &test7, list);
01803 AST_LIST_INSERT_TAIL(&testdatalist, &test8, list);
01804 AST_LIST_INSERT_TAIL(&testdatalist, &test9, list);
01805
01806
01807 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
01808 option_profile = parse_sip_options(testdataptr->input_options, unsupported, ARRAY_LEN(unsupported));
01809 if (option_profile != testdataptr->expected_profile ||
01810 strcmp(unsupported, testdataptr->expected_unsupported)) {
01811 ast_test_status_update(test, "Test with output buffer \"%s\", expected unsupported: %s actual unsupported:"
01812 "%s expected bit profile: %x actual bit profile: %x\n",
01813 testdataptr->name,
01814 testdataptr->expected_unsupported,
01815 unsupported,
01816 testdataptr->expected_profile,
01817 option_profile);
01818 res = AST_TEST_FAIL;
01819 } else {
01820 ast_test_status_update(test, "\"%s\" passed got expected unsupported: %s and bit profile: %x\n",
01821 testdataptr->name,
01822 unsupported,
01823 option_profile);
01824 }
01825
01826 option_profile = parse_sip_options(testdataptr->input_options, NULL, 0);
01827 if (option_profile != testdataptr->expected_profile) {
01828 ast_test_status_update(test, "NULL output test \"%s\", expected bit profile: %x actual bit profile: %x\n",
01829 testdataptr->name,
01830 testdataptr->expected_profile,
01831 option_profile);
01832 res = AST_TEST_FAIL;
01833 } else {
01834 ast_test_status_update(test, "\"%s\" with NULL output buf passed, bit profile: %x\n",
01835 testdataptr->name,
01836 option_profile);
01837 }
01838 }
01839
01840 return res;
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860 static int sip_uri_params_cmp(const char *input1, const char *input2)
01861 {
01862 char *params1 = NULL;
01863 char *params2 = NULL;
01864 char *pos1;
01865 char *pos2;
01866 int zerolength1 = 0;
01867 int zerolength2 = 0;
01868 int maddrmatch = 0;
01869 int ttlmatch = 0;
01870 int usermatch = 0;
01871 int methodmatch = 0;
01872
01873 if (ast_strlen_zero(input1)) {
01874 zerolength1 = 1;
01875 } else {
01876 params1 = ast_strdupa(input1);
01877 }
01878 if (ast_strlen_zero(input2)) {
01879 zerolength2 = 1;
01880 } else {
01881 params2 = ast_strdupa(input2);
01882 }
01883
01884
01885
01886
01887 if (zerolength1 && zerolength2) {
01888 return 0;
01889 }
01890
01891 for (pos1 = strsep(¶ms1, ";"); pos1; pos1 = strsep(¶ms1, ";")) {
01892 char *value1 = pos1;
01893 char *name1 = strsep(&value1, "=");
01894 char *params2dup = NULL;
01895 int matched = 0;
01896 if (!value1) {
01897 value1 = "";
01898 }
01899
01900
01901
01902
01903 if (!zerolength2) {
01904 params2dup = ast_strdupa(params2);
01905 }
01906 for (pos2 = strsep(¶ms2dup, ";"); pos2; pos2 = strsep(¶ms2dup, ";")) {
01907 char *name2 = pos2;
01908 char *value2 = strchr(pos2, '=');
01909 if (!value2) {
01910 value2 = "";
01911 } else {
01912 *value2++ = '\0';
01913 }
01914 if (!strcasecmp(name1, name2)) {
01915 if (strcasecmp(value1, value2)) {
01916 goto fail;
01917 } else {
01918 matched = 1;
01919 break;
01920 }
01921 }
01922 }
01923
01924 if (!strcasecmp(name1, "maddr")) {
01925 if (matched) {
01926 maddrmatch = 1;
01927 } else {
01928 goto fail;
01929 }
01930 } else if (!strcasecmp(name1, "ttl")) {
01931 if (matched) {
01932 ttlmatch = 1;
01933 } else {
01934 goto fail;
01935 }
01936 } else if (!strcasecmp(name1, "user")) {
01937 if (matched) {
01938 usermatch = 1;
01939 } else {
01940 goto fail;
01941 }
01942 } else if (!strcasecmp(name1, "method")) {
01943 if (matched) {
01944 methodmatch = 1;
01945 } else {
01946 goto fail;
01947 }
01948 }
01949 }
01950
01951
01952
01953
01954
01955 for (pos2 = strsep(¶ms2, ";"); pos2; pos2 = strsep(¶ms2, ";")) {
01956 char *value2 = pos2;
01957 char *name2 = strsep(&value2, "=");
01958 if (!value2) {
01959 value2 = "";
01960 }
01961 if ((!strcasecmp(name2, "maddr") && !maddrmatch) ||
01962 (!strcasecmp(name2, "ttl") && !ttlmatch) ||
01963 (!strcasecmp(name2, "user") && !usermatch) ||
01964 (!strcasecmp(name2, "method") && !methodmatch)) {
01965 goto fail;
01966 }
01967 }
01968 return 0;
01969
01970 fail:
01971 return 1;
01972 }
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986 static int sip_uri_headers_cmp(const char *input1, const char *input2)
01987 {
01988 char *headers1 = NULL;
01989 char *headers2 = NULL;
01990 int zerolength1 = 0;
01991 int zerolength2 = 0;
01992 int different = 0;
01993 char *header1;
01994
01995 if (ast_strlen_zero(input1)) {
01996 zerolength1 = 1;
01997 } else {
01998 headers1 = ast_strdupa(input1);
01999 }
02000
02001 if (ast_strlen_zero(input2)) {
02002 zerolength2 = 1;
02003 } else {
02004 headers2 = ast_strdupa(input2);
02005 }
02006
02007
02008
02009
02010 if (zerolength1 != zerolength2) {
02011 return 1;
02012 }
02013
02014 if (zerolength1 && zerolength2)
02015 return 0;
02016
02017
02018
02019
02020
02021 if (strlen(headers1) != strlen(headers2)) {
02022 return 1;
02023 }
02024
02025 for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) {
02026 if (!strcasestr(headers2, header1)) {
02027 different = 1;
02028 break;
02029 }
02030 }
02031
02032 return different;
02033 }
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051 static int sip_uri_domain_cmp(const char *host1, const char *host2)
02052 {
02053 struct ast_sockaddr addr1;
02054 struct ast_sockaddr addr2;
02055 int addr1_parsed;
02056 int addr2_parsed;
02057
02058 addr1_parsed = ast_sockaddr_parse(&addr1, host1, 0);
02059 addr2_parsed = ast_sockaddr_parse(&addr2, host2, 0);
02060
02061 if (addr1_parsed != addr2_parsed) {
02062
02063
02064
02065 return 1;
02066 }
02067
02068
02069
02070
02071
02072
02073 if (!addr1_parsed) {
02074 #ifdef HAVE_XLOCALE_H
02075 if(!c_locale) {
02076 return strcasecmp(host1, host2);
02077 } else {
02078 return strcasecmp_l(host1, host2, c_locale);
02079 }
02080 #else
02081 return strcasecmp(host1, host2);
02082 #endif
02083 }
02084
02085
02086 return ast_sockaddr_cmp(&addr1, &addr2);
02087 }
02088
02089 int sip_uri_cmp(const char *input1, const char *input2)
02090 {
02091 char *uri1;
02092 char *uri2;
02093 char *uri_scheme1;
02094 char *uri_scheme2;
02095 char *host1;
02096 char *host2;
02097 char *params1;
02098 char *params2;
02099 char *headers1;
02100 char *headers2;
02101
02102
02103
02104
02105
02106
02107 if (!input1 || !input2) {
02108 return 1;
02109 }
02110
02111 uri1 = ast_strdupa(input1);
02112 uri2 = ast_strdupa(input2);
02113
02114 ast_uri_decode(uri1);
02115 ast_uri_decode(uri2);
02116
02117 uri_scheme1 = strsep(&uri1, ":");
02118 uri_scheme2 = strsep(&uri2, ":");
02119
02120 if (strcmp(uri_scheme1, uri_scheme2)) {
02121 return 1;
02122 }
02123
02124
02125
02126
02127
02128 if (strcmp(uri_scheme1, "sip") && strcmp(uri_scheme1, "sips")) {
02129 return 1;
02130 }
02131
02132 if (ast_strlen_zero(uri1) || ast_strlen_zero(uri2)) {
02133 return 1;
02134 }
02135
02136 if ((host1 = strchr(uri1, '@'))) {
02137 *host1++ = '\0';
02138 }
02139 if ((host2 = strchr(uri2, '@'))) {
02140 *host2++ = '\0';
02141 }
02142
02143
02144
02145
02146 if ((host1 && !host2) ||
02147 (host2 && !host1) ||
02148 (host1 && host2 && strcmp(uri1, uri2))) {
02149 return 1;
02150 }
02151
02152 if (!host1) {
02153 host1 = uri1;
02154 }
02155 if (!host2) {
02156 host2 = uri2;
02157 }
02158
02159
02160
02161
02162
02163 if ((params1 = strchr(host1, ';'))) {
02164 *params1++ = '\0';
02165 }
02166 if ((params2 = strchr(host2, ';'))) {
02167 *params2++ = '\0';
02168 }
02169
02170
02171
02172
02173 if ((headers1 = strchr(S_OR(params1, host1), '?'))) {
02174 *headers1++ = '\0';
02175 }
02176 if ((headers2 = strchr(S_OR(params2, host2), '?'))) {
02177 *headers2++ = '\0';
02178 }
02179
02180 if (sip_uri_domain_cmp(host1, host2)) {
02181 return 1;
02182 }
02183
02184
02185 if (sip_uri_headers_cmp(headers1, headers2)) {
02186 return 1;
02187 }
02188
02189
02190 return sip_uri_params_cmp(params1, params2);
02191 }
02192
02193 #define URI_CMP_MATCH 0
02194 #define URI_CMP_NOMATCH 1
02195
02196 AST_TEST_DEFINE(sip_uri_cmp_test)
02197 {
02198 static const struct {
02199 const char *uri1;
02200 const char *uri2;
02201 int expected_result;
02202 } uri_cmp_tests [] = {
02203
02204 { "sip:bob@example.com", "sip:bob@example.com", URI_CMP_MATCH },
02205
02206 { "sip:alice@example.com", "sip:bob@example.com", URI_CMP_NOMATCH },
02207
02208 { "sip:bob@example.com", "sip:bob@examplez.com", URI_CMP_NOMATCH },
02209
02210 { "sip:bob@1.2.3.4", "sip:bob@1.2.3.4", URI_CMP_MATCH },
02211
02212 { "sip:bob@1.2.3.4", "sip:bob@001.002.003.004", URI_CMP_MATCH },
02213
02214 { "sip:bob@127.0.0.1", "sip:bob@localhost", URI_CMP_NOMATCH },
02215
02216 { "sip:bob@[::1]", "sip:bob@localhost", URI_CMP_NOMATCH },
02217
02218 { "sip:bob@[2001:db8::1234]", "sip:bob@[2001:db8::1234]", URI_CMP_MATCH },
02219
02220 { "sip:bob@[2001:db8::1234]", "sip:bob@[2001:0db8::1234]", URI_CMP_MATCH },
02221
02222 { "sip:bob@1.2.3.4:5060", "sip:bob@1.2.3.4:5061", URI_CMP_NOMATCH },
02223
02224 { "sip:bob@1.2.3.4:5060", "sip:bob@1.2.3.4", URI_CMP_NOMATCH },
02225
02226 { "sip:bob@[2001:db8:1234]:5060", "sip:bob@[2001:db8:1234]", URI_CMP_NOMATCH },
02227
02228 { "sip:bob@example.com", "sip:BOB@example.com", URI_CMP_NOMATCH },
02229
02230 { "sip:bob@example.com", "sip:bob@EXAMPLE.COM", URI_CMP_MATCH },
02231
02232 { "sip:bob@example.com?header1=value1&header2=value2", "sip:bob@example.com?header1=value1&header2=value2", URI_CMP_MATCH },
02233
02234 { "sip:bob@example.com?header1=value1&header2=value2", "sip:bob@example.com", URI_CMP_NOMATCH },
02235
02236 { "sip:bob@example.com?header1=value1&header2=value2", "sip:bob@example.com?header1=value1&header2=value3", URI_CMP_NOMATCH },
02237
02238 { "sip:bob@example.com;param1=value1;param2=value2", "sip:bob@example.com;param1=value1;param2=value2", URI_CMP_MATCH },
02239
02240 { "sip:bob@example.com;param2=value2;param1=value1", "sip:bob@example.com;param1=value1;param2=value2", URI_CMP_MATCH },
02241
02242 { "sip:bob@example.com;param1=value1;param2=value2", "sip:bob@example.com", URI_CMP_MATCH },
02243
02244 { "sip:bob@example.com;param1=value1;param2=value2", "sip:bob@example.com;param1=value1;param2=value3", URI_CMP_NOMATCH },
02245
02246 { "sip:bob@example.com;param1=value1;maddr=192.168.0.1", "sip:bob@example.com;param1=value1", URI_CMP_NOMATCH },
02247
02248 { "sip:bob@example.com;param1=value1;maddr=192.168.0.1", "sip:bob@example.com;param1=value1;maddr=192.168.0.1", URI_CMP_MATCH },
02249
02250 { "sips:bob@example.com", "sip:bob@example.com", URI_CMP_NOMATCH },
02251
02252 { "bob@example.com", "bob@example.com", URI_CMP_NOMATCH },
02253
02254 { "sip", "sips", URI_CMP_NOMATCH },
02255
02256 { "sip", "sip", URI_CMP_NOMATCH },
02257
02258 { "", "", URI_CMP_NOMATCH },
02259
02260 { "", NULL, URI_CMP_NOMATCH },
02261 };
02262 int i;
02263 int test_res = AST_TEST_PASS;
02264 switch (cmd) {
02265 case TEST_INIT:
02266 info->name = "sip_uri_cmp_test";
02267 info->category = "/channels/chan_sip/";
02268 info->summary = "Tests comparison of SIP URIs";
02269 info->description = "Several would-be tricky URI comparisons are performed";
02270 return AST_TEST_NOT_RUN;
02271 case TEST_EXECUTE:
02272 break;
02273 }
02274
02275 for (i = 0; i < ARRAY_LEN(uri_cmp_tests); ++i) {
02276 int cmp_res1;
02277 int cmp_res2;
02278 if ((cmp_res1 = sip_uri_cmp(uri_cmp_tests[i].uri1, uri_cmp_tests[i].uri2))) {
02279
02280
02281
02282 cmp_res1 = URI_CMP_NOMATCH;
02283 }
02284 if (cmp_res1 != uri_cmp_tests[i].expected_result) {
02285 ast_test_status_update(test, "Unexpected comparison result for URIs %s and %s. "
02286 "Expected %s but got %s\n", uri_cmp_tests[i].uri1, uri_cmp_tests[i].uri2,
02287 uri_cmp_tests[i].expected_result == URI_CMP_MATCH ? "Match" : "No Match",
02288 cmp_res1 == URI_CMP_MATCH ? "Match" : "No Match");
02289 test_res = AST_TEST_FAIL;
02290 }
02291
02292
02293
02294
02295 if ((cmp_res2 = sip_uri_cmp(uri_cmp_tests[i].uri2, uri_cmp_tests[i].uri1))) {
02296
02297
02298
02299 cmp_res2 = URI_CMP_NOMATCH;
02300 }
02301 if (cmp_res2 != uri_cmp_tests[i].expected_result) {
02302 ast_test_status_update(test, "Unexpected comparison result for URIs %s and %s. "
02303 "Expected %s but got %s\n", uri_cmp_tests[i].uri2, uri_cmp_tests[i].uri1,
02304 uri_cmp_tests[i].expected_result == URI_CMP_MATCH ? "Match" : "No Match",
02305 cmp_res2 == URI_CMP_MATCH ? "Match" : "No Match");
02306 test_res = AST_TEST_FAIL;
02307 }
02308 }
02309
02310 return test_res;
02311 }
02312
02313 void free_via(struct sip_via *v)
02314 {
02315 if (!v) {
02316 return;
02317 }
02318
02319 ast_free(v->via);
02320 ast_free(v);
02321 }
02322
02323 struct sip_via *parse_via(const char *header)
02324 {
02325 struct sip_via *v = ast_calloc(1, sizeof(*v));
02326 char *via, *parm;
02327
02328 if (!v) {
02329 return NULL;
02330 }
02331
02332 v->via = ast_strdup(header);
02333 v->ttl = 1;
02334
02335 via = v->via;
02336
02337 if (ast_strlen_zero(via)) {
02338 ast_log(LOG_ERROR, "received request without a Via header\n");
02339 free_via(v);
02340 return NULL;
02341 }
02342
02343
02344 via = strsep(&via, ",");
02345
02346
02347 v->protocol = strsep(&via, " \t\r\n");
02348 if (ast_strlen_zero(v->protocol)) {
02349 ast_log(LOG_ERROR, "missing sent-protocol in Via header\n");
02350 free_via(v);
02351 return NULL;
02352 }
02353 v->protocol = ast_skip_blanks(v->protocol);
02354
02355 if (via) {
02356 via = ast_skip_blanks(via);
02357 }
02358
02359
02360 v->sent_by = strsep(&via, "; \t\r\n");
02361 if (ast_strlen_zero(v->sent_by)) {
02362 ast_log(LOG_ERROR, "missing sent-by in Via header\n");
02363 free_via(v);
02364 return NULL;
02365 }
02366 v->sent_by = ast_skip_blanks(v->sent_by);
02367
02368
02369
02370 if (((parm = strchr(v->sent_by, ']')) && *(++parm) == ':') || (parm = strchr(v->sent_by, ':'))) {
02371 char *endptr;
02372
02373 v->port = strtol(++parm, &endptr, 10);
02374 }
02375
02376
02377 while ((parm = strsep(&via, "; \t\r\n"))) {
02378 char *c;
02379 if ((c = strstr(parm, "maddr="))) {
02380 v->maddr = ast_skip_blanks(c + sizeof("maddr=") - 1);
02381 } else if ((c = strstr(parm, "branch="))) {
02382 v->branch = ast_skip_blanks(c + sizeof("branch=") - 1);
02383 } else if ((c = strstr(parm, "ttl="))) {
02384 char *endptr;
02385 c = ast_skip_blanks(c + sizeof("ttl=") - 1);
02386 v->ttl = strtol(c, &endptr, 10);
02387
02388
02389 if (c == endptr) {
02390 v->ttl = 1;
02391 }
02392 }
02393 }
02394
02395 return v;
02396 }
02397
02398 AST_TEST_DEFINE(parse_via_test)
02399 {
02400 int res = AST_TEST_PASS;
02401 int i = 1;
02402 struct sip_via *via;
02403 struct testdata {
02404 char *in;
02405 char *expected_protocol;
02406 char *expected_branch;
02407 char *expected_sent_by;
02408 char *expected_maddr;
02409 unsigned int expected_port;
02410 unsigned char expected_ttl;
02411 int expected_null;
02412 AST_LIST_ENTRY(testdata) list;
02413 };
02414 struct testdata *testdataptr;
02415 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
02416 struct testdata t1 = {
02417 .in = "SIP/2.0/UDP host:port;branch=thebranch",
02418 .expected_protocol = "SIP/2.0/UDP",
02419 .expected_sent_by = "host:port",
02420 .expected_branch = "thebranch",
02421 };
02422 struct testdata t2 = {
02423 .in = "SIP/2.0/UDP host:port",
02424 .expected_protocol = "SIP/2.0/UDP",
02425 .expected_sent_by = "host:port",
02426 .expected_branch = "",
02427 };
02428 struct testdata t3 = {
02429 .in = "SIP/2.0/UDP",
02430 .expected_null = 1,
02431 };
02432 struct testdata t4 = {
02433 .in = "BLAH/BLAH/BLAH host:port;branch=",
02434 .expected_protocol = "BLAH/BLAH/BLAH",
02435 .expected_sent_by = "host:port",
02436 .expected_branch = "",
02437 };
02438 struct testdata t5 = {
02439 .in = "SIP/2.0/UDP host:5060;branch=thebranch;maddr=224.0.0.1;ttl=1",
02440 .expected_protocol = "SIP/2.0/UDP",
02441 .expected_sent_by = "host:5060",
02442 .expected_port = 5060,
02443 .expected_branch = "thebranch",
02444 .expected_maddr = "224.0.0.1",
02445 .expected_ttl = 1,
02446 };
02447 struct testdata t6 = {
02448 .in = "SIP/2.0/UDP host:5060;\n branch=thebranch;\r\n maddr=224.0.0.1; ttl=1",
02449 .expected_protocol = "SIP/2.0/UDP",
02450 .expected_sent_by = "host:5060",
02451 .expected_port = 5060,
02452 .expected_branch = "thebranch",
02453 .expected_maddr = "224.0.0.1",
02454 .expected_ttl = 1,
02455 };
02456 struct testdata t7 = {
02457 .in = "SIP/2.0/UDP [::1]:5060",
02458 .expected_protocol = "SIP/2.0/UDP",
02459 .expected_sent_by = "[::1]:5060",
02460 .expected_port = 5060,
02461 .expected_branch = "",
02462 };
02463 switch (cmd) {
02464 case TEST_INIT:
02465 info->name = "parse_via_test";
02466 info->category = "/channels/chan_sip/";
02467 info->summary = "Tests parsing the Via header";
02468 info->description =
02469 "Runs through various test situations in which various "
02470 " parameters parameter must be extracted from a VIA header";
02471 return AST_TEST_NOT_RUN;
02472 case TEST_EXECUTE:
02473 break;
02474 }
02475
02476 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &t1);
02477 AST_LIST_INSERT_TAIL(&testdatalist, &t2, list);
02478 AST_LIST_INSERT_TAIL(&testdatalist, &t3, list);
02479 AST_LIST_INSERT_TAIL(&testdatalist, &t4, list);
02480 AST_LIST_INSERT_TAIL(&testdatalist, &t5, list);
02481 AST_LIST_INSERT_TAIL(&testdatalist, &t6, list);
02482 AST_LIST_INSERT_TAIL(&testdatalist, &t7, list);
02483
02484
02485 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
02486 via = parse_via(testdataptr->in);
02487 if (!via) {
02488 if (!testdataptr->expected_null) {
02489 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02490 "failed to parse header\n",
02491 i, testdataptr->in);
02492 res = AST_TEST_FAIL;
02493 }
02494 i++;
02495 continue;
02496 }
02497
02498 if (testdataptr->expected_null) {
02499 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02500 "successfully parased invalid via header\n",
02501 i, testdataptr->in);
02502 res = AST_TEST_FAIL;
02503 free_via(via);
02504 i++;
02505 continue;
02506 }
02507
02508 if ((ast_strlen_zero(via->protocol) && !ast_strlen_zero(testdataptr->expected_protocol))
02509 || (!ast_strlen_zero(via->protocol) && strcmp(via->protocol, testdataptr->expected_protocol))) {
02510
02511 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02512 "parsed protocol = \"%s\"\n"
02513 "expected = \"%s\"\n"
02514 "failed to parse protocol\n",
02515 i, testdataptr->in, via->protocol, testdataptr->expected_protocol);
02516 res = AST_TEST_FAIL;
02517 }
02518
02519 if ((ast_strlen_zero(via->sent_by) && !ast_strlen_zero(testdataptr->expected_sent_by))
02520 || (!ast_strlen_zero(via->sent_by) && strcmp(via->sent_by, testdataptr->expected_sent_by))) {
02521
02522 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02523 "parsed sent_by = \"%s\"\n"
02524 "expected = \"%s\"\n"
02525 "failed to parse sent-by\n",
02526 i, testdataptr->in, via->sent_by, testdataptr->expected_sent_by);
02527 res = AST_TEST_FAIL;
02528 }
02529
02530 if (testdataptr->expected_port && testdataptr->expected_port != via->port) {
02531 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02532 "parsed port = \"%d\"\n"
02533 "expected = \"%d\"\n"
02534 "failed to parse port\n",
02535 i, testdataptr->in, via->port, testdataptr->expected_port);
02536 res = AST_TEST_FAIL;
02537 }
02538
02539 if ((ast_strlen_zero(via->branch) && !ast_strlen_zero(testdataptr->expected_branch))
02540 || (!ast_strlen_zero(via->branch) && strcmp(via->branch, testdataptr->expected_branch))) {
02541
02542 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02543 "parsed branch = \"%s\"\n"
02544 "expected = \"%s\"\n"
02545 "failed to parse branch\n",
02546 i, testdataptr->in, via->branch, testdataptr->expected_branch);
02547 res = AST_TEST_FAIL;
02548 }
02549
02550 if ((ast_strlen_zero(via->maddr) && !ast_strlen_zero(testdataptr->expected_maddr))
02551 || (!ast_strlen_zero(via->maddr) && strcmp(via->maddr, testdataptr->expected_maddr))) {
02552
02553 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02554 "parsed maddr = \"%s\"\n"
02555 "expected = \"%s\"\n"
02556 "failed to parse maddr\n",
02557 i, testdataptr->in, via->maddr, testdataptr->expected_maddr);
02558 res = AST_TEST_FAIL;
02559 }
02560
02561 if (testdataptr->expected_ttl && testdataptr->expected_ttl != via->ttl) {
02562 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02563 "parsed ttl = \"%d\"\n"
02564 "expected = \"%d\"\n"
02565 "failed to parse ttl\n",
02566 i, testdataptr->in, via->ttl, testdataptr->expected_ttl);
02567 res = AST_TEST_FAIL;
02568 }
02569
02570 free_via(via);
02571 i++;
02572 }
02573 return res;
02574 }
02575
02576 void sip_request_parser_register_tests(void)
02577 {
02578 AST_TEST_REGISTER(get_calleridname_test);
02579 AST_TEST_REGISTER(sip_parse_uri_test);
02580 AST_TEST_REGISTER(get_in_brackets_test);
02581 AST_TEST_REGISTER(get_name_and_number_test);
02582 AST_TEST_REGISTER(sip_parse_uri_fully_test);
02583 AST_TEST_REGISTER(parse_name_andor_addr_test);
02584 AST_TEST_REGISTER(parse_contact_header_test);
02585 AST_TEST_REGISTER(sip_parse_options_test);
02586 AST_TEST_REGISTER(sip_uri_cmp_test);
02587 AST_TEST_REGISTER(parse_via_test);
02588 }
02589 void sip_request_parser_unregister_tests(void)
02590 {
02591 AST_TEST_UNREGISTER(sip_parse_uri_test);
02592 AST_TEST_UNREGISTER(get_calleridname_test);
02593 AST_TEST_UNREGISTER(get_in_brackets_test);
02594 AST_TEST_UNREGISTER(get_name_and_number_test);
02595 AST_TEST_UNREGISTER(sip_parse_uri_fully_test);
02596 AST_TEST_UNREGISTER(parse_name_andor_addr_test);
02597 AST_TEST_UNREGISTER(parse_contact_header_test);
02598 AST_TEST_UNREGISTER(sip_parse_options_test);
02599 AST_TEST_UNREGISTER(sip_uri_cmp_test);
02600 AST_TEST_UNREGISTER(parse_via_test);
02601 }
02602
02603 int sip_reqresp_parser_init(void)
02604 {
02605 #ifdef HAVE_XLOCALE_H
02606 c_locale = newlocale(LC_CTYPE_MASK, "C", NULL);
02607 if (!c_locale) {
02608 return -1;
02609 }
02610 #endif
02611 return 0;
02612 }
02613
02614 void sip_reqresp_parser_exit(void)
02615 {
02616 #ifdef HAVE_XLOCALE_H
02617 if (c_locale) {
02618 freelocale(c_locale);
02619 c_locale = NULL;
02620 }
02621 #endif
02622 }