1
# -*- coding: utf-8 -*-
3
# This file is part of emesene.
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.
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.
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
24
class MsnObjectsManager(object):
25
def __init__( self, user ):
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]
40
return self.idToContext.keys()
42
def getById( self, id ):
43
return self.getByContext( self.idToContext[id] )
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' )
51
name = filename.split( os.sep )[ -1: ][ 0 ]
52
msnobj = Msnobj( self.user.lower(), size, type, "0", data = f.read(), filename=filename, friendly=id )
54
context = base64.b64encode( str( msnobj )+ '\0' )
55
self.objects.update( {context:msnobj} )
56
if id !='': self.idToContext.update( {id:context} )
59
def remove( self, id=None, context=None ):
62
context = self.getById( id )
63
self.idToContext.pop( id )
64
self.objects.pop( context )
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"/>
71
spoo <msnobj Creator="buddy@hotmail.com" Type="2" SHA1D="87YzhijLQyyp4iIlL2k9LlB2wr0=" Size="1169" Location="0" Friendly="cwBwAG8AbwAAAA=="/>
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
85
DYNAMIC_DISPLAY_PICTURE = 7
88
SAVED_STATE_PROPERTY = 12
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:
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
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
112
self.type = int(type)
113
self.location = location
114
self.friendly = base64.b64encode( unicode( friendly ).encode( 'utf-16' )[2:] )
115
self.filename = filename
122
# always return the same sha1d, amsn requires this
123
self.forceSha1d = True
125
self.sha1d = self.makeSha1d()
126
self.forceSha1d = False
131
self.sha1c = self.makeSha1c()
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 + '" '
143
sha1d = self.makeSha1d()
145
string += 'SHA1D="' + sha1d + '" SHA1C="' + self.makeSha1c() + '"/>'
148
def makeSha1d( self ):
149
return base64.b64encode( sha.new( self.data ).digest() )
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
158
return base64.b64encode( sha.new( string ).digest() )
161
return urllib.quote( self.__repr__() )
163
def getCreator( self ): #XXX: property
166
def setCreator( self, creator ):
167
self.creator = creator
170
return str( self.type )
172
def __eq__(self, obj):
174
if not isinstance(obj, Msnobj):
177
fields = ['creator', 'location', 'friendly', 'size', 'type',
181
if getattr(self, field) != getattr(obj, field):
182
print "DEBUG msnobj %s differ: %s != %s" % (field,
183
getattr(self, field),
188
def __neq__(self, obj):
189
return not (self == obj)
192
def unquote( msnobj ):
193
return urllib.unquote( msnobj )
195
def createFromString( string, quoted=True ):
196
if string == '0': return None
199
msnobjStr = unquote( string )
203
def getData( string, start, stop ):
205
return string.split( start )[1].split(stop)[0]
207
# TODO: what to do when a field is not in the string?
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="', '"' )
217
friendly = str( base64.b64decode( friendly ).decode( 'utf-16' ) )
220
sha1d = getData( msnobjStr, 'SHA1D="', '"' )
221
sha1c = getData( msnobjStr, 'SHA1C="', '"' )
223
return Msnobj(creator, size, _type, location, friendly, sha1c, sha1d)
225
print 'cant create msnobj from: ' + msnobjStr