Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some fixes to make it work with cmd2 (latest version), as well as with iPhone #6

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
361 changes: 254 additions & 107 deletions pbapclient.py

Large diffs are not rendered by default.

98 changes: 61 additions & 37 deletions pbapcommon.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@
"""Common tools and attributes for pbap client and server"""

FILTER_ATTR_DICT = {
0: ('VERSION', 'vCard Version'),
1: ('FN', 'Formatted Name'),
2: ('N', 'Structured Presentation of Name'),
3: ('PHOTO', 'Associated Image or Photo'),
4: ('BDAY', 'Birthday'),
5: ('ADR', 'Delivery Address'),
6: ('LABEL', 'Delivery'),
7: ('TEL', 'Telephone Number'),
8: ('EMAIL', 'Electronic Mail Address'),
9: ('MAILER', 'Electronic Mail'),
10: ('TZ', 'Time Zone'),
11: ('GEO', 'Geographic Position'),
12: ('TITLE', 'Job'),
13: ('ROLE', 'Role within the Organization'),
14: ('LOGO', 'Organization Logo'),
15: ('AGENT', 'vCard of Person Representing'),
16: ('ORG', 'Name of Organization'),
17: ('NOTE', 'Comments'),
18: ('REV', 'Revision'),
19: ('SOUND', 'Pronunciation of Name'),
20: ('URL', 'Uniform Resource Locator'),
21: ('UID', 'Unique ID'),
22: ('KEY', 'Public Encryption Key'),
23: ('NICKNAME', 'Nickname'),
24: ('CATEGORIES', 'Categories'),
25: ('PROID', 'Product ID'),
26: ('CLASS', 'Class information'),
27: ('SORT', 'STRING String used for sorting operations'),
28: ('X-IRMC-CALL-DATETIME', 'Time stamp'),
0: ("VERSION", "vCard Version"),
1: ("FN", "Formatted Name"),
2: ("N", "Structured Presentation of Name"),
3: ("PHOTO", "Associated Image or Photo"),
4: ("BDAY", "Birthday"),
5: ("ADR", "Delivery Address"),
6: ("LABEL", "Delivery"),
7: ("TEL", "Telephone Number"),
8: ("EMAIL", "Electronic Mail Address"),
9: ("MAILER", "Electronic Mail"),
10: ("TZ", "Time Zone"),
11: ("GEO", "Geographic Position"),
12: ("TITLE", "Job"),
13: ("ROLE", "Role within the Organization"),
14: ("LOGO", "Organization Logo"),
15: ("AGENT", "vCard of Person Representing"),
16: ("ORG", "Name of Organization"),
17: ("NOTE", "Comments"),
18: ("REV", "Revision"),
19: ("SOUND", "Pronunciation of Name"),
20: ("URL", "Uniform Resource Locator"),
21: ("UID", "Unique ID"),
22: ("KEY", "Public Encryption Key"),
23: ("NICKNAME", "Nickname"),
24: ("CATEGORIES", "Categories"),
25: ("PROID", "Product ID"),
26: ("CLASS", "Class information"),
27: ("SORT", "STRING String used for sorting operations"),
28: ("X-IRMC-CALL-DATETIME", "Time stamp"),
# 29: ('RESERVED_FUTURE_USE', 'Reserved for future use'),
# 30: ('RESERVED_FUTURE_USE', 'Reserved for future use'),
# 31: ('RESERVED_FUTURE_USE', 'Reserved for future use'),
Expand Down Expand Up @@ -70,15 +70,39 @@
# 63: ('RESERVED_PROPRIETARY_FILTER', 'Reserved for proprietary filter usage')
}

POSSIBLE_VCARD_ATTR = ["VERSION", "FN", "N", "PHOTO", "BDAY", "ADR", "LABEL", "TEL",
"EMAIL", "MAILER", "TZ", "GEO", "TITLE", "ROLE", "LOGO",
"AGENT", "ORG", "NOTE", "REV", "SOUND", "URL", "UID", "KEY",
"NICKNAME", "CATEGORIES", "PROID", "CLASS", "SORT", "X-IRMC-CALL-DATETIME"]
POSSIBLE_VCARD_ATTR = [
"VERSION",
"FN",
"N",
"PHOTO",
"BDAY",
"ADR",
"LABEL",
"TEL",
"EMAIL",
"MAILER",
"TZ",
"GEO",
"TITLE",
"ROLE",
"LOGO",
"AGENT",
"ORG",
"NOTE",
"REV",
"SOUND",
"URL",
"UID",
"KEY",
"NICKNAME",
"CATEGORIES",
"PROID",
"CLASS",
"SORT",
"X-IRMC-CALL-DATETIME",
]

