📄 sbinetvalidator.cpp
字号:
/****************License************************************************ * * Copyright 2000-2003. ScanSoft, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.2 which is * included with this software. * * ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech, * SpeechWorks and the SpeechWorks logo are registered trademarks or * trademarks of SpeechWorks International, Inc. in the United States * and other countries. * ***********************************************************************/ #ifndef _SB_USE_STD_NAMESPACE #define _SB_USE_STD_NAMESPACE #endif #include <wchar.h> #include <stdio.h> #include "SBinetValidator.h" // For this class #include "SBinetLog.h" // For logging definitions #include "HttpUtils.hpp" #include "SBinetUtils.hpp" #include "SBinetChannel.h" using namespace std; /***************************************************************************** ***************************************************************************** * SBinetValidator Implementation ***************************************************************************** ***************************************************************************** */ #if defined(_decunix_) || defined(_solaris_) // On solaris, // wsncasecmp is defined in widec.h but we don't have the right comp. flags to get the prototype. // I'm not sure about decunix though. // extern "C" wsncasecmp(const wchar_t *, const wchar_t *, size_t); #define wcsncasecmp(s1,s2,n) wsncasecmp(s1,s2,n) #if 0 static int my_wcsncasecmp(const wchar_t *s1, const wchar_t *s2, register size_t n) { register unsigned int u1, u2; for (; n != 0; --n) { u1 = (unsigned int) *s1++; u2 = (unsigned int) *s2++; if (HttpUtils::toUpper(u1) != HttpUtils::toUpper(u2)) { return HttpUtils::toUpper(u1) - HttpUtils::toUpper(u2); } if (u1 == '\0') { return 0; } } return 0; } #endif #endif SBinetValidator::SBinetValidator(VXIlogInterface *log, VXIunsigned diagTagBase) : SWIutilLogger(MODULE_SBINET, log, diagTagBase), _freshnessLifetime((time_t) -1), _refTime((time_t) -1), _sizeBytes(0), _eTag(NULL), _mustRevalidateF(false), _url(NULL), _lastModified((time_t) -1) {} SBinetValidator::~SBinetValidator() { delete [] _eTag; delete [] _url; } VXIinetResult SBinetValidator::Create(const VXIchar *filename, VXIulong sizeBytes, time_t refTime) { _lastModified = refTime; _refTime = refTime; return Create(filename, sizeBytes, (time_t) -1, (VXIMap *) NULL); } VXIinetResult SBinetValidator::Create(const VXIchar *url, time_t requestTime, const VXIMap *streamInfo) { if (url == NULL || !*url || streamInfo == NULL) { return VXIinet_RESULT_INVALID_ARGUMENT; } VXIint32 sizeBytes = 0; SBinetUtils::getInteger(streamInfo, INET_INFO_SIZE_BYTES, sizeBytes); return Create(url, (VXIulong) sizeBytes, requestTime, streamInfo); } static time_t computeRefTime(time_t requestTime, const VXIMap* streamInfo, time_t& dateTime) { // The algorithm is based on the RFC section 13.2.3 but instead of computing // an initial age, it computes a reference time that can later be used to // retrieve the age. // The algo in the RFC to compute current-age is as follows. // response_delay = response_time - request_time; // corrected_initial_age = corrected_received_age + response_delay; // resident_time = now - response_time; // current_age = corrected_initial_age + resident_time; // Which can be rewritten as follows: // current_age = (corrected_received_age + response_delay) + (now - response_time) // = (corrected_received_age + response_time - request_time) + (now - response_time) // = corrected_received_age + now - request_time // = now - (request_time - corrected_received_age) // This algorithm computes the ref. time to be equal to request_time - corrected_received_age. // Using this algorithm has two advantages: // // 1) More efficient: less computation required to compute the ref. time // than to compute the corrected initial age. When computing the current // // 2) Only requires to store the ref. time in the validator rather than the // response time and the corrected initial age. VXIint32 tmp; time_t responseTime = time(NULL); time_t computed_age = (time_t) 0; if (SBinetUtils::getInteger(streamInfo, L"Date", tmp)) { dateTime = (time_t) tmp; computed_age = responseTime - dateTime; if (computed_age < (time_t) 0) computed_age = (time_t) 0; } else { dateTime = responseTime; } if (SBinetUtils::getInteger(streamInfo, L"Age", tmp)) { time_t age = (time_t) tmp; if (age > computed_age) computed_age = age; } return requestTime - computed_age; } VXIinetResult SBinetValidator::Create(const VXIchar *url, VXIulong sizeBytes, time_t requestTime, const VXIMap *streamInfo) { if (url == NULL || !*url) { return VXIinet_RESULT_INVALID_ARGUMENT; } if (_url) delete [] _url; _url = ::wcscpy(new VXIchar[::wcslen(url) + 1], url); _sizeBytes = sizeBytes; _freshnessLifetime = (time_t) -1; const VXIchar *eTag = NULL; delete [] _eTag; // // Sanity check // if (_expiresTime >= 0 && _lastModifiedTime >= _expiresTime) // _expiresTime = 0; // time_t now = time(NULL); // if (_lastModifiedTime > now) // _lastModifiedTime = now; if (streamInfo != NULL) { time_t dateTime; _refTime = computeRefTime(requestTime, streamInfo, dateTime); VXIint32 lastModified = -1; SBinetUtils::getInteger(streamInfo, L"Last-Modified", lastModified); _lastModified = (time_t) lastModified; eTag = SBinetUtils::getString(streamInfo, L"ETag"); // Inspect the headers for other relevant directives ('no-cache' etc.) _freshnessLifetime = checkPragma(streamInfo); if (_freshnessLifetime == (time_t) -1) { _freshnessLifetime = checkCacheControl(streamInfo); } if (_freshnessLifetime == (time_t) -1) { VXIint32 expiresTime = -1; if (SBinetUtils::getInteger(streamInfo, L"Expires", expiresTime)) { _freshnessLifetime = ((time_t) expiresTime) - dateTime; } else if (_lastModified != (time_t) -1) { // Use the last modified time from the map to determine a freshness lifetime. _freshnessLifetime = (time_t) ((dateTime - _lastModified) * SBinetChannel::getFreshnessFraction()); time_t maxLifetime = SBinetChannel::getFreshnessLifetime(); if (_freshnessLifetime > maxLifetime) _freshnessLifetime = maxLifetime; } else { Error(302, L"%s%s", L"URL", url); _freshnessLifetime = SBinetChannel::getMaxLifetime(); } } if (_freshnessLifetime < (time_t) 0) _freshnessLifetime = (time_t) 0; } if (eTag == NULL || !*eTag) { _eTag = NULL; } else { _eTag = ::wcscpy(new VXIchar[::wcslen(eTag) + 1], eTag); } Log(L"SBinetValidator::Create"); return VXIinet_RESULT_SUCCESS; } VXIinetResult SBinetValidator::Create(const VXIValue *content) { if (VXIValueGetType(content) != VALUE_CONTENT) { Error(214, L"Type: %d", VXIValueGetType(content)); return VXIinet_RESULT_INVALID_ARGUMENT; } // Get the content const VXIchar *contentType; const VXIbyte *contentData; VXIulong contentSizeBytes; if ( VXIContentValue((const VXIContent*) content, &contentType, &contentData, &contentSizeBytes) != VXIvalue_RESULT_SUCCESS ) { Error(215, NULL); return VXIinet_RESULT_INVALID_ARGUMENT; } else if ( ::wcscmp(contentType, VALIDATOR_MIME_TYPE) != 0 ) { Error(216, L"mimeType: %s", contentType); return VXIinet_RESULT_INVALID_ARGUMENT; } return Create(contentData, contentSizeBytes); } VXIinetResult SBinetValidator::Create(const VXIbyte *data, VXIulong contentSizeBytes) { // Unpack the data const VXIbyte *ptr = data; ::memcpy(&_refTime, ptr, sizeof _refTime); ptr += sizeof _refTime; ::memcpy(&_freshnessLifetime, ptr, sizeof _freshnessLifetime); ptr += sizeof _freshnessLifetime; ::memcpy(&_lastModified, ptr, sizeof _lastModified); ptr += sizeof _lastModified; ::memcpy(&_mustRevalidateF, ptr, sizeof _mustRevalidateF); ptr += sizeof _mustRevalidateF; ::memcpy(&_sizeBytes, ptr, sizeof _sizeBytes); ptr += sizeof _sizeBytes; int len; ::memcpy(&len, ptr, sizeof len); ptr += sizeof len; delete [] _eTag; if (len > 0) { int size = len * sizeof(VXIchar); _eTag = new VXIchar[len + 1]; ::memcpy(_eTag, ptr, size); ptr += size; _eTag[len] = L'\0'; } else _eTag = NULL; ::memcpy(&len, ptr, sizeof len); ptr += sizeof len; delete [] _url; if (len > 0) { int size = len * sizeof(VXIchar); _url = new VXIchar[len + 1]; ::memcpy(_url, ptr, size); ptr += size; _url[len] = L'\0'; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -