From dcab79146b5a6a8092c5b9a730e331bb6222ea81 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 30 Mar 2021 20:14:10 +0300 Subject: [PATCH] net.urllib: allow `urllib.parse_query("format=%l")` --- vlib/net/urllib/urllib.v | 12 +++++++++--- vlib/net/urllib/urllib_test.v | 29 ++++++++++++++++++----------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/vlib/net/urllib/urllib.v b/vlib/net/urllib/urllib.v index 17e354a9e7..4960c26f3d 100644 --- a/vlib/net/urllib/urllib.v +++ b/vlib/net/urllib/urllib.v @@ -53,8 +53,9 @@ fn should_escape(c byte, mode EncodingMode) bool { // we could possibly allow, and parse will reject them if we // escape them (because hosts can`t use %-encoding for // ASCII bytes). - if - c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] { + if c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, + `"`, + ] { return false } } @@ -158,6 +159,11 @@ fn unescape(s_ string, mode EncodingMode) ?string { } n++ if i + 2 >= s.len || !ishex(s[i + 1]) || !ishex(s[i + 2]) { + if mode == .encode_query_component && i + 1 < s.len { + s = s[..i] + '%25' + s[(i + 1)..] + i += 4 // skip the %25 and the next character + continue + } s = s[i..] if s.len > 3 { s = s[..3] @@ -789,7 +795,7 @@ pub fn parse_query(query string) ?Values { // but any errors will be silent fn parse_query_silent(query string) Values { mut m := new_values() - parse_query_values(mut m, query) or { } + parse_query_values(mut m, query) or {} return m } diff --git a/vlib/net/urllib/urllib_test.v b/vlib/net/urllib/urllib_test.v index 947b88cf12..2d354efda7 100644 --- a/vlib/net/urllib/urllib_test.v +++ b/vlib/net/urllib/urllib_test.v @@ -1,7 +1,6 @@ // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. - import net.urllib fn test_net_urllib() { @@ -13,18 +12,14 @@ fn test_net_urllib() { assert false return } - assert u.scheme == 'https' && - u.hostname() == 'www.mydomain.com' && - u.port() == '8080' && - u.path == '/som/url' && - u.fragment == 'testfragment' && - u.user.username == 'joe' && - u.user.password == 'pass' + assert u.scheme == 'https' && u.hostname() == 'www.mydomain.com' && u.port() == '8080' + && u.path == '/som/url' && u.fragment == 'testfragment' && u.user.username == 'joe' + && u.user.password == 'pass' } fn test_str() { - url := urllib.parse("https://en.wikipedia.org/wiki/Brazil_(1985_film)") or { - panic("unable to parse URL") + url := urllib.parse('https://en.wikipedia.org/wiki/Brazil_(1985_film)') or { + panic('unable to parse URL') } assert url.str() == 'https://en.wikipedia.org/wiki/Brazil_(1985_film)' } @@ -33,6 +28,18 @@ fn test_escape_unescape() { original := 'те ст: т\\%' escaped := urllib.query_escape(original) assert escaped == '%D1%82%D0%B5+%D1%81%D1%82%3A+%D1%82%5C%25' - unescaped := urllib.query_unescape(escaped) or { assert false return } + unescaped := urllib.query_unescape(escaped) or { + assert false + return + } assert unescaped == original } + +fn test_parse_query() ? { + q1 := urllib.parse_query('format=%22%25l%3A+%25c+%25t%22') ? + q2 := urllib.parse_query('format="%l:+%c+%t"') ? + // dump(q1) + // dump(q2) + assert q1.data['format'].data == ['"%l: %c %t"'] + assert q2.data['format'].data == ['"%l: %c %t"'] +}