zoukankan      html  css  js  c++  java
  • 将python对象序列化成php能读取的格式(即能反序列化到对象)

    转载自:http://my.oschina.net/zuoan001/blog/94914

    代码如下:

    #coding:utf-8
    # vim: encoding=utf-8:ft=python:et:sw=4:ts=8:sts=4:
    #
    # Copyright (c) 2005 Scott Hurring.
    # Licensed under the GPL (undefined version).
       
    import types, string
       
    """
    Serialize class for the PHP serialization format.
       
    @version v0.4 BETA
    @author Scott Hurring; scott at hurring dot com
    @copyright Copyright (c) 2005 Scott Hurring
    @license http://opensource.org/licenses/gpl-license.php GNU Public License
    $Id: PHPSerialize.py,v 1.1 2006/01/08 21:53:19 shurring Exp $
       
    Most recent version can be found at:
    http://hurring.com/code/python/phpserialize/
       
    Usage:
    # Create an instance of the serialize engine
    s = PHPSerialize()
    # serialize some python data into a string
    serialized_string = s.serialize(string)
    # encode a session list (php's session_encode)
    serialized_string = s.session_encode(list)
    """
       
    class PHPSerialize(object):
        """
        Class to serialize data using the PHP Serialize format.
       
        Usage:
        serialized_string = PHPSerialize().serialize(data)
        serialized_string = PHPSerialize().session_encode(list)
        """
       
        def __init__(self):
            pass
       
        def session_encode(self, session):
            """Thanks to Ken Restivo for suggesting the addition
            of session_encode
            """
            out = ""
            for (k,v) in session.items():
                out = out + "%s|%s" % (k, self.serialize(v))
            return out
       
        def serialize(self, data):
            return self.serialize_value(data)
       
        def is_int(self, data):
            """
            Determine if a string var looks like an integer
            TODO: Make this do what PHP does, instead of a hack
            """
            try:
                int(data)
                return True
            except:
                return False
       
        def serialize_key(self, data):
            """
            Serialize a key, which follows different rules than when
            serializing values.  Many thanks to Todd DeLuca for pointing
            out that keys are serialized differently than values!
       
            From http://us2.php.net/manual/en/language.types.array.php
            A key may be either an integer or a string.
            If a key is the standard representation of an integer, it will be
            interpreted as such (i.e. "8" will be interpreted as int 8,
            while "08" will be interpreted as "08").
            Floats in key are truncated to integer.
            """
            # Integer, Long, Float, Boolean => integer
            if type(data) is types.IntType or type(data) is types.LongType 
            or type(data) is types.FloatType or type(data) is types.BooleanType:
                return "i:%s;" % int(data)
       
            # String => string or String => int (if string looks like int)
            elif type(data) is types.StringType:
                if self.is_int(data):
                    return "i:%s;" % int(data)
                else:
                    return "s:%i:"%s";" % (len(data),  data);
       
            # None / NULL => empty string
            elif type(data) is types.NoneType:
                return "s:0:"";"
       
            # I dont know how to serialize this
            else:
                raise Exception("Unknown / Unhandled key  type (%s)!" % type(data))
       
       
        def serialize_value(self, data):
            """
            Serialize a value.
            """
       
            # Integer => integer
            if type(data) is types.IntType:
                return "i:%s;" % data
       
            # Float, Long => double
            elif type(data) is types.FloatType or type(data) is types.LongType:
                return "d:%s;" % data
       
            # String => string or String => int (if string looks like int)
            # Thanks to Todd DeLuca for noticing that PHP strings that
            # look like integers are serialized as ints by PHP
            elif type(data) is types.StringType:
                if self.is_int(data):
                    return "i:%s;" % int(data)
                else:
                    return "s:%i:"%s";" % (len(data), data);
       
            # None / NULL
            elif type(data) is types.NoneType:
                return "N;";
       
            # Tuple and List => array
            # The 'a' array type is the only kind of list supported by PHP.
            # array keys are automagically numbered up from 0
            elif type(data) is types.ListType or type(data) is types.TupleType:
                i = 0
                out = []
                # All arrays must have keys
                for k in data:
                    out.append(self.serialize_key(i))
                    out.append(self.serialize_value(k))
                    i += 1
                return "a:%i:{%s}" % (len(data), "".join(out))
       
            # Dict => array
            # Dict is the Python analogy of a PHP array
            elif type(data) is types.DictType:
                out = []
                for k in data:
                    out.append(self.serialize_key(k))
                    out.append(self.serialize_value(data[k]))
                return "a:%i:{%s}" % (len(data), "".join(out))
       
            # Boolean => bool
            elif type(data) is types.BooleanType:
                return "b:%i;" % (data == 1)
       
            # I dont know how to serialize this
            else:
                raise Exception("Unknown / Unhandled data type (%s)!" % type(data))
             
    #!/usr/bin/env python2.4
    # vim: encoding=utf-8:ft=python:et:sw=4:ts=8:sts=4:
    #
    # Copyright (c) 2005 Scott Hurring.
    # Licensed under the GPL (undefined version).
       
    import types, string, re
       
    """
    Unserialize class for the PHP serialization format.
       
    @version v0.4 BETA
    @author Scott Hurring; scott at hurring dot com
    @copyright Copyright (c) 2005 Scott Hurring
    @license http://opensource.org/licenses/gpl-license.php GNU Public License
    $Id: PHPUnserialize.py,v 1.1 2006/01/08 21:53:19 shurring Exp $
       
    Most recent version can be found at:
    http://hurring.com/code/python/phpserialize/
       
    Usage:
    # Create an instance of the unserialize engine
    u = PHPUnserialize()
    # unserialize some string into python data
    data = u.unserialize(serialized_string)
    """
       
    class PHPUnserialize(object):
        """
        Class to unserialize something from the PHP Serialize format.
       
        Usage:
        u = PHPUnserialize()
        data = u.unserialize(serialized_string)
        """
       
        def __init__(self):
            pass
       
        def session_decode(self, data):
            """Thanks to Ken Restivo for suggesting the addition
            of session_encode
            """
            session = {}
            while len(data) > 0:
                m = re.match('^(w+)|', data)
                if m:
                    key = m.group(1)
                    offset = len(key)+1
                    (dtype, dataoffset, value) = self._unserialize(data, offset)
                    offset = offset + dataoffset
                    data = data[offset:]
                    session[key] = value
                else:
                    # No more stuff to decode
                    return session
       
            return session
       
        def unserialize(self, data):
            return self._unserialize(data, 0)[2]
       
        def _unserialize(self, data, offset=0):
            """
            Find the next token and unserialize it.
            Recurse on array.
       
            offset = raw offset from start of data
       
            return (type, offset, value)
            """
       
            buf = []
            dtype = string.lower(data[offset:offset+1])
       
            #print "# dtype =", dtype
       
            # 't:' = 2 chars
            dataoffset = offset + 2
            typeconvert = lambda x : x
            chars = datalength = 0
       
             # int => Integer
            if dtype == 'i':
                typeconvert = lambda x : int(x)
                (chars, readdata) = self.read_until(data, dataoffset, ';')
                # +1 for end semicolon
                dataoffset += chars + 1
       
             # bool => Boolean
            elif dtype == 'b':
                typeconvert = lambda x : (int(x) == 1)
                (chars, readdata) = self.read_until(data, dataoffset, ';')
                # +1 for end semicolon
                dataoffset += chars + 1
       
            # double => Floating Point
            elif dtype == 'd':
                typeconvert = lambda x : float(x)
                (chars, readdata) = self.read_until(data, dataoffset, ';')
                # +1 for end semicolon
                dataoffset += chars + 1
       
            # n => None
            elif dtype == 'n':
                readdata = None
       
            # s => String
            elif dtype == 's':
                (chars, stringlength) = self.read_until(data, dataoffset, ':')
                # +2 for colons around length field
                dataoffset += chars + 2
       
                # +1 for start quote
                (chars, readdata) = self.read_chars(data, dataoffset+1, int(stringlength))
                # +2 for endquote semicolon
                dataoffset += chars + 2
       
                if chars != int(stringlength) != int(readdata):
                    raise Exception("String length mismatch")
       
            # array => Dict
            # If you originally serialized a Tuple or List, it will
            # be unserialized as a Dict.  PHP doesn't have tuples or lists,
            # only arrays - so everything has to get converted into an array
            # when serializing and the original type of the array is lost
            elif dtype == 'a':
                readdata = {}
       
                # How many keys does this list have?
                (chars, keys) = self.read_until(data, dataoffset, ':')
                # +2 for colons around length field
                dataoffset += chars + 2
       
                # Loop through and fetch this number of key/value pairs
                for i in range(0, int(keys)):
                    # Read the key
                    (ktype, kchars, key) = self._unserialize(data, dataoffset)
                    dataoffset += kchars
                    #print "Key(%i) = (%s, %i, %s) %i" % (i, ktype, kchars, key, dataoffset)
       
                    # Read value of the key
                    (vtype, vchars, value) = self._unserialize(data, dataoffset)
                    dataoffset += vchars
                    #print "Value(%i) = (%s, %i, %s) %i" % (i, vtype, vchars, value, dataoffset)
       
                    # Set the list element
                    readdata[key] = value
       
                    # +1 for end semicolon
                dataoffset += 1
                #chars = int(dataoffset) - start
       
            # I don't know how to unserialize this
            else:
                raise Exception("Unknown / Unhandled data type (%s)!" % dtype)
       
       
            return (dtype, dataoffset-offset, typeconvert(readdata))
       
        def read_until(self, data, offset, stopchar):
            """
            Read from data[offset] until you encounter some char 'stopchar'.
            """
            buf = []
            char = data[offset:offset+1]
            i = 2
            while char != stopchar:
                # Consumed all the characters and havent found ';'
                if i+offset > len(data):
                    raise Exception("Invalid")
                buf.append(char)
                char = data[offset+(i-1):offset+i]
                i += 1
       
            # (chars_read, data)
            return (len(buf), "".join(buf))
       
        def read_chars(self, data, offset, length):
            """
            Read 'length' number of chars from data[offset].
            """
            buf = []
            # Account for the starting quote char
            #offset += 1
            for i in range(0, length):
                char = data[offset+(i-1):offset+i]
                buf.append(char)
       
            # (chars_read, data)
            return (len(buf), "".join(buf))
     
    def dumps(data, protocol=None):
        return PHPSerialize().serialize(data)
       
    def loads(data):
        return PHPUnserialize().unserialize(data)

    完毕

  • 相关阅读:
    CTF SQL注入知识点
    Rot13加密算法
    LFU缓存
    Redability
    快排
    更新卡片的zIndex
    webshell文件下载器
    [转]背包九讲
    hihocoder第196周
    Python import容易犯的一个错误
  • 原文地址:https://www.cnblogs.com/zl0372/p/python_serialize.html
Copyright © 2011-2022 走看看