# Path: lockdown.py
# class LockdownClient(object):
#     def __init__(self, udid=None):
#         self.service = PlistService(62078, udid)
#         self.hostID = self.generate_hostID()
#         self.paired = False
#         self.label = 'pyMobileDevice'
#         response = self.service.sendRequest({'Request': 'QueryType'})
#         assert response['Type'] == 'com.apple.mobile.lockdown'
# 
#         self.allValues = self.getValue()
#         self.udid = self.allValues.get('UniqueDeviceID')
#         self.osVersion = self.allValues.get('ProductVersion')
#         self.devicePublicKey = self.allValues.get('DevicePublicKey').data
# 
#         if not self.validate_pairing():
#             self.pair()
#             if not self.validate_pairing():
#                 raise FatalPairingError
#         self.paired = True
# 
#     def generate_hostID(self):
#         hostname = platform.node()
#         hostid = uuid.uuid3(uuid.NAMESPACE_DNS, hostname)
#         return str(hostid).upper()
# 
#     def enter_recovery(self):
#         return self.service.sendRequest({'Request': 'EnterRecovery'})
# 
#     def stop_session(self):
#         if self.SessionID and self.service:
#             self.SessionID = None
#             response = self.service.sendRequest({
#                 'Request': 'StopSession',
#                 'SessionID': self.SessionID
#                 })
#             if not response or response.get('Result') != 'Success':
#                 raise CannotStopSessionError
#             return response
# 
#     def validate_pairing(self):
#         record = readHomeFile(HOMEFOLDER, '%s.plist' % self.udid)
#         if record:
#             pair_record = plistlib.readPlistFromString(record)
#             hostCertificate = pair_record['HostCertificate'].data
#             hostPrivateKey = pair_record['HostPrivateKey'].data
#             print "Found pairing record for device %s" % self.udid
#         else:
#             print "No pairing record found for device %s" % self.udid
#             return False
# 
#         ValidatePair = self.service.sendRequest({
#             'Request': 'ValidatePair',
#             'PairRecord': pair_record
#             })
#         if not ValidatePair or 'Error' in ValidatePair:
#             pair_record = None
#             return False
# 
#         StartSession = self.service.sendRequest({
#             'Request': 'StartSession',
#             'HostID': pair_record.get('HostID', self.hostID)
#             })
#         self.SessionID = StartSession.get('SessionID')
# 
#         if StartSession.get('EnableSessionSSL'):
#             keyfile = writeHomeFile(HOMEFOLDER, self.udid + "_ssl.txt", hostCertificate + '\n' + hostPrivateKey)
#             self.service.start_ssl(keyfile)
#             self.allValues = self.getValue()  # iDevice gives more information after being trusted
#         return True
# 
#     def pair(self):
#         print "Creating host key & certificate"
#         hostCertificate, hostPrivateKey, deviceCertificate = generateCertificates(self.devicePublicKey)
# 
#         pair_record = {'DevicePublicKey': plistlib.Data(self.devicePublicKey),
#                        'DeviceCertificate': plistlib.Data(deviceCertificate),
#                        'HostCertificate': plistlib.Data(hostCertificate),
#                        'HostPrivateKey': plistlib.Data(hostPrivateKey),
#                        'HostID': self.hostID,
#                        'RootCertificate': plistlib.Data(hostCertificate),
#                        'SystemBUID': '30142955-444094379208051516'}
# 
#         Pair = self.service.sendRequest({
#             'Request': 'Pair',
#             'PairRecord': pair_record
#             })
# 
#         if self.osVersion[0] == '7' and Pair.get('Error') == 'PasswordProtected':
#             raise NotTrustedError
# 
#         if Pair and Pair.get('Result') == 'Success' or 'EscrowBag' in Pair:
#             if 'EscrowBag' in Pair:
#                 pair_record['EscrowBag'] = Pair['EscrowBag']
#             writeHomeFile(HOMEFOLDER, '%s.plist' % self.udid, plistlib.writePlistToString(pair_record))
#         else:
#             raise PairingError
# 
#     def getValue(self, domain=None, key=None):
#         request = {'Request': 'GetValue', 'Label': self.label}
# 
#         if domain:
#             request['Domain'] = domain
#         if key:
#             request['Key'] = key
#         response = self.service.sendRequest(request)
#         if response:
#             r = response.get('Value')
#             if hasattr(r, 'data'):
#                 return r.data
#             return r
# 
#     def startService(self, name):
#         if not self.paired:
#             raise NotPairedError
# 
#         StartService = self.service.sendRequest({
#             'Request': 'StartService',
#             'Service': name
#             })
# 
#         if not StartService or 'Error' in StartService:
#             raise StartServiceError(StartService['Error'])
#         return PlistService(StartService['Port'])


