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

📄 davutil.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	
	if (!m_pszBuf) {
		m_iSize = GetNextBufSize(dwAlloc);
		if (NULL == (m_pszBuf  = MyRgAllocNZ(char,m_iSize)))
			return FALSE;

		m_iNextIn = CHUNK_PREAMBLE;
	}
	else if (((DWORD)(m_iSize - m_iNextIn) <= cbSize) && (m_iSize != MAX_CHUNK_BUFFER_SIZE)) {
		dwAlloc = GetNextBufSize(dwAlloc);
		PSTR szTempBuf = (PSTR) g_funcRealloc(m_pszBuf,dwAlloc,g_pvAllocData);

		if (!szTempBuf)
			return FALSE;

		m_iSize  = dwAlloc;
		m_pszBuf = szTempBuf;
	}

	BufferConsistencyChecks();
	return TRUE;
}


// GetEndOfFileWithNoSlashes returns the last portion of URL between last '/'
// and optionally trailing '/' (or '\').
// Given the URL foobar/myfile.txt, this function will set szStart=myfile.txt 
// and not modify ppszSave or pcSave.
// Given URL foobar/dirName/, this function will set *ppszStart=dirName, set
// *ppszSave=0 (will be closing '/') and *pcSave=/.

void GetEndOfFileWithNoSlashes(PSTR *ppszStart, PSTR *ppszSave, CHAR *pcSave) {
	DEBUGCHK((*ppszSave) == NULL);
	DEBUGCHK(*pcSave == 0);

	PSTR pszTrav = *ppszStart;
	PSTR pszLastSlash         = NULL;
	PSTR pszSecondToLastSlash = NULL;

	if (strlen(pszTrav) == 1) // special case, len 1
		return;

	while (*pszTrav) {
		if (*pszTrav == '/' || *pszTrav == '\\') {
			pszSecondToLastSlash = pszLastSlash;
			pszLastSlash = pszTrav;
		}

		pszTrav++;
	}
	DEBUGCHK(pszLastSlash);

	// A slash was last char before NULL
	if ((pszTrav - pszLastSlash) == 1) {
		PREFAST_SUPPRESS(11,"Calling function will not call into this unless pszLastSlash will be found");
		*pcSave = *pszLastSlash;
		*ppszSave = pszLastSlash;
		*pszLastSlash = 0;

		DEBUGCHK(pszSecondToLastSlash);
		if (pszSecondToLastSlash)
			*ppszStart = pszSecondToLastSlash+1;
	}
	else {
		if (pszLastSlash)
			*ppszStart = pszLastSlash+1;
	}
}


//
//  Response buffer implementation routines.
//

const CHAR rg_XmlCharacters[]        = {'<', '>', '\'', '"', '&'};
const CHAR *rgsz_EntityReferences[]  = {"&lt;", "&gt;", "&apos;", "&quot;", "&amp;"};
const DWORD dwNumReferences          = SVSUTIL_ARRLEN(rg_XmlCharacters);


BOOL CXMLBuffer::Encode(PCSTR pszData) {
	// Translate pszData into encoded XML.  We have to call
	// CChunkedBuffer::Append every bit individually because we may
	// have to send across a chunked response at any time.

	PSTR  pszTrav = (PSTR)pszData;
	DWORD i;

	while (*pszTrav) {
		for (i = 0; i < dwNumReferences; i++) {
			if (rg_XmlCharacters[i] == *pszTrav) {
				if (! Append(rgsz_EntityReferences[i],strlen(rgsz_EntityReferences[i])))
					return FALSE;
				break;
			}
		}

		if ((*pszTrav == '\r') && (*(pszTrav+1) == '\n')) {
			if (! Append(pszTrav,2))
				return FALSE;

			pszTrav++; // skip past '\n'
		}
		if (*pszTrav == '\n') {
			if (! Append("\r\n",2))
				return FALSE;
		}
		else if (i == dwNumReferences) {
			if (! Append(pszTrav,1))
				return FALSE;
		}

		pszTrav++;
	}
	return TRUE;
}

/*
// This is original table used to determine whether or not we need to encode, from httplite.
// There is no need for 1 bit worth of information to take up a byte of ROM, so this
// table is further compressed in isAcceptable array below, where 2 rows take up one entry.
// Note below that we reverse order of bits for least significant bit.
const CHAR isAcceptableExpanded[] = 
    {0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,    // 2x   !"#$%&'()*+,-./  
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,    // 3x  0123151189:;<=>?  
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    // 4x  @ABCDEFGHIJKLMNO  
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,    // 5X  PQRSTUVWXYZ[\]^_  
     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    // 6x  `abcdefghijklmno  
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0};   // 7X  pqrstuvwxyz{|}~  DEL 
*/

