Gestione di localizzatori di risorse uniformi

Un localizzatore di risorse uniformi (URL) è una rappresentazione compatta della posizione e del metodo di accesso per una risorsa che si trova su Internet. Ogni URL è costituito da uno schema (HTTP, HTTPS o FTP) e una stringa specifica dello schema. Questa stringa può includere anche una combinazione di un percorso di directory, una stringa di ricerca o un nome della risorsa. Le funzioni WinINet consentono di creare, combinare, suddividere e canonizzare gli URL. Per altre informazioni sugli URL, vedere RFC-1738 on Uniform Resource Locators (URL).

Le funzioni URL operano in modo orientato all'attività. Il contenuto e il formato dell'URL assegnato alla funzione non viene verificato. L'applicazione chiamante deve tenere traccia dell'uso di queste funzioni per assicurarsi che i dati siano nel formato previsto. Ad esempio, la funzione InternetCanonicalizeUrl converte il carattere "%" nella sequenza di escape "%25" quando non usa flag. Se InternetCanonicalizeUrl viene usato nell'URL canonico, la sequenza di escape "%25" verrà convertita nella sequenza di escape "%2525", che non funziona correttamente.

Che cos'è un URL canonico?

Il formato di tutti gli URL deve seguire la sintassi e la semantica accettata per accedere alle risorse tramite Internet. La canonizzazione è il processo di formattazione di un URL per seguire questa sintassi e semantica accettata.

