-
Notifications
You must be signed in to change notification settings - Fork 10
/
pbapheaders.py
158 lines (108 loc) · 3.72 KB
/
pbapheaders.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# Copyright (c) 2018 Kannan Subramani <Kannan.Subramani@bmw.de>
# SPDX-License-Identifier: GPL-3.0
# -*- coding: utf-8 -*-
"""Phone Book Access Profile headers"""
from PyOBEX.headers import *
from pbapcommon import FILTER_ATTR_DICT
# Application Parameters Header Properties
class AppParamProperty(object):
def __init__(self, data, encoded=False):
if encoded:
self.data = data
else:
self.data = self.encode(data)
def encode(self, data):
if self.__class__.__name__ == "SearchValue":
self.length = len(data)
return struct.pack(">BB", self.tagid, self.length) + data
def decode(self):
return struct.unpack(">BB", self.data[:2]), self.data[2:]
class OneByteProperty(AppParamProperty):
length = 1 # byte
fmt = ">B"
def encode(self, data):
return super(OneByteProperty, self).encode(struct.pack(self.fmt, data))
def decode(self):
headers, data = super(OneByteProperty, self).decode()
return struct.unpack(self.fmt, data)[0]
class TwoByteProperty(AppParamProperty):
length = 2 # bytes
fmt = ">H"
def encode(self, data):
return super(TwoByteProperty, self).encode(struct.pack(self.fmt, data))
def decode(self):
headers, data = super(TwoByteProperty, self).decode()
return struct.unpack(self.fmt, data)[0]
class EightByteProperty(AppParamProperty):
length = 8 # bytes
fmt = ">Q"
def encode(self, data):
return super(EightByteProperty, self).encode(struct.pack(self.fmt, data))
def decode(self):
headers, data = super(EightByteProperty, self).decode()
return struct.unpack(self.fmt, data)[0]
class VariableLengthProperty(AppParamProperty):
fmt = "{len}s"
def encode(self, data):
return super(VariableLengthProperty, self).encode(struct.pack(self.fmt.format(len=len(data)), data))
def decode(self):
headers, data = super(VariableLengthProperty, self).decode()
tagid, length = headers
return struct.unpack(self.fmt.format(len=length), data)[0]
class PBAPType(UnicodeHeader):
code = 0x42
class Order(OneByteProperty):
tagid = 0x01
class SearchValue(VariableLengthProperty):
tagid = 0x02
class SearchAttribute(OneByteProperty):
tagid = 0x03
class MaxListCount(TwoByteProperty):
tagid = 0x04
class ListStartOffset(TwoByteProperty):
tagid = 0x05
class Filter(EightByteProperty):
tagid = 0x06
attr_dict = FILTER_ATTR_DICT
class Format(OneByteProperty):
tagid = 0x07
class PhonebookSize(TwoByteProperty):
tagid = 0x08
class NewMissedCalls(OneByteProperty):
tagid = 0x09
app_parameters_dict = {
0x01: Order,
0x02: SearchValue,
0x03: SearchAttribute,
0x04: MaxListCount,
0x05: ListStartOffset,
0x06: Filter,
0x07: Format,
0x08: PhonebookSize,
0x09: NewMissedCalls
}
# Sample App Parameters data
# code | length | data
# 4c | 00 18 | 06 08 00 00 00 3f d0 00 00 80 07 01 00 04 02 00 00 05 02 00 00
def extended_decode(self):
# assumption:
# size of tagid = 1 byte
# size of length = 1 byte (This is just the data length)
data = self.data
res_dict = {}
while data:
tagid = ord(data[0])
length = ord(data[1])
app_param_class = app_parameters_dict[tagid]
res_dict[app_param_class.__name__] = app_param_class(data[:length + 2], encoded=True)
data = data[length + 2:]
return res_dict
def extended_encode(self, data_dict):
data = b''
for item in data_dict.values():
if item is None:
continue
data += item.data
return struct.pack(">BH", self.code, len(data) + 3) + data
App_Parameters.decode = extended_decode
App_Parameters.encode = extended_encode