Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
SimpleHTTPserver - Mainform.vb

Mainform.vb

Caricato da: GN
Scarica il programma completo

  1. Imports System.Net
  2. Imports System.Threading
  3.  
  4. Public Class Mainform
  5.     Dim percentEncoding As New Dictionary(Of String, String)
  6.     Dim server As HttpListener
  7.     Dim listenerThread As Thread
  8.     Dim requestsThreads As New List(Of Thread)
  9.  
  10. #Region "Settings"
  11.     Dim port As Integer = 8080
  12.     Dim wwwRoot As String = Application.StartupPath & "\www"
  13.     Dim onlyLocal As Boolean = True
  14.     Dim defDirRes_file As String = ""
  15.     Dim defDirRes_fileIfNotFoundList As Boolean = True
  16. #End Region
  17.  
  18. #Region "Form events"
  19.  
  20.     Sub New()
  21.         InitializeComponent()
  22.         percentEncoding.Add("%20", " ")
  23.         percentEncoding.Add("%21", "!")
  24.         percentEncoding.Add("%23", "#")
  25.         percentEncoding.Add("%24", "$")
  26.         percentEncoding.Add("%26", "&")
  27.         percentEncoding.Add("%27", "'")
  28.         percentEncoding.Add("%28", "(")
  29.         percentEncoding.Add("%29", ")")
  30.         percentEncoding.Add("%2A", "*")
  31.         percentEncoding.Add("%2B", "+")
  32.         percentEncoding.Add("%2C", ",")
  33.         percentEncoding.Add("%2F", "/")
  34.         percentEncoding.Add("%3A", ":")
  35.         percentEncoding.Add("%3B", ";")
  36.         percentEncoding.Add("%3D", "=")
  37.         percentEncoding.Add("%3F", "?")
  38.         percentEncoding.Add("%40", "@")
  39.         percentEncoding.Add("%5B", "[")
  40.         percentEncoding.Add("%5D", "]")
  41.         percentEncoding.Add("%7B", "{")
  42.         percentEncoding.Add("%7D", "}")
  43.     End Sub
  44.  
  45.     Private Sub Mainform_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  46.         Dim cl As ObjectModel.ReadOnlyCollection(Of String) = My.Application.CommandLineArgs
  47.         Dim autoOpenLocalhost As Boolean = False
  48.         If cl.Count > 0 Then
  49.             Try
  50.                 port = CInt(cl(0))
  51.                 If port < 0 Or port > 65535 Then
  52.                     appendLog("Invalid command line argument: port must be an integer between 0 and 65535.")
  53.                     port = 8080
  54.                 End If
  55.             Catch ex As Exception
  56.                 appendLog("Invalid command line argument: port must be an integer.")
  57.                 port = 8080
  58.             End Try
  59.             If cl.Count > 1 Then
  60.                 wwwRoot = cl(1)
  61.                 validateDir()
  62.                 If cl.Count > 2 Then
  63.                     Try
  64.                         onlyLocal = CBool(cl(2))
  65.                     Catch ex As Exception
  66.                         appendLog("Invalid command line argument: the third argument (only local requests accepting) must be a boolean value (""true"" or ""false"")")
  67.                     End Try
  68.                     If cl.Count > 3 Then
  69.                         Try
  70.                             If CBool(cl(3)) Then
  71.                                 autoOpenLocalhost = True
  72.                             End If
  73.                         Catch ex As Exception
  74.                             appendLog("Invalid command line argument: the third argument (opening localhost) must be a boolean value (""true"" or ""false"")")
  75.                         End Try
  76.                     End If
  77.                 End If
  78.             End If
  79.         End If
  80.         Control.CheckForIllegalCrossThreadCalls = False
  81.         showOptions()
  82.         startServ(autoOpenLocalhost)
  83.     End Sub
  84.  
  85.     Private Sub Mainform_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
  86.         e.Cancel = Not stopServ()
  87.     End Sub
  88.  
  89.     Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
  90.         startServ()
  91.     End Sub
  92.  
  93.     Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
  94.         stopServ()
  95.     End Sub
  96.  
  97.     Private Sub btnOptions_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOptions.Click
  98.         Dim ops As New Options(port, wwwRoot, onlyLocal, defDirRes_file, defDirRes_fileIfNotFoundList)
  99.         If ops.ShowDialog() = Windows.Forms.DialogResult.OK Then
  100.             port = ops.portValue.Value
  101.             wwwRoot = ops.dirValue.Text
  102.             onlyLocal = ops.onlyLocalValue.Checked
  103.             If ops.defDirResListing.Checked Then
  104.                 defDirRes_file = ""
  105.                 defDirRes_fileIfNotFoundList = True
  106.             Else
  107.                 defDirRes_file = ops.defDirResFileValue.Text
  108.                 defDirRes_fileIfNotFoundList = ops.defDirResFileIfNotFoundListing.Checked
  109.             End If
  110.             validateDir()
  111.             showOptions()
  112.         End If
  113.     End Sub
  114.  
  115.     Private Sub btnOpenLocalhost_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenLocalhost.Click
  116.         openLocalhost()
  117.     End Sub
  118. #End Region
  119.  
  120. #Region "Server start/stop"
  121.     Sub startServ(Optional ByVal autoOpenLocalhost As Boolean = False)
  122.         appendLog("Starting server...")
  123.         Try
  124.             server = New HttpListener
  125.             listenerThread = New Thread(AddressOf listener)
  126.             btnStart.Enabled = False
  127.             server.Prefixes.Clear()
  128.             server.Prefixes.Add("http://*:" & port & "/")
  129.             server.Start()
  130.             listenerThread.Start()
  131.             btnStop.Enabled = True
  132.             btnOptions.Enabled = False
  133.             appendLog("Server started.")
  134.             If autoOpenLocalhost Then
  135.                 openLocalhost()
  136.             End If
  137.         Catch ex As HttpListenerException
  138.             appendLog("Error starting server. Try with a different port.")
  139.             btnStart.Enabled = True
  140.             btnStop.Enabled = False
  141.             btnOptions.Enabled = True
  142.         End Try
  143.     End Sub
  144.  
  145.     Function stopServ() As Boolean
  146.         If requestsThreads.Count <> 0 Then
  147.             If MsgBox(String.Format("The server is managing {0} requests; if you stop the server, the requests will be interrupted. Continue?", requestsThreads.Count), MsgBoxStyle.YesNo) = MsgBoxResult.No Then Return False
  148.         End If
  149.         appendLog("Stopping server...")
  150.         btnStop.Enabled = False
  151.         For Each t As Thread In requestsThreads
  152.             t.Abort()
  153.         Next
  154.         requestsThreads.Clear()
  155.         listenerThread.Abort()
  156.         server.Stop()
  157.         btnStart.Enabled = True
  158.         btnOptions.Enabled = True
  159.         appendLog("Server stopped.")
  160.         Return True
  161.     End Function
  162. #End Region
  163.  
  164. #Region "Request managment"
  165.     Sub listener()
  166.         Do
  167.             Dim c As HttpListenerContext = server.GetContext()
  168.             requestsThreads.Add(New Thread(AddressOf handleRequest))
  169.             requestsThreads(requestsThreads.Count - 1).Start(c)
  170.         Loop
  171.     End Sub
  172.  
  173.     Sub handleRequest(ByVal _c As Object)
  174.         Dim c As HttpListenerContext = CType(_c, HttpListenerContext)
  175.         Dim ip As String = c.Request.RemoteEndPoint.Address.ToString()
  176.         appendLog(String.Format("Requested {0} from {1} ...", c.Request.RawUrl, ip))
  177.         Dim b() As Byte = Nothing
  178.         Dim os As IO.Stream = c.Response.OutputStream
  179.         Dim r As String = wwwRoot & c.Request.RawUrl.Replace("/", "\")
  180.         For Each i As String In percentEncoding.Keys
  181.             r = r.Replace(i, percentEncoding(i))
  182.         Next
  183.         If onlyLocal And Not (ip = "::1" Or ip = "127.0.0.1") Then
  184.             b = System.Text.Encoding.UTF8.GetBytes(formatHTML("Error", "<h1>403 Error</h1><p>This server accepts only local requests.</p>"))
  185.             c.Response.StatusCode = 403
  186.             appendLog("Request refused (403 not authorized)")
  187.         Else
  188.             If r.EndsWith("\") Then
  189.                 If defDirRes_file = "" Then
  190.                     answerListing(c, b, r)
  191.                 Else
  192.                     If Not answerFile(c, b, r & defDirRes_file) Then
  193.                         If defDirRes_fileIfNotFoundList Then
  194.                             answerListing(c, b, r)
  195.                         Else
  196.                             b = System.Text.Encoding.UTF8.GetBytes(formatHTML("Error", "<h1>404 Error</h1><p>The file you requested doesn't exists.</p>"))
  197.                             c.Response.StatusCode = 404
  198.                             appendLog("Request failed (404 file not found)")
  199.                         End If
  200.                     End If
  201.                 End If
  202.             Else
  203.                 If Not answerFile(c, b, r) Then
  204.                     b = System.Text.Encoding.UTF8.GetBytes(formatHTML("Error", "<h1>404 Error</h1><p>The file you requested doesn't exists.</p>"))
  205.                     c.Response.StatusCode = 404
  206.                     appendLog("Request failed (404 file not found)")
  207.                 End If
  208.             End If
  209.         End If
  210.         os.Write(b, 0, b.Length)
  211.         os.Close()
  212.         requestsThreads.Remove(Thread.CurrentThread)
  213.         Thread.CurrentThread.Abort()
  214.     End Sub
  215.  
  216.     Function answerFile(ByRef c As HttpListenerContext, ByRef b As Byte(), ByVal f As String) As Boolean
  217.         If My.Computer.FileSystem.FileExists(f) Then
  218.             Try
  219.                 b = My.Computer.FileSystem.ReadAllBytes(f)
  220.                 appendLog(String.Format("Request answered with {0} (200 OK)", f))
  221.             Catch ex As IO.IOException
  222.                 b = System.Text.Encoding.UTF8.GetBytes(formatHTML("Error", "<h1>Error: server isn't able to read the requested file.</h1>"))
  223.                 appendLog("IOException: the server can't acces the file. Request answered with error message (200 OK)")
  224.             End Try
  225.             c.Response.StatusCode = 200
  226.             Return True
  227.         Else
  228.             Return False
  229.         End If
  230.     End Function
  231.  
  232.     Sub answerListing(ByRef c As HttpListenerContext, ByRef b As Byte(), ByVal r As String)
  233.         Dim s As String = String.Format("<h1>Index of {0}</h1>", c.Request.RawUrl) & Environment.NewLine
  234.         If c.Request.RawUrl <> "/" Then s &= "<p><a href=""../"">../</a></p>" & Environment.NewLine
  235.         For Each d As String In My.Computer.FileSystem.GetDirectories(r)
  236.             s &= String.Format("<p><a href=""{0}"">{0}</a></p>", d.Remove(0, r.Length) & "/") & Environment.NewLine
  237.         Next
  238.         For Each f As String In My.Computer.FileSystem.GetFiles(r)
  239.             s &= String.Format("<p><a href=""{0}"">{0}</a></p>", f.Remove(0, r.Length)) & Environment.NewLine
  240.         Next
  241.         b = System.Text.Encoding.UTF8.GetBytes(formatHTML("Index of " & c.Request.RawUrl, s))
  242.         c.Response.StatusCode = 200
  243.         appendLog("Request answered with directory listing (200 OK)")
  244.     End Sub
  245. #End Region
  246.  
  247. #Region "Utils"
  248.     Function formatHTML(ByVal title As String, ByVal body As String) As String
  249.         Return String.Format("<html><head><title>{0}</title></head><body>{1}</body></html>", title, body)
  250.     End Function
  251.  
  252.     Sub appendLog(ByVal text As String)
  253.         log.AppendText(String.Format("[{0} {1}] {2}", Date.Now.ToShortDateString, Date.Now.ToLongTimeString, text) & Environment.NewLine)
  254.     End Sub
  255.  
  256.     Sub showOptions()
  257.         appendLog("Port: " & port)
  258.         appendLog("Root directory: " & wwwRoot)
  259.         appendLog("Allow only local requests: " & onlyLocal.ToString())
  260.         Dim s As String = "Response for directory request: "
  261.         If defDirRes_file = "" Then
  262.             s &= "directory listing"
  263.         Else
  264.             s &= """" & defDirRes_file & """; if not found, "
  265.             If defDirRes_fileIfNotFoundList Then
  266.                 s &= "directory listing"
  267.             Else
  268.                 s &= "404 error"
  269.             End If
  270.         End If
  271.         appendLog(s)
  272.     End Sub
  273.  
  274.     Sub validateDir()
  275.         If wwwRoot.EndsWith("\") Then wwwRoot = wwwRoot.Remove(wwwRoot.Length - 1)
  276.         If Not My.Computer.FileSystem.DirectoryExists(wwwRoot) Then
  277.             appendLog("Error: the server root directory doesn't exist; using the default directory instead.")
  278.             wwwRoot = Application.StartupPath & "\www"
  279.         End If
  280.     End Sub
  281.  
  282.     Sub openLocalhost()
  283.         Process.Start("http://localhost:" & port)
  284.     End Sub
  285. #End Region
  286.  
  287. End Class