Condividi tramite


Esempio: Modulo di filigrana immagine

di Fabio Yeon

Questo è un esempio di come scrivere un modulo nativo (C++) che inserisce dinamicamente una filigrana configurata dall'utente in un'immagine in esecuzione, nonché come estendere la configurazione e lo strumento dell'interfaccia utente inetmgr per fornire un'amministrazione semplice del nuovo modulo.

Il modulo filigrana ha le funzionalità seguenti:

  • Può essere abilitato/disabilitato a qualsiasi livello di configurazione (ad esempio sito, applicazione, directory virtuale e così via).
  • Può filigrana i formati di immagine JPG, GIF e PNG.
  • L'immagine filigrana può essere di formato JPG, GIF o PNG. L'immagine filigrana non deve essere lo stesso tipo dell'immagine da filigrana (ad esempio, un'immagine di filigrana GIF può essere usata per filigrana per filigrana di una richiesta di immagine PNG).
  • È possibile configurare la posizione dell'immagine filigrana ("superiore sinistra", "superiore destra", "inferiore sinistra", "inferiore destra", "centro", nonché le opzioni di "riquadro" e "stretch"). Solo l'opzione "stretch" modifica/modifica l'immagine della filigrana se necessario.
  • È anche possibile selezionare il livello di trasparenza dell'immagine di filigrana, da 0 a 100%.

Per compilare l'esempio, è necessario installare Platform SDK per Windows Vista o Windows Server 2008. Il file di progetto incluso nell'esempio può essere caricato in Visual Studio 2005 o 2008.

Il codice sorgente per questi esempi è disponibile qui.

Modulo filigrana

Il primo componente di questo esempio è il modulo filigrana stesso. Si tratta di un modulo C++ nativo che controlla come richieste vengono gestite e se il tipo MIME della richiesta indica che è un'immagine, verrà applicata dinamicamente una filigrana configurata dall'utente all'immagine e sostituirà l'immagine in uscita. Questa operazione viene eseguita in modo trasparente in un modulo eseguito dopo il gestore della richiesta. Per illustrarlo:

Diagramma che mostra un albero delle decisioni dal gestore delle richieste al marcatore Image Water. Se è presente un'immagine dal gestore richieste, viene inviata una nuova immagine, in caso contrario l'immagine originale viene inviata.

  1. La logica del codice è piuttosto semplice:
  2. Quando il modulo viene prima caricato, registra per l'evento post-RQ_EXECUTE_REQUEST_HANDLER, che indica al sistema che vuole ricevere una notifica subito dopo l'esecuzione del gestore della richiesta.
  3. Ora, quando viene attivato l'evento post-RQ_EXECUTE_REQUEST_HANDLER, recupera la configurazione per il percorso. Se non è abilitato, non farà altro per la richiesta e il salvataggio.
  4. Se è abilitata, controlla l'intestazione di risposta "Content-Type" e verifica se è un tipo di immagine. In caso contrario, verrà salvata.
  5. Se si tratta di un'immagine, verrà visualizzato se la risposta è un buffer o un handle di file. Se è il successivo, carica l'immagine in memoria, applica la filigrana in base alle impostazioni configurate dall'utente (ad esempio file di immagine, posizione, trasparenza), salva l'immagine risultante in un buffer in memoria, sostituisci i dati di risposta con il buffer in memoria e restituisce.
  6. Il buffer in memoria verrà rilasciato nel metodo "Dispose" del modulo.

L'uso delle classi CImage di ATL semplifica il caricamento e l'elaborazione dell'immagine, soprattutto perché può modificare facilmente vari formati di immagine.