I caratteri che devono essere codificati includono qualsiasi carattere grafico corrispondente nel set di caratteri codificato us-ASCII (esadecimale 80-FF, che non vengono usati nel set di caratteri codificato us-ASCII e esadecimale 00-1F e 7F, che sono caratteri di controllo, spazi vuoti, "%" (che viene usato per codificare altri caratteri) e caratteri non sicuri (<, ># , {, }, |, ^, ~, [, ]e ').

Uso delle funzioni WinINet per gestire gli URL

La tabella seguente riepiloga le funzioni URL.

Funzione Descrizione
InternetCanonicalizeUrl Canonica l'URL.
InternetCombineUrl Combina URL di base e relativi.
InternetCrackUrl Analizza una stringa URL nei componenti.
InternetCreateUrl Crea una stringa URL dai componenti.
Internetopenurl Inizia a recuperare una risorsa FTP, HTTP o HTTPS.

 

URL canonici

La canonizzazione di un URL è il processo che converte un URL, che potrebbe contenere caratteri non sicuri, ad esempio spazi vuoti, caratteri riservati e così via, in un formato accettato.

La funzione InternetCanonicalizeUrl può essere usata per canonizzare gli URL. Questa funzione è molto orientata all'attività, quindi l'applicazione deve tenere traccia attentamente del relativo utilizzo. InternetCanonicalizeUrl non verifica che l'URL passato sia già canonico e che l'URL restituito sia valido.

I cinque flag seguenti controllano il modo in cui InternetCanonicalizeUrl gestisce un URL specifico. I flag possono essere usati in combinazione. Se non vengono usati flag, la funzione codifica l'URL per impostazione predefinita.

Valore Significato
ICU_BROWSER_MODE Non codificare o decodificare i caratteri dopo "#" o "?"e non rimuovere spazio vuoto finale dopo "?". Se questo valore non è specificato, l'intero URL viene codificato e lo spazio vuoto finale viene rimosso.
ICU_DECODE Convertire tutte le sequenze %XX in caratteri, incluse le sequenze di escape, prima dell'analisi dell'URL.
ICU_ENCODE_SPACES_ONLY Codifica solo spazi.
ICU_NO_ENCODE Non convertire caratteri non sicuri in sequenze di escape.
ICU_NO_META Non rimuovere le sequenze di meta , ad esempio "." e "..") dall'URL.

 

Il flag ICU_DECODE deve essere usato solo sugli URL canonici, perché presuppone che tutte le sequenze %XX siano codici di escape e li converte nei caratteri indicati dal codice. Se l'URL ha un simbolo "%" in esso che non fa parte di un codice di escape, ICU_DECODE lo considera ancora come uno. Questa caratteristica potrebbe causare la creazione di un URL non valido da InternetCanonicalizeUrl .

Per usare InternetCanonicalizeUrl per restituire un URL completamente decodificato, è necessario specificare i flag di ICU_DECODE e ICU_NO_ENCODE. Questa configurazione presuppone che l'URL passato a InternetCanonicalizeUrl sia stato precedentemente canonizzato.

Combinazione di URL di base e relativi

Un URL relativo è una rappresentazione compatta della posizione di una risorsa rispetto a un URL di base assoluto. L'URL di base deve essere noto al parser e in genere include lo schema, il percorso di rete e le parti del percorso URL. Un'applicazione può chiamare InternetCombineUrl per combinare l'URL relativo con il relativo URL di base. InternetCombineUrl canonizza anche l'URL risultante.

URL di cracking

La funzione InternetCrackUrl separa un URL nelle parti del componente e restituisce i componenti indicati dalla struttura URL_COMPONENTS passata alla funzione.

I componenti che costituiscono la struttura URL_COMPONENTS sono il numero di schema, il nome host, il numero di porta, il nome utente, la password, il percorso URL e altre informazioni ,ad esempio i parametri di ricerca. Ogni componente, tranne lo schema e i numeri di porta, ha un membro stringa che contiene le informazioni e un membro che contiene la lunghezza del membro stringa. Lo schema e i numeri di porta hanno solo un membro che archivia il valore corrispondente; vengono restituiti entrambi su tutte le chiamate riuscite a InternetCrackUrl.

Per ottenere il valore di un componente specifico nella struttura URL_COMPONENTS , il membro che archivia la lunghezza della stringa di tale componente deve essere impostata su un valore diverso da zero. Il membro stringa può essere l'indirizzo di un buffer o NULL.

Se il membro del puntatore contiene l'indirizzo di un buffer, il membro della lunghezza della stringa deve contenere le dimensioni del buffer. InternetCrackUrl restituisce le informazioni del componente come stringa nel buffer e archivia la lunghezza della stringa nel membro della lunghezza della stringa.

Se il membro del puntatore è NULL, il membro della lunghezza della stringa può essere impostato su qualsiasi valore diverso da zero. InternetCrackUrl archivia l'indirizzo del primo carattere della stringa URL contenente le informazioni del componente e imposta la lunghezza della stringa sul numero di caratteri nella parte rimanente della stringa URL che riguarda il componente.

Tutti i membri del puntatore impostati su NULL con un membro di lunghezza non zero puntano al punto di partenza appropriato nella stringa URL. La lunghezza archiviata nel membro di lunghezza deve essere usata per determinare la fine delle informazioni del singolo componente.

Per completare l'inizializzazione della struttura URL_COMPONENTS correttamente, il membro dwStructSize deve essere impostato sulle dimensioni della strutturaURL_COMPONENTS, in byte.

Nell'esempio seguente vengono restituiti i componenti dell'URL nella casella di modifica, IDC_PreOpen1 e restituisce i componenti nella casella di riepilogo, IDC_PreOpenList. Per visualizzare solo le informazioni per un singolo componente, questa funzione copia immediatamente il carattere dopo le informazioni del componente nella stringa e lo sostituisce temporaneamente con un valore NULL.

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <wininet.h>
#include <stdlib.h>

#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "user32.lib")

#define  CRACKER_BUFFER_SIZE           MAX_PATH

// For sample source code implementing the InternetErrorOut( ) 
// function referenced below, see the "Handling Errors" topic  
// under "Using WinInet"
extern BOOL WINAPI InternetErrorOut( HWND hWnd, DWORD dwError,
                                     LPCTSTR szFailingFunctionName );

// Forward declaration of listUrlPart helper functions:
BOOL listURLpart( HWND hDlg, int nListBoxID, 
                  LPTSTR szPartName, LPTSTR part, DWORD partLength );
BOOL listURLpart( HWND hDlg, int nListBoxID, 
                  LPTSTR szPartName, int partValue );

// Static list describing the URL Scheme types 
// enumerated in INTERNET_SCHEME:
TCHAR* schemeType[] =
{
  TEXT( "[Partial URL]" ),                //  0
  TEXT( "[Unknown scheme]" ),             //  1
  TEXT( "[Default scheme]" ),             //  2
  TEXT( "FTP" ),                          //  3
  TEXT( "Gopher" ),                       //  4
  TEXT( "HTTP" ),                         //  5
  TEXT( "HTTPS" ),                        //  6
  TEXT( "File" ),                         //  7
  TEXT( "News" ),                         //  8
  TEXT( "MailTo" ),                       //  9
  TEXT( "Socks" ),                        // 10
  TEXT( "JavaScript" ),                   // 11
  TEXT( "VBScript" )                      // 12
};
#define  CRACKER_SCHEME_TYPE_ARRAY_SIZE      13

BOOL WINAPI Cracker( HWND hDlg, int nURLtextBoxId, int nListBoxId )
{
   int i, j;
   TCHAR* failedFunctionName;
   TCHAR URL_buffer[CRACKER_BUFFER_SIZE];

   URL_COMPONENTS URLparts;

   URLparts.dwStructSize = sizeof( URLparts );

   // The following elements determine which components are displayed
   URLparts.dwSchemeLength    = 1;
   URLparts.dwHostNameLength  = 1;
   URLparts.dwUserNameLength  = 1;
   URLparts.dwPasswordLength  = 1;
   URLparts.dwUrlPathLength   = 1;
   URLparts.dwExtraInfoLength = 1;

   URLparts.lpszScheme     = NULL;
   URLparts.lpszHostName   = NULL;
   URLparts.lpszUserName   = NULL;
   URLparts.lpszPassword   = NULL;
   URLparts.lpszUrlPath    = NULL;
   URLparts.lpszExtraInfo  = NULL;

   SendDlgItemMessage( hDlg, nListBoxId, LB_RESETCONTENT, 0, 0 );
   if( !GetDlgItemText( hDlg, nURLtextBoxId, 
                        URL_buffer, CRACKER_BUFFER_SIZE ) )
   {
       failedFunctionName = TEXT( "GetDlgItemText" );
       goto CrackerError_01;
   }

   if( FAILED( StringCchLength( URL_buffer, CRACKER_BUFFER_SIZE, 
                                (size_t*) &i ) ) )
   {
       failedFunctionName = TEXT( "StringCchLength" );
       goto CrackerError_01;
   }

   if( !InternetCrackUrl( URL_buffer, (DWORD)_tcslen( URL_buffer ), 0, 
                          &URLparts ) )
   {
       failedFunctionName = TEXT( "InternetCrackUrl" );
       goto CrackerError_01;
   }

   failedFunctionName = TEXT( "listURLpart" );

   i = URLparts.nScheme + 2;
   if( ( i >= 0 ) && ( i < CRACKER_SCHEME_TYPE_ARRAY_SIZE ) )
   {
       StringCchLength( schemeType[i], 
                        CRACKER_BUFFER_SIZE, 
                        (size_t*) &j );
       if( !listURLpart( hDlg, nListBoxId, 
                         TEXT("Scheme type"), 
                         schemeType[i], j ))
           goto CrackerError_01;
   }

   if( !listURLpart( hDlg, nListBoxId, TEXT( "Scheme text" ), 
                     URLparts.lpszScheme, 
                     URLparts.dwSchemeLength ) ||
       !listURLpart( hDlg, nListBoxId, TEXT( "Host name" ), 
                     URLparts.lpszHostName, 
                     URLparts.dwHostNameLength) ||
       !listURLpart( hDlg, nListBoxId, TEXT( "Port number" ), 
                     (int) URLparts.nPort ) ||
       !listURLpart( hDlg, nListBoxId, TEXT( "User name" ), 
                     URLparts.lpszUserName, 
                     URLparts.dwUserNameLength) ||
       !listURLpart( hDlg, nListBoxId, TEXT( "Password" ), 
                     URLparts.lpszPassword, 
                     URLparts.dwPasswordLength) ||
       !listURLpart( hDlg, nListBoxId, TEXT( "Path" ), 
                     URLparts.lpszUrlPath, 
                     URLparts.dwUrlPathLength) ||
       !listURLpart( hDlg, nListBoxId, TEXT( "Extra information"), 
                     URLparts.lpszExtraInfo, 
                     URLparts.dwExtraInfoLength))
           goto CrackerError_01;

   return( TRUE );

CrackerError_01:
// For sample source code of the InternetErrorOut( ) function 
// referenced below, see the "Handling Errors" 
// topic under "Using WinInet"
   InternetErrorOut( hDlg, GetLastError( ), failedFunctionName );
   return FALSE;
}

// listURLpart( ) helper function for string parts
BOOL listURLpart( HWND hDlg, int nListBoxId, 
                  LPTSTR szPartName, LPTSTR part, DWORD partLength )
{
  TCHAR outputBuffer[CRACKER_BUFFER_SIZE];
  LPTSTR nextStart;
  size_t nextSize;

  if( partLength == 0 )  // Just skip empty ones
    return( TRUE );

  if( FAILED( StringCchCopyEx( outputBuffer, 
                              (size_t) CRACKER_BUFFER_SIZE,
                               szPartName, &nextStart, 
                               &nextSize, 0 ) ) ||
      FAILED( StringCchCopyEx( nextStart, nextSize, TEXT( ": " ), 
                               &nextStart, &nextSize, 0 ) ) ||
      FAILED( StringCchCopyNEx( nextStart, nextSize, part, 
                                (size_t) partLength,
                                &nextStart, &nextSize, 0 ) ) )
    return( FALSE );

  *nextStart = 0;
  if( SendDlgItemMessage( hDlg, nListBoxId, LB_ADDSTRING, 0, 
                          (LPARAM)outputBuffer ) < 0 )
    return( FALSE );
  return( TRUE );
}

// listURLpart( ) helper function for numeric parts
BOOL listURLpart( HWND hDlg, int nListBoxId, 
                  LPTSTR szPartName, int partValue )
{
  TCHAR outputBuffer[CRACKER_BUFFER_SIZE];

  if( FAILED( StringCchPrintf( outputBuffer, 
                               (size_t) CRACKER_BUFFER_SIZE,
                               TEXT( "%s: %d" ), szPartName, 
                               partValue ) ) ||
      ( SendDlgItemMessage( hDlg, nListBoxId, LB_ADDSTRING, 0, 
                            (LPARAM)outputBuffer ) < 0 ) )
    return( FALSE );
  return( TRUE );
}

Creazione di URL

La funzione InternetCreateUrl usa le informazioni nella struttura URL_COMPONENTS per creare un localizzatore di risorse uniforme.

I componenti che costituiscono la struttura URL_COMPONENTS sono lo schema, il nome host, il numero di porta, il nome utente, la password, il percorso URL e altre informazioni (ad esempio i parametri di ricerca). Ogni componente, ad eccezione del numero di porta, ha un membro stringa che contiene le informazioni e un membro che contiene la lunghezza del membro stringa.

Per ogni componente necessario, il membro del puntatore deve contenere l'indirizzo del buffer che contiene le informazioni. Il membro di lunghezza deve essere impostato su zero se il membro puntatore contiene l'indirizzo di una stringa con terminazione zero; Il membro di lunghezza deve essere impostato sulla lunghezza della stringa se il membro del puntatore contiene l'indirizzo di una stringa non terminata zero. Il membro puntatore di tutti i componenti che non sono necessari deve essere NULL.

Accesso diretto agli URL

Le risorse FTP e HTTP su Internet possono essere accessibili direttamente usando le funzioni InternetOpenUrl, InternetReadFile e InternetFindNextFile. InternetOpenUrl apre una connessione alla risorsa all'URL passato alla funzione. Quando questa connessione viene effettuata, sono disponibili due passaggi possibili. Prima di tutto, se la risorsa è un file, InternetReadFile può scaricarla; in secondo luogo, se la risorsa è una directory, InternetFindNextFile può enumerare i file all'interno della directory (tranne quando si usano proxy CERN). Per altre informazioni su InternetReadFile, vedere Lettura di file. Per altre informazioni su InternetFindNextFile, vedere Ricerca del file successivo.

Per le applicazioni che devono funzionare tramite un proxy CERN, InternetOpenUrl può essere usato per accedere a directory e file FTP. Le richieste FTP vengono visualizzate come una richiesta HTTP, che il proxy CERN accetterebbe.

InternetOpenUrl usa l'handle HINTERNET creato dalla funzione InternetOpen e l'URL della risorsa. L'URL deve includere lo schema (http:, ftp:, file: [per un file locale]o https: [per il protocollo hypertext sicuro]) e percorso di rete (ad esempio www.microsoft.com). L'URL può includere anche un percorso, ad esempio /isapi/gomscom.asp? TARGET=/windows/feature/) e nome risorsa (ad esempio, default.htm). Per le richieste HTTP o HTTPS, è possibile includere intestazioni aggiuntive.

InternetQueryDataAvailable, InternetFindNextFile, InternetReadFile e InternetSetFilePointer (SOLO URL HTTP o HTTPS) possono usare l'handle creato da InternetOpenUrl per scaricare la risorsa.

Il diagramma seguente illustra quali handle usare con ogni funzione.

handle da usare con le funzioni

L'handle XAMLNET radice creato da InternetOpen viene usato da InternetOpenUrl. L'handle HINTERNET creato da InternetOpenUrl può essere usato solo da InternetQueryDataAvailable, InternetReadFile, InternetFindNextFile (non illustrato qui) e InternetSetFilePointer (SOLO URL HTTP o HTTPS).

Per altre informazioni, vedere Handle DI HINTERNET.

Nota

WinINet non supporta le implementazioni del server. Inoltre, non deve essere usato da un servizio. Per le implementazioni o i servizi server usano Microsoft Windows HTTP Services (WinHTTP).