C source of SET181UPLO

LANSA

C source of SET181UPLO

/*
Disclaimer: The following material is supplied as
sample material only. No warranty concerning the
material or its use in any way whatsoever is
expressed or implied.

To create the program

CRTBNDC PGM(<your library>/SET181UPLO) SYSIFCOPT(*IFSIO)

In your IBM HTTP Server configuration add the following directive

MAP /cgi-bin/set181uplo* /QSYS.LIB/<your library>.LIB/SET181UPLO.PGM*
MAP /CGI-BIN/SET181UPLO* /QSYS.LIB/<your library>.LIB/SET181UPLO.PGM*
EXEC /QSYS.LIB/<your library>.LIB/*

*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <iconv.h>
#include <qtqiconv.h>
#include <xxdtaa.h>
#include <fcntl.h>
#include <unistd.h>

#define TRUE 1
#define FALSE 0

typedef int BOOL ;

/*
CR, LF are ASCII values
*/
#define CR 0x0D
#define LF 0x0A
#define ASCIIBUFFER_SIZE 500
#define MAX_MIMECOMPONENT 100
#define MIMEHEAD_SIZE 500
#define BOUNDARY_SIZE 100
#define MESSAGE_SIZE 200
#define FIELDNAME_SIZE 10
#define ROOTPATH_SIZE 40
#define PATH_SIZE 100
#define FILEPATH_SIZE 50
#define CLIENTFILEPATH_SIZE 250
#define ABSOLUTEPATH_SIZE ROOTPATH_SIZE + PATH_SIZE + FILEPATH_SIZE

/*
If DATAAREA name is less than 10, then pad it out with blanks
For example #define DATAAREA "SMALLNME "
*/
#define DATAAREA "S_181FUPLO"
#define FIELDNAME_PATH "AS_PATHNAM"
#define FIELDNAME_FILE "S_UPFILE"

void setConversion ( int ) ;
void convert ( char*, char* ) ;
int getContentLimit ( void ) ;
void getRootDirectory ( char* ) ;
BOOL getMimeHead ( char*, int, int, int, char* ) ;
int getMimeHeadLength ( char*, int, int ) ;
void getMimeData ( char*, int, int, int, int*, int* ) ;
BOOL isContentDisposition ( char* ) ;
BOOL getFieldName ( char*, char* ) ;
BOOL getFileName ( char*, char* ) ;
BOOL buildFilePath ( char*, char*, char*, char* ) ;
BOOL saveToFile ( char*, char*, int ) ;
void sendResponse ( char* ) ;
void trim ( char* ) ;

iconv_t atoe ;

