]>
code.delx.au - offlineimap/blob - offlineimap/folder/UIDMaps.py
2 # Copyright (C) 2002 John Goerzen
3 # <jgoerzen@complete.org>
5 # This program 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 # This program 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 this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 from threading
import *
20 from offlineimap
import threadutil
21 from offlineimap
.threadutil
import InstanceLimitedThread
22 from offlineimap
.ui
import UIBase
23 from IMAP
import IMAPFolder
26 class MappingFolderMixIn
:
27 def _initmapping(self
):
29 (self
.diskr2l
, self
.diskl2r
) = self
._loadmaps
()
30 self
._mb
= self
.__class
__.__bases
__[1]
32 def _getmapfilename(self
):
33 return os
.path
.join(self
.repository
.getmapdir(),
34 self
.getfolderbasename())
37 self
.maplock
.acquire()
39 mapfilename
= self
._getmapfilename
()
40 if not os
.path
.exists(mapfilename
):
42 file = open(mapfilename
, 'rt')
46 line
= file.readline()
50 (str1
, str2
) = line
.split(':')
57 self
.maplock
.release()
59 def _savemaps(self
, dolock
= 1):
60 mapfilename
= self
._getmapfilename
()
61 if dolock
: self
.maplock
.acquire()
63 file = open(mapfilename
+ ".tmp", 'wt')
64 for (key
, value
) in self
.diskl2r
.iteritems():
65 file.write("%d:%d\n" % (key
, value
))
67 os
.rename(mapfilename
+ '.tmp', mapfilename
)
69 if dolock
: self
.maplock
.release()
71 def _uidlist(self
, mapping
, items
):
72 return [mapping
[x
] for x
in items
]
74 def cachemessagelist(self
):
75 self
._mb
.cachemessagelist(self
)
76 reallist
= self
._mb
.getmessagelist(self
)
78 self
.maplock
.acquire()
80 # OK. Now we've got a nice list. First, delete things from the
81 # summary that have been deleted from the folder.
83 for luid
in self
.diskl2r
.keys():
84 if not reallist
.has_key(luid
):
85 ruid
= self
.diskl2r
[luid
]
86 del self
.diskr2l
[ruid
]
87 del self
.diskl2r
[luid
]
89 # Now, assign negative UIDs to local items.
90 self
._savemaps
(dolock
= 0)
93 self
.r2l
= self
.diskr2l
.copy()
94 self
.l2r
= self
.diskl2r
.copy()
96 for luid
in reallist
.keys():
97 if not self
.l2r
.has_key(luid
):
100 self
.l2r
[luid
] = ruid
101 self
.r2l
[ruid
] = luid
103 self
.maplock
.release()
105 def getmessagelist(self
):
106 """Gets the current message list.
107 You must call cachemessagelist() before calling this function!"""
110 localhash
= self
._mb
.getmessagelist(self
)
111 self
.maplock
.acquire()
113 for key
, value
in localhash
.items():
117 # Sometimes, the IMAP backend may put in a new message,
118 # then this function acquires the lock before the system
119 # has the chance to note it in the mapping. In that case,
123 value
['uid'] = self
.l2r
[value
['uid']]
127 self
.maplock
.release()
129 def getmessage(self
, uid
):
130 """Returns the content of the specified message."""
131 return self
._mb
.getmessage(self
, self
.r2l
[uid
])
133 def savemessage(self
, uid
, content
, flags
):
134 """Writes a new message, with the specified uid.
135 If the uid is < 0, the backend should assign a new uid and return it.
137 If the backend cannot assign a new uid, it returns the uid passed in
138 WITHOUT saving the message.
140 If the backend CAN assign a new uid, but cannot find out what this UID
141 is (as is the case with many IMAP servers), it returns 0 but DOES save
144 IMAP backend should be the only one that can assign a new uid.
146 If the uid is > 0, the backend should set the uid to this, if it can.
147 If it cannot set the uid to that, it will save it anyway.
148 It will return the uid assigned in any case.
151 # We cannot assign a new uid.
154 self
.savemessageflags(uid
, flags
)
156 newluid
= self
._mb
.savemessage(self
, -1, content
, flags
)
158 raise ValueError, "Backend could not find uid for message"
159 self
.maplock
.acquire()
161 self
.diskl2r
[newluid
] = uid
162 self
.diskr2l
[uid
] = newluid
163 self
.l2r
[newluid
] = uid
164 self
.r2l
[uid
] = newluid
165 self
._savemaps
(dolock
= 0)
167 self
.maplock
.release()
169 def getmessageflags(self
, uid
):
170 return self
._mb
.getmessageflags(self
, self
.r2l
[uid
])
172 def savemessageflags(self
, uid
, flags
):
173 self
._mb
.savemessageflags(self
, self
.r2l
[uid
], flags
)
175 def addmessageflags(self
, uid
, flags
):
176 self
._mb
.addmessageflags(self
, self
.r2l
[uid
], flags
)
178 def addmessagesflags(self
, uidlist
, flags
):
179 self
._mb
.addmessagesflags(self
, self
._uidlist
(self
.r2l
, uidlist
),
182 def _mapped_delete(self
, uidlist
):
183 self
.maplock
.acquire()
187 luid
= self
.r2l
[ruid
]
191 del self
.diskr2l
[ruid
]
192 del self
.diskl2r
[luid
]
195 self
._savemaps
(dolock
= 0)
197 self
.maplock
.release()
199 def deletemessageflags(self
, uid
, flags
):
200 self
._mb
.deletemessageflags(self
, self
.r2l
[uid
], flags
)
202 def deletemessagesflags(self
, uidlist
, flags
):
203 self
._mb
.deletemessagesflags(self
, self
._uidlist
(self
.r2l
, uidlist
),
206 def deletemessage(self
, uid
):
207 self
._mb
.deletemessage(self
, self
.r2l
[uid
])
208 self
._mapped
_delete
([uid
])
210 def deletemessages(self
, uidlist
):
211 self
._mb
.deletemessages(self
, self
._uidlist
(self
.r2l
, uidlist
))
212 self
._mapped
_delete
(uidlist
)
214 #def syncmessagesto_neguid_msg(self, uid, dest, applyto, register = 1):
215 # does not need changes because it calls functions that make the changes
216 # same goes for all other sync messages types.
219 # Define a class for local part of IMAP.
220 class MappedIMAPFolder(MappingFolderMixIn
, IMAPFolder
):
221 def __init__(self
, *args
, **kwargs
):
222 apply(IMAPFolder
.__init
__, (self
,) + args
, kwargs
)