~ubuntu-branches/ubuntu/hardy/emesene/hardy-proposed

« back to all changes in this revision

Viewing changes to emesenelib/Msnobj.py

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2008-02-06 21:57:05 UTC
  • Revision ID: james.westby@ubuntu.com-20080206215705-d1abf07rdwcaju3p
Tags: upstream-1.0~r1013
ImportĀ upstreamĀ versionĀ 1.0~r1013

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
#   This file is part of emesene.
 
4
#
 
5
#    Emesene is free software; you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation; either version 2 of the License, or
 
8
#    (at your option) any later version.
 
9
#
 
10
#    emesene is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
#
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with emesene; if not, write to the Free Software
 
17
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 
 
19
import urllib
 
20
import base64
 
21
import sha
 
22
import os
 
23
 
 
24
class MsnObjectsManager(object):
 
25
    def __init__( self, user ):
 
26
        self.user = user
 
27
        self.objects = {}
 
28
        self.idToContext = {}
 
29
    
 
30
    def getByContext( self, context ):
 
31
        tmp = base64.b64decode( context )
 
32
        if not tmp.endswith( '\0' ):
 
33
            context = base64.b64encode( tmp+'\0' )
 
34
        if self.objects.has_key(context):
 
35
            return self.objects[context]
 
36
        else:
 
37
            return None
 
38
        
 
39
    def getIds( self ):
 
40
        return self.idToContext.keys()
 
41
        
 
42
    def getById( self, id ):
 
43
        return self.getByContext( self.idToContext[id] )
 
44
        
 
45
    def create( self, id, filename, type ):
 
46
        #msnobj = Msnobj.Msnobj( self.user, size, Msnobj.Msnobj.CUSTOM_EMOTICON, name, data = f.read() )
 
47
        f = file( filename, 'r' )
 
48
        f.seek( 0,2 )
 
49
        size = f.tell()
 
50
        f.seek( 0,0 )
 
51
        name = filename.split( os.sep )[ -1: ][ 0 ]
 
52
        msnobj = Msnobj( self.user.lower(), size, type, "0", data = f.read(), filename=filename, friendly=id )
 
53
        f.close()
 
54
        context = base64.b64encode( str( msnobj )+ '\0' )
 
55
        self.objects.update( {context:msnobj} )
 
56
        if id !='': self.idToContext.update( {id:context} )
 
57
        return msnobj
 
58
        
 
59
    def remove( self, id=None, context=None ):
 
60
        try:
 
61
            if id != None:
 
62
                context = self.getById( id )
 
63
                self.idToContext.pop( id )
 
64
            self.objects.pop( context )
 
65
        except: pass
 
66
                
 
67
class Msnobj( object ):
 
68
    '''this class represent the msnobject, for example:
 
69
    <msnobj Creator="buddy@hotmail.com" Size="24539" Type="3" Location="TFR2C.tmp" Friendly="AAA=" SHA1D="snip" SHA1C="snip"/>
 
70
    wlm CE:
 
71
    spoo    <msnobj Creator="buddy@hotmail.com" Type="2" SHA1D="87YzhijLQyyp4iIlL2k9LlB2wr0=" Size="1169" Location="0" Friendly="cwBwAG8AbwAAAA=="/>
 
72
    *  2: Custom Emoticons
 
73
    * 3: Display Pictures
 
74
    * 5: Background Images
 
75
    * 7: Dynamic Display Pictures (Flash-animated DPs)
 
76
    * 8: Winks (short Flash animations)
 
77
    * 11: Voice Clips (Wave sounds)
 
78
    * 12: "SavedState" Property of Add-Ins
 
79
    * 14: MSNP15 Locations 
 
80
    '''
 
81
    
 
82
    CUSTOM_EMOTICON = 2
 
83
    DISPLAY_PICTURE = 3
 
84
    BACKGROUND_IMAGE = 4
 
85
    DYNAMIC_DISPLAY_PICTURE = 7
 
86
    WINK = 8
 
87
    VOICE_CLIP = 11
 
88
    SAVED_STATE_PROPERTY = 12
 
89
    LOCATION = 14
 
90
    
 
91
    def __init__( self, creator, size='', type='', location='', friendly='\x00', sha1c='', sha1d='', data='', filename='' ):
 
92
        '''#  Creator - This field indicates the person who made (and is sending) the object.
 
93
            # Size - The Size field contains the length of the file in bytes
 
94
            # Type - The Type field indicates what sort of image (or file) it is about. At the moment the following flags are known:
 
95
 
 
96
            * 2: Custom Emoticons
 
97
            * 3: Display Pictures
 
98
            * 5: Background Images
 
99
            * 7: Dynamic Display Pictures (Flash-animated DPs)
 
100
            * 8: Winks (short Flash animations)
 
101
            * 11: Voice Clips (Wave sounds)
 
102
            * 12: "SavedState" Property of Add-Ins
 
103
            * 14: MSNP15 Locations 
 
104
 
 
105
            # Location - The Location field contains the filename under which the picture (or file) will be (or has been) stored
 
106
            # Friendly - This field contains the name of the picture in Unicode (UTF-16) format. The string is then encoded with Base64. So far this field has only been seen used with Background Images and Winks. With other file types, its value is "AAA=" (the utf-16 null string, encoded with Base64).
 
107
            # SHA1D - The SHA1D field contains a SHA1 hash of the images data encoded in Base64. It will from now on be called the SHA1 Data field.
 
108
            # SHA1C - This field contains all previous fields hashed with SHA1, and then encoded in Base64'''
 
