]>
code.delx.au - offlineimap/blob - offlineimap/head/offlineimap/repository/Maildir.py
1 # Maildir repository support
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; version 2 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 from Base
import BaseRepository
19 from offlineimap
import folder
, imaputil
20 from offlineimap
. ui
import UIBase
21 from mailbox
import Maildir
24 class MaildirRepository ( BaseRepository
):
25 def __init__ ( self
, root
, accountname
, config
):
26 """Initialize a MaildirRepository object. Takes a path name
27 to the directory holding all the Maildir directories."""
31 self
. accountname
= accountname
33 self
. ui
= UIBase
. getglobalui ()
34 self
. debug ( "MaildirRepository initialized, sep is " + repr ( self
. getsep ()))
37 self
. ui
. debug ( 'maildir' , msg
)
40 if self
. config
. has_option ( self
. accountname
, 'sep' ):
41 return self
. config
. get ( self
. accountname
, 'sep' ). strip ()
45 def makefolder ( self
, foldername
):
46 self
. debug ( "makefolder called with arg " + repr ( foldername
))
47 # Do the chdir thing so the call to makedirs does not make the
48 # self.root directory (we'd prefer to raise an error in that case),
49 # but will make the (relative) paths underneath it. Need to use
50 # makedirs to support a / separator.
51 if self
. getsep () == '/' :
52 for invalid
in [ 'new' , 'cur' , 'tmp' , 'offlineimap.uidvalidity' ]:
53 for component
in foldername
. split ( '/' ):
54 assert component
!= invalid
, "When using nested folders (/ as a separator in the account config), your folder names may not contain 'new', 'cur', 'tmp', or 'offlineimap.uidvalidity'."
56 assert foldername
. find ( './' ) == - 1 , "Folder names may not contain ../"
57 assert not foldername
. startswith ( '/' ), "Folder names may not begin with /"
62 # If we're using hierarchical folders, it's possible that sub-folders
63 # may be created before higher-up ones. If this is the case,
64 # makedirs will fail because the higher-up dir already exists.
65 # So, check to see if this is indeed the case.
67 if self
. getsep () == '/' and os
. path
. isdir ( foldername
):
68 self
. debug ( "makefolder: %s already is a directory" % foldername
)
69 # Already exists. Sanity-check that it's not a Maildir.
70 for subdir
in [ 'cur' , 'new' , 'tmp' ]:
71 assert not os
. path
. isdir ( os
. path
. join ( foldername
, subdir
)), \
72 "Tried to create folder %s but it already had dir %s " % \
75 self
. debug ( "makefolder: calling makedirs %s " % foldername
)
76 os
. makedirs ( foldername
, 0700 )
77 self
. debug ( "makefolder: creating cur, new, tmp" )
78 for subdir
in [ 'cur' , 'new' , 'tmp' ]:
79 os
. mkdir ( os
. path
. join ( foldername
, subdir
), 0700 )
80 # Invalidate the cache
84 def deletefolder ( self
, foldername
):
85 self
. ui
. warn ( "NOT YET IMPLEMENTED: DELETE FOLDER %s " % foldername
)
87 def getfolder ( self
, foldername
):
88 return folder
. Maildir
. MaildirFolder ( self
. root
, foldername
,
89 self
. getsep (), self
, self
. accountname
)
91 def _getfolders_scandir ( self
, root
, extension
= None ):
92 self
. debug ( "_GETFOLDERS_SCANDIR STARTING. root = %s , extension = %s " \
94 # extension willl only be non-None when called recursively when
95 # getsep() returns '/'.
98 # Configure the full path to this repository -- "toppath"
100 if extension
== None :
103 toppath
= os
. path
. join ( root
, extension
)
105 self
. debug ( " toppath = %s " % toppath
)
107 # Iterate over directories in top.
108 for dirname
in os
. listdir ( toppath
):
109 self
. debug ( " *** top of loop" )
110 self
. debug ( " dirname = %s " % dirname
)
111 if dirname
in [ 'cur' , 'new' , 'tmp' , 'offlineimap.uidvalidity' ]:
112 self
. debug ( " skipping this dir (Maildir special)" )
113 # Bypass special files.
115 fullname
= os
. path
. join ( toppath
, dirname
)
116 self
. debug ( " fullname = %s " % fullname
)
117 if not os
. path
. isdir ( fullname
):
118 self
. debug ( " skipping this entry (not a directory)" )
119 # Not a directory -- not a folder.
122 if extension
!= None :
123 foldername
= os
. path
. join ( extension
, dirname
)
124 if ( os
. path
. isdir ( os
. path
. join ( fullname
, 'cur' )) and
125 os
. path
. isdir ( os
. path
. join ( fullname
, 'new' )) and
126 os
. path
. isdir ( os
. path
. join ( fullname
, 'tmp' ))):
127 # This directory has maildir stuff -- process
128 self
. debug ( " This is a maildir folder." )
130 self
. debug ( " foldername = %s " % foldername
)
132 retval
. append ( folder
. Maildir
. MaildirFolder ( self
. root
, foldername
,
133 self
. getsep (), self
, self
. accountname
))
134 if self
. getsep () == '/' :
135 # Check sub-directories for folders.
136 retval
. extend ( self
._ getfolders
_ scandir
( root
, foldername
))
137 self
. debug ( "_GETFOLDERS_SCANDIR RETURNING %s " % \
138 repr ([ x
. getname () for x
in retval
]))
141 def getfolders ( self
):
142 if self
. folders
== None :
143 self
. folders
= self
._ getfolders
_ scandir
( self
. root
)