NextPVR Forums
  • ______
  • Home
  • New Posts
  • Wiki
  • Members
  • Help
  • Search
  • Register
  • Login
  • Home
  • Wiki
  • Members
  • Help
  • Search
NextPVR Forums Public NextPVR Support Other Clients v
« Previous 1 2 3 4
Programming using v5 commands. How to login?

 
  • 0 Vote(s) - 0 Average
Programming using v5 commands. How to login?
drmargarit
Offline

Member

Posts: 184
Threads: 49
Joined: Sep 2013
#1
2019-08-05, 01:14 AM
I have a ton of utilities and a client that I am dragging up to v5 compatibility. All of them currently read and/or modify the database directly and I am trying to get away from that using the http calls.
I know you are super busy and I'm trying to bug you as little as possible.Wink Right now I am trying to learn by reproducing the calls that the web client makes.
My question is this: Do I need to login to use calls like: "/services/service?method=channel.list&format=json"? or is logging in irrelevant for applications?

When the web page logs in, it gets a return code of 302.
When I login using the code below, I get a return code of 200. Yet, I can get a channel listing.
So, I am confused at this point. Did I login successfully? Do I need to login at all? Did I get the channel listing because I am already logged in with the web interface in chrome? How do I log out?

Code:
//function doLogin()
        //{
        //    var salt = getParameterByName("salt");
        //    var username = $("#email").val();
        //    var password = MD5($("#password").val());
        //    var combined = MD5(salt + ":" + username + ":" + password);
        //    window.location.href = 'login.html?hash=' + combined;
        //}
      
        public async Task<bool> doLogin()
        {
            string url = "http://192.168.86.25:8866";            
            try
            {
                //login
                fHttpResponseMsg = await fHttpClient.GetAsync(url);
                fHttpRequestMsg = fHttpResponseMsg.RequestMessage;
                string query = fHttpRequestMsg.RequestUri.Query;                
                var parts = HttpUtility.ParseQueryString(query);
                string salt = parts.Get("salt");                                
                string passMD5 = CreateMD5("password").ToLower();
                string hash = CreateMD5(string.Format("{0}:{1}:{2}", salt, "admin", passMD5));
                hash = hash.ToLower();
                string loginRequest = string.Format("{0}/login.html?hash={1}", url, hash);
                fHttpResponseMsg = await fHttpClient.GetAsync(loginRequest);
                fHttpRequestMsg = fHttpResponseMsg.RequestMessage;
                //get channel listing
                string serviceRequest = string.Format("{0}/services/service?method=channel.list&format=json", url);
                fHttpResponseMsg = await fHttpClient.GetAsync(serviceRequest);                
                string json = await fHttpResponseMsg.Content.ReadAsStringAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }      

        public static string CreateMD5(string input)
        {
            // Use input string to calculate MD5 hash. Cut and paste from Stackoverflow
            using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                // Convert the byte array to hexadecimal string
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("X2"));
                }
                return sb.ToString();
            }
        }

Thanks for your help!

JLM
mvallevand
Offline

Posting Freak

Ontario Canada
Posts: 52,766
Threads: 954
Joined: May 2006
#2
2019-08-05, 01:19 AM
Login is a two step operation. The best public source to the HTTP API use is in the kodi pvr plugin. The knewc plugin has similar logic in python, and I will be posting .net code for Emby soon.

Martin
sub
Offline

Administrator

NextPVR HQ, New Zealand
Posts: 106,626
Threads: 767
Joined: Nov 2003
#3
2019-08-05, 01:21 AM
All the api calls require a sid ("session ID") from a logged in session.

To do the login, the easiest example code to look at is probably the pvr.nextpvr kodi addon code, in the connect() function.
https://github.com/kodi-pvr/pvr.nextpvr/...extpvr.cpp