109
        #FIXME: that docstring sucks
 
110
        self.creator = creator
 
111
        self.size = size
 
112
        self.type = int(type)
 
113
        self.location = location
 
114
        self.friendly = base64.b64encode( unicode( friendly ).encode( 'utf-16' )[2:] )
 
115
        self.filename = filename
 
116
 
 
117
        self.data = data
 
118
        #for received msnobj
 
119
        
 
120
        if sha1d != '':
 
121
            self.sha1d = sha1d
 
122
            # always return the same sha1d, amsn requires this
 
123
            self.forceSha1d = True
 
124
        else:
 
125
            self.sha1d = self.makeSha1d() 
 
126
            self.forceSha1d = False
 
127
        
 
128
        if sha1c != '':
 
129
            self.sha1c = sha1c
 
130
        else:
 
131
            self.sha1c = self.makeSha1c()
 
132
        
 
133
    def __repr__( self ):
 
134
        string = '<msnobj Creator="' + self.creator + '" '
 
135
        string += 'Size="' + str( self.size ) + '" Type="' + str( self.type ) + '" '
 
136
        string += 'Location="'+ self.location +'" '
 
137
        string += 'Friendly="' + self.friendly + '" '
 
138
        
 
139
        sha1d = ''
 
140
        if self.forceSha1d:
 
141
            sha1d = self.sha1d
 
142
        else:
 
143
            sha1d = self.makeSha1d()
 
144
        
 
145
        string += 'SHA1D="' + sha1d + '" SHA1C="' + self.makeSha1c() + '"/>'
 
146
        return string
 
147
    
 
148
    def makeSha1d( self ):
 
149
        return base64.b64encode( sha.new( self.data ).digest() )
 
150
    
 
151
    def makeSha1c( self ):
 
152
        string = 'Creator' + self.creator
 
153
        string += 'Size' + str( self.size ) + 'Type' + str( self.type )
 
154
        string += 'Location'+ unquote( self.location )
 
155
        string += 'Friendly' + self.friendly
 
156
        string += 'SHA1D' + self.sha1d
 
157
        
 
158
        return base64.b64encode( sha.new( string ).digest() )
 
159
    
 
160
    def quote( self ):
 
161
        return urllib.quote( self.__repr__() )
 
162
    
 
163
    def getCreator( self ): #XXX: property
 
164
        return self.creator
 
165
    
 
166
    def setCreator( self, creator ):
 
167
        self.creator = creator
 
168
        
 
169
    def getType(self):
 
170
        return str( self.type )
 
171
 
 
172
    def __eq__(self, obj):
 
173
        status = True
 
174
        if not isinstance(obj, Msnobj):
 
175
            return False
 
176
 
 
177
        fields = ['creator', 'location', 'friendly', 'size', 'type',
 
178
                  'sha1c', 'sha1d']
 
179
 
 
180
        for field in fields:
 
181
            if getattr(self, field) != getattr(obj, field):
 
182
                print "DEBUG msnobj %s differ: %s != %s" % (field,
 
183
                    getattr(self, field),
 
184
                    getattr(obj, field))
 
185
                status = False
 
186
        return status
 
187
 
 
188
    def __neq__(self, obj):
 
189
        return not (self == obj)
 
190
    
 
191
            
 
192
def unquote( msnobj ):    
 
193
    return urllib.unquote( msnobj )
 
194
 
 
195
def createFromString( string, quoted=True ):
 
196
    if string == '0': return None
 
197
    
 
198
    if quoted:
 
199
        msnobjStr = unquote( string )
 
200
    else:
 
201
        msnobjStr = string
 
202
    
 
203
    def getData( string, start, stop ):
 
204
        if start in string:
 
205
            return string.split( start )[1].split(stop)[0]
 
206
        else:
 
207
            # TODO: what to do when a field is not in the string?
 
208
            return ''
 
209
    
 
210
    try:
 
211
        creator = getData( msnobjStr, 'Creator="', '"' )
 
212
        size = getData( msnobjStr, 'Size="', '"' )
 
213
        _type = getData( msnobjStr, 'Type="', '"' )
 
214
        location = getData( msnobjStr, 'Location="', '"' )
 
215
        friendly = getData( msnobjStr, 'Friendly="', '"' )
 
216
        try:
 
217
            friendly = str( base64.b64decode( friendly ).decode( 'utf-16' ) )
 
218
        except:
 
219
            friendly = '\x00'
 
220
        sha1d = getData( msnobjStr, 'SHA1D="', '"' )
 
221
        sha1c = getData( msnobjStr, 'SHA1C="', '"' )
 
222
        
 
223
        return Msnobj(creator, size, _type, location, friendly, sha1c, sha1d)
 
224
    except Exception, e:
 
225
        print 'cant create msnobj from: ' + msnobjStr
 
226
        print str( e )
 
227
        return None
 
228