|
Imports System
Imports System.Collections
Imports System.Configuration
Imports System.Security.Cryptography
Imports System.Security.Principal
Imports System.Text
Imports System.Web
Imports System.Security.Cryptography.X509Certificates
Imports Microsoft.Build.Tasks.Deployment.ManifestUtilities
Imports System.IO
Imports System.Web.Security
Public Class ClickOnceApplicationHandler
Implements IHttpHandler
#Region " Configuration"
Public Shared ReadOnly Property AppManifestName() As String
Get
Return GetConfigSetting("AppManifestName")
End Get
End Property
Public Shared ReadOnly Property PathToManifest() As String
Get
Return GetConfigSetting("PathToManifest")
End Get
End Property
Public Shared ReadOnly Property SiteRoot() As String
Get
Return GetConfigSetting("SiteRoot")
End Get
End Property
Public Shared ReadOnly Property CertFilePath() As String
Get
Return GetConfigSetting("CertFilePath")
End Get
End Property
Private Shared Function GetConfigSetting(ByVal pSettingName As String) As String
Dim _val As String = System.Configuration.ConfigurationManager.AppSettings.Item(pSettingName)
If _val Is Nothing Then
Throw New Exception("Missing configuration setting: " & pSettingName)
End If
Return _val
End Function
#End Region
Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
Return True
End Get
End Property
''' <summary>
''' Make a temp directory to hold the updated manifest while we sign it.
''' </summary>
''' <param name="pContext"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function MakeTempDir(ByVal pContext As HttpContext, ByVal pXbapFilePath As String) As String
Dim _path As String = System.IO.Path.GetTempPath
Dim _guid As Guid = Guid.NewGuid
Dim _XbapFileName As String = Path.GetFileName(pXbapFilePath)
_path = System.IO.Path.Combine(_path, _guid.ToString)
System.IO.Directory.CreateDirectory(_path)
System.IO.File.Copy(pXbapFilePath, System.IO.Path.Combine(_path, _XbapFileName))
Return _path
End Function
''' <summary>
''' Generate the xbap that contains the cookie-less authentication session information.
''' </summary>
''' <param name="pContext">The HttpContext for the request.</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GenerateXbap(ByVal pContext As HttpContext, ByVal pXbapFilePath As String) As String
Dim _path As String = MakeTempDir(pContext, pXbapFilePath)
Dim _fpath As String = Path.Combine(_path, Path.GetFileName(pXbapFilePath))
Dim fest As DeployManifest = CType(ManifestReader.ReadManifest(_fpath, False), DeployManifest)
'This should really get pulled from the machine store, based on a thumbprint from the web.config
SignAndSave(fest, CertFilePath, "", pContext)
Return _fpath
End Function
''' <summary>
''' Entry point for the handler, here we determine if we are dealing with the xbap, and modify its values and resign.
''' </summary>
''' <param name="context"></param>
''' <remarks></remarks>
Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim _path As String = context.Server.MapPath(context.Request.Path).ToLower
If IO.File.Exists(_path) Then
If _path.EndsWith(".xbap") Then
'Set the correct mime type for xbap
context.Response.ContentType = "application/x-ms-xbap"
'Update the xbap with the cookieless authentication session information
Dim _file As String = GenerateXbap(context, _path)
'Write the updated file to the response
context.Response.WriteFile(_file)
context.Response.Flush()
'Clean up the temporary file that has been generated.
Directory.Delete(Path.GetDirectoryName(_file), True)
End If
Else
Throw New HttpException(404, "File not found")
End If
End Sub
Public Shared Sub SignAndSave(ByVal pDeploy As DeployManifest, ByVal pCertPath As String, ByVal pPassword As String, ByVal pContext As HttpContext)
' Update the deployment manifest
UpdateDeployManifestAppReference(pDeploy, pContext)
' Write the deployment manifest
ManifestWriter.WriteManifest(pDeploy)
' Sign the deployment manifest
SignManifest(pDeploy, pCertPath, pPassword)
End Sub
Public Shared Sub SignManifest(ByVal manifest As Manifest, ByVal certFilePath As String, ByVal password As String)
' Make sure the entered cert file exists
If (File.Exists(certFilePath)) Then
' Construct cert object for cert
Dim cert As System.Security.Cryptography.X509Certificates.X509Certificate2
If (String.IsNullOrEmpty(password)) Then
cert = New System.Security.Cryptography.X509Certificates.X509Certificate2(certFilePath)
Else
cert = New System.Security.Cryptography.X509Certificates.X509Certificate2(certFilePath, password)
End If
SecurityUtilities.SignFile(cert, Nothing, manifest.SourcePath)
Else
Throw New ArgumentException("Invalid certificate file path")
End If
End Sub
Public Shared Sub UpdateDeployManifestAppReference(ByVal depManifest As DeployManifest, ByVal pContext As HttpContext)
Dim deployManifestPath As String = Path.GetDirectoryName(depManifest.SourcePath)
'This should be the AssemblyReference for our main application manifest
Dim _assemRef As AssemblyReference = depManifest.EntryPoint
'Get the cookie value to use for the cookieless authentication.
Dim _val As String = pContext.Request.Cookies.Item(FormsAuthentication.FormsCookieName).Value
'Update the target path in the deployment manifest, this path will get reused for all the subsequent requests clickonce makes.
_assemRef.TargetPath = String.Format("{0}(X(1)F({1})){2}{3}", SiteRoot, _val, PathToManifest, AppManifestName)
End Sub
End Class
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.