2 coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
3 Understanding is not required. Only obedience.
5 This program is free software. It comes without any warranty, to
6 the extent permitted by applicable law. You can redistribute it
7 and/or modify it under the terms of the Do What The Fuck You Want
8 To Public License, Version 2, as published by Sam Hocevar. See
9 http://sam.zoy.org/wtfpl/COPYING for more details.
22 (self includes: '<>&') ifFalse: [ ^self ].
23 res := StringBuffer new.
25 c == $< ifTrue: [ res << '<' ]
27 c == $> ifTrue: [ res << '>' ]
29 c == $& ifTrue: [ res << '&' ]
30 ifFalse: [ res << c ]]]].
41 reqMethod "string: GET, POST, etc"
42 reqHost "string: host name"
43 reqPath "string: path"
44 reqFile "string: file name"
45 reqHash "string: text after '#'"
46 reqVars "dictionary: (nameSymbol stringValue)"
47 reqFields "header fields"
50 ^new: s abortBlock: aBlock [
53 obj abortBlock: aBlock.
59 ^self new: s abortBlock: [:err | self error: err ]
63 'method: ' print. reqMethod print. '|' printNl.
64 'host: ' print. reqHost print. '|' printNl.
65 'path: ' print. reqPath print. '|' printNl.
66 'file: ' print. reqFile print. '|' printNl.
67 'hash: ' print. reqHash print. '|' printNl.
68 'vars: ' print. reqVars print. '|' printNl.
69 'fields: ' print. reqFields print. '|' printNl.
97 ^reqVars at: aName asSymbol ifAbsent: [ nil ].
100 var: aName ifAbsent: aBlock [
101 ^reqVars at: aName asSymbol ifAbsent: [ aBlock value ].
104 var: aName put: aValue [
105 reqVars at: aName asSymbol put: aValue.
113 ^reqFields at: aName ifAbsent: [ nil ]
118 lines := (reqStr removeTrailingBlanks break: '\n') asArray.
119 lines size < 1 ifTrue: [ abortBlock value: 'empty header' ].
120 lines transform: [:str | str removeTrailingBlanks ].
121 (req := (lines at: 1) break: ' ') size < 3 ifTrue: [ abortBlock value: 'invalid request line' ].
122 reqMethod := req at: 1.
123 self parsePath: (req at: 2).
124 self parseFields: lines.
125 reqHost := reqFields at: 'host' ifAbsent: [ reqHost ].
130 reqFields := Dictionary new.
131 "TODO: lines starting with space is 'continuation'"
132 2 to: lines size do: [:idx |
133 (p := (s := lines at: idx) position: $:) ifNotNil: [
134 n := (s from: 1 to: p - 1) transform: [:c | c lowerCase ].
136 [(p < s size) and: [ (s at: p) isBlank ]] whileTrue: [ p := p + 1 ].
138 reqFields at: n put: v.
139 "n print. '|' print. v print. '|' printNl."
146 reqHash := ''. reqHost := ''.
147 reqVars := Dictionary new.
148 (aPath from: 1 to: 7) = 'http://' ifTrue: [
149 "we have a host here"
150 (p := (aPath := aPath from: 8) indexOf: '/') ifNil: [
154 reqHost := aPath from: 1 to: p - 1.
155 aPath := aPath from: p.
158 (p := aPath indexOf: '?') ifNil: [
159 (p := aPath indexOf: '#') ifNil: [
162 reqPath := aPath from: 1 to: p - 1.
163 reqHash := aPath from: p + 1.
166 reqPath := aPath from: 1 to: p - 1.
167 aPath := aPath from: p + 1.
168 (p := aPath indexOf: '#') ifNotNil: [
169 reqHash := aPath from: p + 1.
170 aPath := aPath from: 1 to: p - 1.
172 self parseVars: aPath.
175 [ 'rp: ' print. reqPath printNl.
177 'rp: ' print. reqPath print. '|' print. reqFile print. '|' printNl.
184 (aVars break: '&') do: [:vv :p :n :v |
185 (p := vv indexOf: '=') ifNil: [
189 n := (vv from: 1 to: p - 1) fromUrl.
190 v := (vv from: p + 1) fromUrl.
198 reqPath isEmpty ifTrue: [ reqPath := '/'. reqFile := ''. ^self ].
199 reqPath lastChar == $/
203 (p := reqPath lastPosition: $/) ifNil: [ reqFile := reqPath. reqPath := '/'. ^self ].
204 reqFile := reqPath from: p+1.
205 reqPath := reqPath from: 1 to: p-1.
207 p := reqPath break: '/'.
212 res isEmpty ifFalse: [ res removeFirst ]
219 res do: [:dir | p := '/' + dir + p ].