int main ( int argc, char* args[] )
{
int i = 0 ;
int ch = 0 ;
int contentLength = 0 ;
int contentLimit = 0 ;
char* content = NULL ;
int boundaryLength = 0 ;
char boundary[BOUNDARY_SIZE+1] = "" ;

int boundaryCount = 0 ;
int boundaryOffSet[MAX_MIMECOMPONENT] ;

int mimeDataOffSet = 0 ;
int mimeDataLength = 0 ;
char mimeHead[MIMEHEAD_SIZE+1] = "" ;

char* envVariable = NULL ;
char buffer[ASCIIBUFFER_SIZE+1] = "" ;
char message[MESSAGE_SIZE+1] = "" ;

char path[PATH_SIZE+1] = "" ;
char rootPath[ROOTPATH_SIZE+1] = "" ;
char fieldName[FIELDNAME_SIZE+1] = "" ;
char fileName[FILEPATH_SIZE+1] = "" ;
char absolutePath[ABSOLUTEPATH_SIZE+1] = "" ;

/*
Setup CCSID 819 to job CCSID conversion
*/
setConversion ( 819 ) ;

/*
Get configuration
*/
contentLimit = getContentLimit () ;

if ( contentLimit == 0 )
{
sendResponse ( "Cannot accept content" ) ;

return FALSE ;
}

getRootDirectory ( rootPath ) ;

if ( strlen ( rootPath ) == 0 )
{
sendResponse ( "Root path has not been configured" ) ;

return FALSE ;
}

/*
Check executation state of cgi-bin program
*/
envVariable = getenv ( "REQUEST_METHOD" ) ;
if ( strcmp ( envVariable, "POST" ) != 0 )
{
sendResponse ( "Request method is not POST" ) ;
return ;
}

envVariable = getenv ( "CONTENT_TYPE" ) ;
if ( strcmp ( envVariable, "multipart/form-data" ) != 0 )
{
sendResponse ( "Content type is not multipart/form-data" ) ;
return ;
}

envVariable = getenv ( "CONTENT_LENGTH" ) ;
if ( envVariable == NULL )
{
sendResponse ( "No Content length variable" ) ;
return ;
}

contentLength = atoi ( getenv ( "CONTENT_LENGTH" ) ) ;
if ( contentLength > contentLimit )
{
sendResponse ( "Content length exceeds limit" ) ;
return ;
}

/*
Allocate memory to receive standard input
*/
contentLength = atoi ( getenv ( "CONTENT_LENGTH" ) ) ;

content = (char*)malloc ( contentLength ) ;

memset ( content, 0x00, contentLength ) ;

/*
Read entire standard input
*/
for ( i=0; i < contentLength; i++ )
{
ch = fgetc ( stdin ) ;

if ( ch == EOF )
{
break ;
}

content[i] = ch ;
}

/*
Check if entire input has been read
*/
if ( i != contentLength )
{
free ( content ) ;

sendResponse ( "Cannot upload due to standard input error" ) ;

return ;
}

/*
Find boundary pattern from content, normally this is
taken from HTTP header Content-Type
*/
memset ( boundary, 0x00, sizeof(boundary) ) ;
for ( i=0; i < contentLength; i++ )
{
if ( content[i] == CR )
{
boundaryLength = i ;

memcpy ( boundary, &content[0], boundaryLength ) ;

break ;
}
}

/*
If a POST is done with no INPUT fields then the
content will be :

CRLF--boundarypattern--CRLF

*/
if ( boundaryLength == 0 )
{
free ( content ) ;

sendResponse ( "File upload contains no MIME content" );

return ;
}

/*
If a POST is done with 1 or more INPUT fields then
content will be:

--boundarypatternCRLF
MIME component
CRLFCRLF
dataCRLF
--boundarypatternCRLF
MIME component
...
--boundarypattern--CRLF

*/

/*
Find boundary offsets

0,....
*/
for ( i=0; i < contentLength; i++ )
{
if ( memcmp ( &content[i], &boundary[0], boundaryLength ) == 0 )
{
boundaryOffSet[boundaryCount] = i ;
boundaryCount ++ ;

if ( boundaryCount >= MAX_MIMECOMPONENT )
{
sendResponse ( "Too many MIME components" ) ;

free ( content ) ;

return ;
}
}
}

/*
Default path, if path not obtained from browser
*/
strcpy ( path, "/" ) ;

/*
Process each MIME component
*/
for ( i=0; i < boundaryCount - 1; i++ )
{
mimeDataOffSet = 0 ;
mimeDataLength = 0 ;
memset ( mimeHead, 0x00, sizeof(mimeHead) ) ;

if ( !getMimeHead ( content,
boundaryOffSet[i],
boundaryOffSet[i+1],
boundaryLength,
mimeHead ) )
{
free ( content ) ;

return ;
}

if ( !isContentDisposition ( mimeHead ) )
{
free ( content ) ;

return ;
}

if ( !getFieldName ( mimeHead, fieldName ) )
{
free ( content ) ;

return ;
}

/*
Get data offsets
*/
getMimeData ( content,
boundaryOffSet[i],
boundaryOffSet[i+1],
boundaryLength,
&mimeDataOffSet,
&mimeDataLength ) ;

if ( strcmp ( fieldName, FIELDNAME_PATH ) == 0 )
{
/*
Path has been found
*/
if ( mimeDataLength > PATH_SIZE )
{
free ( content ) ;

sendResponse ( "Path is too long" ) ;

return ;
}

if ( mimeDataLength != 0 )
{
/*
A possible path value has been sent
*/
memset ( buffer, 0x00, sizeof ( buffer ) ) ;
memcpy ( buffer, &content[mimeDataOffSet],
mimeDataLength ) ;

/*
Convert ASCII path value into EBCDIC
*/
memset ( path, 0x00, sizeof ( path ) ) ;
convert ( buffer, path ) ;

trim ( path ) ;

}

}

if ( strcmp ( fieldName, FIELDNAME_FILE ) == 0 )
{
/*
File has been found
*/
if ( mimeDataLength == 0 )
{
/*
No file data

Possible unused <INPUT TYPE="FILE"> tag
*/
continue ;
}

if ( !getFileName ( mimeHead, fileName ) )
{
free ( content ) ;

return ;
}

if ( !buildFilePath ( rootPath, path, fileName,
absolutePath ) )
{
free ( content ) ;

return ;
}

if ( !saveToFile ( absolutePath,
&content[mimeDataOffSet], mimeDataLength ) )
{
free ( content ) ;

sprintf ( message, "Cannot save file %s",
absolutePath ) ;

sendResponse ( message ) ;

return ;

}

}

}

free ( content ) ;

sendResponse ( "Files have been uploaded" ) ;

}

