In [287]:
from personal_info import userid, password, sid, progKey # setup your personal information, see personal_info.example.py
In [288]:
%%writefile AsusWebStorage.py
import uuid
import time
import hashlib
import hmac
from urllib2 import quote
from getpass import getpass
import requests
from lxml import etree
from collections import OrderedDict
SERVICE_PORTAL = "https://sp.yostore.net/"

class odict(OrderedDict):
    def __str__(self):        
        def _str(x):
            if isinstance(x,list):
                if len(x)==1:
                    return _str(x[0])
                return "\n"+"\n".join(_str(y).replace("\n", "\n\t") for y in x)
            return str(x) 
        return "ODICT:\n" + "\n".join("\t%s: %s"%(k,_str(v).replace("\n", "\n\t")) for k,v in self.iteritems())
    def _repr_html_(self):
        def _html(x):
            if isinstance(x,list):
                if len(x)==1:
                    return _html(x[0])
                return "<ol><b>LIST</b>:"+"\n".join("<li>"+_html(y)+"</li>" for y in x)+"</ol>"
            elif hasattr(x, "_repr_html_"):
                return x._repr_html_()
            else:
                return str(x) 
        return "<ul><b>ODICT</b>:" + "\n".join("<li>%s: %s</li>"%(k,_html(v)) for k,v in self.iteritems())+"</ul>"
        
def recursive_dict(element):
    # return element.tag, odict(map(recursive_dict,element)) or element.text
    if len(element):        
        rtn = odict()
        for e in element:            
            tag, d = recursive_dict(e)            
            rtn.setdefault(tag, []).append(d)
    else:
        rtn = element.text
        if rtn is None and 'name' in element.attrib and 'value' in element.attrib:
            return element.tag+"."+element.attrib['name'], element.attrib['value']
    return element.tag, rtn

def xml_to_dict(xmlstr):
    try:
        return recursive_dict(etree.fromstring(xmlstr))
    except:
        print "failed", xmlstr

def recursive_xml(d, dep="  "):        
        return "\n".join("%s<%s>%s</%s>"%(dep,  k, 
                                                                ("\n"+recursive_xml(v, dep+"  ") if isinstance(v, dict) else v), 
                                                                k) for k,v in d.items())
            
def dict_to_xml(d, roottag):
    return '<?xml version="1.0" encoding="utf-8"?>\n<%s>\n%s\n</%s>'%(roottag, recursive_xml(d), roottag)

def time_stamp():
    return  int(round(time.time() ))

ERROR_MSG ={0:'Success', 
                       2:'User Authentication Fail', 
                       3: 'Payload is not validate', 
                       5: 'Developer Authentication Fail',                       
                       225: 'Parameter Error',
                       504: 'OTP Auth Failed: USer ID/password/OTP incoreect or without OTP when required',
                       505: 'OTP Credential ID is locked',
                       508: "CAPTCHA Failed", 
                       999:'General Error'}
def arg_props(d, *keys):
    return [(k,d[k]) for k in keys if k in d and d[k] is not None]

