示例#1
0
def parse_qs(qstr, ignore_exc=True, encoding=DEFAULT_ENCODING):
    '''
    Parse a url encoded string (a=b&c=d) into a QueryString object.
    
    @param url_enc_str: The string to parse
    @return: A QueryString object (a dict wrapper). 

    >>> parse_qs('id=3')
    QueryString({u'id': [u'3']})
    >>> parse_qs('id=3&id=4')
    QueryString({u'id': [u'3', u'4']})
    >>> parse_qs('id=3&ff=4&id=5')
    QueryString({u'id': [u'3', u'5'], u'ff': [u'4']})
    >>> parse_qs('pname')
    QueryString({u'pname': [u'']})
    >>> parse_qs(u'%B1%D0%B1%D1=%B1%D6%B1%D7', encoding='euc-jp')
    QueryString({u'\u9834\u82f1': [u'\u75ab\u76ca']})
    >>> parse_qs('%B1%D0%B1%D1=%B1%D6%B1%D7', encoding='euc-jp')
    QueryString({u'\u9834\u82f1': [u'\u75ab\u76ca']})
    '''
    qs = QueryString(encoding=encoding)

    if qstr:
        # convert to string if unicode
        if isinstance(qstr, unicode):
            qstr = qstr.encode(encoding, 'ignore')
        try:
            odict = OrderedDict()
            for name, value in urlparse.parse_qsl(qstr,
                                                  keep_blank_values=True,
                                                  strict_parsing=False):
                if name in odict:
                    odict[name].append(value)
                else:
                    odict[name] = [value]
        except Exception:
            if not ignore_exc:
                raise w3afException('Error while parsing "%r"' % (qstr,))
        else:
            def decode(item):
                return (
                    item[0].decode(encoding, 'ignore'),
                    [e.decode(encoding, 'ignore') for e in item[1]]
                )
            qs.update((decode(item) for item in odict.items()))
    return qs
示例#2
0
def create_fuzzable_request(req_url, method='GET', post_data='',
                            add_headers=None):
    '''
    Creates a fuzzable request based on the input parameters.

    @param req_url: Either a url_object that represents the URL or a
        HTTPRequest instance. If the latter is the case the `method` and
        `post_data` values are taken from the HTTPRequest object as well
        as the values in `add_headers` will be merged with the request's
        headers.
    @param method: A string that represents the method ('GET', 'POST', etc)
    @param post_data: A string that represents the postdata.
    @param add_headers: A dict that holds the headers. If `req_url` is a
        request then this dict will be merged with the request's headers.
    '''
    if isinstance(req_url, HTTPRequest):
        url = req_url.url_object
        post_data = str(req_url.get_data() or '')
        method = req_url.get_method()
        headers = dict(req_url.headers)
        headers.update(add_headers or {})
    else:
        url = req_url
        headers = add_headers or {}

    # Just a query string request! No postdata
    if not post_data:
        req = HTTPQSRequest(url, method, headers)
 
    else: # Seems to be something that has post data
        data = {}
        conttype = ''
        for hname in headers.keys(): # '.keys()' is just fine. Don't
            hnamelow = hname.lower() # remove it.
            if hnamelow == 'content-length':
                del headers[hname]
            elif hnamelow == 'content-type':
                conttype = headers.get('content-type', '').lower()
        
        # Case #1 - JSON request
        try:
            data = json.loads(post_data)
        except:
            pass

        if data:
            req = JSONPostDataRequest(url, method, headers, dc=data)
        
        # Case #2 - XMLRPC request
        elif all(map(lambda stop: stop in post_data.lower(), XMLRPC_WORDS)):
            req = XMLRPCRequest(post_data, url, method, headers)

        else:
            # Case #3 - multipart form data - prepare data container
            if conttype.startswith('multipart/form-data'):
                pdict = cgi.parse_header(conttype)[1]
                try:
                    dc = cgi.parse_multipart(StringIO(post_data), pdict)
                except:
                    om.out.debug('Multipart form data is invalid, the browser '
                                 'sent something weird.')
                else:
                    data = QueryString()
                    data.update(dc)
                    # We process multipart requests as x-www-form-urlencoded
                    # TODO: We need native support of multipart requests!
                    headers['content-type'] = \
                                        'application/x-www-form-urlencoded'
            
            # Case #4 - a typical post request
            else:
                try:
                    data = parse_qs(post_data)
                except:
                    om.out.debug('Failed to create a data container that '
                                 'can store this data: "' + post_data + '".')
            # Finally create request
            req = httpPostDataRequest(url, method, headers, dc=data)
    return req