# vcard_format: bitmask for mandatory attributes
# vcard 2.1 are VERSION ,N and TEL
# vcard 3.0 are VERSION, N, FN and TEL
MANDATORY_ATTR_BITMASK = {
"2.1": int("10000101", 2),
"3.0": int("10000111", 2)
}
MANDATORY_ATTR_BITMASK = {"2.1": int("10000101", 2), "3.0": int("10000111", 2)}
59 changes: 49 additions & 10 deletions pbapheaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
# -*- coding: utf-8 -*-
"""Phone Book Access Profile headers"""

import struct

from PyOBEX.headers import *
from pbapcommon import FILTER_ATTR_DICT


# Application Parameters Header Properties
class AppParamProperty(object):
"""AppParamProperty Class"""

tagid = None

def __init__(self, data, encoded=False):
if encoded:
self.data = data
Expand All @@ -25,91 +31,119 @@ def decode(self):


class OneByteProperty(AppParamProperty):
"""OneByteProperty Class"""

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()
_, data = super(OneByteProperty, self).decode()
return struct.unpack(self.fmt, data)[0]


class TwoByteProperty(AppParamProperty):
"""TwoByteProperty Class"""

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()
_, data = super(TwoByteProperty, self).decode()
return struct.unpack(self.fmt, data)[0]


class EightByteProperty(AppParamProperty):
"""EightByteProperty Class"""

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()
_, 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))
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
_, length = headers
return struct.unpack(self.fmt.format(len=length), data)[0]


class PBAPType(UnicodeHeader):
class PBAPType(Type):
"""PBAPType Class"""

code = 0x42


class Order(OneByteProperty):
"""Order Class"""

tagid = 0x01


class SearchValue(VariableLengthProperty):
"""SearchValue Class"""

tagid = 0x02


class SearchAttribute(OneByteProperty):
"""SearchAttribute Class"""

tagid = 0x03


class MaxListCount(TwoByteProperty):
"""MaxListCount Class"""

tagid = 0x04


class ListStartOffset(TwoByteProperty):
"""ListStartOffset Class"""

tagid = 0x05


class Filter(EightByteProperty):
"""Filter Class"""

tagid = 0x06
attr_dict = FILTER_ATTR_DICT


class Format(OneByteProperty):
"""Format Class"""

tagid = 0x07


class PhonebookSize(TwoByteProperty):
"""PhonebookSize Class"""

tagid = 0x08


class NewMissedCalls(OneByteProperty):
"""NewMissedCalls Class"""

tagid = 0x09


Expand All @@ -122,15 +156,17 @@ class NewMissedCalls(OneByteProperty):
0x06: Filter,
0x07: Format,
0x08: PhonebookSize,
0x09: NewMissedCalls
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):
"""Extended version of the 'decode'"""
# assumption:
# size of tagid = 1 byte
# size of length = 1 byte (This is just the data length)
Expand All @@ -140,13 +176,16 @@ def extended_decode(self):
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:]
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''
"""Extended version of the 'encode'"""
data = b""
for item in data_dict.values():
if item is None:
continue
Expand Down
12 changes: 7 additions & 5 deletions pbapresponses.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ class Service_Unavailable(FailureResponse):
code = OBEX_Service_Unavailable = 0xD3


ResponseHandler.message_dict.update({
Not_Acceptable.code: Not_Acceptable,
Not_Implemented.code: Not_Implemented,
Service_Unavailable.code: Service_Unavailable
})
ResponseHandler.message_dict.update(
{
Not_Acceptable.code: Not_Acceptable,
Not_Implemented.code: Not_Implemented,
Service_Unavailable.code: Service_Unavailable,
}
)
Loading