Skip to content

Commit

Permalink
Fixed issues with POST requests when accessing pretty urls. New
Browse files Browse the repository at this point in the history
implementation does not depend on redirects anymore. See Issue 81.

Fixed Mongoose environment variables: REQUEST_URI, PHP_SELF and others.
It is no more required to use __fix_mongoose_env_variables() php func.
See Issue 137.

Updated pretty-urls.php example.
  • Loading branch information
cztomczak committed Oct 29, 2014
1 parent 647d2d3 commit 39c81a7
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 190 deletions.
6 changes: 4 additions & 2 deletions phpdesktop-chrome/cef/client_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> cefBrowser,
bool isLoading,
bool canGoBack,
bool canGoForward) {
LOG_DEBUG << "OnLoadingStateChange: loading = " << isLoading;
LOG_DEBUG << "OnLoadingStateChange: loading=" << isLoading << ", url="
<< cefBrowser->GetMainFrame()->GetURL().ToString().c_str();
static int calls = 0;
calls++;
if (calls > 1) {
Expand All @@ -336,7 +337,8 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
const CefString& errorText,
const CefString& failedUrl) {
REQUIRE_UI_THREAD();
LOG_DEBUG << "OnLoadError, errorCode=" << errorCode;
LOG_DEBUG << "OnLoadError, errorCode=" << errorCode
<< ", failedUrl=" << failedUrl.ToString().c_str();

// Don't display an error for downloaded files.
if (errorCode == ERR_ABORTED)
Expand Down
127 changes: 91 additions & 36 deletions phpdesktop-chrome/mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ enum {
ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT, _404_HANDLER,
NUM_OPTIONS
};

Expand Down Expand Up @@ -485,6 +485,7 @@ static const char *config_options[] = {
"url_rewrite_patterns", NULL,
"hide_files_patterns", NULL,
"request_timeout_ms", "30000",
"404_handler", NULL,
NULL
};

Expand Down Expand Up @@ -1827,12 +1828,39 @@ int mg_get_cookie(const char *cookie_header, const char *var_name,
return len;
}

static void support_path_info_for_cgi_scripts(
struct mg_connection *conn, char *buf,
size_t buf_len, struct file *filep) {
char *p;
// Support PATH_INFO for CGI scripts.
for (p = buf + strlen(buf); p > buf + 1; p--) {
if (*p == '/') {
*p = '\0';
if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
strlen(conn->ctx->config[CGI_EXTENSIONS]), buf) > 0 &&
mg_stat(conn, buf, filep)) {
// Shift PATH_INFO block one character right, e.g.
// "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
// conn->path_info is pointing to the local variable "path" declared
// in handle_request(), so PATH_INFO is not valid after
// handle_request returns.
conn->path_info = p + 1;
memmove(p + 2, p + 1, strlen(p + 1) + 1); // +1 is for trailing \0
p[1] = '/';
break;
} else {
*p = '/';
}
}
}
}

static void convert_uri_to_file_name(struct mg_connection *conn, char *buf,
size_t buf_len, struct file *filep) {
struct vec a, b;
const char *rewrite, *uri = conn->request_info.uri,
*root = conn->ctx->config[DOCUMENT_ROOT];
char *p;
*root = conn->ctx->config[DOCUMENT_ROOT],
*_404_handler = conn->ctx->config[_404_HANDLER];
int match_len;
char gz_path[PATH_MAX];
char const* accept_encoding;
Expand All @@ -1852,7 +1880,7 @@ static void convert_uri_to_file_name(struct mg_connection *conn, char *buf,
break;
}
}

if (mg_stat(conn, buf, filep)) return;

// if we can't find the actual file, look for the file
Expand All @@ -1871,27 +1899,33 @@ static void convert_uri_to_file_name(struct mg_connection *conn, char *buf,
}
}

// Support PATH_INFO for CGI scripts.
for (p = buf + strlen(buf); p > buf + 1; p--) {
if (*p == '/') {
*p = '\0';
if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
strlen(conn->ctx->config[CGI_EXTENSIONS]), buf) > 0 &&
mg_stat(conn, buf, filep)) {
// Shift PATH_INFO block one character right, e.g.
// "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
// conn->path_info is pointing to the local variable "path" declared
// in handle_request(), so PATH_INFO is not valid after
// handle_request returns.
conn->path_info = p + 1;
memmove(p + 2, p + 1, strlen(p + 1) + 1); // +1 is for trailing \0
p[1] = '/';
break;
} else {
*p = '/';
}
}
support_path_info_for_cgi_scripts(conn, buf, buf_len, filep);

// --------------------------------------------------------------------------
// PHP Desktop 404_handler.
// Condition that checks if file exists (filep->membuf == NULL),
// must run after support_path_info_for_cgi_scripts(). Otherwise
// it will evaluate to false when checking uri "/foo.php/bar/5".
if (
(
!strcmp(conn->request_info.request_method, "GET")
|| !strcmp(conn->request_info.request_method, "HEAD")
|| !strcmp(conn->request_info.request_method, "POST")
)
&& (filep->membuf == NULL && filep->modification_time == (time_t) 0)
&& (root != NULL)
&& (strlen(_404_handler) > 0)
) {
mg_snprintf(conn, buf, buf_len - 1,
"%s%s%s",
root, _404_handler, uri
);
support_path_info_for_cgi_scripts(conn, buf, buf_len, filep);
// cry(conn, "%s%s", "!!! 404_handler=TRUE, buf=", buf);
} else {
// cry(conn, "%s%s", "!!! 404_handler=FALSE, buf=", buf);
}
// --------------------------------------------------------------------------
}

