/* * ignorecase.c: If the requested file is not there, check to see if it * is simply a matter of case. This only checks the file * part of the URL, not the directories. * * Ported from Apache module mod_speling.c (Alexei Kosut) by * Rob Crittenden (rcrit@greyoak.com) * * How to install this program: * * Add the following lines to your obj.conf: * * Init fn=load-modules shlib= funcs=ignorecase * PathCheck fn="ignorecase" * * NOTE: This should be the _last_ PathCheck * */ #include "nsapi.h" /* Forward declarations */ int revindex(const char *s, char c); char * STRNDUP(const char *s, int n); /* * ignorecase() * * Try really hard to find the requested file and update uri and path * accordingly. * */ NSAPI_PUBLIC int ignorecase(pblock *pb, Session *sn, Request *rq) { int return_value=REQ_NOACTION; char * path; /* original path to the file */ char * new_path; /* will hold the new path */ pb_param *pblock_path; /* pointer to path in the pblock */ char * uri; /* the original URI */ char * url; /* the modified URI */ char * filename; char * method; int fileindex; char * directory; /* the physical path to the file */ char * urld; /* the URI path to the file */ SYS_DIR ds; SYS_DIRENT *d; struct stat fi; if (!(path = pblock_findval("path", rq->vars))) { log_error(LOG_WARN, "ignorecase", sn, rq, "No path specified"); return_value = REQ_NOACTION; goto done; } /* only do this for GET's and POST's */ if ((method = pblock_findval( "method", rq->reqpb))) if (strcmp( method, "GET" ) && strcmp( method, "POST")) { return_value = REQ_NOACTION; goto done; } /* If the file is there, do nothing */ if (system_stat(path, &fi) != -1) { return_value = REQ_NOACTION; goto done; } /* break apart the requested filename from the path */ fileindex = revindex(path, '/'); if (fileindex == -1) { return_value = REQ_NOACTION; goto done; } directory = STRNDUP(path, fileindex); uri = pblock_findval("uri", rq->reqpb); if(!(filename = strrchr(path,FILE_PATHSEP))) filename = uri; else ++filename; /* open the directory to find the file, if I can't open it, do nothing, let send-file deal with it */ if(!(ds = dir_open(directory))) { return_value = REQ_NOACTION; goto done; } while( (d = dir_read(ds)) ) { if(d->d_name[0] == '.') continue; /* if the file matches, we're done */ if (strcasecmp(filename, d->d_name) == 0) { /* put the corrected path into the pblock */ new_path = (char *)MALLOC(strlen(path)); util_sprintf(new_path,"%s/%s", directory, d->d_name); pblock_path = pblock_find("path", rq->vars); FREE(pblock_path->value); pblock_path->value = new_path; /* The server caches the stat() of the current path. Update it. */ (void) request_stat_path(NULL, rq); /* put the corrected uri into the pblock */ fileindex = revindex(uri, '/'); urld = (char *)STRNDUP(uri, fileindex); url = (char *)MALLOC(strlen(uri)); util_sprintf(url,"%s/%s", urld, d->d_name); param_free(pblock_remove("uri", rq->reqpb)); pblock_nvinsert("uri", url, rq->reqpb); return_value = REQ_PROCEED; goto done; } } /* exit gracefully (hopefully) */ done: if (url) FREE(url); if (directory) FREE(directory); if (urld) FREE(urld); return(return_value); } /* find a character looking through a string in reverse */ int revindex(const char *s, char c) { int x; for (x=strlen(s) -1; x!= -1;x--) if (s[x] == c) return x; return -1; } /* duplicate a string up to n characters long */ char * STRNDUP(const char *s, int n) { char * result; if (s == NULL) return NULL; result = (char *)MALLOC(n+1); memcpy(result, s, n); result[n] = '\0'; return result; }