Skip to content

Commit e716e7e

Browse files
authored
Merge pull request #40 from pnhowe/master
some more minor security, usability and smell fixes
2 parents 7617700 + e4472ac commit e716e7e

5 files changed

Lines changed: 41 additions & 28 deletions

File tree

cinp/client.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from cinp.common import URI
1313

14-
__CLIENT_VERSION__ = '2.1.0'
14+
__CLIENT_VERSION__ = '2.1.1'
1515
__CINP_VERSION__ = '2.0'
1616

1717
__all__ = [ 'Timeout', 'ResponseError', 'DetailedInvalidRequest',
@@ -101,7 +101,7 @@ def __init__( self, host, root_path, proxy=None, verify_ssl=True, retry_event=No
101101
if retry_event is not None:
102102
self.retry_event = retry_event
103103
else:
104-
self.retry_event = asyncio.Event()
104+
self.retry_event = None
105105

106106
if not host.startswith( ( 'http:', 'https:' ) ):
107107
raise ValueError( 'hostname must start with http(s):' )
@@ -115,10 +115,10 @@ def __init__( self, host, root_path, proxy=None, verify_ssl=True, retry_event=No
115115

116116
self.uri = URI( root_path )
117117

118+
self.ssl_context = ssl.create_default_context()
118119
if not verify_ssl:
119-
self.ssl_context = ssl._create_unverified_context()
120-
else:
121-
self.ssl_context = ssl.create_default_context()
120+
self.ssl_context.check_hostname = False
121+
self.ssl_context.verify_mode = ssl.CERT_NONE
122122

123123
self.connection_pool = None
124124

@@ -132,6 +132,9 @@ def __init__( self, host, root_path, proxy=None, verify_ssl=True, retry_event=No
132132
self.auth_header_list = []
133133

134134
async def __aenter__( self ):
135+
if self.retry_event is None:
136+
self.retry_event = asyncio.Event()
137+
135138
if self.proxy: # not doing 'is not None', so empty strings don't try and proxy
136139
self.connection_pool = httpcore.AsyncHTTPProxy( proxy_url=self.proxy, ssl_context=self.ssl_context )
137140
else:
@@ -339,7 +342,10 @@ async def describe( self, uri, timeout=30, retry_count=0 ):
339342
logging.warning( 'cinp: Unexpected HTTP Code "{0}" for DESCRIBE'.format( http_code ) )
340343
raise ResponseError( 'Unexpected HTTP Code "{0}" for DESCRIBE'.format( http_code ) )
341344

342-
return data, header_map[ 'Type' ]
345+
try:
346+
return data, header_map[ 'Type' ]
347+
except KeyError:
348+
raise ResponseError( 'DESCRIBE Response did not specify the Type' )
343349

344350
async def list( self, uri, filter_name=None, filter_value_map=None, position=0, count=10, timeout=30, retry_count=0 ):
345351
"""
@@ -503,23 +509,19 @@ async def getMulti( self, uri, id_list=None, chunk_size=10, retry_count=0 ):
503509
tmp_id_list = []
504510
id_list = tmp_id_list
505511

506-
result_list = []
507512
pos = 0
508513

509514
while pos < len( id_list ):
510515
tmp_data = await self.get( self.uri.build( namespace, model, None, id_list[ pos: pos + chunk_size ] ), force_multi_mode=True, retry_count=retry_count )
511516
pos += chunk_size
512517
for key in tmp_data:
513-
result_list.append( ( key, tmp_data[ key ] ) )
514-
515-
while len( result_list ) > 0:
516-
yield result_list.pop( 0 )
518+
yield ( key, tmp_data[ key ] )
517519

518520
async def getFilteredObjects( self, uri, filter_name=None, filter_value_map=None, list_chunk_size=100, get_chunk_size=10, timeout=30, retry_count=0 ):
519521
pos = 0
520522
total = 1
521523
while pos < total:
522-
( tmp_id_list, count_map ) = await self.list( uri, filter_name=filter_name, filter_value_map=filter_value_map, position=pos, count=list_chunk_size, retry_count=retry_count )
524+
( tmp_id_list, count_map ) = await self.list( uri, filter_name=filter_name, filter_value_map=filter_value_map, position=pos, count=list_chunk_size, timeout=timeout, retry_count=retry_count )
523525
id_list = self.uri.extractIds( tmp_id_list )
524526
pos = count_map[ 'position' ] + count_map[ 'count' ]
525527
total = count_map[ 'total' ]
@@ -531,7 +533,7 @@ async def getFilteredURIs( self, uri, filter_name=None, filter_value_map=None, l
531533
pos = 0
532534
total = 1
533535
while pos < total:
534-
( tmp_id_list, count_map ) = await self.list( uri, filter_name=filter_name, filter_value_map=filter_value_map, position=pos, count=list_chunk_size, retry_count=retry_count )
536+
( tmp_id_list, count_map ) = await self.list( uri, filter_name=filter_name, filter_value_map=filter_value_map, position=pos, count=list_chunk_size, timeout=timeout, retry_count=retry_count )
535537
id_list = self.uri.extractIds( tmp_id_list )
536538
pos = count_map[ 'position' ] + count_map[ 'count' ]
537539
total = count_map[ 'total' ]
@@ -650,21 +652,31 @@ async def uploadFile( self, uri, filepath, filename=None, cb=None, timeout=30 ):
650652
if isinstance( filepath, str ):
651653
if filename is None:
652654
filename = os.path.basename( filepath )
653-
654-
file_reader = _readerWrapper( open( filepath, 'rb' ), cb )
655-
656655
else:
657656
if filename is None:
658657
filename = os.path.basename( filepath.name )
659658

660-
file_reader = _readerWrapper( filepath, cb )
659+
if '"' in filename or ';' in filename:
660+
raise InvalidRequest( 'filename contains invalid characters' )
661661

662-
header_map = {
663-
'Content-Disposition': 'inline; filename="{0}"'.format( filename ),
664-
'Content-Length': len( file_reader )
665-
}
662+
opened_file = None
663+
try:
664+
if isinstance( filepath, str ):
665+
opened_file = open( filepath, 'rb' )
666+
file_reader = _readerWrapper( opened_file, cb )
667+
else:
668+
file_reader = _readerWrapper( filepath, cb )
666669

667-
( http_code, data, _ ) = await self._request( 'UPLOAD', uri_parser.build( namespace, model ), data=file_reader, header_map=header_map, timeout=timeout )
670+
header_map = {
671+
'Content-Disposition': 'inline; filename="{0}"'.format( filename ),
672+
'Content-Length': len( file_reader )
673+
}
674+
675+
( http_code, data, _ ) = await self._request( 'UPLOAD', uri_parser.build( namespace, model ), data=file_reader, header_map=header_map, timeout=timeout )
676+
677+
finally:
678+
if opened_file is not None:
679+
opened_file.close()
668680

669681
if http_code != 202:
670682
logging.warning( 'cinp: Unexpected HTTP Code "{0}" for File Upload'.format( http_code ) )

cinp/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def uriListToMultiURI( self, uri_list ):
112112

113113

114114
# borrowed from https://www.python.org/dev/peps/pep-0257/
115-
def doccstring_prep( docstring ):
115+
def docstring_prep( docstring ):
116116
if not docstring:
117117
return ''
118118

cinp/readers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ def http( uri ):
6464

6565

6666
READER_REGISTRY[ 'http' ] = http
67+
READER_REGISTRY[ 'https' ] = http

cinp/server_common.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from dateutil import parser as datetimeparser
77
from urllib import parse
88

9-
from cinp.common import URI, doccstring_prep
9+
from cinp.common import URI, docstring_prep
1010
from cinp.readers import READER_REGISTRY
1111

1212
__CINP_VERSION__ = '2.0'
@@ -411,7 +411,7 @@ class Parameter():
411411
def __init__( self, type, name=None, is_array=False, doc=None, length=None, model=None, model_resolve=None, choice_list=None, default=notset, allowed_scheme_list=None ):
412412
super().__init__()
413413
self.name = name
414-
self.doc = doccstring_prep( doc )
414+
self.doc = docstring_prep( doc )
415415
if type is None:
416416
self.type = None
417417

@@ -515,7 +515,7 @@ def __init__( self, name, doc='' ):
515515
super().__init__()
516516
self.parent = None
517517
self.name = name
518-
self.doc = doccstring_prep( doc )
518+
self.doc = docstring_prep( doc )
519519

520520
@property
521521
def path( self ):

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ def build_packages( self ):
3030
author='Peter Howe',
3131
author_email='pnhowe@gmail.com',
3232
url='https://github.com/cinp/python',
33-
python='~=3.6',
33+
python_requires='~=3.8',
3434
license='Apache2',
3535
classifiers=[
3636
'Development Status :: 5 - Production/Stable',
3737
'Intended Audience :: Developers',
3838
'License :: OSI Approved :: Apache Software License',
3939
'Programming Language :: Python :: 3',
40-
'Programming Language :: Python :: 3.6'
40+
'Programming Language :: Python :: 3.8'
4141
],
4242
packages=[ 'cinp' ],
4343
cmdclass={ 'build_py': build }

0 commit comments

Comments
 (0)