Specifically, this bit of code:
Code:
if (DoRequest("/service?method=session.initiate&ver=1.0&device=xbmc", response) == HTTP_OK)
  {
    TiXmlDocument doc;
    if (doc.Parse(response.c_str()) != NULL)
    {
      TiXmlElement* saltNode = doc.RootElement()->FirstChildElement("salt");
      TiXmlElement* sidNode = doc.RootElement()->FirstChildElement("sid");

      if (saltNode != NULL && sidNode != NULL)
      {
        // extract and store sid
        PVR_STRCLR(m_sid);
        PVR_STRCPY(m_sid, sidNode->FirstChild()->Value());
        NextPVR::m_backEnd->setSID(m_sid);
        // extract salt
        char salt[64];
        PVR_STRCLR(salt);
        PVR_STRCPY(salt, saltNode->FirstChild()->Value());

        // a bit of debug
        XBMC->Log(LOG_DEBUG, "session.initiate returns: sid=%s salt=%s", m_sid, salt);


        std::string pinMD5 = PVRXBMC::XBMC_MD5::GetMD5(g_szPin);
        StringUtils::ToLower(pinMD5);

        // calculate combined MD5
        std::string combinedMD5;
        combinedMD5.append(":");
        combinedMD5.append(pinMD5);
        combinedMD5.append(":");
        combinedMD5.append(salt);

        // get digest
        std::string md5 = PVRXBMC::XBMC_MD5::GetMD5(combinedMD5);

        // login session
        std::string loginResponse;
        char request[512];
        sprintf(request, "/service?method=session.login&sid=%s&md5=%s", m_sid, md5.c_str());
        if (DoRequest(request, loginResponse) == HTTP_OK)
        {
          if (strstr(loginResponse.c_str(), "<rsp stat=\"ok\">"))
          {
sub
Offline

Administrator

NextPVR HQ, New Zealand
Posts: 106,626
Threads: 767
Joined: Nov 2003
#4
2019-08-05, 01:24 AM
Basically you call "/service?method=session.initiate" first, which will return you "salt" and "sid" values.

Next you need to login using "/service?method=session.login", passing through an "md5" value (which was derived a string constructed from the md5(":md5(pin)Confusedalt")
drmargarit
Offline

Member

Posts: 184
Threads: 49
Joined: Sep 2013
#5
2019-08-05, 01:33 AM
Thanks for the super quick reply!

JLM
drmargarit
Offline

Member

Posts: 184
Threads: 49
Joined: Sep 2013
#6
2019-08-05, 02:46 AM
Ok, so I am here now but get a login failed result...

In the web interface login you pass MD5("salt:username:MD5(password)")
but the kodi login consists of MD5(":MD5(password)Confusedalt")
Am I missing where the username comes in for the kodi login?
Should I be using "device=xmbc" in the request(s)?

Here's my login code:

Code:
//function doLogin()
        //{
        //    var salt = getParameterByName("salt");
        //    var username = $("#email").val();
        //    var password = MD5($("#password").val());
        //    var combined = MD5(salt + ":" + username + ":" + password);
        //    window.location.href = 'login.html?hash=' + combined;
        //}
      
        public async Task<bool> doLogin()
        {
            string url = "http://192.168.86.25:8866";
            string initiate = "{0}/service?method=session.initiate&ver=1.0&device=xbmc&format=json";
            string login = "{0}/service?method=session.login&sid={1}&md5={2}";

            try
            {
                // initiate
                string httpRequest = string.Format(initiate, url);
                fHttpResponseMsg = await fHttpClient.GetAsync(httpRequest);
                fHttpRequestMsg = fHttpResponseMsg.RequestMessage;
                string loginJson = await fHttpResponseMsg.Content.ReadAsStringAsync();
                fLoginInfo = JsonConvert.DeserializeObject<tLoginInfo>(loginJson);                
                // login
                string passMD5 = CreateMD5("password").ToLower();
                string s = string.Format(":{0}:{1}", passMD5, fLoginInfo.salt);
                string hash = CreateMD5(s).ToLower();
                httpRequest = string.Format(login, url,fLoginInfo.sid, hash);
                fHttpResponseMsg = await fHttpClient.GetAsync(httpRequest);
                fHttpRequestMsg = fHttpResponseMsg.RequestMessage;
                string content = await fHttpResponseMsg.Content.ReadAsStringAsync();
                
                return true;
            }
            catch
            {
                return false;
            }
        }      
    loginJson = {"sid":"7a1b4019c83e47fd92f6d10dfd99c72f","salt":"48b0df52-2c8f-4eb4-ad7c-6f7ac6aa4c8d"}
    s = :5f4dcc3b5aa765d61d8327deb882cf99:48b0df52-2c8f-4eb4-ad7c-6f7ac6aa4c8d
    hash = e1169a5033aa67a0dc9cbbc05df5dd71
    httpRequest = http://192.168.86.25:8866/service?method=session.login&sid=7a1b4019c83e47fd92f6d10dfd99c72f&md5=e1169a5033aa67a0dc9cbbc05df5dd71
    content = <?xml version="1.0" encoding="utf-8" ?><rsp stat="fail"><err code="1" msg="Login Failed" /></rsp>
Any ideas?

JLM
sub
Offline

Administrator

NextPVR HQ, New Zealand
Posts: 106,626
Threads: 767
Joined: Nov 2003
#7
2019-08-05, 02:51 AM
Just to be clear - that login takes the pin, not the password. ie, default pin is 0000
mvallevand
Offline

Posting Freak

Ontario Canada
Posts: 52,766
Threads: 954
Joined: May 2006
#8
2019-08-05, 02:53 AM
I can understand the confusion, the API doesn't require the username/password, it is based on the PIN.

Martin
sub
Offline

Administrator

NextPVR HQ, New Zealand
Posts: 106,626
Threads: 767
Joined: Nov 2003
#9
2019-08-05, 02:57 AM
I can look into providing a version of the login api that accepts a username/password. I havn't needed it to date. (the web app uses it's special access to the web server to do a login in a way that another client couldn't easily replicate)
drmargarit
Offline

Member

Posts: 184
Threads: 49
Joined: Sep 2013
#10
2019-08-05, 03:23 PM (This post was last modified: 2019-08-05, 05:16 PM by drmargarit.)
content = <?xml version="1.0" encoding="utf-8" ?><rsp stat="ok"><sid>481e61328cc54915aa67639973969460</sid></rsp>

Voila! "A password of '0000' gets me an 'OK'. Now I have to figure out where the sid goes...

Quote:All the api calls require a sid ("session ID") from a logged in session.
I haven't run across a call beyond login that includes an sid. When and where do you use the sid?

JLM
« Next Oldest | Next Newest »

Users browsing this thread: 1 Guest(s)

Pages (2): 1 2 Next »


  • View a Printable Version
  • Subscribe to this thread
Forum Jump:

© Designed by D&D, modified by NextPVR - Powered by MyBB

Linear Mode
Threaded Mode