📄 ilibparsers.c
字号:
// entire string if the delimiter is not found. // // Iterate through the string to find delimiters // Token = buffer + offset; for(i=offset;i<(length+offset);++i) { if(StringDelimiter==0) { if(buffer[i]=='"') { // // Ignore everything inside double quotes // StringDelimiter='"'; Ignore=1; } else { if(buffer[i]=='\'') { // // Ignore everything inside single quotes // StringDelimiter='\''; Ignore=1; } } } else { // // Once we isolated everything inside double or single quotes, we can get // on with the real parsing // if(buffer[i]==StringDelimiter) { Ignore=((Ignore==0)?1:0); } } if(Ignore==0 && ILibIsDelimiter(buffer,i,length,Delimiter,DelimiterLength)) { // // We found a delimiter in the string // p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field)); p_resultfield->data = Token; p_resultfield->datalength = TokenLength; p_resultfield->NextResult = NULL; if(RetVal->FirstResult != NULL) { RetVal->LastResult->NextResult = p_resultfield; RetVal->LastResult = p_resultfield; } else { RetVal->FirstResult = p_resultfield; RetVal->LastResult = p_resultfield; } // // After we populate the values, we advance the token to after the delimiter // to prep for the next token // ++RetVal->NumResults; i = i + DelimiterLength -1; Token = Token + TokenLength + DelimiterLength; TokenLength = 0; } else { // // No match yet, so just increment this counter // ++TokenLength; } } // // Create a result for the last token, since it won't be caught in the above loop // because if there are no more delimiters, than the entire last portion of the string since the // last delimiter is the token // p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field)); p_resultfield->data = Token; p_resultfield->datalength = TokenLength; p_resultfield->NextResult = NULL; if(RetVal->FirstResult != NULL) { RetVal->LastResult->NextResult = p_resultfield; RetVal->LastResult = p_resultfield; } else { RetVal->FirstResult = p_resultfield; RetVal->LastResult = p_resultfield; } ++RetVal->NumResults; return(RetVal);}int ILibTrimString(char **theString, int length){ int i; int flag1=0,flag2=0; for(i=0;i<length;++i) { if(!flag2 && (*theString)[length-i-1]!=8 && (*theString)[length-i-1]!=32) { length -= i; flag2=1; if(flag1 && flag2) {break;} } if(!flag1 && (*theString)[i]!=8 && (*theString)[i]!=32) { *theString = *theString + i; length -= i; flag1=1; if(flag1 && flag2) {break;} } } return(length);}/// <summary>/// Parses a string into a linked list of tokens./// </summary>/// <para>/// Differs from ILibParseStringAdv, in that this method does not ignore characters contained within/// quotation marks, whereas ILibParseStringAdv does./// </para>/// <param name="buffer">The buffer to parse</param>/// <param name="offset">The offset of the buffer to start parsing</param>/// <param name="length">The length of the buffer to parse</param>/// <param name="Delimiter">The delimiter</param>/// <param name="DelimiterLength">The length of the delimiter</param>/// <returns>A list of tokens</returns>struct parser_result* ILibParseString(char* buffer, int offset, int length, char* Delimiter, int DelimiterLength){ struct parser_result* RetVal = (struct parser_result*)malloc(sizeof(struct parser_result)); int i=0; char* Token = NULL; int TokenLength = 0; struct parser_result_field *p_resultfield; RetVal->FirstResult = NULL; RetVal->NumResults = 0; // // By default we will always return at least one token, which will be the // entire string if the delimiter is not found. // // Iterate through the string to find delimiters // Token = buffer + offset; for(i=offset;i<length;++i) { if(ILibIsDelimiter(buffer,i,length,Delimiter,DelimiterLength)) { // // We found a delimiter in the string // p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field)); p_resultfield->data = Token; p_resultfield->datalength = TokenLength; p_resultfield->NextResult = NULL; if(RetVal->FirstResult != NULL) { RetVal->LastResult->NextResult = p_resultfield; RetVal->LastResult = p_resultfield; } else { RetVal->FirstResult = p_resultfield; RetVal->LastResult = p_resultfield; } // // After we populate the values, we advance the token to after the delimiter // to prep for the next token // ++RetVal->NumResults; i = i + DelimiterLength -1; Token = Token + TokenLength + DelimiterLength; TokenLength = 0; } else { // // No match yet, so just increment this counter // ++TokenLength; } } // // Create a result for the last token, since it won't be caught in the above loop // because if there are no more delimiters, than the entire last portion of the string since the // last delimiter is the token // p_resultfield = (struct parser_result_field*)malloc(sizeof(struct parser_result_field)); p_resultfield->data = Token; p_resultfield->datalength = TokenLength; p_resultfield->NextResult = NULL; if(RetVal->FirstResult != NULL) { RetVal->LastResult->NextResult = p_resultfield; RetVal->LastResult = p_resultfield; } else { RetVal->FirstResult = p_resultfield; RetVal->LastResult = p_resultfield; } ++RetVal->NumResults; return(RetVal);}/// <summary>/// Frees resources associated with the list of tokens returned from ILibParseString/// and ILibParseStringAdv./// </summary>/// <param name="result">The list of tokens to free</param>void ILibDestructParserResults(struct parser_result *result){ // // All of these nodes only contain pointers // so we just need to iterate through all the nodes and free them // struct parser_result_field *node = result->FirstResult; struct parser_result_field *temp; while(node!=NULL) { temp = node->NextResult; free(node); node = temp; } free(result);}/// <summary>/// Frees resources associated with a Packet that was created either by ILibCreateEmptyPacket/// or ILibParsePacket/// </summary>/// <param name="packet">The packet to free</param>void ILibDestructPacket(struct packetheader *packet){ struct packetheader_field_node *node = packet->FirstField; struct packetheader_field_node *nextnode; // // Iterate through all the headers // while(node!=NULL) { nextnode = node->NextField; if(node->UserAllocStrings!=0) { // // If the user allocated the string, then we need to free it. // Otherwise these are just pointers into others strings, in which // case we don't want to free them // free(node->Field); free(node->FieldData); } free(node); node = nextnode; } if(packet->UserAllocStrings!=0) { // // If this flag was set, it means the used ILibCreateEmptyPacket, // and set these fields manually, which means the string was copied. // In which case, we need to free the strings // if(packet->StatusData!=NULL) {free(packet->StatusData);} if(packet->Directive!=NULL) {free(packet->Directive);} if(packet->DirectiveObj!=NULL) {free(packet->DirectiveObj);} if(packet->Body!=NULL) free(packet->Body); } if(packet->UserAllocVersion!=0) { free(packet->Version); } free(packet);}/// <summary>/// Escapes a string according to HTTP Specifications./// </summary>/// <para>/// The string you would want to escape would typically be the string used in the Path portion/// of an HTTP request. eg:/// GET foo/bar.txt HTTP/1.1/// </para>/// <para>/// It should be noted that the output buffer needs to be allocated prior to calling this method./// The required space can be determined by calling ILibHTTPEscapeLength./// </para>/// <param name="outdata">The escaped string</param>/// <param name="data">The string to escape</param>/// <returns>The length of the escaped string</returns>int ILibHTTPEscape(char* outdata, const char* data){ int i=0; int x=0; char hex[4]; int hexLen; while(data[x]!=0) { if( (data[x]>=63 && data[x]<=90) || (data[x]>=97 && data[x]<=122) || (data[x]>=47 && data[x]<=57) \ || data[x]==59 || data[x]==47 || data[x]==63 || data[x]==58 || data[x]==64 || data[x]==61 \ || data[x]==43 || data[x]==36 || data[x]==45 || data[x]==95 || data[x]==46 || data[x]==42) { // // These are all the allowed values for HTTP. If it's one of these characters, we're ok // outdata[i] = data[x]; ++i; } else { // // If it wasn't one of these characters, then we need to escape it // hexLen = sprintf(hex,"%02X",(unsigned char)data[x]); outdata[i] = '%'; outdata[i+1] = hex[0]; outdata[i+2] = hex[1]; i+=3; } ++x; } outdata[i]=0; return(i+1);}/// <summary>/// Determines the buffer space required to HTTP escape a particular string./// </summary>/// <param name="data">Calculates the length requirements as if this string was escaped</param>/// <returns>The minimum required length</returns>int ILibHTTPEscapeLength(const char* data){ int i=0; int x=0; while(data[x]!=0) { if( (data[x]>=63 && data[x]<=90) || (data[x]>=97 && data[x]<=122) || (data[x]>=47 && data[x]<=57) \ || data[x]==59 || data[x]==47 || data[x]==63 || data[x]==58 || data[x]==64 || data[x]==61 \ || data[x]==43 || data[x]==36 || data[x]==45 || data[x]==95 || data[x]==46 || data[x]==42) { // No need to escape ++i; } else { // Need to escape i+=3; } ++x; } return(i+1);}/// <summary>/// Unescaped a given string/// </summary>/// <para>/// The escaped representation of a string is always longer than the unescaped version/// so this method will overwrite the escaped string, with the unescaped result./// </para>/// <param name="data">The buffer to unescape</param>/// <returns>The length of the unescaped string</returns>int ILibInPlaceHTTPUnEscape(char* data){ char hex[3]; char *stp; int src_x=0; int dst_x=0; int length = (int)strlen(data); hex[2]=0; while(src_x<length) { if(strncmp(data+src_x,"%",1)==0) { // // Since we encountered a '%' we know this is an escaped character // hex[0] = data[src_x+1]; hex[1] = data[src_x+2]; data[dst_x] = (char)strtol(hex,&stp,16); dst_x += 1; src_x += 3; } else if(src_x!=dst_x) { // // This doesn't need to be unescaped. If we didn't unescape anything previously // there is no need to copy the string either // data[dst_x] = data[src_x]; src_x += 1; dst_x += 1; } else { // // This doesn't need to be unescaped, however we need to copy the string // src_x += 1; dst_x += 1; } } return(dst_x);}/// <summary>/// Parses the HTTP headers from a buffer, into a packetheader structure/// </summary>/// <param name="buffer">The buffer to parse</param>/// <param name="offset">The offset of the buffer to start parsing</param>/// <param name="length">The length of the buffer to parse</param>/// <returns>packetheader structure</returns>struct packetheader* ILibParsePacketHeader(char* buffer, int offset, int length){ struct packetheader *RetVal = (struct packetheader*)malloc(sizeof(struct packetheader)); struct parser_result *_packet; struct parser_result *p; struct parser_result *StartLine; struct parser_result_field *HeaderLine; struct parser_result_field *f; char* tempbuffer; struct packetheader_field_node *node = NULL; int i=0; memset(RetVal,0,sizeof(struct packetheader)); // // All the headers are delineated with a CRLF, so we parse on that // p = (struct parser_result*)ILibParseString(buffer,offset,length,"\r\n",2); _packet = p; f = p->FirstResult; // // The first token is where we can figure out the Method, Path, Version, etc. // StartLine = (struct parser_result*)ILibParseString(f->data,0,f->datalength," ",1); HeaderLine = f->NextResult; if(memcmp(StartLine->FirstResult->data, "HTTP/", 5)==0) { // // If the StartLine starts with HTTP/, then we know this is a response packet. // We parse on the '/' character to determine the Version, as it follows. // eg: HTTP/1.1 200 OK // p = (struct parser_result*)ILibParseString(StartLine->FirstResult->data, 0, StartLine->FirstResult->datalength, "/",1); RetVal->Version = p->LastResult->data; RetVal->VersionLength = p->LastResult->datalength; RetVal->Version[RetVal->VersionLength]=0; ILibDestructParserResults(p); tempbuffer = (char*)malloc(1+sizeof(char)*(StartLine->FirstResult->NextResult->datalength)); memcpy(tempbuffer,StartLine->FirstResult->NextResult->data, StartLine->FirstResult->NextResult->datalength); MEMCHECK(assert(StartLine->FirstResult->NextResult->datalength <= 1+(int)sizeof(char)*(StartLine->FirstResult->NextResult->datalength));) // // The other tokens contain the Status code and data // tempbuffer[StartLine->FirstResult->NextResult->datalength] = '\0'; RetVal->StatusCode = (int)atoi(tempbuffer); free(tempbuffer); RetVal->StatusData = StartLine->FirstResult->NextResult->NextResult->data; RetVal->StatusDataLength = StartLine->FirstResult->NextResult->NextResult->datalength; } else { // // If the packet didn't start with HTTP/ then we know it's a request packet // eg: GET /index.html HTTP/1.1 // The method (or directive), is the first token, and the Path // (or DirectiveObj) is the second, and version in the 3rd. // RetVal->Directive = StartLine->FirstResult->data; RetVal->DirectiveLength = StartLine->FirstResult->datalength; RetVal->DirectiveObj = StartLine->FirstResult->NextResult->data; RetVal->DirectiveObjLength = StartLine->FirstResult->NextResult->datalength; R
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -