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