class AsusWebStorage(object):    
    def __init__(self, sid, progkey, userid, password, language='zh_TW', service=1):
        self.__dict__.update(locals())
        self.session = requests.Session()
        
    def authString(self):
        method = "HMAC-SHA1"
        nonce = str(uuid.uuid1()).replace('-','')
        timestamp = time_stamp()
        plain = "nonce=%s&signature_method=%s&timestamp=%s"%(nonce,method,timestamp)
        quoted = quote(plain)    
        signature = quote(hmac.new(self.progkey, quoted, hashlib.sha1).digest().encode('base64').rstrip('\n'))
        return 'signature_method="%s",timestamp="%s",nonce="%s",signature="%s"'%(method, timestamp, nonce, signature)
    
    def post(self, act, url, payload, oauth=False):
        print "post", act, url, payload
        headers =  { "Cookie": "sid=%s;"%self.sid}
        if oauth:
            headers["Authorization"] = self.authString()
        data = dict_to_xml(odict(payload), act)
        self.last_response  = self.session.post(url, data=data, headers=headers)        
        rootname, result = xml_to_dict(self.last_response.content) 
        self.result = result
        status = int(result['status'][0])        
        if status != 0:            
            print "url="+url, "act="+act, "rootname="+rootname
            print "DATA:"
            print data
            if status in ERROR_MSG:                
                print "Error:", ERROR_MSG[status]
            else:
                print "Error: code=%d"%status
            return status, None
        return status, result    

    
    def props(self, *keys):
        return [(k, time_stamp() if k=="time" else getattr(self, k)) for k in keys]
    
    def requestservicegateway(self):
        act = "requestservicegateway"
        url = SERVICE_PORTAL + "member/%s/"%act
        payload = self.props('userid','password', 'language', 'service')
        status, result = self.post(act, url, payload)
        if not status:
            self.gateway = "https://%s/"%result['servicegateway'][0]
            return self.gateway        
    
    def acquiretoken(self):        
        act = "aaa"
        url = self.gateway + "member/acquiretoken/"
        payload = self.props ('userid', 'password', 'time')
        
        status, result = self.post(act, url, payload, oauth=True)
        if not status:
            self.token = result['token'][0]
            self.inforelay = "https://%s/"%result['inforelay'][0]
            self.webrelay = "https://%s/"%result['webrelay'][0]
            self.searchserver = "https://%s/"%result['searchserver'][0]
            self.package = result['package'][0]
            return self.token
        
    def connect(self):
        if self.requestservicegateway():
            for i in range(2): # acquiretoken sometimes fails for some reason
                if self.acquiretoken():
                    return True
                
    def getinfo(self):
        act = "getinfo"
        url = self.gateway + "member/%s/"%act
        payload = self.props ('userid', 'token', 'time')
        status, result = self.post(act, url, payload)
        return result
    
    def browsefolder(self, folderid, type=None, pageno=None, pagesize=None, sortby=1, sortdirection=0):
        act = "browse"
        url = self.inforelay + "inforelay/browsefolder/"
        payload = self.props ('token', 'language', 'userid') 
        payload += arg_props(locals(), "folderid", "type", "pageno", "pagesize", "sortby", "sortdirection")
        status, result = self.post(act, url, payload)
        return result
    
    def getpersonalsystemfolder(self, rawfoldername):
        act = "getpersonalsystemfolder"
        url = self.inforelay + "folder/%s/"%act
        payload = self.props("token", "userid") + arg_props(locals(), "rawfoldername")
        status, result = self.post(act, url, payload)
        if status is 0:
            return result['folderid'][0]
        
    def getlatestchangefiles(self, top=None, targetroot="-5", sortdirection=0):
        act = "getlatestchangefiles"
        url = self.inforelay + "file/%s/"%act
        payload = self.props("token", "userid") + arg_props(locals(), "top", "targetroot", "sortdirection")
        status, result = self.post(act, url, payload)
        if status is 0:
            return result['entry', isdi]
    def getallchangeseq(self):
    
        act = "getentryinfo"
        url = self.inforelay + "fsentry/%s/"%act
        payload = self.props("token") 
        status, result = self.post(act, url, payload)
        if status is 0:
            return result
        
    def getentryinfo(self, isfolder, entryid):
        act = "getentryinfo"
        url = self.inforelay + "fsentry/%s/"%act
        payload = self.props("token") + arg_props(locals(), "isfolder", "entryid")
        status, result = self.post(act, url, payload)
        if status is 0:
            return result
        
    def propfind(self, parent, find, type="system.unknown", isshared=None):
        act = "propfind"
        url = self.inforelay + "find/%s/"%act
        find = find.encode("base64").strip("\n")
        payload = self.props("token", "userid") + arg_props(locals(), "parent", "find", "type", "isshared")
        status, result = self.post(act, url, payload)
        if status is 0:
            return result
    
    def getmysyncfolder(self):
        act = "getmysyncfolder"
        url = self.inforelay + "folder/%s/"%act
        payload = self.props("userid", "token")
        status, result = self.post(act, url, payload)
        if status is 0:
            return result["id"][0]
    
    
