⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   http handling code   Copyright (C) Andrew Tridgell 2005      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "smbd/service_task.h"#include "web_server/web_server.h"#include "smbd/service_stream.h"#include "smbd/service.h"#include "lib/events/events.h"#include "system/time.h"#include "system/wait.h"#include "lib/appweb/esp/esp.h"#include "lib/appweb/ejs/ejsInternal.h"#include "lib/util/dlinklist.h"#include "lib/tls/tls.h"#include "scripting/ejs/smbcalls.h"#include "param/param.h"#define SAMBA_SESSION_KEY "SambaSessionId"#define HTTP_PREAUTH_URI  "/scripting/preauth.esp"/* state of the esp subsystem for a specific request */struct esp_state {	struct websrv_context *web;	struct EspRequest *req;	struct MprVar variables[ESP_OBJ_MAX];	struct session_data *session;};/*  output the http headers*/static void http_output_headers(struct websrv_context *web){	int i;	char *s;	DATA_BLOB b;	uint32_t content_length = 0;	const char *response_string = "Unknown Code";	const struct {		unsigned code;		const char *response_string;	} codes[] = {		{ 200, "OK" },		{ 301, "Moved" },		{ 302, "Found" },		{ 303, "Method" },		{ 304, "Not Modified" },		{ 400, "Bad request" },		{ 401, "Unauthorized" },		{ 403, "Forbidden" },		{ 404, "Not Found" },		{ 500, "Internal Server Error" },		{ 501, "Not implemented" }	};	for (i=0;i<ARRAY_SIZE(codes);i++) {		if (codes[i].code == web->output.response_code) {			response_string = codes[i].response_string;		}	}	if (web->output.headers == NULL) return;	s = talloc_asprintf(web, "HTTP/1.0 %u %s\r\n", 			    web->output.response_code, response_string);	if (s == NULL) return;	for (i=0;web->output.headers[i];i++) {		s = talloc_asprintf_append_buffer(s, "%s\r\n", web->output.headers[i]);	}	/* work out the content length */	content_length = web->output.content.length;	if (web->output.fd != -1) {		struct stat st;		fstat(web->output.fd, &st);		content_length += st.st_size;	}	s = talloc_asprintf_append_buffer(s, "Content-Length: %u\r\n\r\n", content_length);	if (s == NULL) return;	b = web->output.content;	web->output.content = data_blob_string_const(s);	data_blob_append(web, &web->output.content, b.data, b.length);	data_blob_free(&b);}/*  return the local path for a URL*/static const char *http_local_path(struct websrv_context *web,                                   const char *url,                                   const char *base_dir){	int i;	char *path;	/* check that the url is OK */	if (url[0] != '/') return NULL;	for (i=0;url[i];i++) {		if ((!isalnum((unsigned char)url[i]) && !strchr("./_-", url[i])) ||		    (url[i] == '.' && strchr("/.", url[i+1]))) {			return NULL;		}	}	path = talloc_asprintf(web, "%s/%s", base_dir, url+1);	if (path == NULL) return NULL;	if (directory_exist(path)) {		path = talloc_asprintf_append_buffer(path, "/index.esp");	}	return path;}/*  called when esp wants to read a file to support include() calls*/static int http_readFile(EspHandle handle,                         char **buf,                         int *len,                         const char *path,                         const char *base_dir){	struct websrv_context *web = talloc_get_type(handle, 						     struct websrv_context);	int fd = -1;	struct stat st;	*buf = NULL;	path = http_local_path(web, path, base_dir);	if (path == NULL) goto failed;	fd = open(path, O_RDONLY);	if (fd == -1 || fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) goto failed;	*buf = talloc_array(handle, char, st.st_size+1);	if (*buf == NULL) goto failed;	if (read(fd, *buf, st.st_size) != st.st_size) goto failed;	(*buf)[st.st_size] = 0;	close(fd);	*len = st.st_size;	return 0;failed:	DEBUG(0,("Failed to read file %s - %s\n", path, strerror(errno)));	if (fd != -1) close(fd);	talloc_free(*buf);	*buf = NULL;	return -1;}static int http_readFileFromSwatDir(EspHandle handle, char **buf, int *len,                                       const char *path){    return http_readFile(handle, buf, len, path, 			 lp_swat_directory(global_loadparm));}/*  called when esp wants to find the real path of a file*/static int http_mapToStorage(EspHandle handle, char *path, int len, const char *uri, int flags){	if (uri == NULL || strlen(uri) >= len) return -1;	strncpy(path, uri, len);	return 0;}/*  called when esp wants to output something*/static int http_writeBlock(EspHandle handle, const char *buf, int size){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	if (!data_blob_append(web, &web->output.content, buf, size))		return -1;	return size;}/*  set a http header*/static void http_setHeader(EspHandle handle, const char *value, bool allowMultiple){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	char *p = strchr(value, ':');	if (p && !allowMultiple && web->output.headers) {		int i;		for (i=0;web->output.headers[i];i++) {			if (strncmp(web->output.headers[i], value, (p+1)-value) == 0) {				web->output.headers[i] = talloc_strdup(web, value);				return;			}		}	}	web->output.headers = str_list_add(web->output.headers, value);	talloc_steal(web, web->output.headers);}/*  set a http response code*/static void http_setResponseCode(EspHandle handle, int code){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	web->output.response_code = code;}/*  redirect to another web page */static void http_redirect(EspHandle handle, int code, char *url){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	const char *host = web->input.host;		/* form the full url, unless it already looks like a url */	if (strchr(url, ':') == NULL) {		if (host == NULL) {			struct socket_address *socket_address = socket_get_my_addr(web->conn->socket, web);			if (socket_address == NULL) goto internal_error;			host = talloc_asprintf(web, "%s:%u",					       socket_address->addr, socket_address->port);		}		if (host == NULL) goto internal_error;		if (url[0] != '/') {			char *p = strrchr(web->input.url, '/');			if (p == web->input.url) {				url = talloc_asprintf(web, "http%s://%s/%s", 						      tls_enabled(web->conn->socket)?"s":"",						      host, url);			} else {				int dirlen = p - web->input.url;				url = talloc_asprintf(web, "http%s://%s%*.*s/%s",						      tls_enabled(web->conn->socket)?"s":"",						      host, 						      dirlen, dirlen, web->input.url,						      url);			}			if (url == NULL) goto internal_error;		}	}	http_setHeader(handle, talloc_asprintf(web, "Location: %s", url), 0);	/* make sure we give a valid redirect code */	if (code >= 300 && code < 400) {		http_setResponseCode(handle, code);	} else {		http_setResponseCode(handle, 302);	}	return;internal_error:	http_error(web, 500, "Internal server error");}/*  setup a cookie*/static void http_setCookie(EspHandle handle, const char *name, const char *value, 			   int lifetime, const char *path, bool secure){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	char *buf;		if (lifetime > 0) {		buf = talloc_asprintf(web, "Set-Cookie: %s=%s; path=%s; Expires=%s; %s",				      name, value, path?path:"/", 				      http_timestring(web, time(NULL)+lifetime),				      secure?"secure":"");	} else {		buf = talloc_asprintf(web, "Set-Cookie: %s=%s; path=%s; %s",				      name, value, path?path:"/", 				      secure?"secure":"");	}	http_setHeader(handle, "Cache-control: no-cache=\"set-cookie\"", 0);	http_setHeader(handle, buf, 0);	talloc_free(buf);}/*  return the session id*/static const char *http_getSessionId(EspHandle handle){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	return web->session->id;}/*  setup a session*/static void http_createSession(EspHandle handle, int timeout){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	if (web->session) {		web->session->lifetime = timeout;		http_setCookie(web, SAMBA_SESSION_KEY, web->session->id, 			       web->session->lifetime, "/", 0);	}}/*  destroy a session*/static void http_destroySession(EspHandle handle){	struct websrv_context *web = talloc_get_type(handle, struct websrv_context);	talloc_free(web->session);	web->session = NULL;}/*  setup for a raw http level error*/void http_error(struct websrv_context *web, int code, const char *info){	char *s;	s = talloc_asprintf(web,"<HTML><HEAD><TITLE>Error %u</TITLE></HEAD><BODY><H1>Error %u</H1><pre>%s</pre><p></BODY></HTML>\r\n\r\n", 			    code, code, info);	if (s == NULL) {		stream_terminate_connection(web->conn, "http_error: out of memory");		return;	}	http_writeBlock(web, s, strlen(s));	http_setResponseCode(web, code);	http_output_headers(web);	EVENT_FD_NOT_READABLE(web->conn->event.fde);	EVENT_FD_WRITEABLE(web->conn->event.fde);	web->output.output_pending = true;}/*  map a unix error code to a http error*/void http_error_unix(struct websrv_context *web, const char *info){	int code = 500;	switch (errno) {	case ENOENT:	case EISDIR:		code = 404;		break;	case EACCES:		code = 403;		break;	}	info = talloc_asprintf(web, "%s<p>%s<p>\n", info, strerror(errno));	http_error(web, code, info);}/*  a simple file request*/static void http_simple_request(struct websrv_context *web){	const char *url = web->input.url;	const char *path;	struct stat st;	path = http_local_path(web, url, lp_swat_directory(web->task->lp_ctx));	if (path == NULL) goto invalid;	/* looks ok */	web->output.fd = open(path, O_RDONLY);	if (web->output.fd == -1) {		DEBUG(0,("Failed to read file %s - %s\n", path, strerror(errno)));		http_error_unix(web, path);		return;	}	if (fstat(web->output.fd, &st) != 0 || !S_ISREG(st.st_mode)) {		close(web->output.fd);		goto invalid;	}	return;invalid:	http_error(web, 400, "Malformed URL");}/*  setup the standard ESP arrays*/static void http_setup_arrays(struct esp_state *esp){	struct websrv_context *web = esp->web;	struct esp_data *edata = talloc_get_type(web->task->private, struct esp_data);	struct EspRequest *req = esp->req;	struct socket_address *socket_address = socket_get_my_addr(web->conn->socket, esp);	struct socket_address *peer_address = socket_get_peer_addr(web->conn->socket, esp);	char *p;#define SETVAR(type, name, value) do { \		const char *v = value; \		if (v) espSetStringVar(req, type, name, v); \} while (0)	SETVAR(ESP_REQUEST_OBJ, "CONTENT_LENGTH", 	       talloc_asprintf(esp, "%u", web->input.content_length));	SETVAR(ESP_REQUEST_OBJ, "QUERY_STRING", web->input.query_string);	SETVAR(ESP_REQUEST_OBJ, "POST_DATA",               talloc_strndup(esp,                              web->input.partial.data,                              web->input.partial.length));	SETVAR(ESP_REQUEST_OBJ, "REQUEST_METHOD", web->input.post_request?"POST":"GET");	SETVAR(ESP_REQUEST_OBJ, "REQUEST_URI", web->input.url);	p = strrchr(web->input.url, '/');	SETVAR(ESP_REQUEST_OBJ, "SCRIPT_NAME", p+1);	SETVAR(ESP_REQUEST_OBJ, "SCRIPT_FILENAME", web->input.url);	if (peer_address) {		struct MprVar mpv = mprObject("socket_address");		mprSetPtrChild(&mpv, "socket_address", peer_address);		espSetVar(req, ESP_REQUEST_OBJ, "REMOTE_SOCKET_ADDRESS", mpv);		SETVAR(ESP_REQUEST_OBJ, "REMOTE_ADDR", peer_address->addr);	}	p = socket_get_peer_name(web->conn->socket, esp);	SETVAR(ESP_REQUEST_OBJ, "REMOTE_HOST", p);	SETVAR(ESP_REQUEST_OBJ, "REMOTE_USER", "");	SETVAR(ESP_REQUEST_OBJ, "CONTENT_TYPE", web->input.content_type);	if (web->session) {		SETVAR(ESP_REQUEST_OBJ, "SESSION_ID", web->session->id);	}	SETVAR(ESP_REQUEST_OBJ, "COOKIE_SUPPORT", web->input.cookie?"true":"false");	SETVAR(ESP_HEADERS_OBJ, "HTTP_REFERER", web->input.referer);	SETVAR(ESP_HEADERS_OBJ, "HOST", web->input.host);	SETVAR(ESP_HEADERS_OBJ, "ACCEPT_ENCODING", web->input.accept_encoding);	SETVAR(ESP_HEADERS_OBJ, "ACCEPT_LANGUAGE", web->input.accept_language);	SETVAR(ESP_HEADERS_OBJ, "ACCEPT_CHARSET", web->input.accept_charset);	SETVAR(ESP_HEADERS_OBJ, "COOKIE", web->input.cookie);	SETVAR(ESP_HEADERS_OBJ, "USER_AGENT", web->input.user_agent);	if (socket_address) {		SETVAR(ESP_SERVER_OBJ, "SERVER_ADDR", socket_address->addr);		SETVAR(ESP_SERVER_OBJ, "SERVER_NAME", socket_address->addr);		SETVAR(ESP_SERVER_OBJ, "SERVER_HOST", socket_address->addr);		SETVAR(ESP_SERVER_OBJ, "SERVER_PORT", 		       talloc_asprintf(esp, "%u", socket_address->port));	}	SETVAR(ESP_SERVER_OBJ, "DOCUMENT_ROOT", lp_swat_directory(esp->web->task->lp_ctx));	SETVAR(ESP_SERVER_OBJ, "SERVER_PROTOCOL", tls_enabled(web->conn->socket)?"https":"http");	SETVAR(ESP_SERVER_OBJ, "SERVER_SOFTWARE", "SAMBA");	SETVAR(ESP_SERVER_OBJ, "GATEWAY_INTERFACE", "CGI/1.1");	SETVAR(ESP_SERVER_OBJ, "TLS_SUPPORT", tls_support(edata->tls_params)?"true":"false");}#if HAVE_SETJMP_H/* the esp scripting lirary generates exceptions when   it hits a major error. We need to catch these and   report a internal server error via http*/static jmp_buf ejs_exception_buf;static const char *exception_reason;static void web_server_ejs_exception(const char *reason){	Ejs *ep = ejsPtr(0);	if (ep) {		ejsSetErrorMsg(0, "%s", reason);		exception_reason = ep->error;	} else {		exception_reason = reason;	}	DEBUG(0,("%s", exception_reason));	longjmp(ejs_exception_buf, -1);}#elsestatic void web_server_ejs_exception(const char *reason){	DEBUG(0,("%s", reason));	smb_panic(reason);}#endif/*  process a esp request*/static void esp_request(struct esp_state *esp, const char *url){	struct websrv_context *web = esp->web;	int size;	int res;	char *emsg = NULL, *buf;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -