1: #include "stdafx.h"
2: #include <windows.h>
3: #include <httpfilt.h>
4: #include <shlwapi.h>
5: #include <atlstr.h>
6: #pragma comment(lib, "shlwapi.lib")
7:
8: #define DEFAULT_BUFFER_SIZE 2048
9: #define MAX_BUF 2048
10: char szUsername[DEFAULT_BUFFER_SIZE];
11: char *pszUsername = szUsername;
12: const char szIndexFiles[8][13] = {"index.html","index.asp","index.aspx","default.htm","default.html","index.php","default.php","index.mspx"};
13: char pszDebugEnabled[1024];
14: char pszHomePath[1024];
15: DWORD g_dwAppendBufferLen = 0;
16:
17: bool DoInitialize(HMODULE hModule);
18: DWORD DoUrlRewriting(HTTP_FILTER_CONTEXT *pfc, HTTP_FILTER_URL_MAP *pMap);
19:
20: #ifdef _MANAGED
21: #pragma managed(push, off)
22: #endif
23:
24: #define DLC_TRACE(x) DlcReportEventA(EVENTLOG_INFORMATION_TYPE, x)
25:
26: void DlcReportEventA(WORD wType, LPCSTR pszMessage)
27: {
28: if (pszDebugEnabled == NULL || pszDebugEnabled != "True") {
29: return;
30: } // we don’t write anything.
31:
32: HANDLE hEventSource;
33: LPCTSTR lpszStrings[1];
34:
35: lpszStrings[0] = (LPCTSTR)pszMessage;
36:
37: /* Get a handle to use with ReportEvent(). */
38: hEventSource = RegisterEventSourceA(NULL, "IISHome");
39: if (hEventSource != NULL)
40: {
41: /* Write to event log. */
42: ReportEventA(hEventSource, wType, 0, 0, NULL, 1, 0, (LPCSTR*) &lpszStrings[0], NULL);
43: DeregisterEventSource(hEventSource);
44: }
45: }
46:
47: BOOL GetRegistryKey (char *lpszConfigItem, char *outBuffer)
48: {
49: char szRegistryResult[1024];
50: HKEY hKey;
51: BOOL bFoundItem = TRUE;
52: DWORD baseLen = 1024;
53: memset(szRegistryResult, 0, 1024);
54: char dbgInfo[DEFAULT_BUFFER_SIZE];
55: sprintf(dbgInfo, "DEBUG: Value Name: %s", lpszConfigItem);
56: DLC_TRACE(dbgInfo);
57:
58: if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\BrentP\\IISHome", 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
59: bFoundItem = FALSE;
60: DLC_TRACE("DEBUG: RegOpenKeyEx(…) failed to open key.");
61: return bFoundItem;
62: }
63:
64: if (bFoundItem == TRUE) {
65: /* Get Registry Value */
66: DLC_TRACE("DEBUG: Key found - ready for RegQueryValueEx(…)");
67: if (RegQueryValueEx(hKey, lpszConfigItem, NULL, NULL, (LPBYTE)szRegistryResult, &baseLen) != ERROR_SUCCESS) {
68: bFoundItem = FALSE;
69: DLC_TRACE("DEBUG: RegQueryValueEx(…) failed. No Value found.");
70: } else {
71: DLC_TRACE("DEBUG: upto strcpy(outBuffer, szRegistryResult)");
72: strcpy(outBuffer, szRegistryResult);
73: }
74: }
75:
76: RegCloseKey(hKey);
77: DLC_TRACE("DEBUG: RegCloseKey(hKey)");
78:
79: return bFoundItem;
80: }
81:
82: // End Registry Stuff
83:
84: BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
85: {
86: /* Specify the types and order of notification */
87:
88: pVer->dwFlags = (SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_NONSECURE_PORT |
89: SF_NOTIFY_SECURE_PORT | SF_NOTIFY_URL_MAP);
90:
91: pVer->dwFilterVersion = pVer->dwServerFilterVersion;
92: strcpy(pVer->lpszFilterDesc, (LPCSTR)"IISHome version 1.0");
93: DLC_TRACE("DEBUG: Started IISHome");
94:
95: // Now Init Registry Values
96: if (GetRegistryKey("HomePath", pszHomePath) == FALSE) {
97: strcpy(pszHomePath, "C:\\Users\\%s\\%s");
98: }
99: if (GetRegistryKey("DebugEnabled", pszDebugEnabled) == FALSE) {
100: strcpy(pszDebugEnabled, "False");
101: }
102:
103: char dbgInfo[DEFAULT_BUFFER_SIZE];
104: sprintf(dbgInfo, "DEBUG: HomePath: %s DebugEnabled: %s", pszHomePath, pszDebugEnabled);
105: DLC_TRACE(dbgInfo);
106:
107: return TRUE;
108: }
109:
110: BOOL FileExists(char *fileName) {
111: return GetFileAttributes(fileName) != INVALID_FILE_ATTRIBUTES;
112: }
113:
114: BOOL DirectoryExists(char *fileName) {
115: return GetFileAttributes(fileName) == FILE_ATTRIBUTE_DIRECTORY;
116: }
117:
118: DWORD DoUrlRewriting(HTTP_FILTER_CONTEXT *pfc, HTTP_FILTER_URL_MAP *pMap)
119: {
120: char *s;
121: //unsigned int i; //allow conversion between size_t and int.
122: size_t i; // size_t is unsigned int. converting to int might cause loss of data.
123: DWORD dwRet = SF_STATUS_REQ_NEXT_NOTIFICATION;
124: /* Heres what we do:
125: 1) Strip /~
126: 2) Strip remaining /….. to get username alone.
127: 3) Set Path to C:\Users\<username\
128: 4) If any of the index files exist, strcat it on.
129: 5) Now strcpy the physical path to the new path, and pass a return value.
130: */
131:
132: if (pfc == NULL || !pMap)
133: {
134: return dwRet;
135: }
136:
137: char szPhysicalPath[DEFAULT_BUFFER_SIZE];
138: DWORD cbBuf = DEFAULT_BUFFER_SIZE;
139:
140: if (!pszHomePath || pMap->pszURL[0] != ‘/’ || pMap->pszURL[1] != ‘~’) {
141: char dbgInfo[DEFAULT_BUFFER_SIZE];
142: sprintf(dbgInfo, "DEBUG: Could not match URL: %s", pMap->pszURL);
143: DLC_TRACE(dbgInfo);
144: return dwRet;
145: }
146:
147: // only match /~, not /bleh/~user.
148: char dbgInfo[DEFAULT_BUFFER_SIZE];
149: sprintf(dbgInfo, "DEBUG: URL Matched: %s", pMap->pszURL);
150: DLC_TRACE(dbgInfo);
151:
152: strcpy(szUsername, (pMap->pszURL)+2);
153: if (s = strchr(szUsername, ‘/’)) {
154: *s = (char)0; // replace it with a null character.
155: s++;
156: sprintf(szPhysicalPath, pszHomePath, szUsername, s);
157: char dbgInfo[DEFAULT_BUFFER_SIZE];
158: sprintf(dbgInfo, "DEBUG: Preliminary Physical Path: %s", szPhysicalPath);
159: DLC_TRACE(dbgInfo);
160: } else {
161: // we have nothing after the last /, so its http://server/~user/
162: sprintf(szPhysicalPath, pszHomePath, szUsername, "");
163: char dbgInfo[DEFAULT_BUFFER_SIZE];
164: sprintf(dbgInfo, "DEBUG: Preliminary Physical Path: %s", szPhysicalPath);
165: DLC_TRACE(dbgInfo);
166: }
167:
168: for (s = szPhysicalPath; *s; s++) {
169: if (*s == ‘/’) {
170: *s = ‘\\’;
171: } // replace / with a backslash
172: }
173:
174: DLC_TRACE("DEBUG: Replaced Slashes");
175:
176: // replace last character with a null value.
177: if (szPhysicalPath[i=strlen(szPhysicalPath)-1] == ‘\\‘) {
178: szPhysicalPath[i] = (char)0;
179: DLC_TRACE("DEBUG: Replaced Nulls");
180: }
181:
182: // FindFirstFile is inefficient, we use GetFileAttributes inside DirectoryExists.
183: if (szIndexFiles && DirectoryExists(szPhysicalPath)) {
184: DLC_TRACE("DEBUG: DirectoryExists(szPhysicalPath)=TRUE & szIndexFiles defined");
185: if (szPhysicalPath[i=strlen(szPhysicalPath)-1] != ‘\\’) {
186: strcat(szPhysicalPath, "\\"), i++;
187: }
188:
189: for (int j = 0; j < 9; j++) {
190: char szFName[2048];
191: strcpy(szFName, szPhysicalPath);
192: strcat(szFName, szIndexFiles[j]);
193:
194: if (FileExists(szFName)) {
195: strcpy(szPhysicalPath, szFName);
196: char dbgInfo[DEFAULT_BUFFER_SIZE];
197: sprintf(dbgInfo, "DEBUG: Found: %s", szFName);
198: DLC_TRACE(dbgInfo);
199: break;
200: }
201: }
202: }
203:
204: if( strlen(szPhysicalPath) < pMap->cbPathBuff) {
205: strcpy(pMap->pszPhysicalPath, szPhysicalPath);
206: char dbgInfo[DEFAULT_BUFFER_SIZE];
207: sprintf(dbgInfo, "DEBUG: Final Path: %s", pMap->pszPhysicalPath);
208: DLC_TRACE(dbgInfo);
209: } else {
210: DlcReportEventA(EVENTLOG_INFORMATION_TYPE, (LPCSTR)"DEBUG: Couldnt remap URL - Not enough Memory");
211: }
212:
213: return dwRet;
214: }
215:
216: DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType,
217: VOID *pvData)
218: {
219: DWORD status = SF_STATUS_REQ_NEXT_NOTIFICATION;
220: switch (NotificationType)
221: {
222:
223: case SF_NOTIFY_URL_MAP:
224: status = DoUrlRewriting(pfc, (HTTP_FILTER_URL_MAP*)pvData);
225: break;
226: }
227: return status;
228: }
229:
230: bool DoInitialize(HMODULE hModule)
231: {
232: return true;
233: }
234:
235: BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
236: {
237: switch (ul_reason_for_call)
238: {
239: case DLL_PROCESS_ATTACH:
240: {
241: if (!DoInitialize(hModule))
242: {
243: return FALSE;
244: }
245: break;
246: }
247: case DLL_PROCESS_DETACH:
248: {
249: g_dwAppendBufferLen = 0;
250: }
251: break;
252: }
253: return TRUE;
254: }
255: #ifdef _MANAGED
256: #pragma managed(pop)
257: #endif