From 97565826efbc9e551829531875867c8f78378691 Mon Sep 17 00:00:00 2001 From: Oscar NihlgÄrd Date: Tue, 3 Apr 2018 12:15:01 +0200 Subject: Don't assume UTC in cookies.setCookie --- lib/pure/cookies.nim | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'lib/pure/cookies.nim') diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 8f16717ac..aca0ac2b4 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -51,26 +51,26 @@ proc setCookie*(key, value: string, domain = "", path = "", if secure: result.add("; Secure") if httpOnly: result.add("; HttpOnly") -proc setCookie*(key, value: string, expires: DateTime, +proc setCookie*(key, value: string, expires: DateTime|Time, domain = "", path = "", noName = false, secure = false, httpOnly = false): string = ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` - ## - ## **Note:** UTC is assumed as the timezone for ``expires``. return setCookie(key, value, domain, path, - format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"), + format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"), noname, secure, httpOnly) when isMainModule: - var tim = fromUnix(getTime().toUnix + 76 * (60 * 60 * 24)) + let expire = fromUnix(0) + 1.seconds - let cookie = setCookie("test", "value", tim.utc) - when not defined(testing): - echo cookie - let start = "Set-Cookie: test=value; Expires=" - assert cookie[0..start.high] == start + let cookies = [ + setCookie("test", "value", expire), + setCookie("test", "value", expire.local), + setCookie("test", "value", expire.utc) + ] + let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT" + doAssert cookies == [expected, expected, expected] let table = parseCookies("uid=1; kp=2") - assert table["uid"] == "1" - assert table["kp"] == "2" + doAssert table["uid"] == "1" + doAssert table["kp"] == "2" -- cgit 1.4.1-2-gfad0 From 0fad659bf72a48d076978655dd23fe369c2d232e Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 30 Apr 2018 02:52:58 +0200 Subject: make more tests green --- changelog.md | 3 +++ lib/pure/base64.nim | 8 ++++---- lib/pure/cookies.nim | 10 +++++----- lib/pure/httpcore.nim | 4 ++-- lib/pure/httpserver.nim | 8 ++++---- lib/pure/matchers.nim | 16 ++++++++-------- lib/pure/strutils.nim | 2 +- lib/pure/xmldom.nim | 14 +++++++------- tests/async/tlambda.nim | 4 ++-- 9 files changed, 36 insertions(+), 33 deletions(-) (limited to 'lib/pure/cookies.nim') diff --git a/changelog.md b/changelog.md index 17c169d22..251aca4ab 100644 --- a/changelog.md +++ b/changelog.md @@ -83,6 +83,9 @@ - ``nil`` for strings/seqs is finally gone. Instead the default value for these is ``"" / @[]``. +- Accessing the binary zero terminator in Nim's native strings + is now invalid. Internally a Nim string still has the trailing zero for + zero-copy interoperability with ``cstring``. ### Tool changes diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index 4b0d08292..bfb8a1666 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -52,7 +52,7 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped = if numLines > 0: inc(total, (numLines - 1) * newLine.len) result = newString(total) - var + var i = 0 r = 0 currLine = 0 @@ -76,7 +76,7 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped = currLine = 0 if i < s.len-1: - let + let a = ord(s[i]) b = ord(s[i+1]) result[r] = cb64[a shr 2] @@ -130,11 +130,11 @@ proc decode*(s: string): string = # total is an upper bound, as we will skip arbitrary whitespace: result = newString(total) - var + var i = 0 r = 0 while true: - while s[i] in Whitespace: inc(i) + while i < s.len and s[i] in Whitespace: inc(i) if i < s.len-3: let a = s[i].decodeByte diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index aca0ac2b4..eaff86ae6 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -25,16 +25,16 @@ proc parseCookies*(s: string): StringTableRef = result = newStringTable(modeCaseInsensitive) var i = 0 while true: - while s[i] == ' ' or s[i] == '\t': inc(i) + while i < s.len and (s[i] == ' ' or s[i] == '\t'): inc(i) var keystart = i - while s[i] != '=' and s[i] != '\0': inc(i) + while i < s.len and s[i] != '=': inc(i) var keyend = i-1 - if s[i] == '\0': break + if i >= s.len: break inc(i) # skip '=' var valstart = i - while s[i] != ';' and s[i] != '\0': inc(i) + while i < s.len and s[i] != ';': inc(i) result[substr(s, keystart, keyend)] = substr(s, valstart, i-1) - if s[i] == '\0': break + if i >= s.len: break inc(i) # skip ';' proc setCookie*(key, value: string, domain = "", path = "", diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim index f150fa1c1..5df26fdd5 100644 --- a/lib/pure/httpcore.nim +++ b/lib/pure/httpcore.nim @@ -190,11 +190,11 @@ proc len*(headers: HttpHeaders): int = return headers.table.len proc parseList(line: string, list: var seq[string], start: int): int = var i = 0 var current = "" - while line[start + i] notin {'\c', '\l', '\0'}: + while start+i < line.len and line[start + i] notin {'\c', '\l'}: i += line.skipWhitespace(start + i) i += line.parseUntil(current, {'\c', '\l', ','}, start + i) list.add(current) - if line[start + i] == ',': + if start+i < line.len and line[start + i] == ',': i.inc # Skip , current.setLen(0) diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index 632eb198a..9f54ed9e8 100644 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -126,7 +126,7 @@ when false: var dataAvail = false while dataAvail: dataAvail = recvLine(client, buf) # TODO: This is incorrect. - var L = toLower(buf.string) + var L = toLowerAscii(buf.string) if L.startsWith("content-length:"): var i = len("content-length:") while L[i] in Whitespace: inc(i) @@ -199,7 +199,7 @@ when false: notFound(client) else: when defined(Windows): - var ext = splitFile(path).ext.toLower + var ext = splitFile(path).ext.toLowerAscii if ext == ".exe" or ext == ".cgi": # XXX: extract interpreter information here? cgi = true @@ -303,7 +303,7 @@ proc next*(s: var Server) = if s.reqMethod == "POST": # Check for Expect header if s.headers.hasKey("Expect"): - if s.headers["Expect"].toLower == "100-continue": + if s.headers["Expect"].toLowerAscii == "100-continue": s.client.sendStatus("100 Continue") else: s.client.sendStatus("417 Expectation Failed") @@ -427,7 +427,7 @@ proc nextAsync(s: PAsyncHTTPServer) = if s.reqMethod == "POST": # Check for Expect header if s.headers.hasKey("Expect"): - if s.headers["Expect"].toLower == "100-continue": + if s.headers["Expect"].toLowerAscii == "100-continue": s.client.sendStatus("100 Continue") else: s.client.sendStatus("417 Expectation Failed") diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim index 685c3b07a..97223ed01 100644 --- a/lib/pure/matchers.nim +++ b/lib/pure/matchers.nim @@ -29,21 +29,21 @@ proc validEmailAddress*(s: string): bool {.noSideEffect, chars = Letters + Digits + {'!','#','$','%','&', '\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'} var i = 0 - if s[i] notin chars or s[i] == '.': return false - while s[i] in chars: - if s[i] == '.' and s[i+1] == '.': return false + if i >= s.len or s[i] notin chars or s[i] == '.': return false + while i < s.len and s[i] in chars: + if i+1 < s.len and s[i] == '.' and s[i+1] == '.': return false inc(i) - if s[i] != '@': return false + if i >= s.len or s[i] != '@': return false var j = len(s)-1 - if s[j] notin Letters: return false + if j >= 0 and s[j] notin Letters: return false while j >= i and s[j] in Letters: dec(j) inc(i) # skip '@' - while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) - if s[i] != '\0': return false + while i < s.len and s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) + if i != s.len: return false var x = substr(s, j+1) if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true - case toLower(x) + case toLowerAscii(x) of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name", "aero", "jobs", "museum": return true else: return false diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 4500a163f..3f01f0285 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1126,7 +1126,7 @@ proc unindent*(s: string, count: Natural, padding: string = " "): string var indentCount = 0 for j in 0..= line.len or line[j .. j + padding.len-1] != padding: indentCount = j break result.add(line[indentCount*padding.len .. ^1]) diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim index 3c891c81b..c38d36026 100644 --- a/lib/pure/xmldom.nim +++ b/lib/pure/xmldom.nim @@ -232,10 +232,10 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str raise newException(EInvalidCharacterErr, "Invalid character") # Exceptions if qualifiedName.contains(':'): - let qfnamespaces = qualifiedName.toLower().split(':') + let qfnamespaces = qualifiedName.toLowerAscii().split(':') if isNil(namespaceURI): raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil") - elif qfnamespaces[0] == "xml" and + elif qfnamespaces[0] == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace" and qfnamespaces[1] notin stdattrnames: raise newException(ENamespaceErr, @@ -311,10 +311,10 @@ proc createElement*(doc: PDocument, tagName: string): PElement = proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement = ## Creates an element of the given qualified name and namespace URI. if qualifiedName.contains(':'): - let qfnamespaces = qualifiedName.toLower().split(':') + let qfnamespaces = qualifiedName.toLowerAscii().split(':') if isNil(namespaceURI): raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil") - elif qfnamespaces[0] == "xml" and + elif qfnamespaces[0] == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace" and qfnamespaces[1] notin stdattrnames: raise newException(ENamespaceErr, @@ -533,13 +533,13 @@ proc `prefix=`*(n: PNode, value: string) = if isNil(n.fNamespaceURI): raise newException(ENamespaceErr, "namespaceURI cannot be nil") - elif value.toLower() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace": + elif value.toLowerAscii() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace": raise newException(ENamespaceErr, "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"") - elif value.toLower() == "xmlns" and n.fNamespaceURI != "http://www.w3.org/2000/xmlns/": + elif value.toLowerAscii() == "xmlns" and n.fNamespaceURI != "http://www.w3.org/2000/xmlns/": raise newException(ENamespaceErr, "When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"") - elif value.toLower() == "xmlns" and n.fNodeType == AttributeNode: + elif value.toLowerAscii() == "xmlns" and n.fNodeType == AttributeNode: raise newException(ENamespaceErr, "An AttributeNode cannot have a prefix of \"xmlns\"") n.fNodeName = value & ":" & n.fLocalName diff --git a/tests/async/tlambda.nim b/tests/async/tlambda.nim index d187c0d50..8f570689b 100644 --- a/tests/async/tlambda.nim +++ b/tests/async/tlambda.nim @@ -1,7 +1,7 @@ # bug 2007 -import asyncdispatch, asyncnet, logging, json, uri, strutils, future +import asyncdispatch, asyncnet, logging, json, uri, strutils, sugar type Builder = ref object @@ -27,7 +27,7 @@ proc newBuild*(onProgress: ProgressCB): Build = result.onProgress = onProgress proc start(build: Build, repo, hash: string) {.async.} = - let path = repo.parseUri().path.toLower() + let path = repo.parseUri().path.toLowerAscii() proc onProgress(builder: Builder, message: string) {.async.} = debug($message) -- cgit 1.4.1-2-gfad0