Overwriting AsusWebStorage.py
In [289]:
%run AsusWebStorage.py
In [286]:
%%javascript
IPython.notebook.execute_cells_above()
IPython.notebook.get_cells()[1].code_mirror.setSize(null, 400)
In [290]:
# TEST        
aws = AsusWebStorage(sid, progKey, userid, password) 
if aws.connect():    
    folderid = aws.getpersonalsystemfolder('MySyncFolder')
aws.browsefolder(folderid)
    #86259931
post requestservicegateway https://sp.yostore.net/member/requestservicegateway/ [('userid', '[email protected]'), ('password', '5e7c12ebc1d7f16679a75def8f81977b'), ('language', 'zh_TW'), ('service', 1)]
post aaa https://sg01.asuswebstorage.com/member/acquiretoken/ [('userid', '[email protected]'), ('password', '5e7c12ebc1d7f16679a75def8f81977b'), ('time', 1408695874)]
post getpersonalsystemfolder https://ir01.asuswebstorage.com/folder/getpersonalsystemfolder/ [('token', 'es9qwgvsha9st'), ('userid', '[email protected]'), ('rawfoldername', 'MySyncFolder')]
post browse https://ir01.asuswebstorage.com/inforelay/browsefolder/ [('token', 'es9qwgvsha9st'), ('language', 'zh_TW'), ('userid', '[email protected]'), ('folderid', '86258859'), ('sortby', 1), ('sortdirection', 0)]
Out[290]:
    ODICT:
  • status: 0
  • logmessage: None
  • scrip: 1408695876906
  • rawfoldername: MySyncFolder
  • parent: -5
  • rootfolderid: -5
  • page:
      ODICT:
    • pageno: 1
    • pagesize: 3
    • totalcount: 3
    • hasnextpage: 0
  • folder:
      LIST:
      • ODICT:
      • id: 86652770
      • treesize: 3932700026
      • isgroupaware: 0
      • rawfoldername: Discrete Optimization
      • isbackup: 0
      • isorigdeleted: 0
      • ispublic: 1
      • createdtime: 2014-07-25 11:59:22.337
      • contributor: [email protected]
      • ODICT:
      • id: 86436877
      • treesize: 4237994
      • isgroupaware: 0
      • rawfoldername: Sample
      • isbackup: 0
      • isorigdeleted: 0
      • ispublic: 0
      • createdtime: 2014-07-22 21:46:20.763
      • contributor: [email protected]
      • ODICT:
      • id: 86259931
      • treesize: 33404059246
      • isgroupaware: 0
      • rawfoldername: test
      • isbackup: 0
      • isorigdeleted: 0
      • ispublic: 0
      • createdtime: 2014-07-20 16:11:45.103
      • contributor: [email protected]
  • owner: [email protected]
In [ ]:
ACT =  "requestservicegateway"
header = { "Cookie": "sid=%s;ONE_VER=1_0; path=/"%sid }
header = { "Cookie": "sid=%s;"%sid }

payload = odict([ ("userid", userid),
                           ("password", password), 
                           ("language", "zh_TW"),
                           ("service", 1)])
print "payload:\n", dict_to_xml(payload, ACT)
URL = service_portal + "member/%s/"%ACT
print "URL=", URL
r = requests.post(URL, data=dict_to_xml(payload, ACT), headers=header)
print "content:\n", r.content
print "cookie:\n", r.cookies.items()
print "header", r.headers
result =  xml_to_dict(r.content)[1]
print "status=", result['status']
gateway = "https://"+result['servicegateway']+"/"
print "gateway=", gateway
In [ ]:
ACT =  "tocompactform"
header = { "Cookie": "sid=%s;ONE_VER=1_0; path=/"%sid }
payload = odict([ ("userid", userid),
                           ("password", password), 
                           ("sharecode", "fdasfadsfasd"),
                           ])
