161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
if {[catch [list wappInt-readable-unsafe $chan] msg]} {
puts stderr "$msg\n$::errorInfo"
wappInt-close-channel $chan
}
}
proc wappInt-readable-unsafe {chan} {
upvar #0 wappInt-$chan W
set line [string trimright [gets $chan]]
set n [string length $line]
if {$n>0} {
if {[dict get $W .header]=="" || [regexp {^\s+} $line]} {
dict append W .header $line
} else {
dict append W .header \n$line
}
if {[string length [dict get $W .header]]>100000} {
error "HTTP request header too big - possible DOS attack"
}
} elseif {$n==0} {
wappInt-parse-header $chan
if {[dict get $W REQUEST_METHOD]=="POST"
&& [dict exists $W hdr.CONTENT-LENGTH]
&& [string is integer -strict [dict get $W hdr.CONTENT-LENGTH]]} {
dict set W .toread [dict get $W hdr.CONTENT-LENGTH]
fileevent $chan readable [list wappInt-read-post-data $chan]
} else {
wappInt-handle-request $chan
}
}
}
# Read in as much of the POST data as we can
#
proc wappInt-read-post-data {chan} {
if {[catch [list wappInt-read-post-data-unsafe $chan]]} {
wappInt-close-channel $chan
}
}
proc wappInt-read-post-data-unsafe {chan} {
upvar #0 wappInt-$chan W
set got [read $chan [dict get $W .toread]]
dict append W .post $got
dict set W .toread [expr {[dict get $W .toread]-[string length $got]}]
if {[dict get $W .toread]<=0} {
wappInt-parse-post-data $chan
wappInt-handle-request $chan
}
}
# Decode the HTTP request header.
#
# This routine is always running inside of a [catch], so if
# any problems arise, simply raise an error.
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
<
|
|
|
|
|
|
<
<
|
<
<
<
<
<
<
|
|
|
|
|
|
>
|
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
if {[catch [list wappInt-readable-unsafe $chan] msg]} {
puts stderr "$msg\n$::errorInfo"
wappInt-close-channel $chan
}
}
proc wappInt-readable-unsafe {chan} {
upvar #0 wappInt-$chan W
if {![dict exists $W .toread]} {
# If the .toread key is not set, that means we are still reading
# the header
set line [string trimright [gets $chan]]
set n [string length $line]
if {$n>0} {
if {[dict get $W .header]=="" || [regexp {^\s+} $line]} {
dict append W .header $line
} else {
dict append W .header \n$line
}
if {[string length [dict get $W .header]]>100000} {
error "HTTP request header too big - possible DOS attack"
}
} elseif {$n==0} {
wappInt-parse-header $chan
set len 0
if {[dict exists $W .hdr:CONTENT-LENGTH]} {
set len [dict get $W .hdr:CONTENT-LENGTH]
}
if {$len>0} {
dict set W .toread $len
} else {
wappInt-handle-request $chan
}
}
} else {
# If .toread is set, that means we are reading the query content.
# Continue reading until .toread reaches zero.
set got [read $chan [dict get $W .toread]]
dict append W .post $got
dict set W .toread [expr {[dict get $W .toread]-[string length $got]}]
if {[dict get $W .toread]<=0} {
wappInt-parse-post-data $chan
wappInt-handle-request $chan
}
}
}
# Decode the HTTP request header.
#
# This routine is always running inside of a [catch], so if
# any problems arise, simply raise an error.
|
302
303
304
305
306
307
308
|
$str {[encoding convertfrom utf-8 [DecodeHex \1\2\3]]} str
regsub -all -- \
{%([CDcd][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])} \
$str {[encoding convertfrom utf-8 [DecodeHex \1\2]]} str
regsub -all -- {%([0-7][A-Fa-f0-9])} $str {\\u00\1} str
return [subst -novar $str]
}
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
|
$str {[encoding convertfrom utf-8 [DecodeHex \1\2\3]]} str
regsub -all -- \
{%([CDcd][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])} \
$str {[encoding convertfrom utf-8 [DecodeHex \1\2]]} str
regsub -all -- {%([0-7][A-Fa-f0-9])} $str {\\u00\1} str
return [subst -novar $str]
}
# Process POST data
#
proc wappInt-parse-post-data {chan} {
upvar #0 wappInt-$chan W
if {[dict exists $W .hdr:CONTENT-TYPE]
&& [dict get $W .hdr:CONTENT-TYPE]=="application/x-www-form-urlencoded"} {
foreach qterm [split [string trim [dict get $W .post]] &] {
set qsplit [split $qterm =]
set nm [lindex $qsplit 0]
if {[regexp {^[a-z][a-z0-9]*$} $nm]} {
dict set W $nm [wappInt-url-decode [lindex $qsplit 1]]
}
}
return
}
# TODO: Decode multipart/form-data
}
|