diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-19 18:53:43 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-19 18:53:43 +0000 |
commit | 52e15dc50b0eaa30109564dcdbb6b6f9557cd1d9 (patch) | |
tree | 411b894818fcfb539f2cb1805ff4d00439c2f251 | |
parent | f9000c51dbf7bb9544a305ae06e91bba7e17e26a (diff) | |
download | busybox-w32-52e15dc50b0eaa30109564dcdbb6b6f9557cd1d9.tar.gz busybox-w32-52e15dc50b0eaa30109564dcdbb6b6f9557cd1d9.tar.bz2 busybox-w32-52e15dc50b0eaa30109564dcdbb6b6f9557cd1d9.zip |
httpd: get rid of sscanf usage. Rename some variables.
-rw-r--r-- | networking/httpd.c | 204 |
1 files changed, 110 insertions, 94 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index c837d67ad..23d442f17 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -110,6 +110,7 @@ | |||
110 | 110 | ||
111 | static const char default_path_httpd_conf[] ALIGN1 = "/etc"; | 111 | static const char default_path_httpd_conf[] ALIGN1 = "/etc"; |
112 | static const char httpd_conf[] ALIGN1 = "httpd.conf"; | 112 | static const char httpd_conf[] ALIGN1 = "httpd.conf"; |
113 | static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; | ||
113 | 114 | ||
114 | typedef struct has_next_ptr { | 115 | typedef struct has_next_ptr { |
115 | struct has_next_ptr *next; | 116 | struct has_next_ptr *next; |
@@ -135,6 +136,7 @@ struct globals { | |||
135 | smallint flg_deny_all; | 136 | smallint flg_deny_all; |
136 | 137 | ||
137 | unsigned rmt_ip; | 138 | unsigned rmt_ip; |
139 | // TODO: get rid of rmt_port | ||
138 | unsigned rmt_port; /* for set env REMOTE_PORT */ | 140 | unsigned rmt_port; /* for set env REMOTE_PORT */ |
139 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ | 141 | char *rmt_ip_str; /* for set env REMOTE_ADDR */ |
140 | const char *bind_addr_or_port; | 142 | const char *bind_addr_or_port; |
@@ -661,6 +663,22 @@ static char *encodeString(const char *string) | |||
661 | * | 663 | * |
662 | * Returns a pointer to the decoded string (same as input). | 664 | * Returns a pointer to the decoded string (same as input). |
663 | */ | 665 | */ |
666 | static unsigned hex_to_bin(unsigned char c) | ||
667 | { | ||
668 | unsigned v = c | 0x20; /* lowercase */ | ||
669 | v = v - '0'; | ||
670 | if (v <= 9) | ||
671 | return v; | ||
672 | v = v + ('0' - 'a'); | ||
673 | if (v <= 5) | ||
674 | return v + 10; | ||
675 | return ~0; | ||
676 | } | ||
677 | /* For testing: | ||
678 | void t(char c) { printf("'%c' %u\n", c, hex_to_bin(c)); } | ||
679 | int main() { t('0'); t('9'); t('A'); t('F'); t('a'); t('f'); | ||
680 | t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; } | ||
681 | */ | ||
664 | static char *decodeString(char *orig, int option_d) | 682 | static char *decodeString(char *orig, int option_d) |
665 | { | 683 | { |
666 | /* note that decoded string is always shorter than original */ | 684 | /* note that decoded string is always shorter than original */ |
@@ -669,7 +687,7 @@ static char *decodeString(char *orig, int option_d) | |||
669 | char c; | 687 | char c; |
670 | 688 | ||
671 | while ((c = *ptr++) != '\0') { | 689 | while ((c = *ptr++) != '\0') { |
672 | unsigned value1, value2; | 690 | unsigned v; |
673 | 691 | ||
674 | if (option_d && c == '+') { | 692 | if (option_d && c == '+') { |
675 | *string++ = ' '; | 693 | *string++ = ' '; |
@@ -679,21 +697,23 @@ static char *decodeString(char *orig, int option_d) | |||
679 | *string++ = c; | 697 | *string++ = c; |
680 | continue; | 698 | continue; |
681 | } | 699 | } |
682 | if (sscanf(ptr, "%1X", &value1) != 1 | 700 | v = hex_to_bin(ptr[0]); |
683 | || sscanf(ptr+1, "%1X", &value2) != 1 | 701 | if (v > 15) { |
684 | ) { | 702 | bad_hex: |
685 | if (!option_d) | 703 | if (!option_d) |
686 | return NULL; | 704 | return NULL; |
687 | *string++ = '%'; | 705 | *string++ = '%'; |
688 | continue; | 706 | continue; |
689 | } | 707 | } |
690 | value1 = value1 * 16 + value2; | 708 | v = (v * 16) | hex_to_bin(ptr[1]); |
691 | if (!option_d && (value1 == '/' || value1 == '\0')) { | 709 | if (v > 255) |
710 | goto bad_hex; | ||
711 | if (!option_d && (v == '/' || v == '\0')) { | ||
692 | /* caller takes it as indication of invalid | 712 | /* caller takes it as indication of invalid |
693 | * (dangerous wrt exploits) chars */ | 713 | * (dangerous wrt exploits) chars */ |
694 | return orig + 1; | 714 | return orig + 1; |
695 | } | 715 | } |
696 | *string++ = value1; | 716 | *string++ = v; |
697 | ptr += 2; | 717 | ptr += 2; |
698 | } | 718 | } |
699 | *string = '\0'; | 719 | *string = '\0'; |
@@ -1188,13 +1208,13 @@ static void send_cgi_and_exit( | |||
1188 | 1208 | ||
1189 | /* Are we still buffering CGI output? */ | 1209 | /* Are we still buffering CGI output? */ |
1190 | if (buf_count >= 0) { | 1210 | if (buf_count >= 0) { |
1191 | /* According to http://hoohoo.ncsa.uiuc.edu/cgi/out.html, | 1211 | /* HTTP_200[] has single "\r\n" at the end. |
1212 | * According to http://hoohoo.ncsa.uiuc.edu/cgi/out.html, | ||
1192 | * CGI scripts MUST send their own header terminated by | 1213 | * CGI scripts MUST send their own header terminated by |
1193 | * empty line, then data. That's why we have only one | 1214 | * empty line, then data. That's why we have only one |
1194 | * <cr><lf> pair here. We will output "200 OK" line | 1215 | * <cr><lf> pair here. We will output "200 OK" line |
1195 | * if needed, but CGI still has to provide blank line | 1216 | * if needed, but CGI still has to provide blank line |
1196 | * between header and body */ | 1217 | * between header and body */ |
1197 | static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; | ||
1198 | 1218 | ||
1199 | /* Must use safe_read, not full_read, because | 1219 | /* Must use safe_read, not full_read, because |
1200 | * CGI may output a few first bytes and then wait | 1220 | * CGI may output a few first bytes and then wait |
@@ -1489,12 +1509,11 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1489 | { | 1509 | { |
1490 | static const char request_GET[] ALIGN1 = "GET"; | 1510 | static const char request_GET[] ALIGN1 = "GET"; |
1491 | 1511 | ||
1492 | char *url; | ||
1493 | char *purl; | ||
1494 | int count; | ||
1495 | int http_major_version; | ||
1496 | char *test; | ||
1497 | struct stat sb; | 1512 | struct stat sb; |
1513 | char *urlcopy; | ||
1514 | char *urlp; | ||
1515 | char *tptr; | ||
1516 | int http_major_version; | ||
1498 | int ip_allowed; | 1517 | int ip_allowed; |
1499 | #if ENABLE_FEATURE_HTTPD_CGI | 1518 | #if ENABLE_FEATURE_HTTPD_CGI |
1500 | const char *prequest; | 1519 | const char *prequest; |
@@ -1535,58 +1554,57 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1535 | sigaction(SIGALRM, &sa, NULL); | 1554 | sigaction(SIGALRM, &sa, NULL); |
1536 | alarm(HEADER_READ_TIMEOUT); | 1555 | alarm(HEADER_READ_TIMEOUT); |
1537 | 1556 | ||
1538 | if (!get_line()) { | 1557 | if (!get_line()) /* EOF or error or empty line */ |
1539 | /* EOF or error or empty line */ | ||
1540 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1558 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1541 | } | ||
1542 | 1559 | ||
1543 | /* Determine type of request (GET/POST) */ | 1560 | /* Determine type of request (GET/POST) */ |
1544 | purl = strpbrk(iobuf, " \t"); | 1561 | urlp = strpbrk(iobuf, " \t"); |
1545 | if (purl == NULL) { | 1562 | if (urlp == NULL) |
1546 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1563 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1547 | } | 1564 | *urlp++ = '\0'; |
1548 | *purl = '\0'; | ||
1549 | #if ENABLE_FEATURE_HTTPD_CGI | 1565 | #if ENABLE_FEATURE_HTTPD_CGI |
1550 | prequest = request_GET; | 1566 | prequest = request_GET; |
1551 | if (strcasecmp(iobuf, prequest) != 0) { | 1567 | if (strcasecmp(iobuf, prequest) != 0) { |
1552 | prequest = "POST"; | 1568 | prequest = "POST"; |
1553 | if (strcasecmp(iobuf, prequest) != 0) { | 1569 | if (strcasecmp(iobuf, prequest) != 0) |
1554 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | 1570 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); |
1555 | } | ||
1556 | } | 1571 | } |
1557 | #else | 1572 | #else |
1558 | if (strcasecmp(iobuf, request_GET) != 0) { | 1573 | if (strcasecmp(iobuf, request_GET) != 0) |
1559 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | 1574 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); |
1560 | } | ||
1561 | #endif | 1575 | #endif |
1562 | *purl = ' '; | 1576 | urlp = skip_whitespace(urlp); |
1577 | if (urlp[0] != '/') | ||
1578 | send_headers_and_exit(HTTP_BAD_REQUEST); | ||
1563 | 1579 | ||
1564 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ | 1580 | /* Find end of URL and parse HTTP version, if any */ |
1565 | http_major_version = -1; | 1581 | http_major_version = -1; |
1566 | count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &http_major_version); | 1582 | tptr = strchrnul(urlp, ' '); |
1567 | if (count < 1 || iobuf[0] != '/') { | 1583 | /* Is it " HTTP/"? */ |
1568 | /* Garbled request/URL */ | 1584 | if (tptr[0] && strncmp(tptr + 1, HTTP_200, 5) == 0) |
1569 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1585 | http_major_version = (tptr[6] - '0'); |
1570 | } | 1586 | *tptr = '\0'; |
1571 | url = alloca(strlen(iobuf) + sizeof("/index.html")); | 1587 | |
1572 | if (url == NULL) { | 1588 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ |
1573 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | 1589 | urlcopy = alloca((tptr - urlp) + sizeof("/index.html")); |
1574 | } | 1590 | /*if (urlcopy == NULL) |
1575 | strcpy(url, iobuf); | 1591 | * send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);*/ |
1592 | strcpy(urlcopy, urlp); | ||
1593 | /* NB: urlcopy ptr is never changed after this */ | ||
1576 | 1594 | ||
1577 | /* Extract url args if present */ | 1595 | /* Extract url args if present */ |
1578 | test = strchr(url, '?'); | 1596 | tptr = strchr(urlcopy, '?'); |
1579 | g_query = NULL; | 1597 | g_query = NULL; |
1580 | if (test) { | 1598 | if (tptr) { |
1581 | *test++ = '\0'; | 1599 | *tptr++ = '\0'; |
1582 | g_query = test; | 1600 | g_query = tptr; |
1583 | } | 1601 | } |
1584 | 1602 | ||
1585 | /* Decode URL escape sequences */ | 1603 | /* Decode URL escape sequences */ |
1586 | test = decodeString(url, 0); | 1604 | tptr = decodeString(urlcopy, 0); |
1587 | if (test == NULL) | 1605 | if (tptr == NULL) |
1588 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1606 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1589 | if (test == url + 1) { | 1607 | if (tptr == urlcopy + 1) { |
1590 | /* '/' or NUL is encoded */ | 1608 | /* '/' or NUL is encoded */ |
1591 | send_headers_and_exit(HTTP_NOT_FOUND); | 1609 | send_headers_and_exit(HTTP_NOT_FOUND); |
1592 | } | 1610 | } |
@@ -1594,60 +1612,58 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1594 | /* Canonicalize path */ | 1612 | /* Canonicalize path */ |
1595 | /* Algorithm stolen from libbb bb_simplify_path(), | 1613 | /* Algorithm stolen from libbb bb_simplify_path(), |
1596 | * but don't strdup and reducing trailing slash and protect out root */ | 1614 | * but don't strdup and reducing trailing slash and protect out root */ |
1597 | purl = test = url; | 1615 | urlp = tptr = urlcopy; |
1598 | do { | 1616 | do { |
1599 | if (*purl == '/') { | 1617 | if (*urlp == '/') { |
1600 | /* skip duplicate (or initial) slash */ | 1618 | /* skip duplicate (or initial) slash */ |
1601 | if (*test == '/') { | 1619 | if (*tptr == '/') { |
1602 | continue; | 1620 | continue; |
1603 | } | 1621 | } |
1604 | if (*test == '.') { | 1622 | if (*tptr == '.') { |
1605 | /* skip extra '.' */ | 1623 | /* skip extra '.' */ |
1606 | if (test[1] == '/' || !test[1]) { | 1624 | if (tptr[1] == '/' || !tptr[1]) { |
1607 | continue; | 1625 | continue; |
1608 | } | 1626 | } |
1609 | /* '..': be careful */ | 1627 | /* '..': be careful */ |
1610 | if (test[1] == '.' && (test[2] == '/' || !test[2])) { | 1628 | if (tptr[1] == '.' && (tptr[2] == '/' || !tptr[2])) { |
1611 | ++test; | 1629 | ++tptr; |
1612 | if (purl == url) { | 1630 | if (urlp == urlcopy) /* protect root */ |
1613 | /* protect root */ | ||
1614 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1631 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1615 | } | 1632 | while (*--urlp != '/') /* omit previous dir */; |
1616 | while (*--purl != '/') /* omit previous dir */; | ||
1617 | continue; | 1633 | continue; |
1618 | } | 1634 | } |
1619 | } | 1635 | } |
1620 | } | 1636 | } |
1621 | *++purl = *test; | 1637 | *++urlp = *tptr; |
1622 | } while (*++test); | 1638 | } while (*++tptr); |
1623 | *++purl = '\0'; /* so keep last character */ | 1639 | *++urlp = '\0'; /* so keep last character */ |
1624 | test = purl; /* end ptr */ | 1640 | tptr = urlp; /* end ptr */ |
1625 | 1641 | ||
1626 | /* If URL is a directory, add '/' */ | 1642 | /* If URL is a directory, add '/' */ |
1627 | if (test[-1] != '/') { | 1643 | if (tptr[-1] != '/') { |
1628 | if (is_directory(url + 1, 1, &sb)) { | 1644 | if (is_directory(urlcopy + 1, 1, &sb)) { |
1629 | found_moved_temporarily = url; | 1645 | found_moved_temporarily = urlcopy; |
1630 | } | 1646 | } |
1631 | } | 1647 | } |
1632 | 1648 | ||
1633 | /* Log it */ | 1649 | /* Log it */ |
1634 | if (verbose > 1) | 1650 | if (verbose > 1) |
1635 | bb_error_msg("url:%s", url); | 1651 | bb_error_msg("url:%s", urlcopy); |
1636 | 1652 | ||
1637 | test = url; | 1653 | tptr = urlcopy; |
1638 | ip_allowed = checkPermIP(); | 1654 | ip_allowed = checkPermIP(); |
1639 | while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) { | 1655 | while (ip_allowed && (tptr = strchr(tptr + 1, '/')) != NULL) { |
1640 | /* have path1/path2 */ | 1656 | /* have path1/path2 */ |
1641 | *test = '\0'; | 1657 | *tptr = '\0'; |
1642 | if (is_directory(url + 1, 1, &sb)) { | 1658 | if (is_directory(urlcopy + 1, 1, &sb)) { |
1643 | /* may be having subdir config */ | 1659 | /* may be having subdir config */ |
1644 | parse_conf(url + 1, SUBDIR_PARSE); | 1660 | parse_conf(urlcopy + 1, SUBDIR_PARSE); |
1645 | ip_allowed = checkPermIP(); | 1661 | ip_allowed = checkPermIP(); |
1646 | } | 1662 | } |
1647 | *test = '/'; | 1663 | *tptr = '/'; |
1648 | } | 1664 | } |
1649 | if (http_major_version >= 0) { | 1665 | if (http_major_version >= 0) { |
1650 | /* Request was with "... HTTP/n.m", and n >= 0 */ | 1666 | /* Request was with "... HTTP/nXXX", and n >= 0 */ |
1651 | 1667 | ||
1652 | /* Read until blank line for HTTP version specified, else parse immediate */ | 1668 | /* Read until blank line for HTTP version specified, else parse immediate */ |
1653 | while (1) { | 1669 | while (1) { |
@@ -1662,16 +1678,16 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1662 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { | 1678 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { |
1663 | /* extra read only for POST */ | 1679 | /* extra read only for POST */ |
1664 | if (prequest != request_GET) { | 1680 | if (prequest != request_GET) { |
1665 | test = iobuf + sizeof("Content-length:") - 1; | 1681 | tptr = iobuf + sizeof("Content-length:") - 1; |
1666 | if (!test[0]) | 1682 | if (!tptr[0]) |
1667 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1683 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1668 | errno = 0; | 1684 | errno = 0; |
1669 | /* not using strtoul: it ignores leading minus! */ | 1685 | /* not using strtoul: it ignores leading minus! */ |
1670 | length = strtol(test, &test, 10); | 1686 | length = strtol(tptr, &tptr, 10); |
1671 | /* length is "ulong", but we need to pass it to int later */ | 1687 | /* length is "ulong", but we need to pass it to int later */ |
1672 | /* so we check for negative or too large values in one go: */ | 1688 | /* so we check for negative or too large values in one go: */ |
1673 | /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */ | 1689 | /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */ |
1674 | if (test[0] || errno || length > INT_MAX) | 1690 | if (tptr[0] || errno || length > INT_MAX) |
1675 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1691 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1676 | } | 1692 | } |
1677 | } else if (STRNCASECMP(iobuf, "Cookie:") == 0) { | 1693 | } else if (STRNCASECMP(iobuf, "Cookie:") == 0) { |
@@ -1690,13 +1706,13 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1690 | * It shows up as "Authorization: Basic <userid:password>" where | 1706 | * It shows up as "Authorization: Basic <userid:password>" where |
1691 | * the userid:password is base64 encoded. | 1707 | * the userid:password is base64 encoded. |
1692 | */ | 1708 | */ |
1693 | test = skip_whitespace(iobuf + sizeof("Authorization:")-1); | 1709 | tptr = skip_whitespace(iobuf + sizeof("Authorization:")-1); |
1694 | if (STRNCASECMP(test, "Basic") != 0) | 1710 | if (STRNCASECMP(tptr, "Basic") != 0) |
1695 | continue; | 1711 | continue; |
1696 | test += sizeof("Basic")-1; | 1712 | tptr += sizeof("Basic")-1; |
1697 | /* decodeBase64() skips whitespace itself */ | 1713 | /* decodeBase64() skips whitespace itself */ |
1698 | decodeBase64(test); | 1714 | decodeBase64(tptr); |
1699 | credentials = checkPerm(url, test); | 1715 | credentials = checkPerm(urlcopy, tptr); |
1700 | } | 1716 | } |
1701 | #endif /* FEATURE_HTTPD_BASIC_AUTH */ | 1717 | #endif /* FEATURE_HTTPD_BASIC_AUTH */ |
1702 | } /* while extra header reading */ | 1718 | } /* while extra header reading */ |
@@ -1705,13 +1721,13 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1705 | /* We read headers, disable peer timeout */ | 1721 | /* We read headers, disable peer timeout */ |
1706 | alarm(0); | 1722 | alarm(0); |
1707 | 1723 | ||
1708 | if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) { | 1724 | if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || ip_allowed == 0) { |
1709 | /* protect listing [/path]/httpd_conf or IP deny */ | 1725 | /* protect listing [/path]/httpd_conf or IP deny */ |
1710 | send_headers_and_exit(HTTP_FORBIDDEN); | 1726 | send_headers_and_exit(HTTP_FORBIDDEN); |
1711 | } | 1727 | } |
1712 | 1728 | ||
1713 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1729 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
1714 | if (credentials <= 0 && checkPerm(url, ":") == 0) { | 1730 | if (credentials <= 0 && checkPerm(urlcopy, ":") == 0) { |
1715 | send_headers_and_exit(HTTP_UNAUTHORIZED); | 1731 | send_headers_and_exit(HTTP_UNAUTHORIZED); |
1716 | } | 1732 | } |
1717 | #endif | 1733 | #endif |
@@ -1720,24 +1736,24 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1720 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); | 1736 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); |
1721 | } | 1737 | } |
1722 | 1738 | ||
1723 | test = url + 1; /* skip first '/' */ | 1739 | tptr = urlcopy + 1; /* skip first '/' */ |
1724 | 1740 | ||
1725 | #if ENABLE_FEATURE_HTTPD_CGI | 1741 | #if ENABLE_FEATURE_HTTPD_CGI |
1726 | if (strncmp(test, "cgi-bin/", 8) == 0) { | 1742 | if (strncmp(tptr, "cgi-bin/", 8) == 0) { |
1727 | if (test[8] == '\0') { | 1743 | if (tptr[8] == '\0') { |
1728 | /* protect listing "cgi-bin/" */ | 1744 | /* protect listing "cgi-bin/" */ |
1729 | send_headers_and_exit(HTTP_FORBIDDEN); | 1745 | send_headers_and_exit(HTTP_FORBIDDEN); |
1730 | } | 1746 | } |
1731 | send_cgi_and_exit(url, prequest, length, cookie, content_type); | 1747 | send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type); |
1732 | } | 1748 | } |
1733 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | 1749 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR |
1734 | { | 1750 | { |
1735 | char *suffix = strrchr(test, '.'); | 1751 | char *suffix = strrchr(tptr, '.'); |
1736 | if (suffix) { | 1752 | if (suffix) { |
1737 | Htaccess *cur; | 1753 | Htaccess *cur; |
1738 | for (cur = script_i; cur; cur = cur->next) { | 1754 | for (cur = script_i; cur; cur = cur->next) { |
1739 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | 1755 | if (strcmp(cur->before_colon + 1, suffix) == 0) { |
1740 | send_cgi_and_exit(url, prequest, length, cookie, content_type); | 1756 | send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type); |
1741 | } | 1757 | } |
1742 | } | 1758 | } |
1743 | } | 1759 | } |
@@ -1748,20 +1764,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1748 | } | 1764 | } |
1749 | #endif /* FEATURE_HTTPD_CGI */ | 1765 | #endif /* FEATURE_HTTPD_CGI */ |
1750 | 1766 | ||
1751 | if (purl[-1] == '/') | 1767 | if (urlp[-1] == '/') |
1752 | strcpy(purl, "index.html"); | 1768 | strcpy(urlp, "index.html"); |
1753 | if (stat(test, &sb) == 0) { | 1769 | if (stat(tptr, &sb) == 0) { |
1754 | /* It's a dir URL and there is index.html */ | 1770 | /* It's a dir URL and there is index.html */ |
1755 | ContentLength = sb.st_size; | 1771 | ContentLength = sb.st_size; |
1756 | last_mod = sb.st_mtime; | 1772 | last_mod = sb.st_mtime; |
1757 | } | 1773 | } |
1758 | #if ENABLE_FEATURE_HTTPD_CGI | 1774 | #if ENABLE_FEATURE_HTTPD_CGI |
1759 | else if (purl[-1] == '/') { | 1775 | else if (urlp[-1] == '/') { |
1760 | /* It's a dir URL and there is no index.html | 1776 | /* It's a dir URL and there is no index.html |
1761 | * Try cgi-bin/index.cgi */ | 1777 | * Try cgi-bin/index.cgi */ |
1762 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | 1778 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { |
1763 | purl[0] = '\0'; | 1779 | urlp[0] = '\0'; |
1764 | g_query = url; | 1780 | g_query = urlcopy; |
1765 | send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); | 1781 | send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); |
1766 | } | 1782 | } |
1767 | } | 1783 | } |
@@ -1771,7 +1787,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1771 | * } | 1787 | * } |
1772 | */ | 1788 | */ |
1773 | 1789 | ||
1774 | send_file_and_exit(test); | 1790 | send_file_and_exit(tptr); |
1775 | 1791 | ||
1776 | #if 0 /* Is this needed? Why? */ | 1792 | #if 0 /* Is this needed? Why? */ |
1777 | if (DEBUG) | 1793 | if (DEBUG) |