const DWORD isAcceptable[] = {  
	0x2FFFFF92, // 00101111111111111111111110010010
	0xAFFFFFFF, // 10101111111111111111111111111111
	0x47FFFFFE, // 01000111111111111111111111111110
};

BOOL RequiresEncode(CHAR c) {
	if ((c >= 32) && (c <128)) {
		int i = (c & 0x60) >> 6; // rip out 6th and 7th bits
		int m = c & 0x1F;
		DEBUGCHK((i >= 0) && (i <= SVSUTIL_ARRLEN(isAcceptable)));

		return ! (isAcceptable[i] & (1 << m));
	}
	return TRUE;
}

BOOL CBuffer::EncodeURL(PCSTR pszData) {
	PSTR  pszTrav;
	CHAR  szBuf[3];

	szBuf[0] = HEX_ESCAPE;

	for (pszTrav = (PSTR)pszData; *pszTrav; pszTrav++) {
		CHAR c = *pszTrav;

		if (RequiresEncode(c)) {
			szBuf[1] = g_szHexDigits[c >> 4];
			szBuf[2] = g_szHexDigits[c & 15];
		
			if (! AppendData(szBuf,3))
				return FALSE;
		}
		else if (! AppendCHAR(*pszTrav))
			return FALSE;
	}
	return TRUE;
}

BOOL CXMLBuffer::EncodeURL(PCSTR pszData) {
	PSTR  pszTrav;
	CHAR  szBuf[3];

	szBuf[0] = HEX_ESCAPE;

	for (pszTrav = (PSTR)pszData; *pszTrav; pszTrav++) {
		CHAR c = *pszTrav;

		if (RequiresEncode(c)) {
			szBuf[1] = g_szHexDigits[c >> 4];
			szBuf[2] = g_szHexDigits[c & 15];
		
			if (! Append(szBuf,3))
				return FALSE;
		}
		else if (! AppendCHAR(*pszTrav))
			return FALSE;
	}
	return TRUE;
}

BOOL CChunkedBuffer::Append(PCSTR pszData, DWORD ccData) {
	DEBUGCHK(!m_fFinalDataSent);

	if (!AllocMem(ccData))
		return FALSE;

	while ((m_iNextIn+ccData) >= MAX_CHUNK_BODY_SIZE) {
		DWORD ccCopy = MAX_CHUNK_BODY_SIZE-m_iNextIn;
		memcpy(m_pszBuf+m_iNextIn,pszData,ccCopy);
		ccData    -= ccCopy;
		pszData   += ccCopy;
		m_iNextIn += ccCopy;

		if (!FlushBuffer())
			return FALSE;
	}

	memcpy(m_pszBuf+m_iNextIn,pszData,ccData);
	m_iNextIn += ccData;
		
	BufferConsistencyChecks();
	return TRUE;
}


