· 5 years ago · May 01, 2020, 09:22 PM
1#Netsh Advfirewall show allprofiles
2#NetSh Advfirewall set allprofiles state off
3#netsh advfirewall firewall add rule name="Powershell Webserver" dir=in action=allow protocol=TCP localport=8080
4#netsh advfirewall firewall delete rule name="Powershell Webserver"
5
6Param([STRING]$BINDING = 'http://localhost:8080/', [STRING]$BASEDIR = "")
7
8# No adminstrative permissions are required for a binding to "localhost"
9# $BINDING = 'http://localhost:8080/'
10# Adminstrative permissions are required for a binding to network names or addresses.
11# + takes all requests to the port regardless of name or ip, * only requests that no other listener answers:
12# $BINDING = 'http://+:8080/'
13
14if ($BASEDIR -eq "")
15{ # current filesystem path as base path for static content
16 $BASEDIR = (Get-Location -PSProvider "FileSystem").ToString()
17}
18# convert to absolute path
19$BASEDIR = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($BASEDIR)
20
21# MIME hash table for static content
22$MIMEHASH = @{".avi"="video/x-msvideo"; ".crt"="application/x-x509-ca-cert"; ".css"="text/css"; ".der"="application/x-x509-ca-cert"; ".flv"="video/x-flv"; ".gif"="image/gif"; ".htm"="text/html"; ".html"="text/html"; ".ico"="image/x-icon"; ".jar"="application/java-archive"; ".jardiff"="application/x-java-archive-diff"; ".jpeg"="image/jpeg"; ".jpg"="image/jpeg"; ".js"="application/x-javascript"; ".mov"="video/quicktime"; ".mp3"="audio/mpeg"; ".mp4"="video/mp4"; ".mpeg"="video/mpeg"; ".mpg"="video/mpeg"; ".pdf"="application/pdf"; ".pem"="application/x-x509-ca-cert"; ".pl"="application/x-perl"; ".png"="image/png"; ".rss"="text/xml"; ".shtml"="text/html"; ".txt"="text/plain"; ".war"="application/java-archive"; ".wmv"="video/x-ms-wmv"; ".xml"="text/xml"}
23
24# HTML answer templates for specific calls, placeholders !RESULT, !FORMFIELD, !PROMPT are allowed
25$HTMLRESPONSECONTENTS = @{
26 'GET /' = @"
27<!doctype html><html><body>
28 !HEADERLINE
29 <pre>!RESULT</pre>
30 <form method="GET" action="/">
31 <b>!PROMPT </b><input type="text" maxlength=255 size=80 name="command" value='!FORMFIELD'>
32 <input type="submit" name="button" value="Enter">
33 </form>
34</body></html>
35"@
36 'GET /script' = @"
37<!doctype html><html><body>
38 !HEADERLINE
39 <form method="POST" enctype="multipart/form-data" action="/script">
40 <p><b>Script to execute:</b><input type="file" name="filedata"></p>
41 <b>Parameters:</b><input type="text" maxlength=255 size=80 name="parameter">
42 <input type="submit" name="button" value="Execute">
43 </form>
44</body></html>
45"@
46 'GET /download' = @"
47<!doctype html><html><body>
48 !HEADERLINE
49 <pre>!RESULT</pre>
50 <form method="POST" action="/download">
51 <b>Path to file:</b><input type="text" maxlength=255 size=80 name="filepath" value='!FORMFIELD'>
52 <input type="submit" name="button" value="Download">
53 </form>
54</body></html>
55"@
56 'POST /download' = @"
57<!doctype html><html><body>
58 !HEADERLINE
59 <pre>!RESULT</pre>
60 <form method="POST" action="/download">
61 <b>Path to file:</b><input type="text" maxlength=255 size=80 name="filepath" value='!FORMFIELD'>
62 <input type="submit" name="button" value="Download">
63 </form>
64</body></html>
65"@
66 'GET /upload' = @"
67<!doctype html><html><body>
68 !HEADERLINE
69 <form method="POST" enctype="multipart/form-data" action="/upload">
70 <p><b>File to upload:</b><input type="file" name="filedata"></p>
71 <b>Path to store on webserver:</b><input type="text" maxlength=255 size=80 name="filepath">
72 <input type="submit" name="button" value="Upload">
73 </form>
74</body></html>
75"@
76 'POST /script' = "<!doctype html><html><body>!HEADERLINE<pre>!RESULT</pre></body></html>"
77 'POST /upload' = "<!doctype html><html><body>!HEADERLINE<pre>!RESULT</pre></body></html>"
78 'GET /exit' = "<!doctype html><html><body>Stopped powershell webserver</body></html>"
79 'GET /quit' = "<!doctype html><html><body>Stopped powershell webserver</body></html>"
80 'GET /log' = "<!doctype html><html><body>!HEADERLINELog of powershell webserver:<br /><pre>!RESULT</pre></body></html>"
81 'GET /starttime' = "<!doctype html><html><body>!HEADERLINEPowershell webserver started at $(Get-Date -Format s)</body></html>"
82 'GET /time' = "<!doctype html><html><body>!HEADERLINECurrent time: !RESULT</body></html>"
83 'GET /beep' = "<!doctype html><html><body>!HEADERLINEBEEP...</body></html>"
84}
85
86# Set navigation header line for all web pages
87$HEADERLINE = "<p><a href='/'>Command execution</a> <a href='/script'>Execute script</a> <a href='/download'>Download file</a> <a href='/upload'>Upload file</a> <a href='/log'>Web logs</a> <a href='/starttime'>Webserver start time</a> <a href='/time'>Current time</a> <a href='/beep'>Beep</a> <a href='/quit'>Stop webserver</a></p>"
88
89# Starting the powershell webserver
90"$(Get-Date -Format s) Starting powershell webserver..."
91$LISTENER = New-Object System.Net.HttpListener
92$LISTENER.Prefixes.Add($BINDING)
93$LISTENER.Start()
94$Error.Clear()
95
96try
97{
98 "$(Get-Date -Format s) Powershell webserver started."
99 $WEBLOG = "$(Get-Date -Format s) Powershell webserver started.`n"
100 while ($LISTENER.IsListening)
101 {
102 # analyze incoming request
103 $CONTEXT = $LISTENER.GetContext()
104 $REQUEST = $CONTEXT.Request
105 $RESPONSE = $CONTEXT.Response
106 $RESPONSEWRITTEN = $FALSE
107
108 # log to console
109 "$(Get-Date -Format s) $($REQUEST.RemoteEndPoint.Address.ToString()) $($REQUEST.httpMethod) $($REQUEST.Url.PathAndQuery)"
110 # and in log variable
111 $WEBLOG += "$(Get-Date -Format s) $($REQUEST.RemoteEndPoint.Address.ToString()) $($REQUEST.httpMethod) $($REQUEST.Url.PathAndQuery)`n"
112
113 # is there a fixed coding for the request?
114 $RECEIVED = '{0} {1}' -f $REQUEST.httpMethod, $REQUEST.Url.LocalPath
115 $HTMLRESPONSE = $HTMLRESPONSECONTENTS[$RECEIVED]
116 $RESULT = ''
117
118 # check for known commands
119 switch ($RECEIVED)
120 {
121 "GET /"
122 { # execute command
123 # retrieve GET query string
124 $FORMFIELD = ''
125 $FORMFIELD = [URI]::UnescapeDataString(($REQUEST.Url.Query -replace "\+"," "))
126 # remove fixed form fields out of query string
127 $FORMFIELD = $FORMFIELD -replace "\?command=","" -replace "\?button=enter","" -replace "&command=","" -replace "&button=enter",""
128 # when command is given...
129 if (![STRING]::IsNullOrEmpty($FORMFIELD))
130 {
131 try {
132 # ... execute command
133 $RESULT = Invoke-Expression -EA SilentlyContinue $FORMFIELD 2> $NULL | Out-String
134 }
135 catch
136 {
137 # just ignore. Error handling comes afterwards since not every error throws an exception
138 }
139 if ($Error.Count -gt 0)
140 { # retrieve error message on error
141 $RESULT += "`nError while executing '$FORMFIELD'`n`n"
142 $RESULT += $Error[0]
143 $Error.Clear()
144 }
145 }
146 # preset form value with command for the caller's convenience
147 $HTMLRESPONSE = $HTMLRESPONSE -replace '!FORMFIELD', $FORMFIELD
148 # insert powershell prompt to form
149 $PROMPT = "PS $PWD>"
150 $HTMLRESPONSE = $HTMLRESPONSE -replace '!PROMPT', $PROMPT
151 break
152 }
153
154 "GET /script"
155 { # present upload form, nothing to do here
156 break
157 }
158
159 "POST /script"
160 { # upload and execute script
161
162 # only if there is body data in the request
163 if ($REQUEST.HasEntityBody)
164 {
165 # set default message to error message (since we just stop processing on error)
166 $RESULT = "Received corrupt or incomplete form data"
167
168 # check content type
169 if ($REQUEST.ContentType)
170 {
171 # retrieve boundary marker for header separation
172 $BOUNDARY = $NULL
173 if ($REQUEST.ContentType -match "boundary=(.*);")
174 { $BOUNDARY = "--" + $MATCHES[1] }
175 else
176 { # marker might be at the end of the line
177 if ($REQUEST.ContentType -match "boundary=(.*)$")
178 { $BOUNDARY = "--" + $MATCHES[1] }
179 }
180
181 if ($BOUNDARY)
182 { # only if header separator was found
183
184 # read complete header (inkl. file data) into string
185 $READER = New-Object System.IO.StreamReader($REQUEST.InputStream, $REQUEST.ContentEncoding)
186 $DATA = $READER.ReadToEnd()
187 $READER.Close()
188 $REQUEST.InputStream.Close()
189
190 $PARAMETERS = ""
191 $SOURCENAME = ""
192
193 # separate headers by boundary string
194 $DATA -replace "$BOUNDARY--\r\n", "$BOUNDARY`r`n--" -split "$BOUNDARY\r\n" | ForEach-Object {
195 # omit leading empty header and end marker header
196 if (($_ -ne "") -and ($_ -ne "--"))
197 {
198 # only if well defined header (separation between meta data and data)
199 if ($_.IndexOf("`r`n`r`n") -gt 0)
200 {
201 # header data before two CRs is meta data
202 # first look for the file in header "filedata"
203 if ($_.Substring(0, $_.IndexOf("`r`n`r`n")) -match "Content-Disposition: form-data; name=(.*);")
204 {
205 $HEADERNAME = $MATCHES[1] -replace '\"'
206 # headername "filedata"?
207 if ($HEADERNAME -eq "filedata")
208 { # yes, look for source filename
209 if ($_.Substring(0, $_.IndexOf("`r`n`r`n")) -match "filename=(.*)")
210 { # source filename found
211 $SOURCENAME = $MATCHES[1] -replace "`r`n$" -replace "`r$" -replace '\"'
212 # store content of file in variable
213 $FILEDATA = $_.Substring($_.IndexOf("`r`n`r`n") + 4) -replace "`r`n$"
214 }
215 }
216 }
217 else
218 { # look for other headers (we need "parameter")
219 if ($_.Substring(0, $_.IndexOf("`r`n`r`n")) -match "Content-Disposition: form-data; name=(.*)")
220 { # header found
221 $HEADERNAME = $MATCHES[1] -replace '\"'
222 # headername "parameter"?
223 if ($HEADERNAME -eq "parameter")
224 { # yes, look for paramaters
225 $PARAMETERS = $_.Substring($_.IndexOf("`r`n`r`n") + 4) -replace "`r`n$" -replace "`r$"
226 }
227 }
228 }
229 }
230 }
231 }
232
233 if ($SOURCENAME -ne "")
234 { # execute only if a source file exists
235
236 $EXECUTE = "function Powershell-WebServer-Func {`n" + $FILEDATA + "`n}`nPowershell-WebServer-Func " + $PARAMETERS
237 try {
238 # ... execute script
239 $RESULT = Invoke-Expression -EA SilentlyContinue $EXECUTE 2> $NULL | Out-String
240 }
241 catch
242 {
243 # just ignore. Error handling comes afterwards since not every error throws an exception
244 }
245 if ($Error.Count -gt 0)
246 { # retrieve error message on error
247 $RESULT += "`nError while executing script $SOURCENAME`n`n"
248 $RESULT += $Error[0]
249 $Error.Clear()
250 }
251 }
252 else
253 {
254 $RESULT = "No file data received"
255 }
256 }
257 }
258 }
259 else
260 {
261 $RESULT = "No client data received"
262 }
263 break
264 }
265
266 { $_ -like "* /download" } # GET or POST method are allowed for download page
267 { # download file
268
269 # is POST data in the request?
270 if ($REQUEST.HasEntityBody)
271 { # POST request
272 # read complete header into string
273 $READER = New-Object System.IO.StreamReader($REQUEST.InputStream, $REQUEST.ContentEncoding)
274 $DATA = $READER.ReadToEnd()
275 $READER.Close()
276 $REQUEST.InputStream.Close()
277
278 # get headers into hash table
279 $HEADER = @{}
280 $DATA.Split('&') | ForEach-Object { $HEADER.Add([URI]::UnescapeDataString(($_.Split('=')[0] -replace "\+"," ")), [URI]::UnescapeDataString(($_.Split('=')[1] -replace "\+"," "))) }
281
282 # read header 'filepath'
283 $FORMFIELD = $HEADER.Item('filepath')
284 # remove leading and trailing double quotes since Test-Path does not like them
285 $FORMFIELD = $FORMFIELD -replace "^`"","" -replace "`"$",""
286 }
287 else
288 { # GET request
289
290 # retrieve GET query string
291 $FORMFIELD = ''
292 $FORMFIELD = [URI]::UnescapeDataString(($REQUEST.Url.Query -replace "\+"," "))
293 # remove fixed form fields out of query string
294 $FORMFIELD = $FORMFIELD -replace "\?filepath=","" -replace "\?button=download","" -replace "&filepath=","" -replace "&button=download",""
295 # remove leading and trailing double quotes since Test-Path does not like them
296 $FORMFIELD = $FORMFIELD -replace "^`"","" -replace "`"$",""
297 }
298
299 # when path is given...
300 if (![STRING]::IsNullOrEmpty($FORMFIELD))
301 { # check if file exists
302 if (Test-Path $FORMFIELD -PathType Leaf)
303 {
304 try {
305 # ... download file
306 $BUFFER = [System.IO.File]::ReadAllBytes($FORMFIELD)
307 $RESPONSE.ContentLength64 = $BUFFER.Length
308 $RESPONSE.SendChunked = $FALSE
309 $RESPONSE.ContentType = "application/octet-stream"
310 $FILENAME = Split-Path -Leaf $FORMFIELD
311 $RESPONSE.AddHeader("Content-Disposition", "attachment; filename=$FILENAME")
312 $RESPONSE.AddHeader("Last-Modified", [IO.File]::GetLastWriteTime($FORMFIELD).ToString('r'))
313 $RESPONSE.AddHeader("Server", "Powershell Webserver/1.2 on ")
314 $RESPONSE.OutputStream.Write($BUFFER, 0, $BUFFER.Length)
315 # mark response as already given
316 $RESPONSEWRITTEN = $TRUE
317 }
318 catch
319 {
320 # just ignore. Error handling comes afterwards since not every error throws an exception
321 }
322 if ($Error.Count -gt 0)
323 { # retrieve error message on error
324 $RESULT += "`nError while downloading '$FORMFIELD'`n`n"
325 $RESULT += $Error[0]
326 $Error.Clear()
327 }
328 }
329 else
330 {
331 # ... file not found
332 $RESULT = "File $FORMFIELD not found"
333 }
334 }
335 # preset form value with file path for the caller's convenience
336 $HTMLRESPONSE = $HTMLRESPONSE -replace '!FORMFIELD', $FORMFIELD
337 break
338 }
339
340 "GET /upload"
341 { # present upload form, nothing to do here
342 break
343 }
344
345 "POST /upload"
346 { # upload file
347
348 # only if there is body data in the request
349 if ($REQUEST.HasEntityBody)
350 {
351 # set default message to error message (since we just stop processing on error)
352 $RESULT = "Received corrupt or incomplete form data"
353
354 # check content type
355 if ($REQUEST.ContentType)
356 {
357 # retrieve boundary marker for header separation
358 $BOUNDARY = $NULL
359 if ($REQUEST.ContentType -match "boundary=(.*);")
360 { $BOUNDARY = "--" + $MATCHES[1] }
361 else
362 { # marker might be at the end of the line
363 if ($REQUEST.ContentType -match "boundary=(.*)$")
364 { $BOUNDARY = "--" + $MATCHES[1] }
365 }
366
367 if ($BOUNDARY)
368 { # only if header separator was found
369
370 # read complete header (inkl. file data) into string
371 $READER = New-Object System.IO.StreamReader($REQUEST.InputStream, $REQUEST.ContentEncoding)
372 $DATA = $READER.ReadToEnd()
373 $READER.Close()
374 $REQUEST.InputStream.Close()
375
376 # variables for filenames
377 $FILENAME = ""
378 $SOURCENAME = ""
379
380 # separate headers by boundary string
381 $DATA -replace "$BOUNDARY--\r\n", "$BOUNDARY`r`n--" -split "$BOUNDARY\r\n" | ForEach-Object {
382 # omit leading empty header and end marker header
383 if (($_ -ne "") -and ($_ -ne "--"))
384 {
385 # only if well defined header (seperation between meta data and data)
386 if ($_.IndexOf("`r`n`r`n") -gt 0)
387 {
388 # header data before two CRs is meta data
389 # first look for the file in header "filedata"
390 if ($_.Substring(0, $_.IndexOf("`r`n`r`n")) -match "Content-Disposition: form-data; name=(.*);")
391 {
392 $HEADERNAME = $MATCHES[1] -replace '\"'
393 # headername "filedata"?
394 if ($HEADERNAME -eq "filedata")
395 { # yes, look for source filename
396 if ($_.Substring(0, $_.IndexOf("`r`n`r`n")) -match "filename=(.*)")
397 { # source filename found
398 $SOURCENAME = $MATCHES[1] -replace "`r`n$" -replace "`r$" -replace '\"'
399 # store content of file in variable
400 $FILEDATA = $_.Substring($_.IndexOf("`r`n`r`n") + 4) -replace "`r`n$"
401 }
402 }
403 }
404 else
405 { # look for other headers (we need "filepath" to know where to store the file)
406 if ($_.Substring(0, $_.IndexOf("`r`n`r`n")) -match "Content-Disposition: form-data; name=(.*)")
407 { # header found
408 $HEADERNAME = $MATCHES[1] -replace '\"'
409 # headername "filepath"?
410 if ($HEADERNAME -eq "filepath")
411 { # yes, look for target filename
412 $FILENAME = $_.Substring($_.IndexOf("`r`n`r`n") + 4) -replace "`r`n$" -replace "`r$" -replace '\"'
413 }
414 }
415 }
416 }
417 }
418 }
419
420 if ($FILENAME -ne "")
421 { # upload only if a targetname is given
422 if ($SOURCENAME -ne "")
423 { # only upload if source file exists
424
425 # check or construct a valid filename to store
426 $TARGETNAME = ""
427 # if filename is a container name, add source filename to it
428 if (Test-Path $FILENAME -PathType Container)
429 {
430 $TARGETNAME = Join-Path $FILENAME -ChildPath $(Split-Path $SOURCENAME -Leaf)
431 } else {
432 # try name in the header
433 $TARGETNAME = $FILENAME
434 }
435
436 try {
437 # ... save file with the same encoding as received
438 [IO.File]::WriteAllText($TARGETNAME, $FILEDATA, $REQUEST.ContentEncoding)
439 }
440 catch
441 {
442 # just ignore. Error handling comes afterwards since not every error throws an exception
443 }
444 if ($Error.Count -gt 0)
445 { # retrieve error message on error
446 $RESULT += "`nError saving '$TARGETNAME'`n`n"
447 $RESULT += $Error[0]
448 $Error.Clear()
449 }
450 else
451 { # success
452 $RESULT = "File $SOURCENAME successfully uploaded as $TARGETNAME"
453 }
454 }
455 else
456 {
457 $RESULT = "No file data received"
458 }
459 }
460 else
461 {
462 $RESULT = "Missing target file name"
463 }
464 }
465 }
466 }
467 else
468 {
469 $RESULT = "No client data received"
470 }
471 break
472 }
473
474 "GET /log"
475 { # return the webserver log (stored in log variable)
476 $RESULT = $WEBLOG
477 break
478 }
479
480 "GET /time"
481 { # return current time
482 $RESULT = Get-Date -Format s
483 break
484 }
485
486 "GET /starttime"
487 { # return start time of the powershell webserver (already contained in $HTMLRESPONSE, nothing to do here)
488 break
489 }
490
491 "GET /beep"
492 { # Beep
493 [CONSOLE]::beep(800, 300) # or "`a" or [char]7
494 break
495 }
496
497 "GET /quit"
498 { # stop powershell webserver, nothing to do here
499 break
500 }
501
502 "GET /exit"
503 { # stop powershell webserver, nothing to do here
504 break
505 }
506
507 default
508 { # unknown command, check if path to file
509
510 # create physical path based upon the base dir and url
511 $CHECKDIR = $BASEDIR.TrimEnd("/\") + $REQUEST.Url.LocalPath
512 $CHECKFILE = ""
513 if (Test-Path $CHECKDIR -PathType Container)
514 { # physical path is a directory
515 $IDXLIST = "/index.htm", "/index.html", "/default.htm", "/default.html"
516 foreach ($IDXNAME in $IDXLIST)
517 { # check if an index file is present
518 $CHECKFILE = $CHECKDIR.TrimEnd("/\") + $IDXNAME
519 if (Test-Path $CHECKFILE -PathType Leaf)
520 { # index file found, path now in $CHECKFILE
521 break
522 }
523 $CHECKFILE = ""
524 }
525
526 if ($CHECKFILE -eq "")
527 { # generate directory listing
528 $HTMLRESPONSE = "<!doctype html><html><head><title>$($REQUEST.Url.LocalPath)</title><meta charset=""utf-8""></head><body><H1>$($REQUEST.Url.LocalPath)</H1><hr><pre>"
529 if ($REQUEST.Url.LocalPath -ne "" -And $REQUEST.Url.LocalPath -ne "/" -And $REQUEST.Url.LocalPath -ne "`\" -And $REQUEST.Url.LocalPath -ne ".")
530 { # link to parent directory
531 $PARENTDIR = (Split-Path $REQUEST.Url.LocalPath -Parent) -replace '\\','/'
532 if ($PARENTDIR.IndexOf("/") -ne 0) { $PARENTDIR = "/" + $PARENTDIR }
533 $HTMLRESPONSE += "<pre><a href=""$PARENTDIR"">[To Parent Directory]</a><br><br>"
534 }
535
536 # read in directory listing
537 $ENTRIES = Get-ChildItem -EA SilentlyContinue -Path $CHECKDIR
538
539 # process directories
540 $ENTRIES | Where-Object { $_.PSIsContainer } | ForEach-Object { $HTMLRESPONSE += "$($_.LastWriteTime.ToString()) <dir> <a href=""$(Join-Path $REQUEST.Url.LocalPath $_.Name)"">$($_.Name)</a><br>" }
541
542 # process files
543 $ENTRIES | Where-Object { !$_.PSIsContainer } | ForEach-Object { $HTMLRESPONSE += "$($_.LastWriteTime.ToString()) $("{0,10}" -f $_.Length) <a href=""$(Join-Path $REQUEST.Url.LocalPath $_.Name)"">$($_.Name)</a><br>" }
544
545 # end of directory listing
546 $HTMLRESPONSE += "</pre><hr></body></html>"
547 }
548 }
549 else
550 { # no directory, check for file
551 if (Test-Path $CHECKDIR -PathType Leaf)
552 { # file found, path now in $CHECKFILE
553 $CHECKFILE = $CHECKDIR
554 }
555 }
556
557 if ($CHECKFILE -ne "")
558 { # static content available
559 try {
560 # ... serve static content
561 $BUFFER = [System.IO.File]::ReadAllBytes($CHECKFILE)
562 $RESPONSE.ContentLength64 = $BUFFER.Length
563 $RESPONSE.SendChunked = $FALSE
564 $EXTENSION = [IO.Path]::GetExtension($CHECKFILE)
565 if ($MIMEHASH.ContainsKey($EXTENSION))
566 { # known mime type for this file's extension available
567 $RESPONSE.ContentType = $MIMEHASH.Item($EXTENSION)
568 }
569 else
570 { # no, serve as binary download
571 $RESPONSE.ContentType = "application/octet-stream"
572 $FILENAME = Split-Path -Leaf $CHECKFILE
573 $RESPONSE.AddHeader("Content-Disposition", "attachment; filename=$FILENAME")
574 }
575 $RESPONSE.AddHeader("Last-Modified", [IO.File]::GetLastWriteTime($CHECKFILE).ToString('r'))
576 $RESPONSE.AddHeader("Server", "Powershell Webserver/1.2 on ")
577 $RESPONSE.OutputStream.Write($BUFFER, 0, $BUFFER.Length)
578 # mark response as already given
579 $RESPONSEWRITTEN = $TRUE
580 }
581 catch
582 {
583 # just ignore. Error handling comes afterwards since not every error throws an exception
584 }
585 if ($Error.Count -gt 0)
586 { # retrieve error message on error
587 $RESULT += "`nError while downloading '$CHECKFILE'`n`n"
588 $RESULT += $Error[0]
589 $Error.Clear()
590 }
591 }
592 else
593 { # no file to serve found, return error
594 if (!(Test-Path $CHECKDIR -PathType Container))
595 {
596 $RESPONSE.StatusCode = 404
597 $HTMLRESPONSE = '<!doctype html><html><body>Diese Seite ist nicht vorhanden</body></html>'
598 }
599 }
600 }
601
602 }
603
604 # only send response if not already done
605 if (!$RESPONSEWRITTEN)
606 {
607 # insert header line string into HTML template
608 $HTMLRESPONSE = $HTMLRESPONSE -replace '!HEADERLINE', $HEADERLINE
609
610 # insert result string into HTML template
611 $HTMLRESPONSE = $HTMLRESPONSE -replace '!RESULT', $RESULT
612
613 # return HTML answer to caller
614 $BUFFER = [Text.Encoding]::UTF8.GetBytes($HTMLRESPONSE)
615 $RESPONSE.ContentLength64 = $BUFFER.Length
616 $RESPONSE.AddHeader("Last-Modified", [DATETIME]::Now.ToString('r'))
617 $RESPONSE.AddHeader("Server", "Powershell Webserver/1.2 on ")
618 $RESPONSE.OutputStream.Write($BUFFER, 0, $BUFFER.Length)
619 }
620
621 # and finish answer to client
622 $RESPONSE.Close()
623
624 # received command to stop webserver?
625 if ($RECEIVED -eq 'GET /exit' -or $RECEIVED -eq 'GET /quit')
626 { # then break out of while loop
627 "$(Get-Date -Format s) Stopping powershell webserver..."
628 break;
629 }
630 }
631}
632finally
633{
634 # Stop powershell webserver
635 $LISTENER.Stop()
636 $LISTENER.Close()
637 "$(Get-Date -Format s) Powershell webserver stopped."
638}