Domanda

Ho scritto questo filtro ISAPI per riscrivere l'URL perché abbiamo avuto alcuni siti che si muovevano luoghi ... Fondamentalmente il filtro guarda il referrer, e se è il server locale, esamina l'URL richiesto e confrontato in abbondanza referrer. Se il primo percorso è identico, non si fa nulla, se non, prende il primo percorso dal pieno referrer e antepone alla URL. Per esempio: /Content/imgs/img.jpg da un referrer di http: // myserver / WR / apps /Default.htm sarebbe essere riscritta come /wr/Content/imgs/img.jpg.

Quando osservo il file di registro, tutto sembra a posto. Tuttavia la DLL mantiene ha provocato l'errore con le seguenti informazioni:. Errore applicazione w3wp.exe, versione 6.0.3790.3959, ha provocato l'errore modulo URLRedirector.dll, la versione 0.0.0.0, indirizzo errore 0x0002df25

Ecco il codice:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <httpfilt.h>
#include <time.h>
#include <string.h>


#ifdef _DEBUG
#define TO_FILE  // uncomment out to use a log file
#ifdef TO_FILE
#define DEST ghFile
#define DebugMsg(x) WriteToFile x;
HANDLE ghFile;
#define LOGFILE "W:\\Temp\\URLRedirector.log"
void WriteToFile (HANDLE hFile, char *szFormat, ...) {
    char szBuf[1024];
    DWORD dwWritten;
    va_list list;
    va_start (list, szFormat);
    vsprintf (szBuf, szFormat, list);
    hFile = CreateFile (LOGFILE, GENERIC_WRITE, 
                        0, NULL, OPEN_ALWAYS, 
                        FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        SetFilePointer (hFile, 0, NULL, FILE_END);
        WriteFile (hFile, szBuf, lstrlen (szBuf), &dwWritten, NULL);
        CloseHandle (hFile);
    }
    va_end (list);
}
#endif
#endif

BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
    /* Specify the types and order of notification */

    pVer->dwFlags = (SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT
                     | SF_NOTIFY_PREPROC_HEADERS | SF_NOTIFY_END_OF_NET_SESSION);

    pVer->dwFilterVersion = HTTP_FILTER_REVISION;

    strcpy(pVer->lpszFilterDesc, "URL Redirector, Version 1.0");

    return TRUE;
}

DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData)
{
    CHAR *pPhysPath;
    PHTTP_FILTER_URL_MAP pURLMap;
    PHTTP_FILTER_PREPROC_HEADERS pHeaderInfo;
    CHAR szReferrer[255], szServer[255], szURL[255], szNewURL[255];
    DWORD dwRSize = sizeof(szReferrer);
    DWORD dwSSize = sizeof(szServer);
    DWORD dwUSize = sizeof(szURL);
    int iTmp, iTmp2;
    CHAR *pos, tmp[255], *tmp2;

    switch (NotificationType) {

        case SF_NOTIFY_PREPROC_HEADERS :
            pHeaderInfo = (PHTTP_FILTER_PREPROC_HEADERS)pvData;

            if (pfc->GetServerVariable(pfc, "HTTP_REFERER", szReferrer, &dwRSize))
            {
                DebugMsg(( DEST,
                           "Referrer: %s\r\n", szReferrer ));

                if (pfc->GetServerVariable(pfc, "SERVER_NAME", szServer, &dwSSize))
                    DebugMsg(( DEST,
                               "Server Name: %s\r\n", szServer ));

                if (pHeaderInfo->GetHeader(pfc, "URL", szURL, &dwUSize))
                    DebugMsg(( DEST,
                               "URL: %s\r\n", szURL ));

                iTmp = strnstr(szReferrer, szServer, strlen(szReferrer));
                if(iTmp > 0)
                {
                    //Referred is our own server...
                    strcpy(tmp, szReferrer + iTmp);
                    DebugMsg(( DEST,
                               "tmp: %s - %d\r\n", tmp, strlen(tmp) ));
                    pos = strchr(tmp+1, '/');
                    DebugMsg(( DEST,
                               "pos: %s - %d\r\n", pos, strlen(pos) ));

                    iTmp2 = strlen(tmp) - strlen(pos) + 1;

                    strncpy(tmp2, tmp, iTmp2);
                    tmp2[iTmp2] = '\0';
                    DebugMsg(( DEST,
                               "tmp2: %s\r\n", tmp2));

                    if(strncmp(szURL, tmp2, iTmp2) != 0)
                    {
                        //First paths don't match, create new URL...
                        strncpy(szNewURL, tmp2, iTmp2-1);
                        strcat(szNewURL, szURL);
                        DebugMsg(( DEST,
                                   "newURL: %s\r\n", szNewURL));
                        pHeaderInfo->SetHeader(pfc, "URL", szNewURL);
                        return SF_STATUS_REQ_HANDLED_NOTIFICATION;
                    }
                }
            }

            break;

        default :

            break;    
    }

    return SF_STATUS_REQ_NEXT_NOTIFICATION;
}


