/****************************************************************************/ /****************************************************************************/ /* */ /* fixslash.c, fix for Lotus Domino Go webserver trailing slash bug */ /* */ /* LANGUAGE: C/C++ */ /* PLATFORM: OS/2 */ /* EXTENDED LIBS\SDKS: GWAPI */ /* CREATED: 10/10/2002 */ /* AUTHOR: Lisa Carter, (C)2002 */ /* */ /* DESCRIPTION: */ /* Intercepts requests in order to issue a proper 302 redirect when a */ /* directory is requested without the trailing slash. Older versions of */ /* Domino apparently do not issue a redirect at all. Newer versions of */ /* Domino issue a redirect as expected; however, Domino miswrites the */ /* Location header, errantly redirecting the browser to the */ /* default server name instead of the current host name or no */ /* host name at all (which the browser interprets as the current host). */ /* This causes virtual hosts to serve the wrong URL when the user omits */ /* the trailing slash on an url that refers to a directory. */ /* */ /* This dll corrects the failure. */ /* */ /****************************************************************************/ /****************************************************************************/ /*------------------------------------------------------------------------- Includes and Pragmas ---------------------------------------------------------------------------*/ #define INCL_DOSFILEMGR #define INCL_DOSERRORS #include #include #include #include #include "HTAPI.h" #define TRUE 1 #define FALSE 0 /*--------------------------------------------------------------------------- Request Handler, handles PreExit directive Notes: URLs longer than 4096 characters will not be redirected; excessively long URLs will be handled by the server directly. In practical application, URLs are never this long as most browsers can not handle more than 1000 character URLs. The RFC legal limit on URL length is 256 characters. Parameters: unsigned char *handle - connection handle long *return_code - action/return code Returns: modifies return_code ---------------------------------------------------------------------------*/ void HTTPD_LINKAGE FixSlash( unsigned char *handle, long *return_code ) { long rc; unsigned long intNameLen; unsigned long intValueLen; char strUrl[4096]; char strErrorCode[256]; char strVarName[256]; char strValueName[256]; BOOL bDoDefaultAction; char strMiscValue[4096]; unsigned long intSizeOfMiscValue; char strFilePath[4096]; unsigned long intSizeOfFilePath; FILESTATUS PBuff; // assume we will need to redirect bDoDefaultAction = FALSE; // get the url strcpy(strVarName, "URL"); intNameLen = strlen(strVarName); intValueLen = sizeof(strUrl); HTTPD_extract (handle, (unsigned char *)strVarName, &intNameLen, (unsigned char *)strUrl, &intValueLen, &rc); if ( rc != HTTPD_SUCCESS ) { // on failure, assume the server knows what to do bDoDefaultAction = TRUE; } strUrl[intValueLen] = '\0'; // translate the url to a file on disk... if this works, then presumably everything // is good. if this fails, then we may need to try adding a slash if ( ! bDoDefaultAction ) { intNameLen = strlen(strUrl); intSizeOfMiscValue = sizeof(strMiscValue); intSizeOfFilePath = sizeof(strFilePath); HTTPD_translate(handle, strUrl, &intNameLen, strFilePath, &intSizeOfFilePath, strMiscValue, &intSizeOfMiscValue, strMiscValue, &intSizeOfMiscValue, &rc); if ( rc == HTTPD_SUCCESS ) { // get the file attributes rc = DosQueryPathInfo( strFilePath, FIL_STANDARD, &PBuff, sizeof(PBuff)); if (NO_ERROR == rc) { // if this is *not* a directory, then do the default action if ( ! (PBuff.attrFile & FILE_DIRECTORY) ) { bDoDefaultAction = TRUE; } } // on failure, assume the server knows what to do else { bDoDefaultAction = TRUE; } } // on failure, assume the server knows what to do else { bDoDefaultAction = TRUE; } } // does the url already end in a slash? // if so, don't do anything... if ( ! bDoDefaultAction ) { if ( strUrl[strlen(strUrl) - 1] == '/' ) { bDoDefaultAction = TRUE; } } // if the url doesn't end in a slash, then try appending one if ( ! bDoDefaultAction ) { strcat(strUrl, "/"); } // if for some reason you needed to change the path or use the full host name, // you could use HTTPD_reversetranslate on strFilePath here // let the server take the default action if ( bDoDefaultAction ) { *return_code = HTTP_NOACTION; strcpy(strVarName, "PreExit_rc"); intNameLen = strlen(strVarName); strcpy(strValueName, "HTTP_NOACTION"); intValueLen = strlen(strValueName); HTTPD_set(handle, (unsigned char *)strVarName, &intNameLen, (unsigned char *)strValueName, &intValueLen, &rc); } // issue a redirect else { *return_code = HTTP_MOVED_TEMPORARILY; strcpy(strErrorCode, "302"); strcpy(strVarName, "HTTP_RESPONSE"); intNameLen = strlen(strVarName); intValueLen = strlen(strErrorCode); HTTPD_set(handle, (unsigned char *)strVarName, &intNameLen, (unsigned char *)strErrorCode, &intValueLen, &rc); strcpy(strVarName, "HTTP_LOCATION"); intNameLen = strlen(strVarName); intValueLen = strlen(strUrl); HTTPD_set(handle, (unsigned char *)strVarName, &intNameLen, (unsigned char *)strUrl, &intValueLen, &rc); strcpy(strVarName, "PreExit_rc"); intNameLen = strlen(strVarName); strcpy(strValueName, "HTTP_MOVED_TEMPORARILY"); intValueLen = strlen(strValueName); HTTPD_set(handle, (unsigned char *)strVarName, &intNameLen, (unsigned char *)strValueName, &intValueLen, &rc); } }