print "payload:\n", dict_to_xml(payload, ACT)
URL = service_portal + "sharecode/%s/"%ACT
print "URL=", URL
r = requests.post(URL, data=dict_to_xml(payload, ACT), headers=header)
print "content:\n", r.content
print "cookie:\n", r.cookies.items()
print "header", r.headers
print "body:\n", r.content
result =  xml_to_dict(r.content)[1]
print result
print "status=", result['status']
print  result['compactsharecode']
In [ ]:
ACT =  "acquiretoken"
x = authString(progKey)
print x
header = { "Cookie": "sid=%s;ONE_VER=1_0; path=/"%sid, "Authorization": x  }
payload = odict([ ("userid", userid),
                           ("password", password), 
                           ("time", int(time.time())),
                           ])
URL = gateway + "member/%s/"%ACT
print "URL=", URL
print dict_to_xml(payload, 'aaa')
r = requests.post(URL, data=dict_to_xml(payload, 'aaa'), headers=header)
print "content:\n", r.content
print "cookie:\n", r.cookies.items()
print "header", r.headers
result =  xml_to_dict(r.content)[1]
print "status=", result['status']
token = result['token']
inforelay = "https://"+result['inforelay']+"/"
webrelay = "https://"+result['webrelay']+"/"
searchserver = "https://"+result['searchserver']+"/"
print inforelay, webrelay, searchserver, token
In [ ]:
ACT =  "acquiretoken"
payload = odict([ ("userid", aws.userid),
                           ("password", aws.password), 
                           ("time", time_stamp()),
                           ])
URL = gateway + "member/%s/"%ACT
print "URL=", URL
print dict_to_xml(payload, 'aaa')
status, result = aws.xxx('aaa', URL, payload, oauth=True)
print "status=", result['status']
token = result['token']
inforelay = "https://"+result['inforelay']+"/"
webrelay = "https://"+result['webrelay']+"/"
searchserver = "https://"+result['searchserver']+"/"
print inforelay, webrelay, searchserver, token
In [ ]:
ACT =  "getinfo"
header = { "Cookie": "sid=%s;ONE_VER=1_0; path=/"%sid  }
payload = odict([ ("userid", userid),
                           ("token", token), 
                           ("time", int(time.time())),
                           ])
URL = gateway + "member/%s/"%ACT
print "URL=", URL
data = dict_to_xml(payload, ACT)
r = requests.post(URL, data=data, headers=header)
print "content:\n", r.content
print "cookie:\n", r.cookies.items()
print "header", r.headers
result =  xml_to_dict(r.content)[1]
print "status=", result['status']
In [ ]:
ACT = ROOT = "getpersonalsystemfolder"
URL = inforelay + "folder/%s/"%ACT
print "URL=", URL
header = { "Cookie": "sid=%s;ONE_VER=1_0; path=/"%sid  }
payload = odict([ ("userid", userid),
                           ("token", token), 
                           ("rawfoldername", "MySyncFolder"),
                           ])
data = dict_to_xml(payload, ROOT)
r = requests.post(URL, data=data, headers=header)
print "content:\n", r.content
print "cookie:\n", r.cookies.items()
print "header", r.headers
result =  xml_to_dict(r.content)[1]
print "status=", result['status']

for k,v in result.items():
    print "%s:%s"%(k,v)
In [ ]:
ACT =  "browsefolder"
ROOT = "browse"
URL = inforelay + "inforelay/%s/"%ACT
print "URL=", URL
header = { "Cookie": "sid=%s;ONE_VER=1_0; path=/"%sid  }
payload = odict([ ("userid", userid),
                           ("token", token), 
                           ("language", "zh_TW"),
                           ("type", "VIDEO"),
                           ("folderid", 86259931),
                           ("pageno", 1),
                           ("pagesize", 10),
                           ("sortby", 1),
                           ("sortdirection", 0),
                           ("time", int(time.time())),
                           ])
data = dict_to_xml(payload, ROOT)
r = requests.post(URL, data=data, headers=header)
print "content:\n", r.content
print "cookie:\n", r.cookies.items()
print "header", r.headers
result =  xml_to_dict(r.content)[1]
print "status=", result['status']

for k,v in result.items():
    print "%s:%s"%(k,v)