10a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom test.test_support import run_unittest, check_warnings
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport cgi
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport tempfile
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport unittest
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass HackedSysModule:
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # The regression test will have real values in sys.argv, which
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # will completely confuse the test of the cgi module
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    argv = []
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    stdin = sys.stdin
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaocgi.sys = HackedSysModule()
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry:
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from cStringIO import StringIO
180a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept ImportError:
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from StringIO import StringIO
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass ComparableException:
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, err):
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.err = err
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __str__(self):
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return str(self.err)
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __cmp__(self, anExc):
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not isinstance(anExc, Exception):
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return -1
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        x = cmp(self.err.__class__, anExc.__class__)
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if x != 0:
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return x
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return cmp(self.err.args, anExc.args)
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __getattr__(self, attr):
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return getattr(self.err, attr)
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef do_test(buf, method):
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    env = {}
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if method == "GET":
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fp = None
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env['REQUEST_METHOD'] = 'GET'
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env['QUERY_STRING'] = buf
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    elif method == "POST":
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fp = StringIO(buf)
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env['REQUEST_METHOD'] = 'POST'
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env['CONTENT_LENGTH'] = str(len(buf))
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        raise ValueError, "unknown method: %s" % method
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return cgi.parse(fp, env, strict_parsing=1)
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except StandardError, err:
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return ComparableException(err)
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoparse_strict_test_cases = [
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("", ValueError("bad query field: ''")),
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("&", ValueError("bad query field: ''")),
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("&&", ValueError("bad query field: ''")),
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    (";", ValueError("bad query field: ''")),
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    (";&;", ValueError("bad query field: ''")),
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # Should the next few really be valid?
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("=", {}),
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("=&=", {}),
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("=;=", {}),
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # This rest seem to make sense
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("=a", {'': ['a']}),
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("&=a", ValueError("bad query field: ''")),
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("=a&", ValueError("bad query field: ''")),
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("=&a", ValueError("bad query field: 'a'")),
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("b=a", {'b': ['a']}),
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("b+=a", {'b ': ['a']}),
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("a=b=a", {'a': ['b=a']}),
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("a=+b=a", {'a': [' b=a']}),
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("&b=a", ValueError("bad query field: ''")),
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("b&=a", ValueError("bad query field: 'b'")),
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("a=a+b&b=b+c", {'a': ['a b'], 'b': ['b c']}),
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("a=a+b&a=b+a", {'a': ['a b', 'b a']}),
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("x=1&y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("x=1;y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("x=1;y=2.0;z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("Hbc5161168c542333633315dee1182227:key_store_seqid=400006&cuyer=r&view=bustomer&order_id=0bb2e248638833d48cb7fed300000f1b&expire=964546263&lobale=en-US&kid=130003.300038&ss=env",
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao     {'Hbc5161168c542333633315dee1182227:key_store_seqid': ['400006'],
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'cuyer': ['r'],
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'expire': ['964546263'],
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'kid': ['130003.300038'],
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'lobale': ['en-US'],
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'order_id': ['0bb2e248638833d48cb7fed300000f1b'],
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'ss': ['env'],
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'view': ['bustomer'],
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      }),
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ("group_id=5470&set=custom&_assigned_to=31392&_status=1&_category=100&SUBMIT=Browse",
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao     {'SUBMIT': ['Browse'],
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      '_assigned_to': ['31392'],
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      '_category': ['100'],
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      '_status': ['1'],
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'group_id': ['5470'],
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      'set': ['custom'],
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao      })
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    ]
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef first_elts(list):
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return map(lambda x:x[0], list)
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef first_second_elts(list):
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return map(lambda p:(p[0], p[1][0]), list)
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef gen_result(data, environ):
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    fake_stdin = StringIO(data)
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    fake_stdin.seek(0)
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form = cgi.FieldStorage(fp=fake_stdin, environ=environ)
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    result = {}
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for k, v in dict(form).items():
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result[k] = isinstance(v, list) and form.getlist(k) or v.value
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return result
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass CgiTests(unittest.TestCase):
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_escape(self):
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual("test & string", cgi.escape("test & string"))
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual("&lt;test string&gt;", cgi.escape("<test string>"))
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual("&quot;test string&quot;", cgi.escape('"test string"', True))
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_strict(self):
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for orig, expect in parse_strict_test_cases:
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # Test basic parsing
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            d = do_test(orig, "GET")
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(d, expect, "Error parsing %s" % repr(orig))
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            d = do_test(orig, "POST")
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(d, expect, "Error parsing %s" % repr(orig))
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            env = {'QUERY_STRING': orig}
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            fcd = cgi.FormContentDict(env)
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sd = cgi.SvFormContentDict(env)
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            fs = cgi.FieldStorage(environ=env)
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if isinstance(expect, dict):
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # test dict interface
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertEqual(len(expect), len(fcd))
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertItemsEqual(expect.keys(), fcd.keys())
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertItemsEqual(expect.values(), fcd.values())
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertItemsEqual(expect.items(), fcd.items())
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertEqual(fcd.get("nonexistent field", "default"), "default")
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertEqual(len(sd), len(fs))
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertItemsEqual(sd.keys(), fs.keys())
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertEqual(fs.getvalue("nonexistent field", "default"), "default")
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # test individual fields
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                for key in expect.keys():
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    expect_val = expect[key]
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.assertTrue(fcd.has_key(key))
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.assertItemsEqual(fcd[key], expect[key])
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.assertEqual(fcd.get(key, "default"), fcd[key])
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.assertTrue(fs.has_key(key))
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if len(expect_val) > 1:
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        single_value = 0
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    else:
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        single_value = 1
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    try:
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        val = sd[key]
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    except IndexError:
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertFalse(single_value)
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertEqual(fs.getvalue(key), expect_val)
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    else:
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertTrue(single_value)
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertEqual(val, expect_val[0])
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertEqual(fs.getvalue(key), expect_val[0])
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.assertItemsEqual(sd.getlist(key), expect_val)
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if single_value:
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertItemsEqual(sd.values(),
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                                first_elts(expect.values()))
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        self.assertItemsEqual(sd.items(),
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                                first_second_elts(expect.items()))
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_weird_formcontentdict(self):
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Test the weird FormContentDict classes
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env = {'QUERY_STRING': "x=1&y=2.0&z=2-3.%2b0&1=1abc"}
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        expect = {'x': 1, 'y': 2.0, 'z': '2-3.+0', '1': '1abc'}
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        d = cgi.InterpFormContentDict(env)
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for k, v in expect.items():
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(d[k], v)
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for k, v in d.items():
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(expect[k], v)
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertItemsEqual(expect.values(), d.values())
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_log(self):
1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cgi.log("Testing")
1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cgi.logfp = StringIO()
1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cgi.initlog("%s", "Testing initlog 1")
1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cgi.log("%s", "Testing log 2")
1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(cgi.logfp.getvalue(), "Testing initlog 1\nTesting log 2\n")
1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if os.path.exists("/dev/null"):
1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.logfp = None
1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.logfile = "/dev/null"
1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.initlog("%s", "Testing log 3")
1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.log("Testing log 4")
2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_fieldstorage_readline(self):
2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # FieldStorage uses readline, which has the capacity to read all
2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # contents of the input file into memory; we use readline's size argument
2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # to prevent that for files that do not contain any newlines in
2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # non-GET/HEAD requests
2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        class TestReadlineFile:
2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def __init__(self, file):
2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.file = file
2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.numcalls = 0
2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def readline(self, size=None):
2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.numcalls += 1
2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if size:
2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    return self.file.readline(size)
2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                else:
2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    return self.file.readline()
2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            def __getattr__(self, name):
2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                file = self.__dict__['file']
2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                a = getattr(file, name)
2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if not isinstance(a, int):
2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    setattr(self, name, a)
2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return a
2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f = TestReadlineFile(tempfile.TemporaryFile())
2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f.write('x' * 256 * 1024)
2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f.seek(0)
2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env = {'REQUEST_METHOD':'PUT'}
2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fs = cgi.FieldStorage(fp=f, environ=env)
2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # if we're not chunking properly, readline is only called twice
2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # (by read_binary); if we are chunking properly, it will be called 5 times
2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # as long as the chunksize is 1 << 16.
2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertTrue(f.numcalls > 2)
2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_fieldstorage_multipart(self):
2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        #Test basic FieldStorage multipart parsing
2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        env = {'REQUEST_METHOD':'POST', 'CONTENT_TYPE':'multipart/form-data; boundary=---------------------------721837373350705526688164684', 'CONTENT_LENGTH':'558'}
2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        postdata = """-----------------------------721837373350705526688164684
2390a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="id"
2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao1234
2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao-----------------------------721837373350705526688164684
2430a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="title"
2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao-----------------------------721837373350705526688164684
2470a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="file"; filename="test.txt"
2480a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Type: text/plain
2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2500a8c90248264a8b26970b4473770bcc3df8515fJosh GaoTesting 123.
2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao-----------------------------721837373350705526688164684
2530a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="submit"
2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Add\x20
2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao-----------------------------721837373350705526688164684--
2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""
2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fs = cgi.FieldStorage(fp=StringIO(postdata), environ=env)
2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(fs.list), 4)
2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        expect = [{'name':'id', 'filename':None, 'value':'1234'},
2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                  {'name':'title', 'filename':None, 'value':''},
2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                  {'name':'file', 'filename':'test.txt','value':'Testing 123.\n'},
2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                  {'name':'submit', 'filename':None, 'value':' Add '}]
2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for x in range(len(fs.list)):
2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            for k, exp in expect[x].items():
2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                got = getattr(fs.list[x], k)
2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.assertEqual(got, exp)
2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    _qs_result = {
2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        'key1': 'value1',
2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        'key2': ['value2x', 'value2y'],
2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        'key3': 'value3',
2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        'key4': 'value4'
2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    }
2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def testQSAndUrlEncode(self):
2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = "key2=value2x&key3=value3&key4=value4"
2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ = {
2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'CONTENT_LENGTH':   str(len(data)),
2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'CONTENT_TYPE':     'application/x-www-form-urlencoded',
2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'QUERY_STRING':     'key1=value1&key2=value2y',
2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'REQUEST_METHOD':   'POST',
2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        }
2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        v = gen_result(data, environ)
2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(self._qs_result, v)
2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def testQSAndFormData(self):
2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = """
2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
2890a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="key2"
2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gaovalue2y
2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
2930a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="key3"
2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gaovalue3
2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
2970a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="key4"
2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gaovalue4
3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123--
3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""
3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ = {
3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'CONTENT_LENGTH':   str(len(data)),
3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'CONTENT_TYPE':     'multipart/form-data; boundary=-123',
3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'QUERY_STRING':     'key1=value1&key2=value2x',
3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'REQUEST_METHOD':   'POST',
3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        }
3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        v = gen_result(data, environ)
3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(self._qs_result, v)
3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def testQSAndFormDataFile(self):
3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = """
3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
3140a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="key2"
3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gaovalue2y
3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
3180a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="key3"
3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gaovalue3
3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
3220a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="key4"
3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gaovalue4
3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123
3260a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Disposition: form-data; name="upload"; filename="fake.txt"
3270a8c90248264a8b26970b4473770bcc3df8515fJosh GaoContent-Type: text/plain
3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gaothis is the content of the fake file
3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao---123--
3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""
3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ = {
3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'CONTENT_LENGTH':   str(len(data)),
3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'CONTENT_TYPE':     'multipart/form-data; boundary=-123',
3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'QUERY_STRING':     'key1=value1&key2=value2x',
3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'REQUEST_METHOD':   'POST',
3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        }
3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result = self._qs_result.copy()
3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result.update({
3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            'upload': 'this is the content of the fake file\n'
3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        })
3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        v = gen_result(data, environ)
3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(result, v)
3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_deprecated_parse_qs(self):
3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # this func is moved to urlparse, this is just a sanity check
3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        with check_warnings(('cgi.parse_qs is deprecated, use urlparse.'
3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'parse_qs instead', PendingDeprecationWarning)):
3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual({'a': ['A1'], 'B': ['B3'], 'b': ['B2']},
3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             cgi.parse_qs('a=A1&b=B2&B=B3'))
3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_deprecated_parse_qsl(self):
3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # this func is moved to urlparse, this is just a sanity check
3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        with check_warnings(('cgi.parse_qsl is deprecated, use urlparse.'
3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'parse_qsl instead', PendingDeprecationWarning)):
3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual([('a', 'A1'), ('b', 'B2'), ('B', 'B3')],
3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             cgi.parse_qsl('a=A1&b=B2&B=B3'))
3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_parse_header(self):
3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header("text/plain"),
3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("text/plain", {}))
3640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header("text/vnd.just.made.this.up ; "),
3660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("text/vnd.just.made.this.up", {}))
3670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header("text/plain;charset=us-ascii"),
3690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("text/plain", {"charset": "us-ascii"}))
3700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header('text/plain ; charset="us-ascii"'),
3720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("text/plain", {"charset": "us-ascii"}))
3730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header('text/plain ; charset="us-ascii"; another=opt'),
3750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("text/plain", {"charset": "us-ascii", "another": "opt"}))
3760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header('attachment; filename="silly.txt"'),
3780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("attachment", {"filename": "silly.txt"}))
3790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header('attachment; filename="strange;name"'),
3810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("attachment", {"filename": "strange;name"}))
3820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header('attachment; filename="strange;name";size=123;'),
3840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("attachment", {"filename": "strange;name", "size": "123"}))
3850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(
3860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cgi.parse_header('form-data; name="files"; filename="fo\\"o;bar"'),
3870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ("form-data", {"name": "files", "filename": 'fo"o;bar'}))
3880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3900a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef test_main():
3910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    run_unittest(CgiTests)
3920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3930a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__':
3940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    test_main()
395