示例#1
0
文件: srvcgi.cpp 项目: bduck/livecode
// $_POST_RAW contains the entire post message and is read from stdin on access
static Exec_stat cgi_compute_post_raw_var(void *p_context, MCVariable *p_var)
{
	MCCacheHandle *t_stdin = new MCCacheHandle(s_cgi_stdin_cache);
	
	bool t_success = true;
	
	char *t_content_length;
	t_content_length = MCS_getenv("CONTENT_LENGTH");
	if (t_content_length != NULL)
	{
		uint32_t t_length;
		t_length = atoi(t_content_length);
		
		uint32_t t_read = 0;
		
		char *t_data;
		t_data = new char[t_length];
		t_success = t_stdin->Read(t_data, t_length, t_read) && t_length == t_read;

		// Store the raw POST data
		if (t_success)
			s_cgi_post_raw -> copysvalue(MCString(t_data, t_length));
		
		delete t_data;
	}
	
	delete t_stdin;

	return t_success ? ES_NORMAL : ES_ERROR;
}
示例#2
0
bool MCSessionGenerateID(MCStringRef &r_id)
{
	// php calculates session ids by hashing a string composed of REMOTE_ADDR, time in seconds & milliseconds, and a random value

	MCAutoStringRef t_remote_addr_string;
	char *t_remote_addr;
	t_remote_addr = NULL;

	if (MCS_getenv(MCSTR("REMOTE_ADDR"), &t_remote_addr_string))
		MCCStringClone(MCStringGetCString(*t_remote_addr_string), t_remote_addr);
		
	time_t t_time;
	time(&t_time);
	
	MCAutoDataRef t_randombytes;
    
    // MW-2013-05-21; [[ RandomBytes ]] Use system primitive rather than SSL
	//   directly.
	/* UNCHECKED */ MCU_random_bytes(64, &t_randombytes);
	
	md5_state_t t_state;
	md5_byte_t t_digest[16];
	md5_init(&t_state);
	if (t_remote_addr != NULL)
		md5_append(&t_state, (md5_byte_t *)t_remote_addr, MCCStringLength(t_remote_addr));
	md5_append(&t_state, (md5_byte_t *)&t_time, sizeof(t_time));
	md5_append(&t_state, (md5_byte_t *)MCDataGetBytePtr(*t_randombytes), 64);
	md5_finish(&t_state, t_digest);
	
	return byte_to_hex((uint8_t*)t_digest, 16, r_id);
}
示例#3
0
Boolean MCDispatch::openenv(const char *sname, const char *env,
                            char **outpath, IO_handle &stream, uint4 offset)
{
	if ((env = MCS_getenv(env)) != NULL)
	{
		char *pathstring = strclone(env);
		char *fullpath = new char[strlen(env) + strlen(sname) + 2];
		char *eptr = pathstring;
		while (eptr != NULL)
		{
			char *path = eptr;
			eptr = strchr(eptr, ENV_SEPARATOR);
			if (eptr != NULL)
				*eptr++ = '\0';
#ifdef _WIN32
			sprintf(fullpath, "%s\\%s", path, sname);
#else
			sprintf(fullpath, "%s/%s", path, sname);
#endif

			if ((stream = MCS_open(fullpath, IO_READ_MODE, True, False,
			                       offset)) != NULL)
			{
				delete pathstring;
				*outpath = fullpath;
				return True;
			}
		}
		delete pathstring;
		delete fullpath;
	}
	return False;
}
示例#4
0
文件: srvcgi.cpp 项目: bduck/livecode
// MM-2011-07-13: Added new deferred variable $_GET_BINARY.
//   $_GET_BINARY is just the binary get data not encoded in the native charset.
static Exec_stat cgi_compute_get_binary_var(void *p_context, MCVariable *p_var)
{
	MCExecPoint ep;
	
	const char *t_query_string;
	t_query_string = MCS_getenv("QUERY_STRING");
	if (t_query_string != NULL)
		cgi_store_form_urlencoded(ep, s_cgi_get_binary, t_query_string, t_query_string + strlen(t_query_string), false);
	
	return ES_NORMAL;
}
示例#5
0
文件: srvcgi.cpp 项目: bduck/livecode
// MM-2011-07-13: Added new deferred variable $_GET_RAW.
//   $_GET_RAW is just a copy of the QUERY_STRING.
static Exec_stat cgi_compute_get_raw_var(void *p_context, MCVariable *p_var)
{
	MCExecPoint ep;
	
	const char *t_query_string;
	t_query_string = MCS_getenv("QUERY_STRING");
	if (t_query_string != NULL)
		s_cgi_get_raw -> copysvalue(MCString(t_query_string, strlen(t_query_string)));
	
	return ES_NORMAL;
}
示例#6
0
bool MCSessionCreateSession(MCSessionIndexRef p_index, MCStringRef p_session_id, MCSession *&r_session)
{
	bool t_success = true;
	
	MCSession *t_session = NULL;

	MCAutoStringRef t_remote_addr_string;
	char *t_remote_addr;
	t_remote_addr = NULL;

	if (MCS_getenv(MCSTR("REMOTE_ADDR"), &t_remote_addr_string))
		MCCStringClone(MCStringGetCString(*t_remote_addr_string), t_remote_addr);
	
	t_success = MCMemoryNew(t_session);
	
	if (t_success)
		t_success = MCCStringClone(t_remote_addr ? t_remote_addr : "", t_session->ip);

	if (t_success)
	{
		if (p_session_id != nil && !MCStringIsEmpty(p_session_id))
		{
			t_session->id = strdup(MCStringGetCString(p_session_id));
			t_success = true;
		}
		else
		{
			MCAutoStringRef t_session_id;
			t_success = MCSessionGenerateID(&t_session_id);
			t_session->id = strdup(MCStringGetCString(*t_session_id));
		}
	}
	
	if (t_success)
		t_success = MCCStringFormat(t_session->filename, "%s_%s", t_remote_addr ? t_remote_addr : "", t_session->id);
	
	if (t_success)
		t_success = MCSessionIndexAddSession(p_index, t_session);
	
	if (t_success)
		r_session = t_session;
	else
	{
		if (t_session != NULL)
			MCSessionCloseSession(t_session, false);
	}
	
	return t_success;
}
示例#7
0
文件: srvcgi.cpp 项目: bduck/livecode
static Exec_stat cgi_compute_cookie_var(void *p_context, MCVariable *p_var)
{
	bool t_success = true;
	char *t_cookie_string;
	t_cookie_string = MCS_getenv("HTTP_COOKIE");
	
	MCExecPoint ep;
	
	if (t_cookie_string == NULL)
		return ES_NORMAL;
	
	cgi_store_cookie_urlencoded(ep, s_cgi_cookie, t_cookie_string, t_cookie_string + MCCStringLength(t_cookie_string), true);

	return ES_NORMAL;
}
示例#8
0
文件: srvcgi.cpp 项目: bduck/livecode
static bool cgi_multipart_get_boundary(char *&r_boundary)
{
	bool t_success = true;
	char *t_content_type;
	t_content_type = MCS_getenv("CONTENT_TYPE");

	char *t_params = NULL;
	uint32_t t_index = 0;
	
	char **t_names = NULL;
	char **t_values = NULL;
	uint32_t t_param_count = 0;
	
	t_success = MCCStringFirstIndexOf(t_content_type, ';', t_index);

	if (t_success)
		t_success = MCMultiPartParseHeaderParams(t_content_type + t_index + 1, t_names, t_values, t_param_count);

	r_boundary = NULL;
	
	if (t_success)
	{
		for (uint32_t i = 0; i < t_param_count; i++)
		{
			if (MCCStringEqualCaseless(t_names[i], "boundary") && MCCStringLength(t_values[i]) > 0)
			{
				r_boundary = t_values[i];
				t_values[i] = NULL;
				break;
			}
		}
	}
	
	if (t_success)
		t_success = r_boundary != NULL;
	
	for (uint32_t i = 0; i < t_param_count; i++)
	{
		MCCStringFree(t_names[i]);
		MCCStringFree(t_values[i]);
	}
	MCMemoryDeleteArray(t_names);
	MCMemoryDeleteArray(t_values);
	
	return t_success;
}
示例#9
0
文件: srvcgi.cpp 项目: bduck/livecode
// IM-2011-08-05: Reorganization of post variables, now generating all at the same time
static Exec_stat cgi_compute_post_variables()
{
	Exec_stat t_stat = ES_NORMAL;
	
	if (s_cgi_processed_post)
		return ES_NORMAL;
	
	s_cgi_processed_post = true;
	
	char *t_content_type;
	t_content_type = MCS_getenv("CONTENT_TYPE");
	
	if (t_content_type != NULL && strcasecmp(t_content_type, "application/x-www-form-urlencoded") == 0)
	{
		// TODO: currently we assume that urlencoded form data is small enough to fit into memory,
		// so we fetch the contents from $_POST_RAW (which automatically reads the data from stdin).
		// in the future we should read from stdin to avoid duplicating large amounts of data
		MCExecPoint raw_ep, ep;
		MCVarref *t_raw_ref;
		t_raw_ref = s_cgi_post_raw->newvarref();
		
		t_stat = t_raw_ref->eval(raw_ep);
		if (t_stat == ES_NORMAL)
		{
			MCString t_raw_string;
			t_raw_string = raw_ep.getsvalue();
			cgi_store_form_urlencoded(ep, s_cgi_post_binary, t_raw_string.getstring(), t_raw_string.getstring() + t_raw_string.getlength(), false);
			cgi_store_form_urlencoded(ep, s_cgi_post, t_raw_string.getstring(), t_raw_string.getstring() + t_raw_string.getlength(), true);
		}
		delete t_raw_ref;
	}
	else if (t_content_type != NULL && MCCStringBeginsWithCaseless(t_content_type, "multipart/form-data;"))
	{
		// read post-data from stdin, via the stream cache
		MCExecPoint ep;

		MCCacheHandle *t_stdin = new MCCacheHandle(s_cgi_stdin_cache);
		IO_handle t_stdin_handle = new IO_header(t_stdin, 0);
		
		cgi_store_form_multipart(ep, t_stdin_handle);
		MCS_close(t_stdin_handle);
	}
	return t_stat;
}
示例#10
0
bool MCSessionFindMatchingSession(MCSessionIndexRef p_index, MCStringRef p_session_id, MCSession *&r_session)
{
	MCAutoStringRef t_remote_addr_str;
	
	const char *t_remote_addr = NULL;

	if (!MCS_getenv(MCSTR("REMOTE_ADDR"), &t_remote_addr_str))
		t_remote_addr = "";
	else
		t_remote_addr = MCStringGetCString(*t_remote_addr_str);

	for (uint32_t i = 0; i < p_index->session_count; i++)
	{
		if (MCStringIsEqualToCString(p_session_id, p_index->session[i]->id, kMCCompareExact) && MCCStringEqual(p_index->session[i]->ip, t_remote_addr))
		{
			r_session = p_index->session[i];
			return true;
		}
	}
	
	return false;
}
示例#11
0
文件: srvcgi.cpp 项目: bduck/livecode
static void cgi_fix_path_variables()
{
	char *t_path, *t_path_end;
	t_path = strdup(MCS_getenv("PATH_TRANSLATED"));
	t_path_end = t_path + strlen(t_path);

#ifdef _WINDOWS_SERVER
	for(uint32_t i = 0; t_path[i] != '\0'; i++)
		if (t_path[i] == '\\')
			t_path[i] = '/';
#endif

	char t_sep;
	t_sep = '\0';

	while (!MCS_exists(t_path, True))
	{
		char *t_new_end;
		t_new_end = strrchr(t_path, '/');
		*t_path_end = t_sep;
		if (t_new_end == NULL)
		{
			t_sep = '\0';
			break;
		}
		t_path_end = t_new_end;
		t_sep = *t_path_end;
		*t_path_end = '\0';
	}

	MCS_setenv("PATH_TRANSLATED", t_path);
	*t_path_end = t_sep;
	MCS_setenv("PATH_INFO", t_path_end);

	free(t_path);
}
示例#12
0
IO_stat MCDispatch::loadfile(const char *inname, MCStack *&sptr)
{
	IO_handle stream;
	char *openpath = NULL;
	char *fname = strclone(inname);
	if ((stream = MCS_open(fname, IO_READ_MODE, True, False, 0)) != NULL)
		if (fname[0] != PATH_SEPARATOR && fname[1] != ':')
		{
			char *curpath = MCS_getcurdir();
			if (curpath[strlen(curpath) - 1] == '/')
				curpath[strlen(curpath) - 1] = '\0';
			openpath = new char[strlen(curpath) + strlen(fname) + 2];
			sprintf(openpath, "%s/%s", curpath, fname);
			delete curpath;
		}
		else
			openpath = strclone(fname);
	else
	{
		char *tmparray = new char[strlen(fname) + 1];
		strcpy(tmparray, fname);
		char *tname = strrchr(tmparray, PATH_SEPARATOR);
		if (tname == NULL)
			tname = tmparray;
		else
			tname++;
		if ((stream = MCS_open(tname, IO_READ_MODE, True, False, 0)) != NULL)
		{
			char *curpath = MCS_getcurdir();
			openpath = new char[strlen(curpath) + strlen(tname) + 2];
			sprintf(openpath, "%s/%s", curpath, tname);
			delete curpath;
		}
		else
		{
			if (!openstartup(tname, &openpath, stream)
			        && !openenv(tname, "MCPATH", &openpath, stream, 0)
			        && !openenv(tname, "PATH", &openpath, stream, 0))
			{
				char *homename;
				if ((homename = MCS_getenv("HOME")) != NULL)
				{
					openpath = new char[strlen(homename) + strlen(tname) + 13];
					if (homename[strlen(homename) - 1] == '/')
						homename[strlen(homename) - 1] = '\0';
					sprintf(openpath, "%s/%s", homename,  tname);
					if ((stream = MCS_open(openpath, IO_READ_MODE, True,
					                       False, 0)) == NULL)
					{
						sprintf(openpath, "%s/stacks/%s", homename, tname);
						if ((stream = MCS_open(openpath, IO_READ_MODE, True,
						                       False, 0)) == NULL)
						{
							sprintf(openpath, "%s/components/%s", homename, tname);
							if ((stream = MCS_open(openpath, IO_READ_MODE, True,
							                       False, 0)) == NULL)
							{
								delete openpath;
								openpath = NULL;
							}
						}
					}
				}
			}
		}
		delete tmparray;
	}
	if (stream == NULL)
	{
		if (openpath != NULL)
			delete openpath;
		delete fname;
		return IO_ERROR;
	}
	delete fname;
	IO_stat stat = readfile(openpath, inname, stream, sptr);
	delete openpath;
	MCS_close(stream);
	return stat;
}
示例#13
0
文件: srvcgi.cpp 项目: bduck/livecode
bool cgi_initialize()
{
	// need to ensure PATH_TRANSLATED points to the script and PATH_INFO contains everything that follows
	cgi_fix_path_variables();

	// Resolve the main script that has been requested by the CGI interface.
	MCserverinitialscript = MCsystem -> ResolvePath(MCS_getenv("PATH_TRANSLATED"));
	
	// Set the current folder to be that containing the CGI file.
	char *t_server_script_folder;
	t_server_script_folder = strdup(MCserverinitialscript);
#ifdef _WINDOWS_SERVER
	strrchr(t_server_script_folder, '\\')[0] = '\0';
#else
	strrchr(t_server_script_folder, '/')[0] = '\0';
#endif
	MCsystem -> SetCurrentFolder(t_server_script_folder);
	delete t_server_script_folder;
	
	// Initialize the headers.
	MCservercgiheaders = NULL;
	MCservercgiheaders_sent = false;
	
	// Get the document root
	MCservercgidocumentroot = getenv("DOCUMENT_ROOT");
	
	// Initialize the input wrapper.  This creates a cache of the input stream
	// which is filled as the stream is read from.  this allows stdin to be used
	// to populate the post data arrays, and also to be read from by the script
	// without conflicting
	s_cgi_stdin_cache = new MCStreamCache(IO_stdin->handle);
	IO_stdin = new IO_header(new MCCacheHandle(s_cgi_stdin_cache), 0);
		
	// Initialize the output wrapper, this simply ensures we output headers
	// before any content.
	IO_stdout = new IO_header(new cgi_stdout, 0);
	
	// Need an exec-point for variable creation.
	MCExecPoint ep;
	
	// Construct the _SERVER variable
	/* UNCHECKED */ MCVariable::createwithname_cstring("$_SERVER", s_cgi_server);
	s_cgi_server -> setnext(MCglobals);
	MCglobals = s_cgi_server;
	for(uint32_t i = 0; environ[i] != NULL; i++)
	{
		
		static const char *s_cgi_vars[] =
		{
			"GATEWAY_INTERFACE=",
			"SERVER_ADDR=",
			"SERVER_NAME=",
			"SERVER_SOFTWARE=",
			"SERVER_PROTOCOL=",
			"REQUEST_METHOD=",
			"REQUEST_TIME=",
			"QUERY_STRING=",
			"DOCUMENT_ROOT=",
			"HTTPS=",
			
			// MW-2009-08-12: For some reason I missed this first time around :o)
			"REMOTE_USER="******"REMOTE_ADDR=",
			"REMOTE_HOST=",
			"REMOTE_PORT=",
			
			// MM-2011-09-08: Added as part of customer support request for REMOTE_USER.
			//   The standard Apache LiveCode server config redirects the script to the server engine.
			//   This appears to mean that REMOTE_USER is never set 
			//   (I guess it will only ever be set if the server engine itself is behind authentication)
			//   but REDIRECT_REMOTE_USER is.
			"REDIRECT_REMOTE_USER="******"SERVER_ADMIN=",
			"SERVER_PORT=",
			"SERVER_SIGNATURE=",
			
			"PATH_TRANSLATED=",
			
			"REQUEST_URI=",

			"PATH_INFO=",
			"SCRIPT_NAME=",
			"SCRIPT_FILENAME=",

			"CONTENT_TYPE=",
			"CONTENT_LENGTH=",

			NULL
		};
		
		bool t_found;
		t_found = false;
		
		if (strncasecmp(environ[i], "HTTP_", 5) == 0)
			t_found = true;
		else
			for(uint32_t j = 0; s_cgi_vars[j] != NULL && !t_found; j++)
				if (strncasecmp(environ[i], s_cgi_vars[j], strlen(s_cgi_vars[j])) == 0)
					t_found = true;

		if (t_found)
		{
			const char *t_value;
			t_value = strchr(environ[i], '=');
			if (t_value == NULL)
			{
				ep . clear();
				t_value = environ[i] + strlen(environ[i]);
			}
			else
				ep . setsvalue(t_value + 1);
			
			s_cgi_server -> getvalue() . store_element(ep, MCString(environ[i], t_value - environ[i]));
		}
	}
	
	// Construct the GET variables by parsing the QUERY_STRING
	
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_GET_RAW", cgi_compute_get_raw_var, nil, s_cgi_get_raw);
	s_cgi_get_raw -> setnext(MCglobals);
	MCglobals = s_cgi_get_raw;	
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_GET", cgi_compute_get_var, nil, s_cgi_get);
	s_cgi_get -> setnext(MCglobals);
	MCglobals = s_cgi_get;
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_GET_BINARY", cgi_compute_get_binary_var, nil, s_cgi_get_binary);
	s_cgi_get_binary -> setnext(MCglobals);
	MCglobals = s_cgi_get_binary;	
	
	// Construct the _POST variables by reading stdin.
	
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_POST_RAW", cgi_compute_post_raw_var, nil, s_cgi_post_raw);
	s_cgi_post_raw -> setnext(MCglobals);
	MCglobals = s_cgi_post_raw;
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_POST", cgi_compute_post_var, nil, s_cgi_post);
	s_cgi_post -> setnext(MCglobals);
	MCglobals = s_cgi_post;
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_POST_BINARY", cgi_compute_post_binary_var, nil, s_cgi_post_binary);
	s_cgi_post_binary -> setnext(MCglobals);
	MCglobals = s_cgi_post_binary;	
	
	// Construct the FILES variable by reading stdin

	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_FILES", cgi_compute_files_var, nil, s_cgi_files);
	s_cgi_files -> setnext(MCglobals);
	MCglobals = s_cgi_files;
	
	// Construct the COOKIES variable by parsing HTTP_COOKIE
	/* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_COOKIE", cgi_compute_cookie_var, nil, s_cgi_cookie);
	s_cgi_cookie -> setnext(MCglobals);
	MCglobals = s_cgi_cookie;
	
	// Create the $_SESSION variable explicitly, to be populated upon calls to "start session"
	// required as implicit references to "$_SESSION" will result in its creation as an env var
	MCVariable *t_session_var = NULL;
	/* UNCHECKED */ MCVariable::createwithname_cstring("$_SESSION", t_session_var);
	t_session_var->setnext(MCglobals);
	MCglobals = t_session_var;

	return true;
}