BOOL buildFilePath ( char* root,
char* path,
char* fileName,
char* absolutePath )
{
int offSet = 0 ;
char filePath[ABSOLUTEPATH_SIZE+1] = "" ;

/*
Validate root path
*/
if ( strcmp ( root, "/" ) == 0 )
{
sendResponse ( "Root path cannot be /" ) ;

return FALSE ;
}

/*
Check root path must start with "/"
*/
if ( root[0] != '/' )
{
sendResponse ( "Root path needs to start with /" ) ;

return FALSE ;
}

/*
Build up file path
*/
strcpy ( filePath, root ) ;

/*
Remove possible "/" at end of filePath
*/
offSet = strlen ( filePath ) - 1 ;
if ( filePath[offSet] == '/' )
{
filePath[offSet] = 0x00 ;
}

/*
Validate path
*/
if ( strlen ( path ) == 0 )
{
sendResponse ( "Path must be specified" ) ;

return FALSE ;
}

/*
path must start with "/"
*/
if ( path[0] != '/' )
{
sendResponse ( "Path needs to start with /" ) ;

return FALSE ;
}

/*
Add path to filePath
*/
strcat ( filePath, path ) ;

/*
Remove possible "/" at end of filePath
*/
offSet = strlen ( filePath ) - 1 ;
if ( filePath[offSet] == '/' )
{
filePath[offSet] = 0x00 ;
}

/*
Validate filename
*/
if ( fileName[0] != '/' )
{
sendResponse ( "Filename needs to start with /" ) ;

return FALSE ;
}

/*
Add filename to filePath
*/
strcat ( filePath, fileName ) ;

/*
Check for any mutiple "//" in filePath
*/
if ( strstr ( filePath, "//" ) != NULL )
{
sendResponse ( "File path contains multiple separators" ) ;

return FALSE ;
}

strcpy ( absolutePath, filePath ) ;

return TRUE ;

}

BOOL getFieldName ( char* mimeHead, char* fieldName )
{
char* offSet = NULL ;
char buffer[MIMEHEAD_SIZE+1] = "" ;

/*
Find name pattern in MIME head

For example: name="AS_PATHNAM"
*/
offSet = strstr ( mimeHead, "name=\"" ) ;
if ( offSet == NULL )
{
sendResponse ( "name keyword not found in MIME head" ) ;
return FALSE ;
}

/*
Move to first character after name="
*/
offSet = offSet + 6 ;

strcpy ( buffer, offSet ) ;

/*
Find closing "
*/
offSet = strstr ( buffer, "\"" ) ;
if ( offSet == NULL )
{
sendResponse ( "name keyword is missing closing quote" ) ;
return FALSE ;
}
offSet[0] = 0x00 ;

if ( strlen ( buffer ) > FIELDNAME_SIZE )
{
sendResponse ( "Field name is too long" ) ;
return FALSE ;
}

strcpy ( fieldName, buffer ) ;

return TRUE ;
}

