import re, sys, os
try:
    from urllib.parse import unquote, unquote_plus
except ImportError:
    from urlparse import unquote
    from urllib import unquote_plus    
import json
from hashlib import md5
import random

####################################################################################
# Utitlities
####################################################################################
REQUEST = re.compile ('([^ ]+) ([^ ]+)(( HTTP/([0-9.]+))$|$)')
CONNECTION = re.compile ('Connection: (.*)', re.IGNORECASE)

def crack_query (r):
    if type (r) is bytes:
        r = r.decode ("utf8")

    if not r: return {}
    if r[0]=='?': r=r[1:]    
    arg={}
    q = [x.split('=', 1) for x in r.split('&')]
    
    for each in q:
        k = unquote_plus (each [0])
        try: 
            t, k = k.split (":", 1)
        except ValueError:
            t = "str"

        v = unquote_plus (each [1])
        if len (each) == 2:
            if t == "str":
                pass
            elif t in ("i", "int"):
                v = int (v)
            elif t in ("n", "null"):
                v = None    
            elif t in ("f", "float"):
                v = float (v)
            elif t in ("l", "list"):
                v = v.split (",")
            elif t in ("b", "bool"):
                v = v.lower () in ("1", "true", "yes")
                
        if k in arg:
            if type (arg [k]) is not type ([]):
                arg[k] = [arg[k]]
            arg[k].append (v)
            
        else:
            arg[k] = v
            
    return arg

def crack_request (r):
    m = REQUEST.match (r)
    if m.end() == len(r):        
        uri=m.group(2)        
        if m.group(3):
            version = m.group(5)
        else:
            version = None    
        return m.group(1).lower(), uri, version
    else:
        return None, None, None

def join_headers (headers):
    r = []
    for i in range(len(headers)):
        if headers[i][0] in ' \t':    
            r[-1] = r[-1] + headers[i][1:]
        else:
            r.append (headers[i])
    return r

def get_header (head_reg, lines, group=1):
    for line in lines:
        m = head_reg.match (line)
        if m and m.end() == len(line):
            return m.group (group)
    return ''

def get_header_match (head_reg, lines):
    for line in lines:
        m = head_reg.match (line)
        if m and m.end() == len(line):
            return m
    return ''        

def get_extension (path):
    dirsep = path.rfind ('/')
    dotsep = path.rfind ('.')
    if dotsep > dirsep:
        return path[dotsep+1:]
    else:
        return ''

ALNUM = '0123456789abcdefghijklmnopqrstuvwxyz'
def md5uniqid (length = 13):    
    global ALNUM
    _id = ''
    for i in range (0, length):
        _id += random.choice(ALNUM)
    return md5 (_id.encode ("utf8")).hexdigest ()[length:]

def parse_params (header_val):
    d = {}
    header_filed = ""
    last_key = None
    for each in header_val.split (";"):
        if last_key:
            d [last_key] += ";" + each
            if each [-1] == '"':
                last_key = None
            continue
        
        each = each.strip ()
        if not each: continue
        
        try:
            a, b = each.split ("=", 1)
        except ValueError:
            if header_filed:
                header_filed += ":" + each
            else:    
                header_filed = each
            continue
            
        key = a.lower ()
        d [key] = b
        if len (b) >= 2 and  b [0] == '"' and b [-1] != '"':
            last_key = key    
    
    return header_filed, d
