提交 bdbe8d50196c253143c039c8da0e1bcc548407a3

作者 LJH 李佳桓
1 个父辈 41ffc819

add

正在显示 1 个修改的文件 包含 632 行增加0 行删除
  1 +/*
  2 + * Copyright 2007 Stephen Liu
  3 + * For license terms, see the file COPYING along with this library.
  4 + */
  5 +
  6 +#include <stdio.h>
  7 +#include <string.h>
  8 +#include <stdlib.h>
  9 +
  10 +#include "spporting.hpp"
  11 +
  12 +#include "sphttpmsg.hpp"
  13 +#include "sputils.hpp"
  14 +
  15 +static char * sp_strsep(char **s, const char *del)
  16 +{
  17 + char *d, *tok;
  18 +
  19 + if (!s || !*s) return NULL;
  20 + tok = *s;
  21 + d = strstr(tok, del);
  22 +
  23 + if (d) {
  24 + *s = d + strlen(del);
  25 + *d = '\0';
  26 + } else {
  27 + *s = NULL;
  28 + }
  29 +
  30 + return tok;
  31 +}
  32 +
  33 +SP_HttpMsgParser :: SP_HttpMsgParser()
  34 +{
  35 + mMessage = NULL;
  36 + mStatus = eStartLine;
  37 + mIgnoreContent = 0;
  38 +}
  39 +
  40 +SP_HttpMsgParser :: ~SP_HttpMsgParser()
  41 +{
  42 + if( NULL != mMessage ) delete mMessage;
  43 +}
  44 +
  45 +void SP_HttpMsgParser :: setIgnoreContent( int ignoreContent )
  46 +{
  47 + mIgnoreContent = ignoreContent;
  48 +}
  49 +
  50 +int SP_HttpMsgParser :: isIgnoreContent() const
  51 +{
  52 + return 0 != mIgnoreContent;
  53 +}
  54 +
  55 +int SP_HttpMsgParser :: parseStartLine( SP_HttpMessage ** message,
  56 + const void * buffer, int len )
  57 +{
  58 + int lineLen = 0;
  59 +
  60 + char * pos = (char*)memchr( buffer, '\n', len );
  61 + if( NULL != pos ) {
  62 + lineLen = pos - (char*)buffer + 1;
  63 +
  64 + char * line = (char*)malloc( lineLen + 1 );
  65 + memcpy( line, buffer, lineLen );
  66 + line[ lineLen ] = '\0';
  67 +
  68 + pos = line;
  69 +
  70 + char * first, * second;
  71 + first = sp_strsep( &pos, " " );
  72 + second = sp_strsep( &pos, " " );
  73 +
  74 + if( 0 == strncasecmp( line, "HTTP", 4 ) ) {
  75 + SP_HttpResponse * response = new SP_HttpResponse();
  76 + if( NULL != first ) response->setVersion( first );
  77 + if( NULL != second ) response->setStatusCode( atoi( second ) );
  78 + if( NULL != pos ) response->setReasonPhrase( strtok( pos, "\r\n" ) );
  79 +
  80 + *message = response;
  81 + } else {
  82 + SP_HttpRequest * request = new SP_HttpRequest();
  83 + if( NULL != first ) request->setMethod( first );
  84 + if( NULL != second ) request->setURL( second );
  85 + if( NULL != second ) request->setURI( sp_strsep( &second, "?" ) );
  86 + if( NULL != pos ) request->setVersion( strtok( pos, "\r\n" ) );
  87 +
  88 + char * params = second;
  89 + for( ; NULL != params && '\0' != *params; ) {
  90 + char * value = sp_strsep( &params, "&" );
  91 + char * name = sp_strsep( &value, "=" );
  92 + request->addParam( name, NULL == value ? "" : value );
  93 + }
  94 +
  95 + *message = request;
  96 + }
  97 +
  98 + free( line );
  99 + }
  100 +
  101 + return lineLen;
  102 +}
  103 +
  104 +int SP_HttpMsgParser :: parseHeader( SP_HttpMessage * message,
  105 + const void * buffer, int len )
  106 +{
  107 + int lineLen = 0;
  108 +
  109 + char * pos = (char*)memchr( buffer, '\n', len );
  110 + if( NULL != pos ) {
  111 + lineLen = pos - (char*)buffer + 1;
  112 +
  113 + char * line = (char*)malloc( lineLen + 1 );
  114 + memcpy( line, buffer, lineLen );
  115 + line[ lineLen ] = '\0';
  116 +
  117 + pos = line;
  118 +
  119 + char * name = sp_strsep( &pos, ":" );
  120 +
  121 + if( NULL != pos ) {
  122 + pos = strtok( pos, "\r\n" );
  123 + pos += strspn( pos, " " );
  124 + message->addHeader( name, pos );
  125 + }
  126 +
  127 + free( line );
  128 + }
  129 +
  130 + return lineLen;
  131 +}
  132 +
  133 +int SP_HttpMsgParser :: getLine( const void * buffer, int len,
  134 + char * line, int size )
  135 +{
  136 + int lineLen = 0;
  137 +
  138 + char * pos = (char*)memchr( buffer, '\n', len );
  139 + if( NULL != pos ) {
  140 + lineLen = pos - (char*)buffer + 1;
  141 +
  142 + int realLen = size - 1;
  143 + realLen = realLen > lineLen ? lineLen : realLen;
  144 +
  145 + memcpy( line, buffer, realLen );
  146 + line[ realLen ] = '\0';
  147 + strtok( line, "\r\n" );
  148 + }
  149 +
  150 + return lineLen;
  151 +}
  152 +
  153 +int SP_HttpMsgParser :: parseChunked( SP_HttpMessage * message,
  154 + const void * buffer, int len, int * status )
  155 +{
  156 + int parsedLen = 0, hasChunk = 1;
  157 +
  158 + for( ; 0 != hasChunk && eCompleted != *status; ) {
  159 +
  160 + hasChunk = 0;
  161 +
  162 + char chunkSize[ 32 ] = { 0 };
  163 +
  164 + int lineLen = getLine( ((char*)buffer) + parsedLen, len - parsedLen,
  165 + chunkSize, sizeof( chunkSize ) );
  166 +
  167 + int contentLen = strtol( chunkSize, NULL, 16 );
  168 +
  169 + if( contentLen > 0 && ( len - parsedLen ) > ( contentLen + lineLen ) ) {
  170 + int emptyLen = getLine( ((char*)buffer) + parsedLen + lineLen + contentLen,
  171 + len - parsedLen - lineLen - contentLen,
  172 + chunkSize, sizeof( chunkSize ) );
  173 +
  174 + if( emptyLen > 0 ) {
  175 + parsedLen += lineLen;
  176 + message->appendContent( ((char*)buffer) + parsedLen, contentLen );
  177 + parsedLen += contentLen + emptyLen;
  178 + hasChunk = 1;
  179 + }
  180 + }
  181 +
  182 + if( 0 == contentLen && lineLen > 0 ) {
  183 + parsedLen += lineLen;
  184 + *status = eCompleted;
  185 + }
  186 + }
  187 +
  188 + return parsedLen;
  189 +}
  190 +
  191 +int SP_HttpMsgParser :: parseContent( SP_HttpMessage * message,
  192 + const void * buffer, int len, int * status )
  193 +{
  194 + int parsedLen = 0;
  195 +
  196 + const char * value = message->getHeaderValue( SP_HttpMessage::HEADER_CONTENT_LENGTH );
  197 + int contentLen = atoi( NULL == value ? "0" : value );
  198 +
  199 + if( contentLen > 0 && len >= contentLen ) {
  200 + message->appendContent( ((char*)buffer), contentLen );
  201 + parsedLen = contentLen;
  202 + }
  203 +
  204 + if( contentLen == message->getContentLength() ) *status = eCompleted;
  205 +
  206 + return parsedLen;
  207 +}
  208 +
  209 +int SP_HttpMsgParser :: append( const void * buffer, int len )
  210 +{
  211 + int parsedLen = 0;
  212 +
  213 + if( eCompleted == mStatus ) return parsedLen;
  214 +
  215 + // parse start-line
  216 + if( NULL == mMessage ) {
  217 + parsedLen = parseStartLine( &mMessage, buffer, len );
  218 + if( parsedLen > 0 ) mStatus = eHeader;
  219 + }
  220 +
  221 + if( NULL != mMessage ) {
  222 + // parse header
  223 + for( int headerLen = 1; eHeader == mStatus
  224 + && headerLen > 0 && parsedLen < len; parsedLen += headerLen ) {
  225 + headerLen = parseHeader( mMessage, ((char*)buffer) + parsedLen, len - parsedLen );
  226 +
  227 + char ch = * ( ((char*)buffer) + parsedLen );
  228 + if( '\r' == ch || '\n' == ch ) mStatus = eContent;
  229 + }
  230 +
  231 + if( SP_HttpMessage::eResponse == mMessage->getType()
  232 + && eContent == mStatus && mIgnoreContent ) mStatus = eCompleted;
  233 +
  234 + // parse content
  235 + if( eContent == mStatus ) {
  236 + const char * encoding = mMessage->getHeaderValue( SP_HttpMessage::HEADER_TRANSFER_ENCODING );
  237 + if( NULL != encoding && 0 == strcasecmp( encoding, "chunked" ) ) {
  238 + parsedLen += parseChunked( mMessage, ((char*)buffer) + parsedLen,
  239 + len - parsedLen, &mStatus );
  240 + } else {
  241 + parsedLen += parseContent( mMessage, ((char*)buffer) + parsedLen,
  242 + len - parsedLen, &mStatus );
  243 + }
  244 + }
  245 +
  246 + if( eCompleted == mStatus ) postProcess( mMessage );
  247 + }
  248 +
  249 + return parsedLen;
  250 +}
  251 +
  252 +void SP_HttpMsgParser :: postProcess( SP_HttpMessage * message )
  253 +{
  254 + if( SP_HttpMessage::eRequest == message->getType() ) {
  255 + SP_HttpRequest * request = (SP_HttpRequest*)message;
  256 + const char * contentType = request->getHeaderValue(
  257 + SP_HttpMessage::HEADER_CONTENT_TYPE );
  258 + if( request->getContentLength() > 0 && NULL != contentType
  259 + && 0 == strcasecmp( contentType, "application/x-www-form-urlencoded" ) ) {
  260 +
  261 + char * content = (char*)malloc( request->getContentLength() + 1 );
  262 + memcpy( content, request->getContent(), request->getContentLength() );
  263 + content[ request->getContentLength() ] = '\0';
  264 +
  265 + char * params = content;
  266 + for( ; NULL != params && '\0' != *params; ) {
  267 + char * value = sp_strsep( &params, "&" );
  268 + char * name = sp_strsep( &value, "=" );
  269 + request->addParam( name, NULL == value ? "" : value );
  270 + }
  271 +
  272 + free( content );
  273 + }
  274 + }
  275 +}
  276 +
  277 +int SP_HttpMsgParser :: isCompleted() const
  278 +{
  279 + return eCompleted == mStatus;
  280 +}
  281 +
  282 +SP_HttpRequest * SP_HttpMsgParser :: getRequest() const
  283 +{
  284 + if( NULL != mMessage && SP_HttpMessage::eRequest == mMessage->getType() ) {
  285 + return (SP_HttpRequest*)mMessage;
  286 + }
  287 +
  288 + return NULL;
  289 +}
  290 +
  291 +SP_HttpResponse * SP_HttpMsgParser :: getResponse() const
  292 +{
  293 + if( NULL != mMessage && SP_HttpMessage::eResponse== mMessage->getType() ) {
  294 + return (SP_HttpResponse*)mMessage;
  295 + }
  296 +
  297 + return NULL;
  298 +}
  299 +
  300 +//---------------------------------------------------------
  301 +
  302 +const char * SP_HttpMessage :: HEADER_CONTENT_LENGTH = "Content-Length";
  303 +const char * SP_HttpMessage :: HEADER_CONTENT_TYPE = "Content-Type";
  304 +const char * SP_HttpMessage :: HEADER_CONNECTION = "Connection";
  305 +const char * SP_HttpMessage :: HEADER_PROXY_CONNECTION = "Proxy-Connection";
  306 +const char * SP_HttpMessage :: HEADER_TRANSFER_ENCODING = "Transfer-Encoding";
  307 +const char * SP_HttpMessage :: HEADER_DATE = "Date";
  308 +const char * SP_HttpMessage :: HEADER_SERVER = "Server";
  309 +
  310 +SP_HttpMessage :: SP_HttpMessage( int type )
  311 + : mType( type )
  312 +{
  313 + mContent = NULL;
  314 + mContentLength = 0;
  315 + mMaxLength = 0;
  316 +
  317 + mHeaderNameList = new SP_ArrayList();
  318 + mHeaderValueList = new SP_ArrayList();
  319 +
  320 + snprintf( mVersion, sizeof( mVersion ), "%s", "HTTP/1.0" );
  321 +}
  322 +
  323 +SP_HttpMessage :: ~SP_HttpMessage()
  324 +{
  325 + for( int i = mHeaderNameList->getCount() - 1; i >= 0; i-- ) {
  326 + free( mHeaderNameList->takeItem( i ) );
  327 + free( mHeaderValueList->takeItem( i ) );
  328 + }
  329 +
  330 + delete mHeaderNameList;
  331 + delete mHeaderValueList;
  332 +
  333 + if( NULL != mContent ) free( mContent );
  334 +}
  335 +
  336 +int SP_HttpMessage :: getType() const
  337 +{
  338 + return mType;
  339 +}
  340 +
  341 +void SP_HttpMessage :: setVersion( const char * version )
  342 +{
  343 + snprintf( mVersion, sizeof( mVersion ), "%s", version );
  344 +}
  345 +
  346 +const char * SP_HttpMessage :: getVersion() const
  347 +{
  348 + return mVersion;
  349 +}
  350 +
  351 +void SP_HttpMessage :: appendContent( const void * content, int length, int maxLength )
  352 +{
  353 + if( length <= 0 ) length = strlen( (char*)content );
  354 +
  355 + int realLength = mContentLength + length;
  356 + realLength = realLength > maxLength ? realLength : maxLength;
  357 +
  358 + if( realLength > mMaxLength ) {
  359 + if( NULL == mContent ) {
  360 + mContent = malloc( realLength + 1 );
  361 + } else {
  362 + mContent = realloc( mContent, realLength + 1 );
  363 + }
  364 + mMaxLength = realLength;
  365 + }
  366 +
  367 + memcpy( ((char*)mContent) + mContentLength, content, length );
  368 + mContentLength = mContentLength + length;
  369 +
  370 + ((char*)mContent)[ mContentLength ] = '\0';
  371 +}
  372 +
  373 +void SP_HttpMessage :: setContent( const void * content, int length )
  374 +{
  375 + mContentLength = 0;
  376 + appendContent( content, length );
  377 +}
  378 +
  379 +void SP_HttpMessage :: directSetContent( void * content, int length )
  380 +{
  381 + if( NULL != mContent ) free( mContent );
  382 +
  383 + length = length > 0 ? length : strlen( (char*)content );
  384 +
  385 + mContentLength = mMaxLength = length;
  386 + mContent = content;
  387 +}
  388 +
  389 +const void * SP_HttpMessage :: getContent() const
  390 +{
  391 + return mContent;
  392 +}
  393 +
  394 +int SP_HttpMessage :: getContentLength() const
  395 +{
  396 + return mContentLength;
  397 +}
  398 +
  399 +void SP_HttpMessage :: addHeader( const char * name, const char * value )
  400 +{
  401 + mHeaderNameList->append( strdup( name ) );
  402 + mHeaderValueList->append( strdup( value ) );
  403 +}
  404 +
  405 +int SP_HttpMessage :: removeHeader( const char * name )
  406 +{
  407 + int ret = 0;
  408 +
  409 + for( int i = 0; i < mHeaderNameList->getCount() && 0 == ret; i++ ) {
  410 + if( 0 == strcasecmp( name, (char*)mHeaderNameList->getItem( i ) ) ) {
  411 + free( mHeaderNameList->takeItem( i ) );
  412 + free( mHeaderValueList->takeItem( i ) );
  413 + ret = 1;
  414 + }
  415 + }
  416 +
  417 + return ret;
  418 +}
  419 +
  420 +int SP_HttpMessage :: removeHeader( int index )
  421 +{
  422 + int ret = 0;
  423 +
  424 + if( index >= 0 && index < mHeaderNameList->getCount() ) {
  425 + ret = 1;
  426 +
  427 + free( mHeaderNameList->takeItem( index ) );
  428 + free( mHeaderValueList->takeItem( index ) );
  429 + }
  430 +
  431 + return ret;
  432 +}
  433 +
  434 +int SP_HttpMessage :: getHeaderCount() const
  435 +{
  436 + return mHeaderNameList->getCount();
  437 +}
  438 +
  439 +const char * SP_HttpMessage :: getHeaderName( int index ) const
  440 +{
  441 + return (char*)mHeaderNameList->getItem( index );
  442 +}
  443 +
  444 +const char * SP_HttpMessage :: getHeaderValue( int index ) const
  445 +{
  446 + return (char*)mHeaderValueList->getItem( index );
  447 +}
  448 +
  449 +const char * SP_HttpMessage :: getHeaderValue( const char * name ) const
  450 +{
  451 + const char * value = NULL;
  452 +
  453 + for( int i = 0; i < mHeaderNameList->getCount() && NULL == value; i++ ) {
  454 + if( 0 == strcasecmp( name, (char*)mHeaderNameList->getItem( i ) ) ) {
  455 + value = (char*)mHeaderValueList->getItem( i );
  456 + }
  457 + }
  458 +
  459 + return value;
  460 +}
  461 +
  462 +int SP_HttpMessage :: isKeepAlive() const
  463 +{
  464 + const char * proxy = getHeaderValue( HEADER_PROXY_CONNECTION );
  465 + const char * local = getHeaderValue( HEADER_CONNECTION );
  466 +
  467 + if( ( NULL != proxy && 0 == strcasecmp( proxy, "Keep-Alive" ) )
  468 + || ( NULL != local && 0 == strcasecmp( local, "Keep-Alive" ) ) ) {
  469 + return 1;
  470 + }
  471 +
  472 + return 0;
  473 +}
  474 +
  475 +//---------------------------------------------------------
  476 +
  477 +SP_HttpRequest :: SP_HttpRequest()
  478 + : SP_HttpMessage( eRequest )
  479 +{
  480 + memset( mMethod, 0, sizeof( mMethod ) );
  481 + memset( mClientIP, 0, sizeof( mClientIP ) );
  482 + mURI = mURL = NULL;
  483 +
  484 + mParamNameList = new SP_ArrayList();
  485 + mParamValueList = new SP_ArrayList();
  486 +}
  487 +
  488 +SP_HttpRequest :: ~SP_HttpRequest()
  489 +{
  490 + if( NULL != mURI ) free( mURI );
  491 + if( NULL != mURL ) free( mURL );
  492 +
  493 + for( int i = mParamNameList->getCount() - 1; i >= 0; i-- ) {
  494 + free( mParamNameList->takeItem( i ) );
  495 + free( mParamValueList->takeItem( i ) );
  496 + }
  497 + delete mParamNameList;
  498 + delete mParamValueList;
  499 +}
  500 +
  501 +void SP_HttpRequest :: setMethod( const char * method )
  502 +{
  503 + snprintf( mMethod, sizeof( mMethod ), "%s", method );
  504 +}
  505 +
  506 +const char * SP_HttpRequest :: getMethod() const
  507 +{
  508 + return mMethod;
  509 +}
  510 +
  511 +void SP_HttpRequest :: setURI( const char * uri )
  512 +{
  513 + char * temp = mURI;
  514 +
  515 + mURI = strdup( uri );
  516 +
  517 + if( NULL != temp ) free( temp );
  518 +}
  519 +
  520 +const char * SP_HttpRequest :: getURI() const
  521 +{
  522 + return mURI;
  523 +}
  524 +
  525 +void SP_HttpRequest :: setURL( const char * url )
  526 +{
  527 + char * temp = mURL;
  528 +
  529 + mURL = strdup( url );
  530 +
  531 + if( NULL != temp ) free( temp );
  532 +}
  533 +
  534 +const char * SP_HttpRequest :: getURL() const
  535 +{
  536 + return mURL;
  537 +}
  538 +
  539 +void SP_HttpRequest :: setClinetIP( const char * clientIP )
  540 +{
  541 + snprintf( mClientIP, sizeof( mClientIP ), "%s", clientIP );
  542 +}
  543 +
  544 +const char * SP_HttpRequest :: getClientIP() const
  545 +{
  546 + return mClientIP;
  547 +}
  548 +
  549 +void SP_HttpRequest :: addParam( const char * name, const char * value )
  550 +{
  551 + mParamNameList->append( strdup( name ) );
  552 + mParamValueList->append( strdup( value ) );
  553 +}
  554 +
  555 +int SP_HttpRequest :: removeParam( const char * name )
  556 +{
  557 + int ret = 0;
  558 +
  559 + for( int i = 0; i < mParamNameList->getCount() && 0 == ret; i++ ) {
  560 + if( 0 == strcasecmp( name, (char*)mParamNameList->getItem( i ) ) ) {
  561 + free( mParamNameList->takeItem( i ) );
  562 + free( mParamValueList->takeItem( i ) );
  563 + ret = 1;
  564 + }
  565 + }
  566 +
  567 + return ret;
  568 +}
  569 +
  570 +int SP_HttpRequest :: getParamCount() const
  571 +{
  572 + return mParamNameList->getCount();
  573 +}
  574 +
  575 +const char * SP_HttpRequest :: getParamName( int index ) const
  576 +{
  577 + return (char*)mParamNameList->getItem( index );
  578 +}
  579 +
  580 +const char * SP_HttpRequest :: getParamValue( int index ) const
  581 +{
  582 + return (char*)mParamValueList->getItem( index );
  583 +}
  584 +
  585 +const char * SP_HttpRequest :: getParamValue( const char * name ) const
  586 +{
  587 + const char * value = NULL;
  588 +
  589 + for( int i = 0; i < mParamNameList->getCount() && NULL == value; i++ ) {
  590 + if( 0 == strcasecmp( name, (char*)mParamNameList->getItem( i ) ) ) {
  591 + value = (char*)mParamValueList->getItem( i );
  592 + }
  593 + }
  594 +
  595 + return value;
  596 +}
  597 +
  598 +//---------------------------------------------------------
  599 +
  600 +SP_HttpResponse :: SP_HttpResponse()
  601 + : SP_HttpMessage( eResponse )
  602 +{
  603 + mStatusCode = 200;
  604 + snprintf( mReasonPhrase, sizeof( mReasonPhrase ), "%s", "OK" );
  605 +}
  606 +
  607 +SP_HttpResponse :: ~SP_HttpResponse()
  608 +{
  609 +}
  610 +
  611 +void SP_HttpResponse :: setStatusCode( int statusCode )
  612 +{
  613 + mStatusCode = statusCode;
  614 +}
  615 +
  616 +int SP_HttpResponse :: getStatusCode() const
  617 +{
  618 + return mStatusCode;
  619 +}
  620 +
  621 +void SP_HttpResponse :: setReasonPhrase( const char * reasonPhrase )
  622 +{
  623 + snprintf( mReasonPhrase, sizeof( mReasonPhrase ), "%s", reasonPhrase );
  624 +}
  625 +
  626 +const char * SP_HttpResponse :: getReasonPhrase() const
  627 +{
  628 + return mReasonPhrase;
  629 +}
  630 +
  631 +//---------------------------------------------------------
  632 +
... ...
注册登录 后发表评论