Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2013-03-20 Version 0.6.2
* Fixes for bugs:
#75 crash on python 2.7 x64 windows
#73 _convert_query_string return a wrong query string parameter

2012-12-17 Version 0.6.1
* Fixes for bugs:
#69 _get_readable_id doesn't support queues with slashes in their names
Expand Down
145 changes: 86 additions & 59 deletions src/azure/http/winhttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,27 @@
_SysFreeString = _oleaut32.SysFreeString
_SysFreeString.argtypes = [c_void_p]

_CoTaskMemAlloc = _ole32.CoTaskMemAlloc
_CoTaskMemAlloc.restype = c_void_p
_CoTaskMemAlloc.argtypes = [c_size_t]
#SAFEARRAY*
#SafeArrayCreateVector(_In_ VARTYPE vt,_In_ LONG lLbound,_In_ ULONG cElements);
_SafeArrayCreateVector = _oleaut32.SafeArrayCreateVector
_SafeArrayCreateVector.restype = c_void_p
_SafeArrayCreateVector.argtypes = [c_ushort, c_long, c_ulong]

#HRESULT
#SafeArrayAccessData(_In_ SAFEARRAY *psa, _Out_ void **ppvData);
_SafeArrayAccessData = _oleaut32.SafeArrayAccessData
_SafeArrayAccessData.argtypes = [c_void_p, POINTER(c_void_p)]

#HRESULT
#SafeArrayUnaccessData(_In_ SAFEARRAY *psa);
_SafeArrayUnaccessData = _oleaut32.SafeArrayUnaccessData
_SafeArrayUnaccessData.argtypes = [c_void_p]

#HRESULT
#SafeArrayGetUBound(_In_ SAFEARRAY *psa, _In_ UINT nDim, _Out_ LONG *plUbound);
_SafeArrayGetUBound = _oleaut32.SafeArrayGetUBound
_SafeArrayGetUBound.argtypes = [c_void_p, c_ulong, POINTER(c_long)]

_CoTaskMemFree = _ole32.CoTaskMemFree
_CoTaskMemFree.argtypes = [c_void_p]

#------------------------------------------------------------------------------

Expand All @@ -72,26 +87,6 @@ def __init__(self, value):
def __del__(self):
_SysFreeString(self)

class _tagSAFEARRAY(Structure):
'''
SAFEARRAY structure in python. Does not match the definition in
MSDN exactly & it is only mapping the used fields. Field names are also
slighty different.
'''

class _tagSAFEARRAYBOUND(Structure):
_fields_ = [('c_elements', c_ulong), ('l_lbound', c_long)]

_fields_ = [('c_dims', c_ushort),
('f_features', c_ushort),
('cb_elements', c_ulong),
('c_locks', c_ulong),
('pvdata', c_void_p),
('rgsabound', _tagSAFEARRAYBOUND*1)]

def __del__(self):
_CoTaskMemFree(self.pvdata)

class VARIANT(Structure):
'''
VARIANT structure in python. Does not match the definition in
Expand All @@ -110,7 +105,7 @@ class _tagRecord(Structure):
('ival', c_short),
('boolval', c_ushort),
('bstrval', BSTR),
('parray', POINTER(_tagSAFEARRAY)),
('parray', c_void_p),
('record', _tagRecord)]

_fields_ = [('vt', c_ushort),
Expand All @@ -119,6 +114,63 @@ class _tagRecord(Structure):
('wReserved3', c_ushort),
('vdata', _tagData)]

@staticmethod
def create_empty():
variant = VARIANT()
variant.vt = VT_EMPTY
variant.vdata.llval = 0
return variant

@staticmethod
def create_safearray_from_str(text):
variant = VARIANT()
variant.vt = VT_ARRAY | VT_UI1

length = len(text)
variant.vdata.parray = _SafeArrayCreateVector(VT_UI1, 0, length)
pvdata = c_void_p()
_SafeArrayAccessData(variant.vdata.parray, byref(pvdata))
ctypes.memmove(pvdata, text, length)
_SafeArrayUnaccessData(variant.vdata.parray)

return variant

@staticmethod
def create_bstr_from_str(text):
variant = VARIANT()
variant.vt = VT_BSTR
variant.vdata.bstrval = BSTR(text)
return variant

@staticmethod
def create_bool_false():
variant = VARIANT()
variant.vt = VT_BOOL
variant.vdata.boolval = 0
return variant

def is_safearray_of_bytes(self):
return self.vt == VT_ARRAY | VT_UI1

def str_from_safearray(self):
assert self.vt == VT_ARRAY | VT_UI1
pvdata = c_void_p()
count = c_long()
_SafeArrayGetUBound(self.vdata.parray, 1, byref(count))
count = c_long(count.value + 1)
_SafeArrayAccessData(self.vdata.parray, byref(pvdata))
text = ctypes.string_at(pvdata, count)
_SafeArrayUnaccessData(self.vdata.parray)
return text

def __del__(self):
_VariantClear(self)

#HRESULT VariantClear(_Inout_ VARIANTARG *pvarg);
_VariantClear = _oleaut32.VariantClear
_VariantClear.argtypes = [POINTER(VARIANT)]


class GUID(Structure):
''' GUID structure in python. '''

Expand Down Expand Up @@ -165,10 +217,7 @@ def open(self, method, url):
'''
_WinHttpRequest._SetTimeouts(self, 0, 65000, 65000, 65000)

flag = VARIANT()
flag.vt = VT_BOOL
flag.vdata.boolval = 0

flag = VARIANT.create_bool_false()
_method = BSTR(method)
_url = BSTR(url)
_WinHttpRequest._Open(self, _method, _url, flag)
Expand All @@ -195,24 +244,11 @@ def send(self, request = None):

# Sends VT_EMPTY if it is GET, HEAD request.
if request is None:
var_empty = VARIANT()
var_empty.vt = VT_EMPTY
var_empty.vdata.llval = 0
var_empty = VARIANT.create_empty()
_WinHttpRequest._Send(self, var_empty)
else: # Sends request body as SAFEArray.
_request = VARIANT()
_request.vt = VT_ARRAY | VT_UI1
safearray = _tagSAFEARRAY()
safearray.c_dims = 1
safearray.cb_elements = 1
safearray.c_locks = 0
safearray.f_features = 128
safearray.rgsabound[0].c_elements = len(request)
safearray.rgsabound[0].l_lbound = 0
safearray.pvdata = cast(_CoTaskMemAlloc(len(request)), c_void_p)
ctypes.memmove(safearray.pvdata, request, len(request))
_request.vdata.parray = cast(byref(safearray), POINTER(_tagSAFEARRAY))
_WinHttpRequest._Send(self, _request)
_request = VARIANT.create_safearray_from_str(request)
_WinHttpRequest._Send(self, _request)