BOOL getFileName ( char* mimeHead, char* fileName )
{
int i = 0 ;
char* offSet = NULL ;
char buffer[MIMEHEAD_SIZE+1] = "" ;

/*
Find name pattern in MIME head

For example: filename="C:\images\frog.gif"
*/
offSet = strstr ( mimeHead, "filename=\"" ) ;
if ( offSet == NULL )
{
sendResponse ( "filename keyword not found in MIME head" ) ;
return FALSE ;
}

/*
Move to first character after filename="
*/
offSet = offSet + 10 ;

strcpy ( buffer, offSet ) ;

/*
Find closing "
*/
offSet = strstr ( buffer, "\"" ) ;
if ( offSet == NULL )
{
sendResponse ( "filename keyword is missing closing quote" ) ;
return FALSE ;
}
offSet[0] = 0x00 ;

if ( strlen ( buffer ) == 0 )
{
/*
filename="", this should not have happen as
mimeDataLength == 0 logic would have caught this
*/
sendResponse ( "Empty filename keyword encountered" ) ;
return FALSE ;
}

if ( strlen ( buffer ) > CLIENTFILEPATH_SIZE )
{
sendResponse ( "Client file path is too long" ) ;
return FALSE ;
}

/*
Get filename from path
*/
i = strlen ( buffer ) - 1 ;
for ( ; i > 0; i-- )
{
if ( buffer[i] == '/' )
{
break ;
}

if ( buffer[i] == '\\' )
{
buffer[i] = '/' ;

break ;
}
}

if ( buffer[i] != '/' )
{
sendResponse ( "Client path contains no separator" ) ;
return ;
}

if ( strlen(buffer) - i > FILEPATH_SIZE )
{
sendResponse ( "Client filename is too long" ) ;
return FALSE ;
}

strcpy ( fileName, &buffer[i] ) ;

return TRUE ;
}

BOOL isContentDisposition ( char* mimeHead )
{
if ( memcmp ( mimeHead, "Content-Disposition:", 20 ) == 0 )
{
return TRUE ;
}

printf ( "HTTP/1.0 200 OK\n" ) ;
printf ( "Content-Type: text/html\n" ) ;
printf ( "\n" ) ;
printf ( "<HTML>\n" ) ;
printf ( "<B>Invalid MIME head %s<B>\n", mimeHead ) ;
printf ( "</HTML>\n" ) ;

return FALSE ;
}

void sendResponse ( char* message )
{
printf ( "HTTP/1.0 200 OK\n" ) ;
printf ( "Content-Type: text/html\n" ) ;
printf ( "\n" ) ;
printf ( "<HTML>\n" ) ;
printf ( "<B>%s</B>\n", message ) ;
printf ( "</HTML>\n" ) ;
}

BOOL getMimeHead ( char* content,
int boundaryOffSet1,
int boundaryOffSet2,
int boundaryLength,
char* mimeHead )
{
int headOffSet = 0 ;
int headLength = 0 ;
char mimeHeadASCII[MIMEHEAD_SIZE+1] ;

headOffSet = boundaryOffSet1 + boundaryLength + 2 ;

headLength = getMimeHeadLength ( content, headOffSet,
boundaryOffSet2 ) ;

if ( headLength > MIMEHEAD_SIZE )
{
sendResponse ( "MIME head is too big" ) ;
return FALSE ;
}

memset ( mimeHeadASCII, 0x00, sizeof(mimeHeadASCII) ) ;
memcpy ( mimeHeadASCII, &content[headOffSet], headLength ) ;

convert ( mimeHeadASCII, mimeHead ) ;

return TRUE ;
}