// FlushBuffer sends data across to client, does appropriate munging with chunk
// lengths.  If fFinalChunk=TRUE, then it will close off buffer as far as client knows.
BOOL CChunkedBuffer::FlushBuffer(BOOL fFinalChunk) {
	BufferConsistencyChecks();

	if (! AllocMem(CHUNK_RESERVE_SPACE))
		return FALSE;

	// Where to position start of send buffer depends on number of
	// bytes required to encode the content-length.
	DWORD  ccBodyLen = m_iNextIn - CHUNK_PREAMBLE;
	DWORD  ccOffset;
	DWORD  cbSend;
	BOOL   fRet;

	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: WebDav FlushBuffer called for chunked buffer send\r\n"));
	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: FlushBuffer fFinalChunk=%d,ccBodyLen=%d\r\n",fFinalChunk,ccBodyLen));

	DEBUGCHK(ccBodyLen <= MAX_CHUNK_BODY_SIZE);
	DEBUGCHK(m_pszBuf);
	DEBUGCHK(!m_fFinalDataSent);

	if (m_pRequest->m_fResponseHTTP11) {
		// Calculate offsets for chunked encoding
		if (ccBodyLen <= 0xF)
			ccOffset = CHUNK_PREAMBLE - 3; // -2 for CRLF, -1 to store number
		else if (ccBodyLen <= 0xFF)
			ccOffset=  CHUNK_PREAMBLE - 4; // -2 for CRLF, -2 to store number
		else if (ccBodyLen <= 0xFFF)
			ccOffset = CHUNK_PREAMBLE - 5; // -2 for CRLF, -3 to store number
		else
			ccOffset = 0; // need all 4 bytes to store the number

		DWORD dwSprintf = sprintf(m_pszBuf+ccOffset,"%x",ccBodyLen);
		DEBUGCHK(dwSprintf == (CHUNK_PREAMBLE-2-ccOffset));

		// Last two bytes before body will always be CRLF
		m_pszBuf[CHUNK_PREAMBLE-2] = '\r';
		m_pszBuf[CHUNK_PREAMBLE-1] = '\n';

		cbSend = ccBodyLen + (CHUNK_PREAMBLE-ccOffset);

		// Last two bytes after body will always be CRLF
		m_pszBuf[m_iNextIn++] = '\r';
		m_pszBuf[m_iNextIn++] = '\n';
		cbSend += 2;

		if (fFinalChunk) {
			WriteCloseChunk(m_pszBuf,m_iNextIn);
			cbSend += CHUNK_CLOSE_LEN;
		}
	}
	else {
		// In HTTP 1.0 case, assume client doesn't know about chunked-encoding so send back regular.
		ccOffset = CHUNK_PREAMBLE;
		cbSend   = ccBodyLen;

		if (m_pRequest->m_fKeepAlive && fFinalChunk && !m_fSentFirstChunk) {
			// If 1.0 client wants keep-alives and this is our last chunk, then 
			// we know length of body and can do a keep-alive
			CHttpResponse resp(m_pRequest, m_pRequest->GetStatus());
			resp.SetLength(cbSend);
			resp.SendHeadersAndDefaultBodyIfAvailable(NULL,NULL);
		}
		else if (!m_fSentFirstChunk) {
			// We haven't sent body back yet, and either no keep-alives by client request 
			// and/or this isn't final chunk, then no keepalives.
			CHttpResponse resp(m_pRequest, m_pRequest->GetStatus(),CONN_CLOSE);
			m_pRequest->m_fKeepAlive = FALSE;
			resp.SendHeadersAndDefaultBodyIfAvailable(NULL,NULL);
		}
		else {
			// We've already sent first part of data in no-keepalive case.
			DEBUGCHK(m_fSentFirstChunk);
			DEBUGCHK(m_pRequest->m_fKeepAlive == FALSE);
		}

		m_fSentFirstChunk = TRUE;
	}

	DEBUGCHK(cbSend < MAX_CHUNK_BUFFER_SIZE);
	DEBUGCHK(cbSend < m_iSize);

	fRet = m_pRequest->SendData(m_pszBuf+ccOffset,cbSend);

	m_iNextIn = CHUNK_PREAMBLE;
	BufferConsistencyChecks();
	return fRet;
}

// Called when an error has occured.  Ignore any data in buffer already, send back
// code to indicate we're done sending.
BOOL CChunkedBuffer::AbortiveError(void) {
	CHAR szBuf[CHUNK_POSTAMBLE];

	BufferConsistencyChecks();
	DEBUGCHK(!m_fFinalDataSent);

	m_iNextIn = CHUNK_PREAMBLE;

	WriteCloseChunk(szBuf,0);
	return m_pRequest->SendData(szBuf,CHUNK_CLOSE_LEN);
}


void CChunkedBuffer::WriteCloseChunk(PSTR szBuf, DWORD dwOffset) {
#if defined (DEBUG)
	m_fFinalDataSent = TRUE;
#endif

	m_pszBuf[dwOffset++] = '0';
	m_pszBuf[dwOffset++] = '\r';
	m_pszBuf[dwOffset++] = '\n';
	m_pszBuf[dwOffset++] = '\r';
	m_pszBuf[dwOffset++] = '\n';
}


const char  cszPrefixBraceOpenD[]         = "<d:";
const DWORD ccPrefixBraceOpenD            = SVSUTIL_CONSTSTRLEN(cszPrefixBraceOpenD);

BOOL SetEmptyTagWin32NS(CXMLBuffer *pBuffer, PCSTR pszElement, DWORD ccElement) {
	return (pBuffer->Append(cszPrefixBraceOpenD,ccPrefixBraceOpenD) &&
	        pBuffer->Append(pszElement,ccElement)                   &&
	        pBuffer->Append("/>",2));
}

BOOL SetTagWin32NS(CXMLBuffer *pBuffer, PCSTR pszName, DWORD ccName, PCSTR szValue) {
	return (pBuffer->Append(cszPrefixBraceOpenD,ccPrefixBraceOpenD) &&
	        pBuffer->Append(pszName,ccName)                         &&
	        pBuffer->AppendCHAR('>')                                &&
	        pBuffer->Append(szValue,strlen(szValue))                &&
	        pBuffer->Append("</d:",4)                               &&
	        pBuffer->Append(pszName,ccName)                         &&
	        pBuffer->CloseBrace());
}


⌨️ 快捷键说明

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