diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2009-05-08 16:36:06 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2009-05-08 16:36:06 +0200 |
commit | db4f617afcd095db087dcb52e3ea603cca111da7 (patch) | |
tree | eeffcc8fb523171dc394c136acf9b8006ec4138f /lib/base | |
parent | 08bc9ac03c49db7bfcdee82f46aadf95a324e015 (diff) | |
download | Nim-db4f617afcd095db087dcb52e3ea603cca111da7.tar.gz |
version 0.7.8
Diffstat (limited to 'lib/base')
-rw-r--r-- | lib/base/cgi.nim | 119 |
1 files changed, 65 insertions, 54 deletions
diff --git a/lib/base/cgi.nim b/lib/base/cgi.nim index 0dc3a4394..5cf6d0bfa 100644 --- a/lib/base/cgi.nim +++ b/lib/base/cgi.nim @@ -103,71 +103,77 @@ proc cgiError*(msg: string) {.noreturn.} = e.msg = msg raise e -proc readData*(allowedMethods: set[TRequestMethod] = - {methodNone, methodPost, methodGet}): PStringTable = - ## Read CGI data. If the client does not use a method listed in the - ## `allowedMethods` set, an `ECgi` exception is raised. - result = newStringTable() - var enc: string # encoded data +proc getEncodedData(allowedMethods: set[TRequestMethod]): string = case getenv("REQUEST_METHOD") of "POST": if methodPost notin allowedMethods: cgiError("'REQUEST_METHOD' 'POST' is not supported") - # read from stdin: var L = parseInt(getenv("CONTENT_LENGTH")) - enc = newString(L) - if readBuffer(stdin, addr(enc[0]), L) != L: + result = newString(L) + if readBuffer(stdin, addr(result[0]), L) != L: cgiError("cannot read from stdin") of "GET": if methodGet notin allowedMethods: cgiError("'REQUEST_METHOD' 'GET' is not supported") - # read from the QUERY_STRING environment variable: - enc = getenv("QUERY_STRING") + result = getenv("QUERY_STRING") else: - if methodNone in allowedMethods: - return result - else: + if methodNone notin allowedMethods: cgiError("'REQUEST_METHOD' must be 'POST' or 'GET'") - - # decode everything in one pass: - var i = 0 - var name = "" - var value = "" - while true: - setLen(name, 0) # reuse memory - while true: - case enc[i] - of '\0': return - of '%': - var x = 0 - handleHexChar(enc[i+1], x) - handleHexChar(enc[i+2], x) - inc(i, 2) - add(name, chr(x)) - of '+': add(name, ' ') - of '=', '&': break - else: add(name, enc[i]) - inc(i) - if enc[i] != '=': cgiError("'=' expected") - inc(i) # skip '=' - setLen(value, 0) # reuse memory - while true: - case enc[i] - of '%': - var x = 0 - handleHexChar(enc[i+1], x) - handleHexChar(enc[i+2], x) - inc(i, 2) - add(value, chr(x)) - of '+': add(value, ' ') - of '&', '\0': break - else: add(value, enc[i]) - inc(i) - result[name] = value - if enc[i] == '&': inc(i) - elif enc[i] == '\0': break - else: cgiError("'&' expected") +iterator decodeData*(allowedMethods: set[TRequestMethod] = + {methodNone, methodPost, methodGet}): tuple[key, value: string] = + ## Reads and decodes CGI data and yields the (name, value) pairs the + ## data consists of. If the client does not use a method listed in the + ## `allowedMethods` set, an `ECgi` exception is raised. + var enc = getEncodedData(allowedMethods) + if not isNil(enc): + # decode everything in one pass: + var i = 0 + var name = "" + var value = "" + while enc[i] != '\0': + setLen(name, 0) # reuse memory + while true: + case enc[i] + of '\0': break + of '%': + var x = 0 + handleHexChar(enc[i+1], x) + handleHexChar(enc[i+2], x) + inc(i, 2) + add(name, chr(x)) + of '+': add(name, ' ') + of '=', '&': break + else: add(name, enc[i]) + inc(i) + if enc[i] != '=': cgiError("'=' expected") + inc(i) # skip '=' + setLen(value, 0) # reuse memory + while true: + case enc[i] + of '%': + var x = 0 + handleHexChar(enc[i+1], x) + handleHexChar(enc[i+2], x) + inc(i, 2) + add(value, chr(x)) + of '+': add(value, ' ') + of '&', '\0': break + else: add(value, enc[i]) + inc(i) + yield (name, value) + if enc[i] == '&': inc(i) + elif enc[i] == '\0': break + else: cgiError("'&' expected") + +proc readData*(allowedMethods: set[TRequestMethod] = + {methodNone, methodPost, methodGet}): PStringTable = + ## Read CGI data. If the client does not use a method listed in the + ## `allowedMethods` set, an `ECgi` exception is raised. + result = newStringTable() + for name, value in decodeData(allowedMethods): + result[name] = value + proc validateData*(data: PStringTable, validKeys: openarray[string]) = ## validates data; raises `ECgi` if this fails. This checks that each variable ## name of the CGI `data` occurs in the `validKeys` array. @@ -323,8 +329,13 @@ proc setTestData*(keysvalues: openarray[string]) = proc writeContentType*() = ## call this before starting to send your HTML data to `stdout`. This - ## is just a shorthand for: + ## implements this part of the CGI protocol: ## ## .. code-block:: Nimrod ## write(stdout, "Content-type: text/html\n\n") + ## + ## It also modifies the debug stack traces so that they contain + ## ``<br />`` and are easily readable in a browser. write(stdout, "Content-type: text/html\n\n") + system.stackTraceNewLine = "<br />\n" + |