📄 http.c
字号:
int i; //requesting for directory, first try opening default pages *(p++)=SLASH; for (i=0; defaultPages[i]; i++) { strcpy(p,defaultPages[i]); phsSocket->fd=open(hfp.cFilePath,OPEN_FLAG); if (phsSocket->fd>=0) break; } } if (phsSocket->fd<0) { if (!(hp->flags & FLAG_DIR_LISTING)) { _mwSend404Page(phsSocket); return -1; } SETFLAG(phsSocket,FLAG_DATA_RAW); if (!hfp.fTailSlash) { p=phsSocket->request.pucPath; while(*p) p++; //seek to the end of the string SETWORD(p,DEFWORD('/',0)); //add a tailing slash while(--p>(char*)phsSocket->request.pucPath) { if (*p=='/') { p++; break; } } _mwRedirect(phsSocket,p); } else { *(p-1)=0; _mwListDirectory(phsSocket,hfp.cFilePath); } return _mwStartSendRawData(hp, phsSocket); } fstat(phsSocket->fd,&st); phsSocket->response.fileType=HTTPFILETYPE_HTML; } else { // open file phsSocket->fd=open(hfp.cFilePath,OPEN_FLAG); if (phsSocket->fd<0) { _mwSend404Page(phsSocket); return -1; } if (hfp.pchExt) { phsSocket->response.fileType=_mwGetContentType(hfp.pchExt); } DEBUG("Local file name: %s\n",hfp.cFilePath); } // mark if substitution needed if (hp->pfnSubst && (phsSocket->response.fileType==HTTPFILETYPE_HTML ||phsSocket->response.fileType==HTTPFILETYPE_JS)) { SETFLAG(phsSocket,FLAG_SUBST); } if (phsSocket->response.iContentLength==0) phsSocket->response.iContentLength=st.st_size-phsSocket->request.iStartByte; SYSLOG(LOG_INFO,"File/requested size: %d/%d\n",st.st_size,phsSocket->response.iContentLength); // build http header phsSocket->iDataLength=_mwBuildHttpHeader( hp, phsSocket, st.st_mtime, phsSocket->pucData); phsSocket->response.iSentBytes=-phsSocket->iDataLength; hp->stats.fileSentCount++; return 0;} // end of _mwStartSendFile////////////////////////////////////////////////////////////////////////////// _mwSendFileChunk// Send a chunk of a file////////////////////////////////////////////////////////////////////////////int _mwSendFileChunk(HttpParam *hp, HttpSocket* phsSocket){ int iBytesWritten; int iBytesRead; // send a chunk of data iBytesWritten=send(phsSocket->socket, phsSocket->pucData,phsSocket->iDataLength, 0); if (iBytesWritten<=0) { // close connection DEBUG("[%d] error sending data\n", phsSocket->socket); SETFLAG(phsSocket,FLAG_CONN_CLOSE); return -1; } phsSocket->response.iSentBytes+=iBytesWritten; phsSocket->pucData+=iBytesWritten; phsSocket->iDataLength-=iBytesWritten; SYSLOG(LOG_INFO,"[%d] sent %d bytes of %d\n",phsSocket->socket,phsSocket->response.iSentBytes,phsSocket->response.iContentLength); // if only partial data sent just return wait the remaining data to be sent next time if (phsSocket->iDataLength>0) return 0; // used all buffered data - load next chunk of file phsSocket->pucData=phsSocket->buffer; iBytesRead=read(phsSocket->fd,phsSocket->buffer,HTTP_BUFFER_SIZE); if (iBytesRead<=0) { // finished with a file int iRemainBytes=phsSocket->response.iContentLength-phsSocket->response.iSentBytes; DEBUG("[%d] EOF reached\n",phsSocket->socket); if (iRemainBytes>0) { if (iRemainBytes>HTTP_BUFFER_SIZE) iRemainBytes=HTTP_BUFFER_SIZE; DEBUG("Sending %d padding bytes\n",iRemainBytes); memset(phsSocket->buffer,0,iRemainBytes); phsSocket->iDataLength=iRemainBytes; return 0; } else { DEBUG("Closing file (fd=%d)\n",phsSocket->fd); hp->stats.fileSentBytes+=phsSocket->response.iSentBytes; close(phsSocket->fd); return 1; } } if (ISFLAGSET(phsSocket,FLAG_SUBST)) { int iBytesUsed; // substituted file - read smaller chunk phsSocket->iDataLength=_mwSubstVariables(hp, phsSocket->buffer,iBytesRead,&iBytesUsed); if (iBytesUsed<iBytesRead) { lseek(phsSocket->fd,iBytesUsed-iBytesRead,SEEK_CUR); } } else { phsSocket->iDataLength=iBytesRead; } return 0;} // end of _mwSendFileChunk////////////////////////////////////////////////////////////////////////////// _mwStartSendRawData// Start sending raw data blocks////////////////////////////////////////////////////////////////////////////int _mwStartSendRawData(HttpParam *hp, HttpSocket* phsSocket){ unsigned char header[HTTP200_HDR_EST_SIZE]; int offset=0,hdrsize,bytes; hdrsize=_mwBuildHttpHeader(hp, phsSocket,time(NULL),header); // send http header do { bytes=send(phsSocket->socket, header+offset,hdrsize-offset,0); if (bytes<=0) break; offset+=bytes; } while (offset<hdrsize); if (bytes<=0) { // failed to send header (socket may have been closed by peer) SYSLOG(LOG_INFO,"Failed to send header\n"); return -1; } return 0;}////////////////////////////////////////////////////////////////////////////// _mwSendRawDataChunk// Send a chunk of a raw data block////////////////////////////////////////////////////////////////////////////int _mwSendRawDataChunk(HttpParam *hp, HttpSocket* phsSocket){ int iBytesWritten; // send a chunk of data if (phsSocket->iDataLength==0) { if (ISFLAGSET(phsSocket,FLAG_DATA_STREAM) && phsSocket->ptr) { //FIXME: further implementation of FLAG_DATA_STREAM case } hp->stats.fileSentBytes+=phsSocket->response.iSentBytes; return 1; } iBytesWritten=(int)send(phsSocket->socket, phsSocket->pucData,phsSocket->iDataLength, 0); if (iBytesWritten<=0) { // failure - close connection SYSLOG(LOG_INFO,"Connection closed\n"); SETFLAG(phsSocket,FLAG_CONN_CLOSE); return -1; } else { SYSLOG(LOG_INFO,"[%d] sent %d bytes of raw data\n",phsSocket->socket,iBytesWritten); phsSocket->response.iSentBytes+=iBytesWritten; phsSocket->pucData+=iBytesWritten; phsSocket->iDataLength-=iBytesWritten; } if (phsSocket->iDataLength<=0 && ISFLAGSET(phsSocket,FLAG_DATA_STREAM) && phsSocket->response.iSentBytes<phsSocket->response.iContentLength) { //load next chuck of raw data UrlHandlerParam uhp; memset(&uhp,0,sizeof(UrlHandlerParam)); uhp.hp=hp; uhp.iContentBytes=phsSocket->response.iContentLength; uhp.iSentBytes=phsSocket->response.iSentBytes; uhp.pucBuffer=phsSocket->buffer; uhp.iDataBytes=HTTP_BUFFER_SIZE; if ((*(PFNURLCALLBACK)(phsSocket->ptr))(&uhp)) { phsSocket->pucData=uhp.pucBuffer; phsSocket->iDataLength=uhp.iDataBytes; } } return 0;} // end of _mwSendRawDataChunk////////////////////////////////////////////////////////////////////////////// _mwRedirect// Setup for redirect to another file////////////////////////////////////////////////////////////////////////////void _mwRedirect(HttpSocket* phsSocket, char* pchPath){ // raw (not file) data send mode SETFLAG(phsSocket,FLAG_DATA_RAW); // messages is HTML phsSocket->response.fileType=HTTPFILETYPE_HTML; // build redirect message SYSLOG(LOG_INFO,"[%d] Http redirection to %s\n",phsSocket->socket,pchPath); phsSocket->iDataLength=sprintf(phsSocket->pucData,HTTPBODY_REDIRECT,pchPath); phsSocket->response.iContentLength=phsSocket->iDataLength;} // end of _mwRedirect////////////////////////////////////////////////////////////////////////////// _mwSubstVariables// Perform substitution of variables in a buffer// returns new length////////////////////////////////////////////////////////////////////////////int _mwSubstVariables(HttpParam* hp, char* pchData, int iLength, int* piBytesUsed){ int lastpos,pos=0,used=0; SubstParam sp; int iValueBytes; DEBUG("_SubstVariables input len %d\n",iLength); iLength--; for(;;) { lastpos=pos; for (; pos<iLength && *(WORD*)(pchData+pos)!='$$'; pos++); used+=(pos-lastpos); if (pos==iLength) { *piBytesUsed=used+1; return iLength+1; } lastpos=pos; for (pos=pos+2; pos<iLength && *(WORD*)(pchData+pos)!='$$'; pos++); if (pos==iLength) { *piBytesUsed=used; return lastpos; } pos+=2; used+=pos-lastpos; pchData[pos-2]=0; sp.pchParamName=pchData+lastpos+2; sp.iMaxValueBytes=pos-lastpos; sp.pchParamValue=pchData+lastpos; iValueBytes=hp->pfnSubst(&sp); if (iValueBytes>=0) { if (iValueBytes>sp.iMaxValueBytes) iValueBytes=sp.iMaxValueBytes; memmove(pchData+lastpos+iValueBytes,pchData+pos,iLength-pos); iLength=iLength+iValueBytes-(pos-lastpos); pos=lastpos+iValueBytes; } else { DEBUG("No matched variable for %s\n",sp.pchParamName); pchData[pos-2]='$'; } }} // end of _mwSubstVariables////////////////////////////////////////////////////////////////////////////// _mwStrStrNoCase// Case insensitive version of ststr////////////////////////////////////////////////////////////////////////////char* _mwStrStrNoCase(char* pchHaystack, char* pchNeedle){ char* pchReturn=NULL; while(*pchHaystack!='\0' && pchReturn==NULL) { if (toupper(*pchHaystack)==toupper(pchNeedle[0])) { char* pchTempHay=pchHaystack; char* pchTempNeedle=pchNeedle; // start of match while(*pchTempHay!='\0') { if(toupper(*pchTempHay)!=toupper(*pchTempNeedle)) { // failed to match break; } pchTempNeedle++; pchTempHay++; if (*pchTempNeedle=='\0') { // completed match pchReturn=pchHaystack; break; } } } pchHaystack++; } return pchReturn;} // end of _mwStrStrNoCase////////////////////////////////////////////////////////////////////////////// _mwStrDword////////////////////////////////////////////////////////////////////////////char* _mwStrDword(char* pchHaystack, DWORD dwSub, DWORD dwCharMask){ char* pchReturn=NULL; dwCharMask = dwCharMask?(dwCharMask & 0xdfdfdfdf):0xdfdfdfdf; dwSub &= dwCharMask; while(*pchHaystack) { if (((*(DWORD*)pchHaystack) & dwCharMask)==dwSub) return pchHaystack; pchHaystack++; } return NULL;}#if 0////////////////////////////////////////////////////////////////////////////// _mwDecodeCharacter// Convert and individual character////////////////////////////////////////////////////////////////////////////__inline char _mwDecodeCharacter(char* pchEncodedChar){ char chHex[3]; ASSERT(*pchEncodedChar=='%'); chHex[0]=*(pchEncodedChar+1); chHex[1]=*(pchEncodedChar+2); chHex[2]='\0'; // convert from base 16 return (char)strtol(chHex,NULL,16);} // end of _mwDecodeCharacter////////////////////////////////////////////////////////////////////////////// _mwDecodeString// This function converts URLd characters back to ascii. For example// %3A is '.'////////////////////////////////////////////////////////////////////////////void _mwDecodeString(char* pchString){ int bEnd=FALSE; char* pchInput=pchString; char* pchOutput=pchString; do { switch (*pchInput) { case '%': if (*(pchInput+1)=='\0' || *(pchInput+2)=='\0') { // something not right - terminate the string and abort *pchOutput='\0'; bEnd=TRUE; } else { *pchOutput=_mwDecodeCharacter(pchInput); pchInput+=3; } break; case '+': *pchOutput=' '; pchInput++; break; case '\0': bEnd=TRUE; // drop through default: // copy character *pchOutput=*pchInput; pchInput++; } pchOutput++; } while (!bEnd);} // end of _mwDecodeString#endifint _mwGetContentType(char *pchExtname){ int i; int iContentType=HTTPFILETYPE_OCTET; // check type of file requested if (*(pchExtname+1)=='\0') { DEBUG("Unknown content type\n"); return HTTPFILETYPE_OCTET; } else if (*(pchExtname+3)=='\0' || *(pchExtname+3)=='?') { //identify 3-char file extensions for (i=0;fileExtTable[i];i++) { //logic-and with 0xffdfdfdf gets the uppercase of 3 chars if ((GETDWORD(pchExtname)&0xffdfdfdf)==fileExtTable[i]) { iContentType=i; break; } } } else if (*(pchExtname+4)=='\0' || *(pchExtname+4)=='?') { //logic-and with 0xdfdfdfdf gets the uppercase of 4 chars switch (GETDWORD(pchExtname)&0xdfdfdfdf) { case FILEEXT_HTML: iContentType=HTTPFILETYPE_HTML; break; case FILEEXT_MPEG: iContentType=HTTPFILETYPE_MPEG; break; } } return iContentType;}int _mwGrabToken(char *pchToken, char chDelimiter, char *pchBuffer, int iMaxTokenSize){ char *p=pchToken; int iCharCopied=0; while (*p && *p!=chDelimiter && iCharCopied<iMaxTokenSize) { *(pchBuffer++)=*(p++); iCharCopied++; } pchBuffer='\0'; return (*p==chDelimiter)?iCharCopied:0;}int _mwParseHttpHeader(HttpSocket* phsSocket){ int iLen; char buf[12]; char *p=phsSocket->buffer; //pointer to header data HttpRequest *req=&phsSocket->request; //analyze rest of the header for(;;) { //look for a valid field name while (*p && *p!='\r') p++; //travel to '\r' if (!*p || GETDWORD(p)==HTTP_HEADEREND) break; p+=2; //skip "\r\n" switch (*(p++)) { case 'C': if (!memcmp(p,"onnection: ",11)) { p+=11; if (!memcmp(p,"close",5)) { SETFLAG(phsSocket,FLAG_CONN_CLOSE); p+=5; } } else if (!memcmp(p,"ontent-Length: ",15)) { p+=15; p+=_mwGrabToken(p,'\r',buf,sizeof(buf)); phsSocket->response.iContentLength=atoi(buf); } break; case 'R': if (!memcmp(p,"eferer: ",8)) { p+=8; phsSocket->request.ofReferer=(int)p-(int)phsSocket->buffer; } else if (!memcmp(p,"ange: bytes=",12)) { p+=12; iLen=_mwGrabToken(p,'-',buf,sizeof(buf)); if (iLen==0) continue; p+=iLen; phsSocket->request.iStartByte=atoi(buf); iLen=_mwGrabToken(p,'/',buf,sizeof(buf)); if (iLen==0) continue; p+=iLen; phsSocket->response.iContentLength=atoi(buf)-phsSocket->request.iStartByte+1; } break; case 'H': if (!memcmp(p,"ost: ",5)) { p+=5; phsSocket->request.ofHost=(int)p-(int)phsSocket->buffer; } break; } } return 0; //end of header}//////////////////////////// END OF FILE ///////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -