--
You received this message because you are subscribed to the Google Groups "opensocial-client-libraries" group.
To post to this group, send email to opensocial-cl...@googlegroups.com.
To unsubscribe from this group, send email to opensocial-client-l...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/opensocial-client-libraries?hl=en.
--
Anatoly Bubenkov
+380(66)6358527
Zojax inc (http://zojax.com/)
--
You received this message because you are subscribed to the Google Groups "opensocial-client-libraries" group.
To post to this group, send email to opensocial-cl...@googlegroups.com.
To unsubscribe from this group, send email to opensocial-client-l...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/opensocial-client-libraries?hl=en.
Index: setup.py
===================================================================
--- setup.py (revision 85)
+++ setup.py (working copy)
@@ -28,6 +28,10 @@
author_email='david...@google.com',
license='Apache 2.0',
url='http://code.google.com/p/opensocial-python-client',
- packages=['opensocial', 'opensocial.oauth', 'opensocial.simplejson', 'opensocial.Crypto'],
- package_dir={'opensocial': 'src/opensocial'}
+ packages=['opensocial', 'oauth', 'simplejson', 'Crypto', \
+ 'Crypto.PublicKey', 'Crypto.Util'],
+ package_dir={'opensocial': 'src/opensocial',
+ 'oauth': 'src/opensocial/oauth',
+ 'simplejson': 'src/opensocial/simplejson',
+ 'Crypto': 'src/opensocial/Crypto',}
)
Index: src/opensocial/request.py
===================================================================
--- src/opensocial/request.py (revision 89)
+++ src/opensocial/request.py (working copy)
@@ -27,14 +27,14 @@
import data
import http
-from opensocial import simplejson
+import simplejson
def generate_uuid(*args):
"""Simple method for generating a unique identifier.
-
+
Args: Any arguments used to help make this uuid more unique.
-
+
Returns: A 128-bit hex identifier.
"""
@@ -47,45 +47,45 @@
class Request(object):
"""Represents an OpenSocial request that can be processed via RPC or REST."""
-
+
def __init__(self, rest_request, rpc_request, requestor=None):
self.rest_request = rest_request
self.rpc_request = rpc_request
self.set_requestor(requestor)
-
+
def get_requestor(self):
"""Get the requestor id for this request.
-
+
Returns: The requestor's id.
-
+
"""
return self.__requestor
-
+
def set_requestor(self, id):
"""Set the requestor id for this request.
-
+
This does not accept any keywords such as @me.
TODO: Refactor the id check out of here, it feels wrong.
-
+
Args:
id: str The requestor's id.
-
+
"""
if id and id[0] is not '@':
self.__requestor = id
else:
self.__requestor = None
-
+
def get_query_params(self):
"""Returns the query params string for this request."""
query_params = {}
if self.get_requestor():
query_params['xoauth_requestor_id'] = self.get_requestor()
return query_params
-
+
def make_rest_request(self, url_base):
"""Creates a RESTful HTTP request.
-
+
Args:
url_base: str The base REST URL.
@@ -118,11 +118,11 @@
def __init__(self, user_id, params=None):
params = params or {}
rest_request = RestRequestInfo('/'.join(('groups', user_id)),'GET', params )
-
+
super(FetchGroupRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
Args:
@@ -130,76 +130,76 @@
Returns: a Collection of Person objects.
"""
return data.Collection.parse_json(json, data.Group)
-
+
class FetchAlbumRequest(Request):
"""A request for handling Album"""
-
+
def __init__(self, user_id, albumid=None, params=None):
params = params or {}
if albumid != None:
rest_request = RestRequestInfo('/'.join(('albums', user_id,'@self', albumid)),'GET', params )
else:
rest_request = RestRequestInfo('/'.join(('albums', user_id,'@self')),'GET', params )
-
+
super(FetchAlbumRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
Args:
json: dict The JSON structure.
Returns: a Collection of Person objects.
"""
- json_list = json.get('album')
-
+ json_list = json.get('album')
+
if json_list != None:
""" this is individual album """
return data.Album(json_list)
-
+
return data.Collection.parse_json(json, data.Album )
-
-
+
+
class FetchMediaItemsRequest(Request):
"""A request for handling Album"""
-
+
def __init__(self, user_id, albumid=None, mediaitemid=None, params=None):
params = params or {}
if mediaitemid != None:
rest_request = RestRequestInfo('/'.join(('mediaitems', user_id,'@self', albumid, mediaitemid)),'GET', params )
else:
rest_request = RestRequestInfo('/'.join(('mediaitems', user_id,'@self', albumid)),'GET', params )
-
+
super(FetchMediaItemsRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
Args:
json: dict The JSON structure.
Returns: a Collection of Person objects.
"""
- json_list = json.get('mediaItem')
-
+ json_list = json.get('mediaItem')
+
if json_list != None:
""" this is individual album """
return data.MediaItem(json_list)
-
+
return data.Collection.parse_json(json, data.MediaItem )
-
-
+
+
class FetchStatusMoodRequest(Request):
"""A request for handling Statusmoodcomments"""
-
+
def __init__(self, user_id, params=None):
params = params or {}
rest_request = RestRequestInfo('/'.join(('statusmood', user_id,'@self')),'GET', params )
-
+
super(FetchStatusMoodRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
Args:
@@ -210,15 +210,15 @@
class FetchStatusMoodCommentsRequest(Request):
"""A request for handling StatusmoodcommentsRequests"""
-
+
def __init__(self, user_id, params=None):
params = params or {}
rest_request = RestRequestInfo('/'.join(('statusMoodComments', user_id,'@self')),'GET', params )
-
+
super(FetchStatusMoodCommentsRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
Args:
@@ -226,29 +226,29 @@
Returns: a Collection of statusmoodcomments objects objects.
"""
return data.Collection.parse_json(json, data.StatusMoodComments)
-
-
+
+
class FetchProfileCommentsRequest(Request):
"""A request for handling profile comments"""
-
+
def __init__(self, user_id, params=None):
params = params or {}
rest_request = RestRequestInfo('/'.join(('profilecomments', user_id,'@self')),'GET', params )
super(FetchProfileCommentsRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
Args:
json: dict The JSON structure.
Returns: a Collection of statusmoodcomments objects objects.
"""
- return data.Collection.parse_json(json, data.ProfileComments)
+ return data.Collection.parse_json(json, data.ProfileComments)
-class FetchPeopleRequest(Request):
+class FetchPeopleRequest(Request):
"""A request for handling fetching a collection of people."""
-
+
def __init__(self, user_id, group_id, fields=None, params=None):
params = params or {}
if fields:
@@ -262,19 +262,19 @@
super(FetchPeopleRequest, self).__init__(rest_request,
rpc_request,
user_id)
-
+
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
-
+
Args:
json: dict The JSON structure.
-
+
Returns: a Collection of Person objects.
"""
return data.Collection.parse_json(json, data.Person)
-
+
class FetchPersonRequest(FetchPeopleRequest):
"""A request for handling fetching a single person by id."""
@@ -286,10 +286,10 @@
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
-
+
Args:
json: dict The JSON structure.
-
+
Returns: A Person object.
"""
@@ -299,15 +299,15 @@
class FetchAppDataRequest(Request):
"""A request for handling fetching app data."""
- def __init__(self, user_id, group_id, app_id='@app', fields=None,
+ def __init__(self, user_id, group_id, app_id='@app', fields=None,
params=None):
params = params or {}
if fields:
params['fields'] = ','.join(fields)
-
+
rest_path = '/'.join(('appdata', user_id, group_id, app_id))
rest_request = RestRequestInfo(rest_path, params=params)
-
+
# TODO: Handle REST fields.
params.update({'userId': user_id,
'groupId': group_id,
@@ -320,10 +320,10 @@
def process_json(self, json):
"""Construct the appropriate OpenSocial object from a JSON dict.
-
+
Args:
json: dict The JSON structure.
-
+
Returns: An AppData object.
"""
@@ -336,12 +336,12 @@
class UpdateAppDataRequest(Request):
"""A request for handling updating app data."""
- def __init__(self, user_id, group_id, app_id='@app', fields=None, data={},
+ def __init__(self, user_id, group_id, app_id='@app', fields=None, data={},
params=None):
params = params or {}
if fields:
params['fields'] = ','.join(fields)
- else:
+ else:
params['fields'] = ','.join(data.keys())
params['data'] = data
@@ -362,7 +362,7 @@
class DeleteAppDataRequest(Request):
"""A request for handling deleting app data."""
- def __init__(self, user_id, group_id, app_id='@app', fields=None,
+ def __init__(self, user_id, group_id, app_id='@app', fields=None,
params=None):
params = params or {}
if fields:
@@ -386,7 +386,7 @@
class CreateNotificationRequest(Request):
""" A request for creating an Notification. """
- def __init__(self, user_id, recipients, mediaitems = None, templateParameters = None,
+ def __init__(self, user_id, recipients, mediaitems = None, templateParameters = None,
params=None):
params = params or {}
@@ -397,19 +397,19 @@
itemdict = {}
itemdict['msMediaItemUri'] = mediaitem;
itemlist.append(itemdict);
-
+
bodycontent['mediaItems'] = itemlist
bodycontent['recipientIds'] = recipients
bodycontent['templateParameters'] = templateParameters
-
- #if user_id != "@me":
+
+ #if user_id != "@me":
# params['xoauth_requestor_id'] = user_id;
-
+
rest_request = RestRequestInfo('/'.join(('notifications', user_id,'@self')),'POST', params, bodycontent, False)
super(CreateNotificationRequest, self).__init__(rest_request,
None,
user_id)
-
+
def process_json(self, json):
return json
@@ -419,13 +419,13 @@
rest_request = RestRequestInfo('/'.join(('albums', user_id,'@self')),'POST', params, body , False)
super(CreateAlbumRequest, self ).__init__(rest_request, None, user_id)
pass
-
+
def process_json(self, json):
return json
class CreateActivityRequest(Request):
""" A request for creating an activity. """
- def __init__(self, user_id, activity, group_id='@self', app_id='@app',
+ def __init__(self, user_id, activity, group_id='@self', app_id='@app',
params=None):
params = params or {}
params['activity'] = activity
@@ -438,7 +438,7 @@
super(CreateActivityRequest, self).__init__(None,
rpc_request,
user_id)
-
+
def process_json(self, json):
return json
@@ -456,11 +456,11 @@
rest_request = RestRequestInfo('/'.join(('activities', user_id,'@self', app_id)),'GET', params)
else:
rest_request = RestRequestInfo('/'.join(('activities', user_id,'@self')),'GET', params)
-
+
super(FetchActivityRequest, self).__init__(rest_request,
rpc_request,
user_id)
-
+
def process_json(self, json):
return data.Collection.parse_json(json, data.Activity)
@@ -477,10 +477,10 @@
def make_http_request(self, url_base, query_params=None):
"""Generates a http.Request object for the UrlFetch interface.
-
+
Args:
url_base: str The base REST URL.
-
+
Returns: The http.Request object.
"""
@@ -537,10 +537,10 @@
self.method = method
self.params = params
self.id = id or generate_uuid(method)
-
+
def get_rpc_body(self):
"""Creates the JSON dict structure for thie RPC request.
-
+
Returns: dict The JSON body for this RPC.
"""
@@ -554,14 +554,14 @@
class RequestBatch(object):
"""This class will manage the batching of requests."""
-
+
def __init__(self):
self.requests = {}
self.data = {}
-
+
def add_request(self, key, request):
"""Adds a request to this batch.
-
+
Args:
key: str A unique key to pair with the result of this request.
request: obj The request object.
@@ -573,7 +573,7 @@
def get(self, key):
"""Get the result value for a given request key.
-
+
Args:
key: str The key to retrieve.
@@ -582,7 +582,7 @@
def send(self, container):
"""Execute the batch with the specified container.
-
+
Args:
container: The container to execute this batch on.
Index: src/opensocial/validator.py
===================================================================
--- src/opensocial/validator.py (revision 89)
+++ src/opensocial/validator.py (working copy)
@@ -23,8 +23,8 @@
import hmac
import logging
-from opensocial.Crypto.PublicKey import RSA
-from opensocial.Crypto.Util import number
+from Crypto.PublicKey import RSA
+from Crypto.Util import number
class RequestValidator(object):
def get_signature_base_string(self, method, url, params):
@@ -36,7 +36,7 @@
url: string The fully-qualified url of the request.
params: string Parameters used to sign the request. Should be a merged
set of all querystring, form-urlencoded POST body, and header params.
-
+
Returns: string A signature base string as defined by the OAuth spec.
"""
encoded_params = {}
@@ -44,8 +44,8 @@
encoded_params[key] = value.encode('utf-8', 'ignore')
oauth_request = oauth.OAuthRequest(
- http_method=method.upper(),
- http_url=url,
+ http_method=method.upper(),
+ http_url=url,
parameters=encoded_params)
base_str = '&'.join((
@@ -54,17 +54,17 @@
oauth.escape(oauth_request.get_normalized_parameters())))
return base_str
-
+
def validate(self, method, url, params):
"""
Determines the validity of an OAuth-signed HTTP request.
-
+
Args:
method: string The HTTP method used for signing the request.
url: string The fully-qualified url of the request.
params: string Parameters used to sign the request. Should be a merged
set of all querystring, form-urlencoded POST body, and header params.
-
+
Returns: bool True if the request validated, False otherwise.
"""
raise NotImplementedError('RequestValidator must be subclassed.')
@@ -74,10 +74,10 @@
def __init__(self, public_key_str, exponent=65537):
"""
Creates a validator based off of the RSA-SHA1 signing mechanism.
-
+
Args:
- public_key_str: string The RSA public key modulus, expressed in hex
- format. Typically, this will look something like:
+ public_key_str: string The RSA public key modulus, expressed in hex
+ format. Typically, this will look something like:
0x00b1e057678343866db89d7dec2518
99261bf2f5e0d95f5d868f81d600c9a1
01c9e6da20606290228308551ed3acf9
@@ -87,45 +87,45 @@
efb45d26694caf4f26b9765b9f656652
45524de957e8c547c358781fdfb68ec0
56d1
- A list of such values can be found at
+ A list of such values can be found at
https://opensocialresources.appspot.com/certificates/
exponent: int The RSA public key exponent.
"""
public_key_long = long(public_key_str, 16)
self.public_key = RSA.construct((public_key_long, exponent))
-
+
def validate(self, method, url, params):
"""
Determines the validity of an OAuth-signed HTTP request.
-
+
Args:
method: string The HTTP method used for signing the request.
url: string The fully-qualified url of the request.
params: string Parameters used to sign the request. Should be a merged
set of all querystring, form-urlencoded POST body, and header params.
-
+
Returns: bool True if the request validated, False otherwise.
"""
base_string = self.get_signature_base_string(method, url, params)
local_hash = hashlib.sha1(base_string).digest()
-
+
if not params.has_key("oauth_signature"):
return False
-
+
try:
encoded_remote_signature = urllib.unquote(params["oauth_signature"])
remote_signature = base64.decodestring(encoded_remote_signature)
remote_hash = self.public_key.encrypt(remote_signature, '')[0][-20:]
except:
return False
-
+
return local_hash == remote_hash
class HmacSha1Validator(RequestValidator):
def __init__(self, key):
"""
Creates a validator based off of the HMAC-SHA1 signing mechanism.
-
+
Args:
key: string The shared secret key used to sign this request. Typically,
this value will be shared with the owner of an application at the
@@ -133,17 +133,17 @@
exponent: int The RSA public key exponent.
"""
self.hmac_key = '%s&' % oauth.escape(key)
-
+
def validate(self, method, url, params):
"""
Determines the validity of an OAuth-signed HTTP request.
-
+
Args:
method: string The HTTP method used for signing the request.
url: string The fully-qualified url of the request.
params: string Parameters used to sign the request. Should be a merged
set of all querystring, form-urlencoded POST body, and header params.
-
+
Returns: bool True if the request validated, False otherwise.
"""
base_string = self.get_signature_base_string(method, url, params)
@@ -159,5 +159,5 @@
return False
return local_hash == remote_hash
-
-
+
+