// Check whether full request is buffered. Return:
Expand Down Expand Up @@ -3295,10 +3329,13 @@ static char *addenv(struct cgi_env_block *block, const char *fmt, ...) {
static void prepare_cgi_environment(struct mg_connection *conn,
const char *prog,
struct cgi_env_block *blk) {
const char *s, *slash;
const char *s;
struct vec var_vec;
char *p, src_addr[IP_ADDR_STR_LEN];
int i;
char prog2[PATH_MAX] = "";
char script_name[PATH_MAX] = "";
int root_len = strlen(conn->ctx->config[DOCUMENT_ROOT]);

blk->len = blk->nvars = 0;
blk->conn = conn;
Expand All @@ -3320,18 +3357,36 @@ static void prepare_cgi_environment(struct mg_connection *conn,
addenv(blk, "REQUEST_METHOD=%s", conn->request_info.request_method);
addenv(blk, "REMOTE_ADDR=%s", src_addr);
addenv(blk, "REMOTE_PORT=%d", conn->request_info.remote_port);
addenv(blk, "REQUEST_URI=%s", conn->request_info.uri);
if (conn->request_info.query_string == NULL) {
addenv(blk, "REQUEST_URI=%s", conn->request_info.uri);
} else {
addenv(blk, "REQUEST_URI=%s?%s", conn->request_info.uri,
conn->request_info.query_string);
}

// SCRIPT_NAME
// SCRIPT_NAME - original code was buggy and was removed.
assert(conn->request_info.uri[0] == '/');
slash = strrchr(conn->request_info.uri, '/');
if ((s = strrchr(prog, '/')) == NULL)
s = prog;
addenv(blk, "SCRIPT_NAME=%.*s%s", (int) (slash - conn->request_info.uri),
conn->request_info.uri, s);

addenv(blk, "SCRIPT_FILENAME=%s", prog);
addenv(blk, "PATH_TRANSLATED=%s", prog);
// Detect SCRIPT_NAME using "prog" and document root.
if ((int)strlen(prog) > root_len) {
for (i = root_len; i < (int)strlen(prog); i++) {
assert(i-root_len >= 0);
script_name[i-root_len] = prog[i];
}
}
addenv(blk, "SCRIPT_NAME=%s", script_name);

// Fix "prog", replace forward slashes with backslashes on Windows.
strcpy(prog2, prog);
#if defined(_WIN32)
for (i = 0; i < (int)strlen(prog2); i++) {
if (prog2[i] == '/') {
prog2[i] = '\\';
}
#endif
}

addenv(blk, "SCRIPT_FILENAME=%s", prog2);
addenv(blk, "PATH_TRANSLATED=%s", prog2);
addenv(blk, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");

if ((s = mg_get_header(conn, "Content-Type")) != NULL)
Expand Down Expand Up @@ -4455,7 +4510,7 @@ static void handle_request(struct mg_connection *conn) {
convert_uri_to_file_name(conn, path, sizeof(path), &file);
conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
get_remote_ip(conn), ri->uri);

DEBUG_TRACE(("%s", ri->uri));
// Perform redirect and auth checks before calling begin_request() handler.
// Otherwise, begin_request() would need to perform auth checks and redirects.
Expand Down
33 changes: 4 additions & 29 deletions phpdesktop-chrome/web_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,13 @@ static void end_request(const struct mg_connection* conn, int reply_status_code)
LOG_INFO << message;
}

// Called when mongoose is about to send HTTP error to the client.
// Implementing this callback allows to create custom error pages.
// Parameters:
// status: HTTP error status code.
static int http_error(struct mg_connection* conn, int status) {
mg_request_info* request = mg_get_request_info(
const_cast<mg_connection*>(conn));
std::string request_uri;
request_uri.append(request->uri);
if (request->query_string != NULL) {
request_uri.append("?").append(request->query_string);
}
LOG_INFO << "http_error(), status=" << status
<< ", uri=" << request_uri.c_str();
json_value* appSettings = GetApplicationSettings();
std::string _404_handler = (*appSettings)["web_server"]["404_handler"];
if (status == 404 && !_404_handler.empty()) {
mg_printf(conn,
"HTTP/1.1 302 Found\r\n"
"Location: %s%s\r\n\r\n",
_404_handler.c_str(),
request_uri.c_str()
);
return 0;
}
return 1;
}

bool StartWebServer() {
LOG_INFO << "Starting Mongoose " << mg_version() << " web server";
json_value* appSettings = GetApplicationSettings();

// 404_handler
std::string _404_handler = (*appSettings)["web_server"]["404_handler"];

// Ip address and port. If port was set to 0, then real port
// will be known only after the webserver was started.
std::string ipAddress = (*appSettings)["web_server"]["listen_on"][0];
Expand Down Expand Up @@ -178,6 +153,7 @@ bool StartWebServer() {
"cgi_interpreter", cgiInterpreter.c_str(),
"cgi_pattern", cgiPattern.c_str(),
"cgi_environment", cgiEnvironment.c_str(),
"404_handler", _404_handler.c_str(),
NULL
};

Expand All @@ -188,7 +164,6 @@ bool StartWebServer() {
mg_callbacks callbacks = {0};
callbacks.log_message = &log_message;
callbacks.end_request = &end_request;
callbacks.http_error = &http_error;
g_mongooseContext = mg_start(&callbacks, NULL, options);
if (g_mongooseContext == NULL)
return false;
Expand Down
Loading

0 comments on commit 39c81a7

Please sign in to comment.