def status(self):
''' Gets status of response. '''
Expand All @@ -238,10 +274,8 @@ def response_body(self):
'''
var_respbody = VARIANT()
_WinHttpRequest._ResponseBody(self, byref(var_respbody))
if var_respbody.vt == VT_ARRAY | VT_UI1:
safearray = var_respbody.vdata.parray.contents
respbody = ctypes.string_at(safearray.pvdata, safearray.rgsabound[0].c_elements)

if var_respbody.is_safearray_of_bytes():
respbody = var_respbody.str_from_safearray()
if respbody[3:].startswith('<?xml') and respbody.startswith('\xef\xbb\xbf'):
respbody = respbody[3:]
return respbody
Expand All @@ -259,18 +293,11 @@ def set_tunnel(self, host, port):
if port:
url = url + u':' + port

var_host = VARIANT()
var_host.vt = VT_BSTR
var_host.vdata.bstrval = BSTR(url)

var_empty = VARIANT()
var_empty.vt = VT_EMPTY
var_empty.vdata.llval = 0
var_host = VARIANT.create_bstr_from_str(url)
var_empty = VARIANT.create_empty()

_WinHttpRequest._SetProxy(self, HTTPREQUEST_PROXYSETTING_PROXY, var_host, var_empty)

_SysFreeString(var_host.vdata.bstrval)

def __del__(self):
if self.value is not None:
_WinHttpRequest._Release(self)
Expand Down
8 changes: 4 additions & 4 deletions src/azure/storage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ def __init__(self):
class AccessPolicy(WindowsAzureData):
''' Access Policy class in service properties. '''

def __init__(self):
self.start = u''
self.expiry = u''
self.permission = u''
def __init__(self, start=u'', expiry=u'', permission='u'):
self.start = start
self.expiry = expiry
self.permission = permission

class SignedIdentifier(WindowsAzureData):
''' Signed Identifier class for service properties. '''
Expand Down
19 changes: 6 additions & 13 deletions src/azure/storage/sharedaccesssignature.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import base64
import hmac
import hashlib
import urllib2

#-------------------------------------------------------------------------
# Constants for the share access signature
Expand All @@ -24,8 +25,8 @@
SIGNED_PERMISSION = 'sp'
SIGNED_IDENTIFIER = 'si'
SIGNED_SIGNATURE = 'sig'
RESOURCE_BLOB = 'blob'
RESOURCE_CONTAINER = 'container'
RESOURCE_BLOB = 'b'
RESOURCE_CONTAINER = 'c'
SIGNED_RESOURCE_TYPE = 'resource'
SHARED_ACCESS_PERMISSION = 'permission'

Expand Down Expand Up @@ -126,11 +127,11 @@ def _convert_query_string(self, query_string):
convert_str += SIGNED_START + '=' + query_string[SIGNED_START] + '&'
convert_str += SIGNED_EXPIRY + '=' + query_string[SIGNED_EXPIRY] + '&'
convert_str += SIGNED_PERMISSION + '=' + query_string[SIGNED_PERMISSION] + '&'
convert_str += SIGNED_RESOURCE_TYPE + '=' + query_string[SIGNED_RESOURCE] + '&'
convert_str += SIGNED_RESOURCE + '=' + query_string[SIGNED_RESOURCE] + '&'

if query_string.has_key(SIGNED_IDENTIFIER):
convert_str += SIGNED_IDENTIFIER + '=' + query_string[SIGNED_IDENTIFIER] + '&'
convert_str += SIGNED_SIGNATURE + '=' + query_string[SIGNED_SIGNATURE] + '&'
convert_str += SIGNED_SIGNATURE + '=' + urllib2.quote(query_string[SIGNED_SIGNATURE]) + '&'
return convert_str

def _generate_signature(self, path, resource_type, shared_access_policy):
Expand All @@ -150,7 +151,7 @@ def get_value_to_append(value, no_new_line=False):
canonicalized_resource = '/' + self.account_name + path;

#form the string to sign from shared_access_policy and canonicalized resource.
#The order of values is import.
#The order of values is important.
string_to_sign = (get_value_to_append(shared_access_policy.access_policy.permission) +
get_value_to_append(shared_access_policy.access_policy.start) +
get_value_to_append(shared_access_policy.access_policy.expiry) +
Expand Down Expand Up @@ -180,11 +181,3 @@ def _sign(self, string_to_sign):
decode_account_key = base64.b64decode(self.account_key)
signed_hmac_sha256 = hmac.HMAC(decode_account_key, string_to_sign, hashlib.sha256)
return base64.b64encode(signed_hmac_sha256.digest())








2 changes: 1 addition & 1 deletion src/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from distutils.core import setup

setup(name='azure',
version='0.6.1',
version='0.6.2',
description='Windows Azure client APIs',
url='https://github.com/WindowsAzure/azure-sdk-for-python',
packages=['azure',
Expand Down
Loading