Ora, in questo esempio sono presenti alcuni avvisi e deve essere considerato, soprattutto se si vuole usarlo in un ambiente di produzione "reale":

  • Il codice funziona solo per i tipi di immagine in cui la risposta si trova in un handle di file. L'oggetto HTTP_RESPONSE può invece contenere l'immagine in una serie di buffer. Un esercizio interessante consiste nel creare un'implementazione IStream in memoria che esegue il wrapping dei buffer nell'oggetto risposta (watch out per le risposte a più buffer!).
  • Il modulo non tenta di modificare o aggiornare l'intestazione di risposta "ETag". Ciò significa che l'immagine con filigrana risultante verrà considerata l'immagine "reale" per quanto riguarda il client (come dovrebbe), ma può anche confondere la logica di memorizzazione nella cache del client. Un'implementazione corretta di questa operazione deve modificare "ETag" per tenere conto della configurazione dell'immagine con filigrana. Ad esempio, nell'implementazione corrente, se si è filigranata un'immagine con "WatermarkFileA" nella posizione "UpperLeft" con una trasparenza "50%" e quindi è stata effettuata una richiesta con un browser (ad esempio Internet Explorer), IE memorizza nella cache tale immagine in base alle varie intestazioni di risposta. Se si modifica la configurazione del modulo filigrana (ad esempio, è stata modificata l'immagine, la posizione o la trasparenza) e richiesto di nuovo il file (tramite "F5"), perché l'immagine è stata memorizzata nella cache da Internet Explorer, anziché richiedere l'immagine, semplicemente eseguire una richiesta "HEAD", inviando le informazioni relative all'immagine. Il gestore della richiesta, non sapendo che l'immagine è stata modificata, risponderà che la risposta inviata in precedenza è ancora valida e terminare l'elaborazione della richiesta. Sfortunatamente, in questo caso, il modulo filigrana non avrà la possibilità di eseguire e rigrangranare l'immagine con la nuova configurazione, quindi il client continuerà a mostrare l'immagine con filigrana precedente. Una correzione corretta per questo avrebbe il modulo filigrana in qualche modo incorporare la relativa configurazione nella risposta "ETag" in modo che eventuali modifiche apportate all'immagine o al modulo filigrana causeranno un'invalidazione di qualsiasi immagine memorizzata nella cache del client e rielaborazione di esso.

Configurazione

La configurazione del modulo filigrana viene eseguita tramite una nuova sezione nello spazio dei nomi "system.webServer". Il file dello schema è il seguente:

<configSchema> 
 <sectionSchema name="system.webServer/watermark"> 
  <attribute name="enabled" type="bool" defaultValue="false" /> 
  <attribute name="watermarkImage" type="string" /> 
  <attribute name="transparency" type="uint" defaultValue="50" validationType="integerRange" validationParameter="0,100" /> 
  <attribute name="position" type="enum" defaultValue="LowerRight" > 
    <enum name="UpperLeft" value="0" /> 
    <enum name="UpperRight" value="1" /> 
    <enum name="LowerLeft" value="2" /> 
    <enum name="LowerRight" value="3" /> 
    <enum name="Center" value="4" /> 
    <enum name="Stretch" value="5" /> 
    <enum name="Tile" value="6" /> 
  </attribute> 
 </sectionSchema> 
</configSchema>

Il file "watermark.xml" deve essere eliminato nella directory per l'effetto, nonché l'aggiunta della definizione di sezione nel %windir%\system32\inetsrv\config\schema file "applicationhost.config", nello spazio dei nomi "system.webServer":

<section name="Watermark" overrideModeDefault="Allow" />

Per usare il modulo, è quindi necessario installare il modulo nell'elenco di moduli globali "system.webServer\globalModules":

<add name="WatermarkModule" image="c:\Watermark\Watermark.dll" />

All'elenco dei moduli per l'applicazione, "system.webServer\modules":

<add name="WatermarkModule" />

Inetmgr

Insieme all'esempio di modulo, è un set di classi gestite che sono plug-in di gestione al nuovo strumento di amministrazione dell'interfaccia utente "Inetmgr". Sono disponibili varie altre documentazioni su come scrivere ed estendere il nuovo "Inetmgr", disponibile qui. In breve, per usarli, è necessario compilare, aggiungere le dll alla GAC (Global Assembly Cache) e aggiungere la configurazione seguente al %windir%\system32\inetsrv\config\administration.config file:

Nell'insieme <moduleProviders> aggiungere la voce seguente:

<add name="Watermark" type="WatermarkServer.WatermarkModuleProvider, Watermarkserver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5f6f8f3f74d67fe4" />

Aggiungere la riga seguente alla <modules> raccolta:

<add name="Watermark" />

Riavviare lo strumento e una nuova icona deve essere disponibile nel sito.