/*---------------------------------------------------------------------------- "http.c" HTTP Access Microsoft C/C++ 32bit Compiler ver11.00 GNU/Linux / GNU C Compiler Copyright (c) S.Tsuneoka ----------------------------------------------------------------------------*/ #include "http.h" /*----------------------------------------------------------------------------- [形 式] HttpCreateHandle [引 数] lpcszUserAgent ... ユーザエージェント名 lpcszProxy ... プロキシサーバ名(IPアドレス) nPort ... プロキシポート番号 [説 明] HTTPハンドルを生成する [戻 り 値] 正常終了 HTTPハンドル 異常終了 0 -----------------------------------------------------------------------------*/ HTTPHANDLE HttpCreateHandle(const char *lpcszUserAgent, const char *lpcszProxy, unsigned short nPort) { LPHTTPINFO lphi = NULL; #ifdef WIN32 WORD wVersionRequested; WSADATA wsaData; /* WinSock の初期化 */ wVersionRequested = (WORD)0x0101; if(WSAStartup(wVersionRequested, &wsaData) != 0){ return 0; } #endif /* 管理情報構造体領域確保 */ if((lphi = malloc(sizeof(HTTPINFO))) == NULL){ return 0; } /* ユーザエージェント名 */ if(lpcszUserAgent){ strcpy(lphi->szAgentName, lpcszUserAgent); } /* プロキシサーバの設定 */ if(lpcszProxy){ strcpy(lphi->szProxy, lpcszProxy); lphi->nProxyPort = nPort; } return (HTTPHANDLE)lphi; } /*----------------------------------------------------------------------------- [形 式] HttpCloseHandle [引 数] hHttp ... HTTPハンドル [説 明] HTTPハンドルを解放する [戻 り 値] なし -----------------------------------------------------------------------------*/ void HttpCloseHandle(HTTPHANDLE hHttp) { if(hHttp){ HttpClose(hHttp); free((void*)hHttp); } #ifdef WIN32 WSACleanup(); #endif } /*--------------------------------------------------------------------------- URLからホスト名とポート番号を摘出する ---------------------------------------------------------------------------*/ static int GetHostNameByUrl(const char *lpcszUrl, char *lpszHostName, unsigned short *lpusPort, char *lpszContents, int *lpfSsl) { char *lpszSrc, *lpszDest; *lpszHostName = '\0'; *lpfSsl = FALSE; *lpusPort = 0; *lpszContents = '/'; *(lpszContents+1) = '\0'; /* プロトコルをチェックする */ if(StrIStr(lpcszUrl, "http://") == lpcszUrl){ *lpusPort = INTERNET_DEFAULT_HTTP_PORT; } #ifdef OPENSSL else if(StrIStr(lpcszUrl, "https://") == lpcszUrl){ *lpusPort = INTERNET_DEFAULT_HTTPS_PORT; *lpfSsl = TRUE; } #endif else{ return E_INVALID_PARAMETER; } /* ホスト名を取得する */ lpszSrc = strstr(lpcszUrl, "://") + 3; if(*lpszSrc == '\0'){ return E_INVALID_PARAMETER; } lpszDest = lpszHostName; while((*lpszSrc != ':') && (*lpszSrc != '/') && (*lpszSrc != '\0')){ *lpszDest++ = *lpszSrc++; } *lpszDest = '\0'; if(*lpszSrc == '\0'){ return 0; } /* ポート番号を取得する */ if(*lpszSrc == ':'){ *lpusPort = (unsigned short)atoi(lpszSrc+1); if((lpszSrc = strchr(lpszSrc, '/')) == NULL){ return 0; } } /* コンテンツパスを取得する */ strcpy(lpszContents, lpszSrc); return 0; } #ifdef OPENSSL /*---------------------------------------------------------------------------- プロキシサーバにSSL接続要求を行う ----------------------------------------------------------------------------*/ static int ConnectSSL(int sock, const char *lpcszServer, unsigned short nPort) { char szBuff[MAX_HEADERS]; unsigned uHeaderSize = 0, uReaded = 1, uStatus = 0; char *lpsz = NULL; /* プロキシサーバに対してhttpsサーバの接続を要求する */ sprintf(szBuff, "CONNECT %s:%d HTTP/1.0\r\n\r\n", lpcszServer, nPort); if(send(sock, szBuff, strlen(szBuff), 0) < 0){ return WSAGetLastError(); } /* プロキシサーバのステータスコードを読み出す */ /* HTTPヘッダを読み込む */ for(lpsz = szBuff; uReaded != 0; lpsz++){ if((uReaded = recv(sock, lpsz, 1, 0)) == -1){ return WSAGetLastError(); } uHeaderSize += uReaded; if(uHeaderSize >= (MAX_HEADERS - 1)){ break; } if(*lpsz == '\n' && uHeaderSize > 4){ if((*(lpsz-1) == '\r') &&(*(lpsz-2) == '\n') &&(*(lpsz-3) == '\r')){ uReaded = 0; } } } *lpsz = '\0'; /* プロキシサーバステータスが200以外の場合はエラーとする */ if((lpsz = StrIStr(szBuff, "HTTP/")) != NULL){ if((lpsz = strchr(lpsz, ' ')) != NULL){ uStatus = atoi(lpsz+1); } } if(uStatus != HTTP_STATUS_OK){ return uStatus; } return 0; } /*---------------------------------------------------------------------------- OpenSSL初期化 ----------------------------------------------------------------------------*/ static int InitOpenSSL(LPHTTPINFO lphi) { const char *seed = "DHJSHD2HSDopHSFewqAJKAJKytFrJKAFuKytJAFJKAS4DFJ"; RAND_seed(seed, strlen(seed)); SSL_library_init(); lphi->lpSslMethod = SSLv23_client_method(); SSL_load_error_strings(); if((lphi->lpCtx = SSL_CTX_new(lphi->lpSslMethod)) == NULL){ return E_SSLFAILD; } SSL_CTX_set_mode(lphi->lpCtx, SSL_MODE_AUTO_RETRY); return 0; } /*---------------------------------------------------------------------------- HTTPSサーバへの接続 ----------------------------------------------------------------------------*/ static int ConnectToHttpsServer(LPHTTPINFO lphi) { if((lphi->lpSsl = SSL_new(lphi->lpCtx)) == NULL){ return E_SSLFAILD; } SSL_set_fd(lphi->lpSsl, lphi->sock); if(SSL_connect(lphi->lpSsl) == -1){ return E_SSLFAILD; } return 0; } /*---------------------------------------------------------------------------- サーバ証明書の情報取得 ----------------------------------------------------------------------------*/ void GetServerCertificate(LPHTTPINFO lphi) { X509 *lpX509; char *lpsz; strcpy(lphi->szX509, SSL_get_cipher(lphi->lpSsl)); strcat(lphi->szX509, "\r\n"); if((lpX509 = SSL_get_peer_certificate(lphi->lpSsl)) == NULL){ return; } if((lpsz = X509_NAME_oneline(X509_get_subject_name(lpX509),0,0)) != NULL){ strcat(lphi->szX509, lpsz); strcat(lphi->szX509, "\r\n"); } if((lpsz = X509_NAME_oneline(X509_get_issuer_name(lpX509),0,0)) != NULL){ strcat(lphi->szX509, lpsz); strcat(lphi->szX509, "\r\n"); } lphi->uX509Size = strlen(lphi->szX509); X509_free(lpX509); } #endif /*----------------------------------------------------------------------------- [形 式] HttpGetServerCertificate [引 数] hHttp ... HTTPハンドル [説 明] サーバ証明書の情報取得 [戻 り 値] 正常終了 サーバ証明書の情報を格納する領域を指すポインタ 異常終了 NULL -----------------------------------------------------------------------------*/ const char *HttpGetServerCertificate(HTTPHANDLE hHttp, unsigned int *lpuSize) { #ifdef OPENSSL LPHTTPINFO lphi = GetHttpInfo(hHttp); if(lpuSize){ *lpuSize = lphi->uX509Size; } return lphi->szX509; #else return NULL; #endif } /*--------------------------------------------------------------------------- HTTPサーバへの接続 ---------------------------------------------------------------------------*/ static int ConnectToHttpServer( char *lpszHost, unsigned short usPort, int *lpiSock) { int sock = 0; struct sockaddr_in sockaddr; int iResult = 0; if((sock = socket(PF_INET, SOCK_STREAM, 0)) == 0){ return WSAGetLastError(); } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(usPort); sockaddr.sin_addr.s_addr = inet_addr(lpszHost); if(connect(sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0){ iResult = WSAGetLastError(); closesocket(sock); return iResult; } *lpiSock = sock; return iResult; } /*----------------------------------------------------------------------------- [形 式] HttpOpen [引 数] hHttp ... HTTPハンドル lpcszUrl ... URL(NULL可) lpcszUserName ... 認証ユーザ名(NULL可) lpcszPassword ... 認証パスワード(NULL可) [説 明] HTTPコネクションを確立する NULL可のパラメータは最後にHttpOpenを実行したときの値を 利用することを指す。 [戻 り 値] 正常終了 0 異常終了 上記以外 -----------------------------------------------------------------------------*/ int HttpOpen(HTTPHANDLE hHttp, const char *lpcszUrl, const char *lpcszUserName, const char *lpcszPassword) { LPHTTPINFO lphi = GetHttpInfo(hHttp); char szServer[MAX_DOMAIN]; char szConnHost[MAX_DOMAIN]; char szObject[MAX_URL]; unsigned short nPort, nConnPort; int fSsl = FALSE; int fSetUrl = FALSE; int iResult = 0; if(lphi == NULL){ return E_INVALID_HANDLE; } if((lpcszUrl != NULL) && (strstr(lpcszUrl, "://") != NULL)){ strcpy(lphi->szUrl, lpcszUrl); fSetUrl = TRUE; } if(lpcszUserName){ strcpy(lphi->szUserName, lpcszUserName); } if(lpcszPassword){ strcpy(lphi->szPassword, lpcszPassword); } /* URLを分解する */ iResult = GetHostNameByUrl(lphi->szUrl, szServer, &nPort, szObject, &fSsl); if(iResult != 0){ return iResult; } strcpy(szConnHost, szServer); nConnPort = nPort; strcpy(lphi->szHost, szServer); if((nPort != INTERNET_DEFAULT_HTTP_PORT) &&(nPort != INTERNET_DEFAULT_HTTPS_PORT)){ sprintf(lphi->szHost, "%s:%d", szServer, nPort); } #ifdef OPENSSL lphi->fUseSsl = fSsl; #endif if((lpcszUrl != NULL) && (fSetUrl == FALSE)){ /* パス指定(Locationヘッダ受信時) */ if(*lpcszUrl == '/'){ /* 絶対パス */ strcpy(szObject, lpcszUrl); } else{ /* 相対パス */ char *lpsz = szObject + strlen(szObject); while(szObject <= lpsz){ if(*lpsz == '/'){ *(lpsz+1) = '\0'; break; } lpsz--; } strcat(szObject, lpcszUrl); } sprintf(lphi->szUrl, "%s://%s%s", fSsl ? "https" : "http", lphi->szHost, szObject); } if(*lphi->szProxy != '\0'){ /* Proxyの設定を利用する場合はフルURL指定 */ strcpy(szConnHost, lphi->szProxy); nConnPort = lphi->nProxyPort; sprintf(lphi->szReqUrl, "%s://%s%s", fSsl ? "https" : "http", lphi->szHost, szObject); } else{ /* サーバに直接アクセスする場合はパス指定 */ strcpy(lphi->szReqUrl, szObject); } if(IsIPAddess(szConnHost) == FALSE){ struct hostent *lphostent; /* ドメイン名からIPアドレスを得る */ if((lphostent = gethostbyname(szConnHost)) != NULL){ struct in_addr inaddr; memcpy(&inaddr, lphostent->h_addr, lphostent->h_length); strcpy(szConnHost, inet_ntoa(inaddr)); } else{ return WSAGetLastError(); } } #ifdef OPENSSL if(lphi->fUseSsl == TRUE){ if((iResult = InitOpenSSL(lphi)) != 0){ return iResult; } } #endif /* 接続する */ iResult = ConnectToHttpServer(szConnHost, nConnPort, &lphi->sock); if(iResult != 0){ return iResult; } #ifdef OPENSSL /* SSLで接続する */ if(lphi->fUseSsl == TRUE){ if(*lphi->szProxy != '\0'){ /* プロキシサーバへの接続 */ if((iResult = ConnectSSL(lphi->sock, szServer, nPort)) != 0){ return iResult; } } ConnectToHttpsServer(lphi); GetServerCertificate(lphi); } #endif return 0; } /*----------------------------------------------------------------------------- [形 式] HttpClose [引 数] hHttp ... HTTPハンドル [説 明] HTTPコネクションを切断する [戻 り 値] なし -----------------------------------------------------------------------------*/ void HttpClose(HTTPHANDLE hHttp) { LPHTTPINFO lphi = GetHttpInfo(hHttp); char szBuff[256]; unsigned uReaded; int iResult; if(hHttp == NULL){ return; } /* 受信していないデータを空読みする */ do{ iResult = HttpRecive(hHttp, szBuff, sizeof(szBuff), &uReaded); if(iResult != 0){ break; } }while(uReaded > 0); memset(&(lphi->szHeaders), 0, sizeof(lphi->szHeaders)); #ifdef OPENSSL /* ハンドル解放 */ if(lphi->lpSsl){ SSL_shutdown(lphi->lpSsl); lphi->lpSsl = NULL; } #endif if(lphi->sock){ closesocket(lphi->sock); lphi->sock = 0; } #ifdef OPENSSL if(lphi->lpSsl){ SSL_free(lphi->lpSsl); lphi->lpSsl = NULL; } if(lphi->lpCtx){ SSL_CTX_free(lphi->lpCtx); lphi->lpCtx = NULL; } #endif } /*----------------------------------------------------------------------------- [形 式] HttpSend [引 数] hHttp ... HTTPハンドル lpcszBuff ... 送信を行うデータを指すポインタ uBuffSize ... データサイズ [説 明] データの送信を行う [戻 り 値] 正常終了 0 異常終了 上記以外 -----------------------------------------------------------------------------*/ int HttpSend(HTTPHANDLE hHttp, const char *lpcszBuff, unsigned int uBuffSize) { LPHTTPINFO lphi = GetHttpInfo(hHttp); if(lphi == NULL){ return E_INVALID_HANDLE; } #ifdef OPENSSL if((lphi->fUseSsl == TRUE) && (lphi->lpSsl != NULL)){ if(SSL_write(lphi->lpSsl, lpcszBuff, uBuffSize) == -1){ return E_SSLSENDFAILED; } } else{ #else { #endif if(send(lphi->sock, lpcszBuff, uBuffSize, 0) == -1){ return WSAGetLastError(); } } return 0; } /*----------------------------------------------------------------------------- [形 式] HttpRecive [引 数] hHttp ... HTTPハンドル lpszBuff ... 受信データを格納する領域を指すポインタ uBuffSize ... バッファサイズ lpuReaded ... 受信バイト数を格納する領域を指すポインタ [説 明] データの受信を行う [戻 り 値] 正常終了 0 異常終了 上記以外 -----------------------------------------------------------------------------*/ int HttpRecive(HTTPHANDLE hHttp, char *lpszBuff, unsigned int uBuffSize, unsigned int *lpuReaded) { LPHTTPINFO lphi = GetHttpInfo(hHttp); unsigned int uReaded = 0; if(lphi == NULL){ return E_INVALID_HANDLE; } *lpuReaded = 0; #ifdef OPENSSL if((lphi->fUseSsl == TRUE) && (lphi->lpSsl != NULL)){ uReaded = SSL_read(lphi->lpSsl, lpszBuff, uBuffSize); if(uReaded == -1){ return E_SSLRECIVEFAILED; } } else{ #else { #endif uReaded = recv(lphi->sock, lpszBuff, uBuffSize, 0); if(uReaded == -1){ return WSAGetLastError(); } } *lpuReaded = uReaded; return 0; } /*---------------------------------------------------------------------------- ユーザ名とパスワードを設定する ----------------------------------------------------------------------------*/ static void GetBasicAuthHeader(LPHTTPINFO lphi, char *lpszUidPwd) { char szUIDPassWd[MAX_UIDPWD*3]; char szEncode[MAX_UIDPWD*4]; if(*(lphi->szUserName) == '\0'){ *lpszUidPwd = '\0'; return; } /* ユーザ名とパスワードをBASE64でエンコードする */ sprintf(szUIDPassWd, "%s:%s",lphi->szUserName, lphi->szPassword); EncodeBase64(szUIDPassWd, szEncode); /* 送信データを作成 */ sprintf(lpszUidPwd, "Authorization: Basic %s\r\n", szEncode); } /*---------------------------------------------------------------------------- HTTPリクエストヘッダを送信する ----------------------------------------------------------------------------*/ static int SendRequestHeaders(HTTPHANDLE hHttp, const char *lpcszHttpVersion, const char *lpcszMethod, int fBasicAuth, const char *lpcszHeader, unsigned int uHeaderSize, const char *lpcszOption, unsigned int uOptionSize) { LPHTTPINFO lphi = GetHttpInfo(hHttp); char szHeader[256]; unsigned int uSize = 0; int iResult = 0; /* HTTPヘッダを送信 */ uSize = sprintf(szHeader, "%s ", lpcszMethod); if((iResult = HttpSend(hHttp, szHeader, uSize)) != 0){ return iResult; } uSize = strlen(lphi->szReqUrl); if((iResult = HttpSend(hHttp, lphi->szReqUrl, uSize)) != 0){ return iResult; } uSize = sprintf(szHeader, " HTTP/%s\r\n", lpcszHttpVersion ? lpcszHttpVersion : DEFAULT_HTTP_VERSION); if((iResult = HttpSend(hHttp, szHeader, uSize)) != 0){ return iResult; } uSize = sprintf(szHeader,"Host: %s\r\n", lphi->szHost); if((iResult = HttpSend(hHttp, szHeader, uSize)) != 0){ return iResult; } if(*lphi->szAgentName != '\0'){ uSize = sprintf(szHeader,"User-Agent: %s\r\n", lphi->szAgentName); if((iResult = HttpSend(hHttp, szHeader, uSize)) != 0){ return iResult; } } if(fBasicAuth == TRUE){ /* 基本認証 */ char szAuthHeader[MAX_UIDPWD*4]; GetBasicAuthHeader(lphi, szAuthHeader); if((uSize = strlen(szAuthHeader)) > 0){ if((iResult = HttpSend(hHttp, szAuthHeader, uSize)) != 0){ return iResult; } } } if((lpcszOption != NULL) && (uOptionSize != 0)){ /* オプションが指定されている場合は、データサイズを設定する */ uSize = sprintf(szHeader, "Accept-Ranges: bytes\r\n" "Content-Length: %u\r\n", uOptionSize); if((iResult = HttpSend(hHttp, szHeader, uSize)) != 0){ return iResult; } } if(lpcszHeader){ /* 追加ヘッダ */ const char *lpcszNext, *lpcszTop, *lpcszBottom; int iSize; for(lpcszNext = lpcszHeader; lpcszNext < (lpcszHeader + uHeaderSize);){ lpcszTop = lpcszNext; if((lpcszBottom = strchr(lpcszTop, '\n')) == NULL){ break; } lpcszNext = lpcszBottom + 1; if(*(lpcszBottom - 1) == '\r'){ lpcszBottom--; } if((iSize = lpcszBottom - lpcszTop) <= 0){ continue; } if((iResult = HttpSend(hHttp, lpcszTop, iSize)) != 0){ return iResult; } HttpSend(hHttp, "\r\n", 2); } } HttpSend(hHttp, "\r\n", 2); /* オプションを送信 */ if(lpcszOption){ if((iResult = HttpSend(hHttp, lpcszOption, uOptionSize)) != 0){ return iResult; } } return 0; } /*---------------------------------------------------------------------------- HTTPヘッダを受信する ----------------------------------------------------------------------------*/ static int ReciveHeaders(HTTPHANDLE hHttp, unsigned int *lpuStatus) { LPHTTPINFO lphi = GetHttpInfo(hHttp); char *lpsz = NULL; unsigned uReaded = 1; unsigned uHeaderSize = 0; unsigned uStatus = 0; int iResult = 0; if(lpuStatus == NULL){ lpuStatus = &uStatus; } /* HTTPヘッダを読み込む */ for(lpsz = lphi->szHeaders; uReaded != 0; lpsz++){ if((iResult = HttpRecive(hHttp, lpsz, 1, &uReaded)) != 0){ return iResult; } uHeaderSize += uReaded; if(uHeaderSize >= (MAX_HEADERS - 1)){ break; } if(*lpsz == '\n' && uHeaderSize > 4){ if((*(lpsz-1) == '\r') &&(*(lpsz-2) == '\n') &&(*(lpsz-3) == '\r')){ uReaded = 0; } } } *lpsz = '\0'; lphi->uHeaderSize = strlen(lphi->szHeaders); if((lpsz = StrIStr(lphi->szHeaders, "HTTP/")) != NULL){ if((lpsz = strchr(lpsz, ' ')) != NULL){ *lpuStatus = atoi(lpsz+1); } } return 0; } /*----------------------------------------------------------------------------- [形 式] HttpGetAllHeaders [引 数] hHttp ... HTTPハンドル lpuSize ... サイズを返す領域を指すポインタ [説 明] サーバから取得したHTTPヘッダを格納する領域を得る [戻 り 値] 正常終了 HTTPヘッダを格納する領域を指すポインタ 異常終了 NULL -----------------------------------------------------------------------------*/ const char *HttpGetAllHeaders(HTTPHANDLE hHttp, unsigned int *lpuSize) { LPHTTPINFO lphi = GetHttpInfo(hHttp); if(lphi == NULL){ return NULL; } if(lpuSize){ *lpuSize = lphi->uHeaderSize; } return lphi->szHeaders; } /*----------------------------------------------------------------------------- [形 式] HttpGetHeader [引 数] hHttp ... HTTPハンドル lpcszName ... ヘッダ名 lpszValue ... 値を格納する領域を指すポインタ [説 明] 指定されたHTTPヘッダに設定されている値を取得する HttpSendRequest の実行後でなければ値を取得できない。 [戻 り 値] 正常終了 0 異常終了 上記以外 -----------------------------------------------------------------------------*/ int HttpGetHeader(HTTPHANDLE hHttp, const char *lpcszName, char *lpszValue) { LPHTTPINFO lphi = GetHttpInfo(hHttp); const char *lpcszNameTop, *lpcszValTop, *lpcszValTail; char *lpsz; if(lphi == NULL){ return E_INVALID_HANDLE; } *lpszValue = '\0'; lpcszNameTop = lphi->szHeaders; while((lpcszNameTop = StrIStr(lpcszNameTop, lpcszName)) != NULL){ if((lpcszValTop = strchr(lpcszNameTop, ':')) == NULL){ return E_INVALID_PARAMETER; } lpcszValTop++; while(*lpcszValTop == ' '){ lpcszValTop++; } if((lpcszValTail = strchr(lpcszValTop, '\n')) == NULL){ return E_INVALID_DATA; } /* 値をコピーする */ if(*lpszValue != '\0'){ strcat(lpszValue, "; "); } for(lpsz = lpszValue + strlen(lpszValue); lpcszValTop < lpcszValTail;){ *lpsz++ = *lpcszValTop++; } *lpsz = '\0'; if(*(lpsz-1) == '\r'){ *--lpsz = '\0'; } lpcszNameTop = lpcszValTail + 1; } return 0; } /*---------------------------------------------------------------------------- 基本認証 ----------------------------------------------------------------------------*/ static int DoBasicAuthenticate(HTTPHANDLE hHttp, const char *lpcszVersion, const char *lpcszMethod, const char *lpcszHeader, unsigned int uHeaderSize, const char *lpcszOption, unsigned int uOptionSize, unsigned int *lpuStatus) { char szAuth[MAX_UIDPWD]; int iResult; if((iResult = HttpGetHeader(hHttp, "WWW-Authenticate", szAuth) != 0)){ return iResult; } if(StrIStr(szAuth, "Basic") == NULL){ return 0; } HttpClose(hHttp); if((iResult = HttpOpen(hHttp, NULL, NULL, NULL)) != 0){ return iResult; } iResult = SendRequestHeaders(hHttp, lpcszVersion, lpcszMethod, TRUE, lpcszHeader, uHeaderSize, lpcszOption, uOptionSize); if(iResult != 0){ return iResult; } return ReciveHeaders(hHttp, lpuStatus); } /*---------------------------------------------------------------------------- ロケーション ----------------------------------------------------------------------------*/ static int DoLocation(HTTPHANDLE hHttp, const char *lpcszVersion, const char *lpcszMethod, const char *lpcszHeader, unsigned int uHeaderSize, const char *lpcszOption, unsigned int uOptionSize, unsigned int *lpuStatus) { char szLocation[MAX_URL]; int iResult; if((iResult = HttpGetHeader(hHttp, "Location", szLocation)) != 0){ return iResult; } if(*szLocation == '\0'){ return E_NODATA; } HttpClose(hHttp); if((iResult = HttpOpen(hHttp, szLocation, NULL, NULL)) != 0){ return iResult; } iResult = SendRequestHeaders(hHttp, lpcszVersion, "GET", FALSE, lpcszHeader, uHeaderSize, NULL, 0); if(iResult != 0){ return iResult; } return ReciveHeaders(hHttp, lpuStatus); } /*----------------------------------------------------------------------------- [形 式] HttpSendRequest [引 数] hHttp ... HTTPハンドル lpcszVersion ... HTTPバージョン(NULL可 "1.0"とみなす) lpcszMethod ... メソッド("GET", "POST", ...) lpcszHeader ... 追加ヘッダ(NULL可) 各ヘッダの終端には"\n"を設定する uHeaderSize ... 追加ヘッダ長 lpcszOption ... オプションデータ(NULL可) uOptionSize ... オプションデータ長 lpuStatus ... サーバステータス格納領域を指す(NULL可) [説 明] HTTPリクエストを発行する HttpSendRequest の実行後でなければ値を取得できない。 [戻 り 値] 正常終了 0 異常終了 上記以外 -----------------------------------------------------------------------------*/ int HttpSendRequest(HTTPHANDLE hHttp, const char *lpcszVersion, const char *lpcszMethod, const char *lpcszHeader, unsigned int uHeaderSize, const char *lpcszOption, unsigned int uOptionSize, unsigned int *lpuStatus) { LPHTTPINFO lphi = GetHttpInfo(hHttp); unsigned int uStatus = 0; int iResult = 0; if(lphi == NULL){ return E_INVALID_HANDLE; } if(lpuStatus == NULL){ lpuStatus = &uStatus; } /* HTTPリクエストヘッダを送信 */ iResult = SendRequestHeaders(hHttp, lpcszVersion, lpcszMethod, FALSE, lpcszHeader, uHeaderSize, lpcszOption, uOptionSize); if(iResult != 0){ return iResult; } /* HTTPサーバヘッダを受信 */ if((iResult = ReciveHeaders(hHttp, lpuStatus)) != 0){ return iResult; } /* ステータスチェックを行い、必要に応じて再リクエストを行う */ while(iResult == 0){ switch((int)*lpuStatus){ case HTTP_STATUS_OK: return iResult; case HTTP_STATUS_MOVED: case HTTP_STATUS_REDIRECT: iResult = DoLocation(hHttp, lpcszVersion, lpcszMethod, lpcszHeader, uHeaderSize, lpcszOption, uOptionSize, lpuStatus); break; case HTTP_STATUS_DENIED: case HTTP_STATUS_PROXY_AUTH_REQ: iResult = DoBasicAuthenticate(hHttp, lpcszVersion, lpcszMethod, lpcszHeader, uHeaderSize, lpcszOption, uOptionSize, lpuStatus); if((*lpuStatus == HTTP_STATUS_DENIED) ||(*lpuStatus == HTTP_STATUS_PROXY_AUTH_REQ)){ return iResult; } break; default: return iResult; /* その他のステータス */ } } return iResult; }