require('common')

function issupport(url)
	if url:match('^http://u.115.com/file/') then return true end
	if url:match('^http://115.com/file/') then return true end
	return false
end

function GetRandString(size)
	local bstring = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
	local s = ''
	for i = 1, size do
		local n = math.random(1, 62)
		s = s .. bstring:sub(n, n)
	end
	return s
end

function GetRandKey(rs, ri, char1)
	print("---------------------------GetRandKey Start")
	local t = {
		['a'] = {{1,4,0},{2,4,1},{3,4,2},{4,3,0}},
		['b'] = {{3,3,0},{2,4,0},{1,4,2},{4,4,0}},
		['c'] = {{4,4,0},{2,3,1},{3,4,0},{1,4,0}},
		['d'] = {{2,4,1},{1,4,1},{3,3,2},{4,4,0}},
		['e'] = {{1,4,0},{2,4,1},{3,3,2},{4,4,0}},
		['x'] = {{4,4,0},{2,4,0},{3,4,2},{1,3,0}},
	}
	
	if char1:find("[abcde]") == nil then 
		char1 = 'x'
	end

	local rule = t[char1]
	local rand_key = char1
	for i,node in ipairs(rule) do
		local tmp = rs:sub(ri[node[1]]+1, ri[node[1]]+node[2])
		if node[3] == 1 then tmp = tmp:upper() 
		elseif node[3] == 2 then tmp = tmp:lower()
		end
		rand_key = rand_key..tmp
		print(tmp)
	end
	print("---------------------------GetRandKey End")
	return rand_key
end
--0756FA24   0689E378  ASCII "193902B6BD6A8657"
default_key = "193902B6BD6A8657"

function yywencrypt(message, key)
    local ffi = require("ffi")
    ffi.cdef[[
    void YYWEncrypt(const char* data, const char* key, char* outdata);
    ]]
    local dll = ffi.load("115encrypt")
    local len = (#message+16)*4/3 + 1
    local outdata = ffi.new("char [?]", len)
    dll.YYWEncrypt(message, key, outdata)
    return ffi.string(outdata)
end

function yywdecrypt(message, key)
    local ffi = require("ffi")
    ffi.cdef[[
    void YYWDecrypt(const char* data, const char* key, char* outdata);
    ]]
    local dll = ffi.load("115encrypt")
    local len = #message
    local outdata = ffi.new("char [?]", len)
    dll.YYWDecrypt(message, key, outdata)
    return ffi.string(outdata)
end

function YYWPackData(message, char1)
	print(message)
	print(char1)

	rs = GetRandString(115)
	print(rs)
	
	ri = {math.random(1,26), math.random(4, 111), math.random(8, 111), math.random(12, 111)}

	if char1:find("[abcde]") == nil then 
		char1 = 'x'
	end

	local rand_key = GetRandKey(rs, ri, char1)
	print("rand_key:"..rand_key)
			
	time = '1'..(ri[2]+char1:byte()+222)..(ri[3]+ri[1]+333)..(ri[4]*2+444)
	print(time)
	
	i = math.random(1, 107)
	pickcode = char1..string.char(0x41+ri[1])..rs:sub(i, i+7)
	print(pickcode)
	
	psize = #message
	print(psize)
	
	s = pickcode .. time .. psize .. default_key
	token = idown.crypt.md5(s, #s)
	print(token)
	
	enp = yywencrypt(message, rand_key)
	mask = yywencrypt(GetRandString(5)..string.reverse(rs), default_key)
	
	local data = {}
	data.enp = enp
	data.mask = mask
	data.picktime = time
	data.pickcode = pickcode
	data.psize = tostring(#message)
	data.secure = "2"
	data.token = token
	
	return data
end

function YYWUnpackData(data)
	mask = yywdecrypt(urldecode(data.mask), default_key)
	print(mask, #mask)
	mask = mask:sub(6)
	
	char1 = data.pickcode:sub(1,1)
	char2 = data.pickcode:sub(2,2)
	print(char1, char2)
	rs = string.reverse(mask)
	print(rs, #rs)
	
	print(data.picktime)
	ri = {}
	ri[1] = string.byte(char2) - 0x41
	ri[4] = (data.picktime:sub(8,10) - 444)/2
	ri[3] = (data.picktime:sub(5,7) - 333)-ri[1]
	ri[2] = (data.picktime:sub(2,4) - 222)-string.byte(char1)
	print(ri[1],ri[2],ri[3],ri[4])
	
	rand_key = GetRandKey(rs, ri, char1)
	print(rand_key, #rand_key)

	print(urldecode(data.enp))
	message = yywdecrypt(urldecode(data.enp), rand_key)
	--print(message)
	
	return message
end

function analyze(url)
    local json = require('json')
	print('-----------------------Enter analyze-----------------------')
	print('url:'..url)
	
	local agent = "UDown 3.3.1.13"
	
	local id = url:match('/file/([%w%d]+)')
	print('id:'..id)
	if id == nil then
		id = url:match('pickcode=([%w]+)')
	end
	
	local ip, addr = getmyip()
	print('ip:'..ip, 'addr:'..addr)
	
	local msg = string.format('{\n   "client_version" : "3.0",\n   "file_answer" : "",\n   "pick_code" : "%s"\n}\n', id)
	data = YYWPackData(msg, id:sub(1,1))
	postdata = string.format("enp=%s&pickcode=%s&picktime=%s&token=%s&mask=%s&secure=%s&psize=%s",
	urlencode(data.enp), urlencode(data.pickcode), data.picktime, data.token, urlencode(data.mask), data.secure, data.psize)
	
	local req = {}
	req.verb= "POST"
	req.agent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; .NET CLR 1.1.4322;.NET CLR 2.0.50727;.NET CLR 3.0.04506.648;.NET CLR 3.5.21022;.NET CLR 3.0.4506.2152;.NET CLR 3.5.30729;.NET4.0C;.NET4.0E; "..agent..")"
	req.postdata = postdata
	print(postdata)
	
	page = idown.requesturl("http://pro.api.115.com/default/index.php", "", json:encode(req))
	print(page)
	
	retmsg = YYWUnpackData(json:decode(page))
	
	if (retmsg:sub(1,1)~='{') then
		print('decode error!')
		return -1
	end
	print(retmsg)	
	retdata = json:decode(retmsg)
	if retdata.State ~= true then 
		print(print(idown.toansi(retdata.Message)))
		return -1
	end

	realurl = retdata['DownloadUrl'][addr]['Url'] or retdata['DownloadUrl'][1]['Url']
	print(realurl)
  
	realfilename = retdata.FileName
	title = realfilename
	
	result = {}
	result.realurl = realurl
	result.title = title
	result.realname = realfilename
	result.encode = 65001
	result.agent = agent

	retstr = json:encode(result)
	print('ret:'..retstr)
	
	return 1, retstr	
end