/*****************************************************************************/ /* FileDot.c Miscellaneous file processing module. (We might end up stuffing all sort of miscellaneous file-type functionality into here!) FILE.URL -------- This file type parallels the Microsoft 'file.URL' files that contain Web URLs as a type of symbolic or soft link into the Internet. These files are enabled by creating an WASD_CONFIG_GLOBAL content-type mapping a file extension (e.g. .URL) to the content-type "x-internal/url". This results in FileDotUrlBegin() being activqted by REQUEST.C module when a file of type .URL is accessed. Lines beginning with '#' or '[' are ignored. Recognised redirections: URL=scheme://the.host.name/the/path/ URL=./relative/path URL=../relative/path URL=relative/path scheme://the.host.name/the/path/ ./relative/path ../relative/path VERSION HISTORY --------------- 25-FEB-2002 MGD modifications inline with suggestions (ssh@S-and-B.ru) 01-JAN-2001 MGD new for HTTPd version 7.2 */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include #include /* VMS related header files */ #include #include /* application-related header files */ #include "wasd.h" #define WASD_MODULE "DOTFILE" /**********/ /* macros */ /**********/ /* if not in the first 2048 bytes of the file then quit */ #define FILE_DOT_URL_QUIT_AFTER 2048 /********************/ /* external storage */ /********************/ extern int ToLowerCase[], ToUpperCase[]; extern char SoftwareID[]; extern ACCOUNTING_STRUCT *AccountingPtr; extern MSG_STRUCT Msgs; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Using the configuration file (contents supplied by a preceding call to FileBegin()) interpret the mappings. */ FileDotUrlBegin (REQUEST_STRUCT *rqptr) { int Length; char *cptr, *sptr, *zptr; char FileName [ODS_MAX_FILE_NAME_LENGTH+1]; FILE_CONTENT *fcptr; /*********/ /* begin */ /*********/ if (!rqptr->AccountingDone++) InstanceGblSecIncrLong (&AccountingPtr->DoDotUrlCount); /* take control of the file contents structure */ fcptr = rqptr->FileContentPtr; rqptr->FileContentPtr = NULL; if (WATCHING(rqptr) && WATCH_CATEGORY(WATCH_RESPONSE)) WatchThis (rqptr, FI_LI, WATCH_RESPONSE, "URL !AZ !UL bytes", fcptr->FileName, fcptr->ContentLength); /* get the start of the file contents */ cptr = sptr = fcptr->ContentPtr; while (*cptr) { if (cptr > sptr + FILE_DOT_URL_QUIT_AFTER) break; while (*cptr && ISLWS(*cptr)) cptr++; if (*cptr == '#' || *cptr == '[' || EOL(*cptr)) { /* ignore comment/directive/empty lines */ while (*cptr && NOTEOL(*cptr)) cptr++; while (*cptr && EOL(*cptr)) cptr++; continue; } if (TOUP(cptr[0]) == 'U' && TOUP(cptr[1]) == 'R' && TOUP(cptr[2]) == 'L' && TOUP(cptr[3]) == '=') { /* no question about this one! */ cptr += 4; } else if (cptr[0] == '.') { /* possible relative URL (e.g. "../whatever" or "./whatever") */ if (!((cptr[1] == '.' && cptr[2] == '/') || cptr[1] != '/')) { cptr++; continue; } } else { /* possible absolute URL (e.g. "scheme://the.host.name/the/path") */ if (cptr[0] != ':') { cptr++; continue; }; if (cptr[1] != '/') { cptr++; continue; }; if (cptr[2] != '/') { cptr++; continue; }; /* looks like it, find the start of the scheme, looking backwards */ if (cptr > fcptr->ContentPtr) cptr--; while (cptr > fcptr->ContentPtr && isalpha(*cptr)) cptr--; if (!isalpha(*cptr)) cptr++; } /* find the end of the URL, then use it as a redirection location */ sptr = cptr; while (*cptr && !ISLWS(*cptr) && !EOL(*cptr)) cptr++; rqptr->rqResponse.LocationPtr = VmGetHeap (rqptr, cptr-sptr+1); cptr = rqptr->rqResponse.LocationPtr; while (*sptr && !isspace(*sptr)) *cptr++ = *sptr++; *cptr = '\0'; break; } if (rqptr->rqResponse.LocationPtr) { /************/ /* redirect */ /************/ SysDclAst (fcptr->NextTaskFunction, rqptr); return; } /*****************************/ /* output file as plain-text */ /*****************************/ ResponseHeader (rqptr, 200, "text/plain", -1, NULL, NULL); NetWrite (rqptr, fcptr->NextTaskFunction, fcptr->ContentPtr, fcptr->ContentLength); } /*****************************************************************************/