| 1 | --- a/include/usage.src.h |
| 2 | +++ b/include/usage.src.h |
| 3 | @@ -1623,7 +1623,8 @@ INSERT |
| 4 | IF_FEATURE_HTTPD_SETUID(" [-u USER[:GRP]]") \ |
| 5 | IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]") \ |
| 6 | " [-h HOME]\n" \ |
| 7 | - "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" |
| 8 | + "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" \ |
| 9 | + " [-R <path> [-H <host>]]" |
| 10 | #define httpd_full_usage "\n\n" \ |
| 11 | "Listen for incoming HTTP requests\n" \ |
| 12 | "\nOptions:" \ |
| 13 | @@ -1641,6 +1642,8 @@ INSERT |
| 14 | "\n -m STRING MD5 crypt STRING") \ |
| 15 | "\n -e STRING HTML encode STRING" \ |
| 16 | "\n -d STRING URL decode STRING" \ |
| 17 | + "\n -R PATH Redirect target path" \ |
| 18 | + "\n -H HOST Redirect target host" \ |
| 19 | |
| 20 | #define hwclock_trivial_usage \ |
| 21 | IF_FEATURE_HWCLOCK_LONG_OPTIONS( \ |
| 22 | --- a/networking/httpd.c |
| 23 | +++ b/networking/httpd.c |
| 24 | @@ -243,6 +243,8 @@ struct globals { |
| 25 | |
| 26 | const char *found_mime_type; |
| 27 | const char *found_moved_temporarily; |
| 28 | + const char *redirect_path; |
| 29 | + const char *redirect_host; |
| 30 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ |
| 31 | |
| 32 | IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) |
| 33 | @@ -293,6 +295,8 @@ struct globals { |
| 34 | #define index_page (G.index_page ) |
| 35 | #define found_mime_type (G.found_mime_type ) |
| 36 | #define found_moved_temporarily (G.found_moved_temporarily) |
| 37 | +#define redirect_path (G.redirect_path ) |
| 38 | +#define redirect_host (G.redirect_host ) |
| 39 | #define last_mod (G.last_mod ) |
| 40 | #define ip_a_d (G.ip_a_d ) |
| 41 | #define g_realm (G.g_realm ) |
| 42 | @@ -999,8 +1003,11 @@ static void send_headers(int responseNum |
| 43 | } |
| 44 | #endif |
| 45 | if (responseNum == HTTP_MOVED_TEMPORARILY) { |
| 46 | - len += sprintf(iobuf + len, "Location: %s/%s%s\r\n", |
| 47 | + len += sprintf(iobuf + len, "Location: %s%s%s%s%s%s\r\n", |
| 48 | + (redirect_host ? "http://" : ""), |
| 49 | + (redirect_host ? redirect_host : ""), |
| 50 | found_moved_temporarily, |
| 51 | + (redirect_host ? "" : "/"), |
| 52 | (g_query ? "?" : ""), |
| 53 | (g_query ? g_query : "")); |
| 54 | } |
| 55 | @@ -1967,8 +1974,12 @@ static void handle_incoming_and_exit(con |
| 56 | } while (*++tptr); |
| 57 | *++urlp = '\0'; /* terminate after last character */ |
| 58 | |
| 59 | + /* redirect active */ |
| 60 | + if (redirect_path && (strncmp(urlcopy, redirect_path, strlen(redirect_path)) != 0)) |
| 61 | + found_moved_temporarily = redirect_path; |
| 62 | + |
| 63 | /* If URL is a directory, add '/' */ |
| 64 | - if (urlp[-1] != '/') { |
| 65 | + if (!redirect_path && (urlp[-1] != '/')) { |
| 66 | if (is_directory(urlcopy + 1, 1, NULL)) { |
| 67 | found_moved_temporarily = urlcopy; |
| 68 | } |
| 69 | @@ -2325,7 +2336,9 @@ static void sighup_handler(int sig UNUSE |
| 70 | } |
| 71 | |
| 72 | enum { |
| 73 | - c_opt_config_file = 0, |
| 74 | + R_opt_redirect_path = 0, |
| 75 | + H_opt_redirect_host, |
| 76 | + c_opt_config_file, |
| 77 | d_opt_decode_url, |
| 78 | h_opt_home_httpd, |
| 79 | IF_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,) |
| 80 | @@ -2374,12 +2387,13 @@ int httpd_main(int argc UNUSED_PARAM, ch |
| 81 | /* We do not "absolutize" path given by -h (home) opt. |
| 82 | * If user gives relative path in -h, |
| 83 | * $SCRIPT_FILENAME will not be set. */ |
| 84 | - opt = getopt32(argv, "c:d:h:" |
| 85 | + opt = getopt32(argv, "R:H:c:d:h:" |
| 86 | IF_FEATURE_HTTPD_ENCODE_URL_STR("e:") |
| 87 | IF_FEATURE_HTTPD_BASIC_AUTH("r:") |
| 88 | IF_FEATURE_HTTPD_AUTH_MD5("m:") |
| 89 | IF_FEATURE_HTTPD_SETUID("u:") |
| 90 | "p:ifv", |
| 91 | + &redirect_path, &redirect_host, |
| 92 | &opt_c_configFile, &url_for_decode, &home_httpd |
| 93 | IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) |
| 94 | IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) |
| 95 | |