]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blobdiff - ctypescrypto/bio.py
Fixes some style. Improved tests coverage for bio,oid,digest and cipher. Prepare...
[oss/ctypescrypto.git] / ctypescrypto / bio.py
index 1263ce64dc12a305924a0ce8dedb6a309b1d0a73..b1700b9a869ca80dd1eba7dba1c13117782202b0 100644 (file)
@@ -1,30 +1,98 @@
+"""
+Interface to OpenSSL BIO library
+"""
 from ctypescrypto import libcrypto
-from ctypes import c_char_p, c_int, string_at
-class Membio:
+from ctypes import c_char_p, c_void_p, c_int, string_at, c_long,POINTER,byref, create_string_buffer
+class Membio(object):
        """ 
                Provides interface to OpenSSL memory bios 
-               use str() to get contents of writable bio
+               use str() or unicode() to get contents of writable bio
                use bio member to pass to libcrypto function
        """
        def __init__(self,data=None):
                """ If data is specified, creates read-only BIO. If data is
-                       None, creates writable BIO
+                       None, creates writable BIO, contents of which can be retrieved by str() or unicode()
                """
                if data is None:
                        method=libcrypto.BIO_s_mem()
                        self.bio=libcrypto.BIO_new(method)
                else:
-                       self.bio=libcrypto.BIO_new_mem_buf(c_char_p(data),len(data))q
+                       self.bio=libcrypto.BIO_new_mem_buf(c_char_p(data),len(data))
        def __del__(self):
+               """
+               Cleans up memory used by bio
+               """
                libcrypto.BIO_free(self.bio)
                del(self.bio)
        def __str__(self):
+               """
+               Returns current contents of buffer as byte string
+               """
                p=c_char_p(None)
-               l=BIO_get_mem_data(self.bio,byref(p))
+               l=libcrypto.BIO_ctrl(self.bio,3,0,byref(p))
                return string_at(p,l)
-#FIXME TODO - BIO should have stream-like interface
+       def __unicode__(self):
+               """
+               Attempts to interpret current contents of buffer as UTF-8 string and convert it to unicode
+               """
+               return str(self).decode("utf-8")
+       def read(self,length=None):
+               """
+               Reads data from readble BIO. For test purposes.
+               @param length - if specifed, limits amount of data read. If not BIO is read until end of buffer
+               """
+               if not length is None:
+                       if not isinstance(length,(int,long)):
+                               raise TypeError("length to read should be number")
+                       buf=create_string_buffer(length)
+                       readbytes=libcrypto.BIO_read(self.bio,buf,length)
+                       if readbytes==-2:
+                               raise NotImplementedError("Function is not supported by this BIO")
+                       if readbytes==-1:
+                               raise IOError
+                       if readbytes==0:
+                               return ""
+                       return buf.raw[:readbytes]
+               else:
+                       buf=create_string_buffer(1024)
+                       out=""
+                       r=1
+                       while r>0:
+                               r=libcrypto.BIO_read(self.bio,buf,1024)
+                               if r==-2:
+                                       raise NotImplementedError("Function is not supported by this BIO")
+                               if r==-1:
+                                       raise IOError
+                               if (r>0):
+                                       out+=buf.raw[:r]
+                       return out      
+
+       def write(self,data):
+               """
+               Writes data to writable bio. For test purposes
+               """
+               if isinstance(data,unicode):
+                       data=data.encode("utf-8")
+               r=libcrypto.BIO_write(self.bio,data,len(data))
+               if r==-2:
+                       raise NotImplementedError("Function not supported by this BIO")
+               if r<len(data):
+                       raise IOError("Not all data were successfully written")
+       def reset(self):
+               """
+               Resets the read-only bio to start and discards all data from writable bio
+               """
+               libcrypto.BIO_ctrl(self.bio,1,0,None)
+
+__all__ = ['Membio']
 libcrypto.BIO_s_mem.restype=c_void_p
 libcrypto.BIO_new.restype=c_void_p
 libcrypto.BIO_new.argtypes=(c_void_p,)
-libcrypto.BIO_get_mem_data.restype=c_long
-libcrypto.BIO_get_mem_data.argtypes=(c_void_p,POINTER(c_char_p))
+libcrypto.BIO_ctrl.restype=c_long
+libcrypto.BIO_ctrl.argtypes=(c_void_p,c_int,c_long,POINTER(c_char_p))
+libcrypto.BIO_read.argtypes=(c_void_p,c_char_p,c_int)
+libcrypto.BIO_write.argtypes=(c_void_p,c_char_p,c_int)
+libcrypto.BIO_free.argtypes=(c_void_p,)
+libcrypto.BIO_new_mem_buf.restype=c_void_p
+libcrypto.BIO_new_mem_buf.argtypes=(c_char_p,c_int)
+libcrypto.BIO_ctrl.argtypes=(c_void_p,c_int,c_int,c_void_p)