int getMimeHeadLength ( char* content, int startIndex, int endIndex )
{
int i = 0 ;

for ( i=0; i < endIndex - startIndex; i++ )
{
/*
Locate CRLFCRLF sequence
*/

if ( content[startIndex + i + 0] == CR &&
content[startIndex + i + 1] == LF &&
content[startIndex + i + 2] == CR &&
content[startIndex + i + 3] == LF )
{
return i ;
}
}

return 0 ;

}

void getMimeData ( char* content,
int boundaryOffSet1,
int boundaryOffSet2,
int boundaryLength,
int* mimeDataOffSet,
int* mimeDataLength )
{
int headOffSet = 0 ;
int headLength = 0 ;
int startIndex = 0 ;
int endIndex = 0 ;

headOffSet = boundaryOffSet1 + boundaryLength + 2 ;

headLength = getMimeHeadLength ( content, headOffSet,
boundaryOffSet2 ) ;

/*
Skip the head and CRLFCRLF
*/
startIndex = headOffSet + headLength + 4 ;

/*
Position before the CRLF which marks the end of mime data
and the start of the next boundary pattern
*/
endIndex = boundaryOffSet2 - 3 ;

*mimeDataOffSet = startIndex ;
*mimeDataLength = endIndex - startIndex + 1 ;
}

void setConversion ( int clientCCSID )
{
QtqCode_T local ;
QtqCode_T remote ;

memset ( &local, 0x00, sizeof ( QtqCode_T ) ) ;
local.CCSID = 0 ;

memset ( &remote, 0x00, sizeof ( QtqCode_T ) ) ;
remote.CCSID = clientCCSID ;

atoe = QtqIconvOpen ( &local, &remote ) ;
}

void convert ( char* pszIn, char* pszOut )
{
unsigned iSize = strlen ( pszIn ) ;
unsigned oSize = iSize ;
char* ptrI = &pszIn[0] ;
char* ptrO = &pszOut[0] ;

iconv ( atoe, &ptrI, &iSize, &ptrO, &oSize ) ;

}

BOOL saveToFile ( char* path, char* mimeData, int mimeDataLength )
{
int fdFile = -1 ;
int writeCount = 0 ;
char message[MESSAGE_SIZE+1] = "" ;

fdFile = open ( path,
O_CREAT | O_WRONLY | O_TRUNC | O_CODEPAGE,
S_IRWXU | S_IROTH,
437 ) ;

if ( fdFile == -1 )
{
sprintf ( message, "Cannot open file %s", path ) ;

sendResponse ( message ) ;

return FALSE ;
}

writeCount = write ( fdFile, mimeData, mimeDataLength ) ;

if ( writeCount != mimeDataLength )
{
sprintf ( message, "Cannot write to file %s", path ) ;

sendResponse ( message ) ;

return FALSE ;
}

close ( fdFile ) ;

return TRUE ;

}

int getContentLimit ()
{
char buffer[10+1] ;
_DTAA_NAME_T dtaname = { DATAAREA, "*LIBL " } ;

memset ( buffer, 0x00, sizeof(buffer) ) ;

/*

QXXRTVDA ( dtaname, 1, 10, buffer ) ;

*/
strcpy ( buffer, "4000000" ) ;

return atoi ( buffer ) ;

}

void getRootDirectory ( char* directory )
{
char buffer[40+1] ;
_DTAA_NAME_T dtaname = { DATAAREA, "*LIBL " } ;

memset ( buffer, 0x00, sizeof(buffer) ) ;

/*

QXXRTVDA ( dtaname, 11, 40, buffer ) ;

trim ( buffer ) ;

*/
strcpy ( buffer, "/tmp" ) ;

strcpy ( directory, buffer ) ;

}

void trim ( char* buffer )
{
int i = strlen ( buffer ) - 1 ;

for ( ; i > 0; i-- )
{
if ( buffer[i] != ' ' )
{
break ;
}
buffer[i] = 0x00 ;
}

}