import os
import plistlib
import struct
import posixpath
from cmd import Cmd
from construct.core import Struct
from construct.lib.container import Container
from construct.macros import String, ULInt64
from util import hexdump, parsePlist
from lockdown import LockdownClient
        while True:
            buff = self.read(buffer_size)
            if buff:
                r += buff
            else:
                # Reached EOF
                if r:  # yield the last line if it wasn't already
                    yield r
                break

            lines = r.splitlines(True)
            r = ""
            for line in lines:
                if line[-1] == '\n':
                    yield line
                else:
                    r = line  # Continue reading

    xreadlines = __iter__

# AFCShell is doomed because of try-catch approach
# This makes coding AFCClient easier and AFCShell harder.
# I'm thinking about a solution

class AFCShell(Cmd):
    def __init__(self, completekey='tab', stdin=None, stdout=None, afc=None):
        super(AFCShell, self).__init__(self, completekey=completekey, stdin=stdin, stdout=stdout)
        if afc:
            self.afc = afc
        else:

# Path: lockdown.py
# class LockdownClient(object):
#     def __init__(self, udid=None):
#         self.service = PlistService(62078, udid)
#         self.hostID = self.generate_hostID()
#         self.paired = False
#         self.label = 'pyMobileDevice'
#         response = self.service.sendRequest({'Request': 'QueryType'})
#         assert response['Type'] == 'com.apple.mobile.lockdown'
# 
#         self.allValues = self.getValue()
#         self.udid = self.allValues.get('UniqueDeviceID')
#         self.osVersion = self.allValues.get('ProductVersion')
#         self.devicePublicKey = self.allValues.get('DevicePublicKey').data
# 
#         if not self.validate_pairing():
#             self.pair()
#             if not self.validate_pairing():
#                 raise FatalPairingError
#         self.paired = True
# 
#     def generate_hostID(self):
#         hostname = platform.node()
#         hostid = uuid.uuid3(uuid.NAMESPACE_DNS, hostname)
#         return str(hostid).upper()
# 
#     def enter_recovery(self):
#         return self.service.sendRequest({'Request': 'EnterRecovery'})
# 
#     def stop_session(self):
#         if self.SessionID and self.service:
#             self.SessionID = None
#             response = self.service.sendRequest({
#                 'Request': 'StopSession',
#                 'SessionID': self.SessionID
#                 })
#             if not response or response.get('Result') != 'Success':
#                 raise CannotStopSessionError
#             return response
# 
#     def validate_pairing(self):
#         record = readHomeFile(HOMEFOLDER, '%s.plist' % self.udid)
#         if record:
#             pair_record = plistlib.readPlistFromString(record)
#             hostCertificate = pair_record['HostCertificate'].data
#             hostPrivateKey = pair_record['HostPrivateKey'].data
#             print "Found pairing record for device %s" % self.udid
#         else:
#             print "No pairing record found for device %s" % self.udid
#             return False
# 
#         ValidatePair = self.service.sendRequest({
#             'Request': 'ValidatePair',
#             'PairRecord': pair_record
#             })
#         if not ValidatePair or 'Error' in ValidatePair:
#             pair_record = None
#             return False
# 
#         StartSession = self.service.sendRequest({
#             'Request': 'StartSession',
#             'HostID': pair_record.get('HostID', self.hostID)
#             })
#         self.SessionID = StartSession.get('SessionID')
# 
#         if StartSession.get('EnableSessionSSL'):
#             keyfile = writeHomeFile(HOMEFOLDER, self.udid + "_ssl.txt", hostCertificate + '\n' + hostPrivateKey)
#             self.service.start_ssl(keyfile)
#             self.allValues = self.getValue()  # iDevice gives more information after being trusted
#         return True
# 
#     def pair(self):
#         print "Creating host key & certificate"
#         hostCertificate, hostPrivateKey, deviceCertificate = generateCertificates(self.devicePublicKey)
# 
#         pair_record = {'DevicePublicKey': plistlib.Data(self.devicePublicKey),
#                        'DeviceCertificate': plistlib.Data(deviceCertificate),
#                        'HostCertificate': plistlib.Data(hostCertificate),
#                        'HostPrivateKey': plistlib.Data(hostPrivateKey),
#                        'HostID': self.hostID,
#                        'RootCertificate': plistlib.Data(hostCertificate),
#                        'SystemBUID': '30142955-444094379208051516'}
# 
#         Pair = self.service.sendRequest({
#             'Request': 'Pair',
#             'PairRecord': pair_record
#             })
# 
#         if self.osVersion[0] == '7' and Pair.get('Error') == 'PasswordProtected':
#             raise NotTrustedError
# 
#         if Pair and Pair.get('Result') == 'Success' or 'EscrowBag' in Pair:
#             if 'EscrowBag' in Pair:
#                 pair_record['EscrowBag'] = Pair['EscrowBag']
#             writeHomeFile(HOMEFOLDER, '%s.plist' % self.udid, plistlib.writePlistToString(pair_record))
#         else:
#             raise PairingError
# 
#     def getValue(self, domain=None, key=None):
#         request = {'Request': 'GetValue', 'Label': self.label}
# 
#         if domain:
#             request['Domain'] = domain
#         if key:
#             request['Key'] = key
#         response = self.service.sendRequest(request)
#         if response:
#             r = response.get('Value')
#             if hasattr(r, 'data'):
#                 return r.data
#             return r
# 
#     def startService(self, name):
#         if not self.paired:
#             raise NotPairedError
# 
#         StartService = self.service.sendRequest({
#             'Request': 'StartService',
#             'Service': name
#             })
# 
#         if not StartService or 'Error' in StartService:
#             raise StartServiceError(StartService['Error'])
#         return PlistService(StartService['Port'])


# Path: afc.py
import os
import plistlib
import struct
import posixpath
from cmd import Cmd
from construct.core import Struct
from construct.lib.container import Container
from construct.macros import String, ULInt64
from util import hexdump, parsePlist
from lockdown import LockdownClient

        while True:
            buff = self.read(buffer_size)
            if buff:
                r += buff
            else:
                # Reached EOF
                if r:  # yield the last line if it wasn't already
                    yield r
                break

            lines = r.splitlines(True)
            r = ""
            for line in lines:
                if line[-1] == '\n':
                    yield line
                else:
                    r = line  # Continue reading

    xreadlines = __iter__

# AFCShell is doomed because of try-catch approach
# This makes coding AFCClient easier and AFCShell harder.
# I'm thinking about a solution

class AFCShell(Cmd):
    def __init__(self, completekey='tab', stdin=None, stdout=None, afc=None):
        super(AFCShell, self).__init__(self, completekey=completekey, stdin=stdin, stdout=stdout)
        if afc:
            self.afc = afc
        else:

            self.lockdown = LockdownClient()