home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 April B
/
Pcwk4b98.iso
/
ie401gb
/
IEAK4.CAB
/
signup.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-08
|
13KB
|
486 lines
/******************************************************************************\
*
* Copyright (C) 1996 Microsoft Corporation
* All rights reserved.
*
******************************************************************************
*
* Program: Signup.cpp
*
* Purpose: Little CGI applet to handle ISP signup forms
*
\******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h> // time f/n's
#include "windows.h" // Get/WriteProfile()
#include "cgiutil.h"
#include "random.h"
/******************************************************************************\
*
* Main code starts here...
*
\******************************************************************************/
/* Function */ int __cdecl main ( int argc, char *argv[] )
{
// fwd refs
int FormtoDB() ;
void ProcessCurrent() ;
void ProcessNext() ;
// Turn buffering off for stdin/stdout
setvbuf ( stdin, NULL, _IONBF, 0 ) ;
setvbuf ( stdout, NULL, _IONBF, 0 ) ;
ParseCGI() ;
if ( !FormtoDB() ) // validate and save form vars
{
ProcessCurrent() ; // repump the current doc out
}
else
{
ProcessNext() ; // pump the next doc out
}
return 0 ; // done!
}
/******************************************************************************\
*
* ISP Customization Section
*
* The code in the following section needs to be customized by the ISP for
* their specific database keywords and database handlers. Please see the
* IAK documentation for more information on implementing these.
*
\******************************************************************************/
static char Session[25]={0} ; // global session handle string
static char Session1[25]={0} ; // global session handle string
// Data name definitions
static char *DataName[] =
{
"fname", "lname", "addr1", "addr2", "city", "state", "zip",
"areac", "exch", "last4", "homebiz",
"ccard", "cardnum", "cardexp", "cardname",
"username", "passw", "passconf",
NULL
} ;
static char *PairName[2][4] =
{
{ "homebiz", "home", "business", NULL },
{ NULL, NULL, NULL, NULL }
} ;
/* Function */ UINT BeginTransaction()
{
// get new session handle and increment for next time
UINT hSession = GetPrivateProfileInt ( "ISS", "NextHandle", 0, "ISS.INI" ) ;
sprintf ( Session, "%d", random(hSession) ) ; // increment for next time
WritePrivateProfileString ( "ISS", "NextHandle", Session, "ISS.INI" ) ;
sprintf ( Session, "%d", hSession ) ; // use current for this session
// log start time of this session
time_t now ;
time ( &now ) ;
struct tm *nowtime = gmtime ( &now ) ;
WritePrivateProfileString ( Session, "StartTime", asctime ( nowtime ), "ISS.INI" ) ;
// set in-progress status
WritePrivateProfileString ( Session, "Status", "InProgress", "ISS.INI" ) ;
// set in-progress status
WritePrivateProfileString ( Session, "Status", "InProgress", "ISS.INI" ) ;
return ( hSession ) ;
}
/* Function */ void AcceptTransaction()
{
WritePrivateProfileString ( Session, "Status", "Accepted", "ISS.INI" ) ;
}
/* Function */ void CancelTransaction()
{
WritePrivateProfileString ( Session, "Status", "Canceled", "ISS.INI" ) ;
}
/* Function */ int DBStore ( char *did, char *val )
{
WritePrivateProfileString ( Session, did, val, "ISS.INI" ) ;
return ( 1 ) ; // return 0 if data validation failed
}
/* Function */ int DBFetch ( char *did, char *val, int len )
{
GetPrivateProfileString ( Session, did, "", val, len, "ISS.INI" ) ;
return ( 1 ) ;
}
/******************************************************************************\
*
* Function to fetch the next HTML template for processing
*
\******************************************************************************/
/* Function */ void ProcessNext()
{
char e[MAX_PATH] ; // just a little temp array
int bHTML = 1 ;
void ProcessDoc ( char *fna, int bHTML ) ; // fwd ref
// fetch template for next doc
char t[80] ;
if ( FetchVar ( "Prev", e ) )
{
FetchVar ( "PBPrev", t ) ;
}
else if ( FetchVar ( "Next", e ) )
{
FetchVar ( "PBNext", t ) ;
}
else if ( FetchVar ( "Accept", e ) )
{
FetchVar ( "PBAccept", t ) ;
// strcpy ( t, "acc2.ins" );
bHTML = 0 ;
AcceptTransaction() ;
}
else if ( FetchVar ( "Cancel", e ) )
{
FetchVar ( "PBCancel", t ) ;
bHTML = 0 ;
CancelTransaction() ;
}
else
{
//(dec) 3-May-96
// strcpy ( t, "Default.htm" ) ;
FetchVar ( "PBNext", t ) ;
}
ProcessDoc ( t, bHTML ) ;
}
/******************************************************************************\
*
* Function to resend current HTML doc, probably due to a data validation
* failure.
*
\******************************************************************************/
/* Function */ void ProcessCurrent()
{
void ProcessDoc ( char *fna, int bHTML ) ; // fwd ref
char t[80] ;
if ( FetchVar ( "ThisDoc", t ) ) // fetch template for current doc again
{
ProcessDoc ( t, 1 ) ; // send this doc again
}
else // can't get current doc, we must continue to next one
{
ProcessNext() ;
}
}
/******************************************************************************\
*
* Function to process an HTML template and pump it back to client
*
\******************************************************************************/
/* Function */ void ProcessDoc ( char *fna, int bHTML )
{
// open template file
char Template[MAX_PATH] ;
strcpy ( Template, "template\\" ) ;//this line is all that I changes !!!
strcat ( Template, fna ) ;
FILE *fip = fopen ( Template, "r" ) ;
if ( fip == NULL )
{
strcpy ( Template, "scripts\\templates\\" ) ;
strcat ( Template, fna ) ;
if ( ( fip = fopen ( Template, "r" ) ) == NULL )
{
return ;
}
}
// dispatch based on doc type
if ( bHTML )
{
void DBtoForm ( FILE *fip, FILE *fop ) ; // fwd ref
// tell the client we're sending html
printf ( "Content-type: text/html\n\n" ) ;
// now process the template
DBtoForm ( fip, stdout ) ;
fclose ( fip ) ;
}
else // it's an INS file
{
// This is a demo mode version of the INS file transmission.
// In this demo, we're just tranmitting a previously built INS file,
// one for Accept, or another for Cancel.
// create the session-specific INS file
char OutputINS[MAX_PATH] ;
// get new session1 handle and increment for next time
if (Session1[0]==0){
UINT hSession1 = GetPrivateProfileInt ( "ISS", "NextHandle1", 0, "ISS.INI" ) ;
sprintf ( Session1, "%d", hSession1+1 ) ; // increment for next time
WritePrivateProfileString ( "ISS", "NextHandle1", Session1, "ISS.INI" ) ;
sprintf ( Session1, "%d", hSession1 ) ; // use current for this session
};
// >>>>> Note! <<<<<
// This path is unique to Microsoft IIS - set this for your HTTP server
sprintf ( OutputINS, "..\\wwwroot\\insfiles\\%s%s", Session1, fna ) ;
// >>>>> Note! <<<<<
FILE *fop = fopen ( OutputINS, "w" ) ;
if ( fop == NULL )
{
return ;
}
// This is where the INS template would be interpreted and the
// ISP-specific stuff inserted. For demo purposes, we're just pumping
// the INS template file out as-is.
int num ;
char buf[1024] ;
for ( num = fread ( buf, sizeof(char), sizeof(buf), fip ) ;
num > 0 ;
num = fread ( buf, sizeof(char), sizeof(buf), fip ) )
{
fwrite ( buf, sizeof(char), num, fop ) ;
}
fclose ( fip ) ;
fclose ( fop ) ;
// Now the Session-specific INS file has been created in the insfiles
// subdirectory. We are just redirecting the client to fetch this file.
// Get the base reference for this server's HTML docs
// If we've specified our own, then use it.
// Otherwise, parse it from the environment variable.
char Server[40] ;
if ( !FetchVar ( "HTTP_REFERER", Server ) )
{
char *p = getenv ( "HTTP_REFERER" ) ;
if ( p == NULL ) return ;
// The problem here is that all we want is our server's base name,
// not the referring document, so I'm parsing off (in a pathetically
// crude manner) the server name.
char *p1 = p ;
for ( int i = 0 ; i < 3 ; i++ )
{
char *p2 = strchr ( p1, '/' ) ;
p1 = p2 ; ;
*p1++ ;
}
*p1 = '\0' ;
strcpy ( Server, p ) ;
}
// simply redirect the client to the INS file
printf ( "Status: 301 Redirection\n" ) ;
printf ( "Location: %s/insfiles/%s%s\n\n", Server, Session1, fna ) ;
}
}
/******************************************************************************\
*
* Function to fetch the variables from a form and put into database
*
\******************************************************************************/
/* Function */ int FormtoDB()
{
// if we didn't receive a session handle, we need to create one
int ret = FetchVar ( "SessionHandle", Session ) ;
if ( ret ) ret = *Session != '$' ;
if ( !ret )
{
BeginTransaction() ;
}
for ( int i = 0 ; DataName[i] ; i++ )
{
char name[80] ;
if ( FetchVar ( DataName[i], name ) )
{
if ( !DBStore ( DataName[i], name ) )
{
return ( 0 ) ; // data validation failed
}
}
}
return ( 1 ) ; // data validation(s) succeeded
}
/******************************************************************************\
*
* Function to interpret and HTML template
*
\******************************************************************************/
/* Function */ void DBtoForm ( FILE *fip, FILE *fop )
{
char buf[4096] ;
// fwd refs
int ReplaceChk ( char *buf, char *str[], FILE *fop ) ;
int ReplaceVal ( char *buf, char *str, FILE *fop ) ;
// read file into buffer and process a line at a time
for ( fgets ( buf, 4096, fip ) ;
! feof ( fip ) ;
fgets ( buf, 4096, fip ) )
{
// scan for tokens
for ( int i = 0 ; i < (int)strlen(buf) ; i++ )
{
if ( buf[i] == '$' ) // if token found, parse and replace
{
int j ;
// 1) Special case for session handle processing
if ( memcmp ( &buf[i+1], "SessionHandle", strlen("SessionHandle") ) == 0 )
{
fprintf ( fop, "%s", Session ) ;
i += strlen ( "$SessionHandle" ) - 1 ;
continue ;
}
// 2) Special case for cancel page - need to substitute PrevPage
// with where we came from...
if ( memcmp ( &buf[i+1], "PrevPage", strlen("PrevPage") ) == 0 )
{
char PrevPage[40] ;
FetchVar ( "ThisPage", PrevPage ) ;
fprintf ( fop, "%s", PrevPage ) ;
i += strlen ( "$PrevPage" ) - 1 ;
continue ;
}
// 3) Special case for data-value pair names
for ( j = 0 ; PairName[j][0] ; j++ )
{
int k = ReplaceChk ( &buf[i+1], &PairName[j][0], fop ) ;
if ( k != 0 )
{
i += k ;
break ;
}
}
// 4) Finally, check data-name list
for ( j = 0 ; DataName[j] ; j++ )
{
int k = ReplaceVal ( &buf[i+1], DataName[j], fop ) ;
if ( k != 0 )
{
i += k ;
break ;
}
}
// 5) If no valid token found in list, just copy input to output
if ( !DataName[j] )
{
fputc ( (int)buf[i], fop ) ;
}
}
else // not a token, just copy the character to the output file
{
fputc ( (int)buf[i], fop ) ;
}
} // for ( strlen(buf )
} // while ( !feof() )
}
/******************************************************************************\
*
* Functions to replace token strings in the input stream with data in the
* output stream.
*
\******************************************************************************/
/*
* Handles data-value pair name data (radio buttons)
* Returns 0 (zero) if the string was not found
* Returns the number of characters to skip if it was found
*/
/* Function */ int ReplaceChk ( char *buf, char *str[], FILE *fop )
{
char val[80] ;
// if input buffer doesn't match the token in str[0], we're done
if ( memcmp ( buf, str[0], strlen(str[0]) ) != 0 )
return ( 0 ) ;
// verify that the input buffer has an '=' delimiter for the control name
char *p = &buf[strlen(str[0])] ;
if ( *p != '=' )
{
return ( 0 ) ;
}
// group-name=control-name is correct syntax
// fetch the value of this data item
DBFetch ( str[0], val, sizeof(val) ) ;
// scan the control names in str[1...] to find data name match
int i = 1 ;
for ( *p++ ; str[i] ; i++ )
{
if ( memcmp ( p, str[i], strlen(str[i]) ) == 0 )
{
if ( strcmp ( str[i], val ) == 0 )
{
fprintf ( fop, "checked" ) ;
}
// in either case, we skip over the entire token
return ( strlen(str[0]) + 1 + strlen(str[i]) + 1 ) ;
}
}
return ( 0 ) ;
}
/*
* Function to replace a token string in the output stream with data value
* Returns 0 (zero) if the string was not found
* Returns the number of characters to skip if it was found
*/
/* Function */ int ReplaceVal ( char *buf, char *str, FILE *fop )
{
char val[80] ;
if ( memcmp ( buf, str, strlen(str) ) != 0 )
return ( 0 ) ;
DBFetch ( str, val, sizeof(val) ) ;
fprintf ( fop, "%s", val ) ;
return ( strlen(str) ) ;
}