/* simple function to compare two strings and return the position at which the compare ended */
static int strnstr ( const char *string, const char *strCharSet, int n)
{
    int len = (strCharSet  != NULL ) ? ((int)strlen(strCharSet )) : 0 ;
    int ret, I, J, found;

    if ( 0 == n || 0 == len )
    {
        return -1;
    }

    ret = -1;
    found = 0;
    for (I = 0 ; I <= n - len && found != 1 ; I++)
    {
        J = 0 ;
        for ( ; J < len ; J++ )
        {
            if (toupper(string[I + J]) != toupper(strCharSet [J]))
            {
                break; // Exit For(J)
            }
        }

        if ( J == len)
        {
            ret = I + (J);
            found = 1;
        } 
    }

    return ret;
}
È stato utile?

Soluzione

So che stai chiedendo una questione di programmazione, ma si potrebbe evitare il tutto abbandonando lo sforzo di scrivere un filtro ISAPI, e di utilizzare invece un off-the-shelf uso generale masterizzatore, come IIRF .

Questa è la regola che avrebbe fatto ciò che si vuole:

RewriteCond %{HTTP_REFERER} ^http://localserver/([^/]+)/etc/etc$
RewriteCond $1              !*1
RewriteRule ^/([^/]+)/([^/]+)\.(jpg|gif|png)$    /*1/$1/$2.$3    [L]

Altri suggerimenti

Se davvero si vuole scrivere e mantenere un filtro ISAPI personalizzato, consiglio vivamente due cose:

  1. Debug utilizzando Visual Studio
    .
    Se il problema è riproducibile, utilizzare Visual Studio o un altro debugger per connettersi a w3wp.exe al fine di catturare l'eccezione. Quello che dovete fare è iniziare IIS ed eseguire una richiesta attraverso di essa, in modo che il filtro viene caricato. Assicurarsi che il file PDB per la DLL è co-location con la DLL.
    .
    Allora avete bisogno di avviare Visual Studio, quindi connettersi al processo w3wp.exe all'interno del debugger. Quindi eseguire la richiesta che conduce al guasto. All'interno di Visual Studio, il debugger vi mostrerà l'esatta linea che porta al problema.

  2. Usa StackWalker
    .
    Se il problema non è affidabile e riproducibile, avrete bisogno di organizzare per registrare il dump stack, compresi i numeri di riga, quando il problema non si verificano, al fine di aiutare la diagnosi di esso. Per questo utilizzare il Stackwalker progetto CodePlex. Quando si verifica l'eccezione, il tuo ISAPI può scaricare lo stack di chiamate in un file di log, che consente di individuare poi la riga nel codice che porta al guasto.

Un potenziale problema è che se szReferrer e szServer sono gli esatti valori stessi (non so se questo è possibile). Ma se dovesse accadere, allora strnstr restituisce la lunghezza del valore di stringa. In altre parole, restituisce la lunghezza della prima stringa. In tale situazione, lo strcpy in tmp Credo che mette solo un byte di terminazione pari a zero in tmp. Il seguente strchr(tmp+1, ‘/’); ha quindi un comportamento indefinito. Il valore restituito da esso potrebbe essere qualsiasi cosa (si potrebbe infatti causare una violazione di accesso perché potrebbe leggere oltre memoria che si suppone). Le cose potrebbero cadere a pezzi dopo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top