📄 pgplicensenumbernet.c
字号:
static const char *kContentLength = "Content-Length: ";
static const char *kWarning = "Warning: ";
// look for HTTP optional header
// Warning: warn-code SP warn-agent SP warn-text
// and parse it, if it was generated by us.
static PGPError parseHttpWarningHeader( const PGPByte *header, PGPError *remoteError ) {
PGPByte *p;
*remoteError = kPGPError_NoErr;
p = strstr( header, kWarning );
if( p == NULL )
return kPGPError_NoErr;
if( p > header+2 && *(p-1)=='\n' && *(p-2)=='\r' ) {
p += strlen(kWarning);
// HTTP Warning: warn-code SP warn-agent SP warn-text
// p now points on warn-code
if( atoi(p) == 99 ) { // we pass PGPError as this "Miscellaneous warning"
p = strchr( p, ' ' );
if( p )
p++; // p points on warn-agent
else
return kPGPError_CorruptData; // HTTP violation
p = strchr( p, ' ' ); // skip warn-agent
if( !p )
return kPGPError_CorruptData; // HTTP violation
{
PGPByte warn_text[40];
const static PGPByte pgperror[] = "PGPError=";
p++; // p points on warn-text, this is quoted PGPError=errcode
if( *p == '"' ) {
strncpy( warn_text, p+1, sizeof(warn_text) );
warn_text[sizeof(warn_text)-1] = '\0';
p = strchr( warn_text, '"' ); // check for another quote
if( p )
*p = '\0';
else
return kPGPError_CorruptData; // HTTP violation
p = warn_text;
}
if( strncmp( p, pgperror, sizeof(pgperror)-1 )==0 ) {
p += sizeof(pgperror)-1;
*remoteError = atoi(p); // set output parameter
}
}
}
}
return kPGPError_NoErr;
}
/* we assume that the first line in HTTP response is in the buffer
other fields can be absent
*/
static PGPError parseHttpHeader( PGPByte header[kPGPLANet_ReceiveSize],
PGPSize *bodySize, PGPSize *headerSize, PGPUInt32 *statusCode )
{
PGPByte *p, *p2;
PGPUInt32 i;
int curBodySize = 0;
int curHeaderSize = 0;
int curStatusCode = 0;
*bodySize = 0;
*headerSize = 0;
*statusCode = 0;
/* find where body begins and eliminate it. It may not be present */
p = strstr( header, "\r\n\r\n" );
if( p != NULL ) {
p[2] = '\0';
curHeaderSize = p-header+4;
}
/* check for content lenght */
p = strstr( header, kContentLength );
if( p != NULL ) {
if( p > header+2 && *(p-1)=='\n' && *(p-2)=='\r' ) {
p += strlen(kContentLength);
i = atoi(p);
/* check content length that we could generate */
if( i > 160*2/8 && i < 4*1024 ) {
curBodySize = i;
}
}
}
/* now we are done with sizes - parse first line to get return code */
p2 = strchr( header, '\r' );
if( !p2 ) { /* we expect to get at least one line */
return kPGPError_CorruptData;
}
// header =?= HTTP-Version SP Status-Code SP Reason-Phrase CRLF
if( strncmp( header, "HTTP/", 5 )!=0 )
return kPGPError_CorruptData;
p = strchr( header, ' ' );
if( !p )
return kPGPError_CorruptData;
p++;
i = atoi(p);
if( i<100 )
return kPGPError_CorruptData;
curStatusCode = i;
p = strchr(p, ' ');
if( !p )
return kPGPError_CorruptData;
p++;
/* p is reason */
if( strchr(p, '\r') != (char *) p2 )
return kPGPError_CorruptData; // this wasn't on the first line
*bodySize = curBodySize;
*headerSize = curHeaderSize;
*statusCode = curStatusCode;
return kPGPError_NoErr;
}
static void sleepSeconds( PGPUInt32 sec ) {
#if PGP_UNIX || PGP_OSX
usleep(sec * 1000000);
#elif PGP_WIN32
Sleep(sec * 1000);
#else
sleep( sec );
#endif
}
static PGPError roundTrip( PGPSocketRef socket,
const PGPByte *host_port, const PGPByte *resource,
PGPBoolean last,
const PGPByte *inData,
PGPByte bufferRead[kPGPLANet_ReceiveSize],
PGPUInt32 *httpError, PGPError *remotePgpError )
{
static const char *kPost = "POST ";
static const char *kHTTPVersion_term = " HTTP/1.1\r\n";
static const char *kContentType = "Content-type: application/x-www-form-urlencoded\r\n";
static const char *kConnectionKeepAlive = "Connection: Keep-Alive\r\n";
static const char *kConnectionClose = "Connection: close\r\n";
static const char *kHost = "Host: ";
PGPByte bufferSend[kPGPLANet_SendSize];
#if PGP_MACINTOSH
#define OS " (Macintosh)"
#elif PGP_WIN32
#define OS " (Windows)"
#elif PGP_UNIX
#define OS " (Unix)"
#endif
static const char * kUserAgent = "User-Agent: PGP" OS "\r\n";
#undef OS
PGPInt32 socketResult=0;
const PGPSize inDataLength = inData != NULL ? strlen( inData ) : 0;
bufferSend[0] = '\0';
bufferRead[0] = '\0';
if( httpError )
*httpError = 0;
if( remotePgpError )
*remotePgpError = kPGPError_NoErr;
if( inData!=NULL && inData[0]=='\0' )
inData = NULL;
/* send first line */
strcat( bufferSend, kPost );
strcat( bufferSend, resource);
strcat( bufferSend, kHTTPVersion_term);
strcat( bufferSend, kUserAgent);
strcat( bufferSend, kContentType);
/* sending Host field */
strcat( bufferSend, kHost );
strcat( bufferSend, host_port );
strcat( bufferSend, "\r\n" );
strcat( bufferSend, last ? kConnectionClose : kConnectionKeepAlive );
/* forth line - content length */
{
char s[20];
strcat(bufferSend, kContentLength );
sprintf(s, "%u\r\n", (unsigned) inDataLength);
strcat(bufferSend, s );
}
/* insert empty line */
strcat(bufferSend, "\r\n");
#if PGP_DEBUG_PRINT
fprintf( stderr,"-----begin sending packet-----\n");
fprintf( stderr,"%s%s\n", bufferSend, inData==NULL ? (const PGPByte*)" " : inData);
fprintf( stderr,"-----end sending packet-----\n");
#endif
PGPSend( socket, bufferSend, strlen(bufferSend), kPGPSendFlagNone );
/* finally, send data */
if( inData != NULL )
PGPSend( socket, inData, inDataLength, kPGPSendFlagNone );
/* now receive data */
{
PGPUInt32 bytesRead = 0;
PGPInt32 avail;
PGPSize headerSize, bodySize;
PGPUInt32 httpStatusCode;
PGPError err;
PGPError remote_err;
PGPInt32 max_wait=5; /* how long receiver waits before declaring timeout */
do {
avail = PGPReceive( socket, bufferRead, kPGPLANet_ReceiveSize, MSG_PEEK );
if( avail == 0 ) {
sleepSeconds( 1 );
#if PGP_DEBUG_PRINT
fprintf( stderr,"\twaited one sec to receive data from the socket...\n");
#endif
}
} while(max_wait-- > 0 && avail==0);
if( avail==0 ) { /* timed out */
#if PGP_DEBUG_PRINT
fprintf( stderr,"timed out: no data in the socket\n");
#endif
return kPGPError_ServerTimedOut;
}
if( avail < 0 )
return PGPGetLastSocketsError();
err = parseHttpHeader( bufferRead, &bodySize, &headerSize, &httpStatusCode );
if( IsPGPError(err) )
return err;
if( httpError )
*httpError = httpStatusCode;
/* check for remote PGPError code returned as a warn-text in Warning: */
err = parseHttpWarningHeader( bufferRead, &remote_err );
if( IsPGPError(err) )
return err;
if( remotePgpError )
*remotePgpError = remote_err;
if( bodySize && headerSize && httpStatusCode==200 && bodySize + headerSize == avail ) { /* already read */
bytesRead = avail;
PGPReceive( socket, bufferSend, avail, kPGPReceiveFlagNone );
// reuse bufferSend for cleaning the socket
}
else {
avail = bodySize + headerSize;
if( avail > kPGPLANet_ReceiveSize )
avail = kPGPLANet_ReceiveSize;
while( bytesRead < avail )
{
socketResult = PGPReceive( socket, ( (PGPByte *) bufferRead ) + bytesRead,
avail-bytesRead, kPGPReceiveFlagNone );
if( socketResult <= 0 )
break;
bytesRead += socketResult;
}
}
if( socketResult < 0 ) {
PGPError err = PGPGetLastSocketsError();
return err;
}
if( headerSize ) {
bufferRead[headerSize-2] = '\0';
bufferRead[headerSize-1] = '\0';
bufferRead[bodySize + headerSize] = '\0';
}
#if PGP_DEBUG_PRINT
fprintf( stderr,"-----begin received packet-----\n" );
fprintf( stderr, "%s\n", bufferRead );
fprintf( stderr, "-----begin body-----\n" );
fprintf( stderr, "%s\n", bufferRead+headerSize );
fprintf( stderr,"-----end received packet-----\n");
#endif /* PGP_DEBUG_PRINT */
if( bodySize )
memmove( bufferRead, bufferRead+headerSize, bodySize+1 );
else
bufferRead[0] = '\0';
}
return kPGPError_NoErr;
}
/* appends application/x-www-form-urlencoded parameter and value,
encodes all illegal characters as %XX
See section 2.2 from RFC 1738
*/
static void addFormUrlEncodedParam( const PGPByte *name, const PGPByte *value,
PGPByte *buffer )
{
PGPByte v[kPGPLANet_SendSize];
PGPSize len = strlen( buffer );
PGPUInt32 w_value_len=0;
PGPByte *p;
static const PGPByte illegal[] = "&=+% \t\n\r<>\"#{}|\\^[]~`";
PGPUInt16 wv[kPGPLANet_SendSize];
PGPUInt32 i;
if( name == NULL || value == NULL )
return;
/* name expect to be OK */
pgpAssert( strchr(name, '=')==NULL );
pgpUTF8StringToUCS2 (
value, kPGPUnicodeNullTerminated, wv, sizeof(wv)/sizeof(wv[0]), &w_value_len);
if( w_value_len==0 )
return; /* ignore the pair */
p = v;
for( i=0; i<w_value_len; i++ ) {
PGPByte utf8[8];
PGPUInt32 utf8_len=0;
pgpUCS2StringToUTF8( wv+i, 1, utf8, sizeof(utf8), &utf8_len );
if( utf8_len==0 )
return; /* ignore the pair */
utf8[sizeof(utf8)-1] = '\0';
if( utf8_len==1 && strchr( illegal, wv[i] )==NULL && wv[i] > 0x1f && wv[i] < 0x80 )
*(p++) = (PGPByte)wv[i]; /* unchacnged */
else {
/* encode all bytes for the Unicode character */
PGPUInt32 j;
PGPByte e[8];
for( j=0; j<utf8_len; j++ ) {
sprintf( e, "%%%02X", utf8[j] );
strcpy( p, e );
p += 3;
}
}
}
*p = '\0';
if( !len )
sprintf( buffer, "%s=%s", name, v );
else {
buffer += len;
sprintf( buffer, "&%s=%s", name, v );
}
}
/* parse parametes in the form of application/x-www-form-urlencoded */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -