bincimap-tech.html (17972B)
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2 <HTML> 3 4 <HEAD> 5 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> 6 <META HTTP-EQUIV="Content-Language" CONTENT="en"> 7 8 <TITLE>Binc IMAP - Technical Documentation</TITLE> 9 <META NAME="revisit-after" CONTENT="14 days"> 10 <META NAME="keywords" CONTENT="Binc IMAP technical documentation checkpassword daemontools tcpserver xinetd Maildir qmail"> 11 <META NAME="description" CONTENT="Andreas Aardal Hanssen"> 12 <META NAME="copyright" CONTENT="Copyright Andreas Aardal Hanssen 2002, 2003"> 13 <META NAME="distribution" CONTENT="global"> 14 <META NAME="author" CONTENT="Andreas Aardal Hanssen"> 15 <LINK REL="stylesheet" HREF="bincimap.css" TYPE="text/css"> 16 <LINK REL="icon" HREF="/favicon.ico" TYPE="image/ico"> 17 <LINK REL="shortcut icon" HREF="/favicon.ico"> 18 19 </HEAD> 20 21 <BODY BGCOLOR="#000000"> 22 23 <TABLE WIDTH="95%" ALIGN="CENTER" CELLSPACING="0" CELLPADDING="4"> 24 <TR> 25 <TD BGCOLOR="#004444"> 26 27 <TABLE WIDTH="99%" ALIGN="CENTER" CELLSPACING="0" CELLPADDING="4"> 28 <TR> 29 <TD CLASS="headtext" BGCOLOR="#226666" ALIGN="LEFT"> 30 <TABLE> 31 <TR> 32 <TD ALIGN="center" VALIGN="middle"><IMG ALT="Binc IMAP logo" SRC="b-button64.png" BORDER="0"></TD> 33 <TD ALIGN="center" VALIGN="middle">Binc IMAP - Technical Documentation</TD> 34 </TR> 35 </TABLE> 36 </TD> 37 <TD CLASS="bodytext" BGCOLOR="#226666" ALIGN="RIGHT"> 38 <A HREF="http://www.gnu.org/licenses/gpl.html">GNU General Public License</A><BR> 39 Andreas Aardal Hanssen <andreas@hanssen.name> 40 </TD> 41 </TR> 42 <TR> 43 <TD CLASS="bodytext" BGCOLOR="#FFFFFF" COLSPAN="2"></TD> 44 </TR> 45 </TABLE> 46 47 <DIV CLASS="bodytext"> 48 49 <P><U><B>Binc in my home area, IMAPdir and cousins</B></U></P> 50 51 <BLOCKQUOTE> 52 53 <P>Binc IMAP uses either <A 54 HREF="http://www.inter7.com/courierimap/README.maildirquota.html">Maildir++</A> 55 or a structure called <A HREF="bincimap-imapdir.html">IMAPdir</A> to 56 store its set of mailboxes. <A 57 HREF="bincimap-imapdir.html">IMAPdir</A> is more or less similar to <A 58 HREF="http://www.inter7.com/courierimap/README.maildirquota.html">Maildir++</A>, 59 but it provides more flexibility with regards to mailbox names and 60 hierarchy structure.</P> 61 62 <P>In a sense, <A HREF="bincimap-imapdir.html">IMAPdir</A> takes all 63 the goods from <A 64 HREF="http://cr.yp.to/proto/maildir.html">Maildir</A> and adds root 65 level mailboxes, submailboxes both of regular root level mailboxes and 66 of the special mailbox INBOX, mail in mailboxes of any level, and with 67 no restrictions.</P> 68 69 <P>In the root of the <A HREF="bincimap-imapdir.html">IMAPdir</A> 70 structure, Binc IMAP stores the list of a user's subscribed folders in 71 a file called 72 <B>bincimap-subscribed</B>. This file should only be edited manually 73 if you are confident with <B>Binc::Storage</B>. Normally the 74 administrator and the IMAP user will leave this to Binc IMAP.</P> 75 76 <P>Binc IMAP's <A 77 HREF="http://cr.yp.to/proto/maildir.html">Maildir</A> backend 78 (default) will temporarily create a lock file called 79 <B>bincimap-scan-lock</B> inside a <A 80 HREF="http://cr.yp.to/proto/maildir.html">Maildir</A> when it is 81 scanning for mailbox changes and delegating unique message 82 identifiers. This is to ensure that UIDs are delegated exactly once to 83 every message that has been detected by any one Binc IMAP server 84 instance.</P> 85 86 <P>Inside each <A 87 HREF="http://cr.yp.to/proto/maildir.html">Maildir</A>, Binc IMAP 88 stores two files that allow multiple instances of the server to 89 communicate the state and changes of the mailbox: 90 <B>bincimap-uidvalidity</B> and 91 <B>bincimap-cache</B>. These files are safe to delete, although that 92 will trigger UIDVALIDITY to bounce and clients may have to 93 resynchronize their local state.</P> 94 95 </BLOCKQUOTE> 96 97 <P><U><B>Object Oriented Design: Brokers, Depots, Operators.</B></U></P> 98 99 <BLOCKQUOTE> 100 101 <TABLE WIDTH="100%"> 102 <TR> 103 <TD VALIGN="TOP"> 104 <P>Binc IMAP's design is <I>simple</I> and <I>modular</I>. This 105 makes it <I>easy</I> to maintain and extend.</P> 106 107 <P>Although the IMAP protocol is relatively complex, you will 108 find that Binc IMAP's solution is surprisingly easy to 109 grasp.</P> 110 111 <P>At the heart of Binc IMAP's implementation lies the basic 112 functionality for Object Oriented Design provided by the ISO C++ 113 standard and general knowledge in the area of standard Design 114 Patterns.</P> 115 116 <P>The main components are:</P> 117 118 <UL> 119 <LI>The <A HREF="#Broker">Broker</A></LI> 120 <LI>The <A HREF="#BrokerFactory">BrokerFactory</A></LI> 121 <LI>The <A HREF="#Command">Command</A></LI> 122 <LI>The <A HREF="#Depot">Depot</A></LI> 123 <LI>The <A HREF="#DepotFactory">DepotFactory</A></LI> 124 <LI>The <A HREF="#Mailbox">Mailbox</A></LI> 125 <LI>The <A HREF="#Operator">Operator</A></LI> 126 <LI>The <A HREF="#Session">Session</A></LI> 127 <LI>The <A HREF="#IO">IO</A></LI> 128 </UL> 129 </TD> 130 <TD> 131 <IMG BORDER="0" SRC="bincimap-design-tiny.png" ALT="Binc IMAP, Object Oriented Design"> 132 </TD> 133 </TR> 134 </TABLE> 135 136 <HR> 137 <A NAME="Broker"><B>Broker</B></A> 138 139 <P>One <A HREF="#Broker">Broker</A> holds a set of <A 140 HREF="#Operator">Operators</A>. For each 141 <I>state</I> Binc IMAP is in, the <A 142 HREF="#BrokerFactory">BrokerFactory</A> delegates exactly one <A 143 HREF="#Broker">Broker</A> to hold the relevant <A 144 HREF="#Operator">Operator</A> objects.</P> 145 146 <P>Typically, an <A HREF="#Operator">Operator</A> can be assigned to 147 more than one <A HREF="#Broker">Broker</A>. For example, the <A 148 HREF="#Operator">Operator</A> that serves the IMAP command "NOOP" (a 149 command that is available in all three IMAP <I>states</I>), 150 <B>NoopOperator</B>, is available in all <A 151 HREF="#Broker">Broker</A> objects.</P> 152 153 <P>The <A HREF="#Broker">Broker</A> is responsible for first passing 154 the <A HREF="#Depot">Depot</A> and the <A HREF="#IO">IO</A> 155 singleton to the appropriate <A HREF="#Operator">Operator</A>, 156 generating a <A HREF="#Command">Command</A> object.</P> 157 158 <P>The <A HREF="#Broker">Broker</A> is also responsible for passing 159 the resulting <A HREF="#Command">Command</A> object to the <A 160 HREF="#Operator">Operator</A> together with the <A 161 HREF="#Depot">Depot</A>, generating the <I>untagged responses</I> 162 that come as a result of the processing.</P> 163 164 <BR> 165 <TABLE> 166 <TR> 167 <TD BGCOLOR="#555555"> 168 <PRE> 169 Broker *broker = BrokerFactory.getBroker(STATE_SELECTED); 170 if (broker != NULL) 171 throw CriticalException("no broker for selected state"); 172 173 Command command; 174 175 try { 176 broker.parse(com, command); 177 broker.process(depot, command); 178 } catch (... 179 </PRE> 180 </TD> 181 </TR> 182 </TABLE> 183 184 <HR> 185 <A NAME="BrokerFactory"><B>BrokerFactory</B></A> 186 187 <P>The <A HREF="#BrokerFactory">BrokerFactory</A> manages the <A 188 HREF="#Broker">Broker</A> objects.</P> 189 190 <P>Given a <I>state</I>, the <A 191 HREF="#BrokerFactory">BrokerFactory</A> provides a <A 192 HREF="#Broker">Broker</A> that holds all the <A 193 HREF="#Operator">Operator</A> objects available to the client.</P> 194 195 <P>This provides a modular and safe separation of the priviledges 196 available at the different <I>states</I> in the IMAP session.</P> 197 198 <P>The <I>preauthenticate stub</I> has a <A 199 HREF="#BrokerFactory">BrokerFactory</A> that can only generate <A 200 HREF="#Broker">Broker</A> objects for the <I>non-authenticated</I> 201 state.</P> 202 203 <HR> 204 <A NAME="Command"><B>Command</B></A> 205 206 <P>A <A HREF="#Command">Command</A> object holds all information 207 that was passed to the <A HREF="#Operator">Operator</A> that served 208 a specific IMAP command.</P> 209 210 <P><A HREF="#Command">Command</A> objects are named. Examples of 211 such names are "CHECK", "SUBSCRIBE" and "LOGOUT".</P> 212 213 <P>For the name "FETCH", the <A HREF="#Command">Command</A> object 214 is decorated with 215 <I>sequence set</I>, optionally a <I>section</I> and so on. The 216 <B>parse()</B> method in each <A HREF="#Operator">Operator</A> is 217 responsible for decorating the <A HREF="#Command">Command</A> 218 object.</P> 219 220 <P>The <A HREF="#Command">Command</A> object is 221 <I>short-lived</I>. It is created, decorated, passed on to the <A 222 HREF="#Operator">Operator</A>, then discarded.</P> 223 224 <HR> 225 <A NAME="Depot"><B>Depot</B></A> 226 227 <P>A <A HREF="#Depot">Depot</A> is responsible for handling the 228 different <A HREF="#Mailbox">Mailbox</A> objects, and it is the 229 mailbox structure authority.</P> 230 231 <P>Given an IMAP mailbox path as input, a <A HREF="#Depot">Depot</A> 232 can give the caller a corresponding <A HREF="#Mailbox">Mailbox</A> 233 object if it finds one that successfully identifies the type of <A 234 HREF="#Mailbox">Mailbox</A>. 235 236 <P>The <A HREF="#Depot">Depot</A> is also aware of what the 237 <I>default</I> <A HREF="#Mailbox">Mailbox</A> type object is. This 238 <A HREF="#Mailbox">Mailbox</A> object is used when creating new IMAP 239 mailboxes.</P> 240 241 <P>Finally, the <A HREF="#Depot">Depot</A> is used to translate 242 mailbox names to a representation on the file system and back. There 243 are currently two specializations of the <A HREF="#Depot">Depot</A> 244 object available: one for <A 245 HREF="http://www.inter7.com/courierimap/README.maildirquota.html">Maildir++</A> 246 and one for <A HREF="bincimap-imapdir.html">IMAPdir</A>. Each has 247 its own characteristics in how do translate the mailbox hierarchy to 248 the file system.</P> 249 250 <TABLE> 251 <TR> 252 <TD BGCOLOR="#555555"> 253 <PRE> 254 Mailbox *mailbox = depot.getDefaultMailbox(); 255 if (mailbox == NULL) 256 throw CriticalException("no default mailbox provided"); 257 258 try { 259 mailbox->imapCreate("work/2003/07/todo"); 260 } catch (... 261 </PRE> 262 </TD> 263 </TR> 264 </TABLE> 265 266 <HR> 267 <A NAME="DepotFactory"><B>DepotFactory</B></A> 268 269 <P>The <A NAME="DepotFactory">DepotFactory</A> manages the <A 270 HREF="#Depot">Depot</A> objects.</P> 271 272 <P>New <A HREF="#Depot">Depot</A> objects are assigned to the <A 273 NAME="DepotFactory">DepotFactory</A> in runtime. This makes it easy 274 to add new <A HREF="#Depot">Depot</A> objects using loadable 275 modules. The <A HREF="#Depot">Depot</A> objects are registered and 276 accessed via their <I>names</I>, such as "<A 277 HREF="http://www.inter7.com/courierimap/README.maildirquota.html">Maildir++</A>" 278 or "<A HREF="bincimap-imapdir.html">IMAPdir</A>".</P> 279 280 <P>The <A NAME="DepotFactory">DepotFactory</A> gives individual 281 users of Binc IMAP the option to choose the <A 282 HREF="#Depot">Depot</A> object that suits their needs the best.</P> 283 284 <HR> 285 <A NAME="IO"><B>IO</B></A> 286 287 <P>The <A HREF="#IO">IO</A> is a <I>global</I>. It consists of two instances - 288 <U>com</U> and <U>logger</U>.</P> 289 290 <P><U>com</U> reads and writes characters to and from the client, 291 and hides the optional SSL encryption.</P> 292 293 <P><U>logger</U> writes characters to Binc IMAP's log files. It 294 hides the method used to log data. Currently it supports logging to 295 stderr and syslog.</P> 296 297 <HR> 298 <A NAME="Mailbox"><B>Mailbox</B></A> 299 300 <P>The <A HREF="#Mailbox">Mailbox</A> is an abstract for Binc IMAP's different 301 <I>backends</I>. Bundled with Binc is a backend for <A 302 HREF="http://cr.yp.to/proto/maildir.html">Maildir</A>. The class 303 Maildir <I>inherits</I> <A HREF="#Mailbox">Mailbox</A>.</P> 304 305 <P>In short, a <A HREF="#Mailbox">Mailbox</A> contains all methods needed for Binc 306 IMAP to serve a specific backend. It also holds a method to identify 307 a <A HREF="#Mailbox">Mailbox</A> of its own kind.</P> 308 309 <P>All registered <A HREF="#Mailbox">Mailbox</A> objects are held by the 310 <A HREF="#Depot">Depot</A>.</P> 311 312 <BR> 313 <TABLE> 314 <TR> 315 <TD BGCOLOR="#555555"> 316 <PRE> 317 Mailbox *mailbox = depot.getSelectedMailbox(); 318 if (mailbox == NULL) 319 throw CriticalException("no selected mailbox in selected state"); 320 321 mailbox->imapExpunge(); 322 mailbox->imapClose(); 323 </PRE> 324 </TD> 325 </TR> 326 </TABLE> 327 328 <HR> 329 <A NAME="Operator"><B>Operator</B></A> 330 331 <P>An <A HREF="#Operator">Operator</A> is associated with an IMAP command such as 332 "SEARCH" or "AUTHENTICATE". In short, the <A HREF="#Operator">Operator</A> is used to 333 perform an arbitrary operation on a <A HREF="#Mailbox">Mailbox</A>.<P> 334 335 <P>Typically, an <A HREF="#Operator">Operator</A> can be assigned to one or more 336 <A HREF="#Broker">Broker</A> objects. 337 338 <P>Operators contain, among others, the two public methods: 339 <B>parse()</B> and <B>process()</B>.</P> 340 341 <P>When given the <B>IO singleton</B> as input, the <B>parse()</B> 342 method generates a <A HREF="#Command">Command</A> object. This object can then be 343 fed to <B>process()</B> together with a <A HREF="#Depot">Depot</A>.</P> 344 345 <P>When processing its command, an <A HREF="#Operator">Operator</A> is allowed to 346 generate <I>untagged responses</I> and it can also update the 347 <I>state</I> of a <A HREF="#Mailbox">Mailbox</A>, the <A HREF="#Depot">Depot</A> or the 348 <A HREF="#Session">Session</A> singleton.</P> 349 350 <P><A HREF="#Operator">Operator</A> objects are assigned 351 <I>dynamically</I> to each <A HREF="#Broker">Broker</A>, making it 352 very easy to write 353 <I>extensions</I> that add or replace existing <A 354 HREF="#Operator">Operator</A> objects using Binc IMAP's <I>loadable 355 module support.</I></P> 356 357 <HR> 358 <A NAME="Session"><B>Session</B></A> 359 360 <P>The <A HREF="#Session">Session</A> is a <I>singleton</I> object that holds 361 information that is relevant to the current IMAP session.</P> 362 363 <P>Currently, the <A HREF="#Session">Session</A> contains information about:</P> 364 365 <UL> 366 <LI>Global configuration (administrator settings)</LI> 367 <LI>Local configuration (user settings)</LI> 368 <LI>Command line arguments</LI> 369 <LI>Folder subscription list</LI> 370 </UL> 371 372 <HR> 373 374 <P>Last updated on <B>2003-03-20</B>.</P> 375 376 <P>Please direct comments on this document to the <A 377 HREF="/#mailinglist">Binc IMAP mailing list</A>. Remember to <I>search 378 the archives</I> first.</P> 379 380 </BLOCKQUOTE> 381 382 <TABLE WIDTH="99%" ALIGN="CENTER" CELLSPACING="0" CELLPADDING="4"> 383 <TR> 384 <TD CLASS="bodytext" BGCOLOR="#FFFFFF"></TD> 385 </TR> 386 <TR> 387 <TD CLASS="headtext" BGCOLOR="#226666"> 388 <A HREF="http://validator.w3.org/check/referer"> 389 <IMG BORDER="0" SRC="http://www.w3.org/Icons/valid-html401" 390 ALT="Valid HTML 4.01!" HEIGHT="31" WIDTH="88"> 391 </A> 392 <A HREF="http://cr.yp.to/djbdns.html"><IMG BORDER="0" WIDTH="88" 393 HEIGHT="31" SRC="djbdns.jpg" ALT="Powered by djbdns!"></A> 394 <IMG BORDER="0" WIDTH="88" HEIGHT="30" SRC="binclogo.gif" 395 ALT="Powered by Binc IMAP"> 396 </TD> 397 </TR> 398 </TABLE> 399 400 </DIV> 401 </TD> 402 </TR> 403 </TABLE> 404 <BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> 405 <BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> 406 407 </BODY> 408 </HTML> 409 style with only LF. The MaildirMessage is an 410 implementation of Message used in Maildir. When using a Maildir 411 mailbox, Mailbox::iterator will return a reference to a 412 MaildirMessage. MaildirMessage also uses a MaildirMessageCache 413 singleton to handle cacheing of messages.</P> 414 415 <P>Although the inside of MaildirMessage both deals with files, 416 cacheing and MIME, the Operator needs not think about this.</P> 417 418 </BLOCKQUOTE> 419 420 <HR> 421 <A NAME="Operator"><B>Operator</B></A> 422 <BLOCKQUOTE> 423 424 <P>An <A HREF="#Operator">Operator</A> is associated with an IMAP command such as 425 "SEARCH" or "AUTHENTICATE". In short, the <A HREF="#Operator">Operator</A> is used to 426 perform an arbitrary operation on a <A HREF="#Mailbox">Mailbox</A>.<P> 427 428 <P>Typically, an <A HREF="#Operator">Operator</A> can be assigned to one or more 429 <A HREF="#Broker">Broker</A> objects. 430 431 <P>Operators contain, among others, the two public methods: 432 <B>parse()</B> and <B>process()</B>.</P> 433 434 <P>The <B>parse()</B> method decorates a <A 435 HREF="#Request">Request</A> object. This object can then be fed to 436 <B>process()</B> together with a <A HREF="#Depot">Depot</A>.</P> 437 438 <P>When processing its request, an <A HREF="#Operator">Operator</A> 439 is allowed to generate <I>untagged responses</I> and it can also 440 update the <I>state</I> of a <A HREF="#Mailbox">Mailbox</A>, the <A 441 HREF="#Depot">Depot</A> or the <A HREF="#Session">Session</A> 442 singleton.</P> 443 444 <P><A HREF="#Operator">Operator</A> objects are assigned 445 <I>dynamically</I> to each <A HREF="#Broker">Broker</A>, making it 446 very easy to write <I>extensions</I> that add or replace existing <A 447 HREF="#Operator">Operator</A> objects using Binc IMAP's <I>loadable 448 module support.</I></P> 449 </BLOCKQUOTE> 450 451 <HR> 452 <A NAME="Session"><B>Session</B></A> 453 <BLOCKQUOTE> 454 <P>The <A HREF="#Session">Session</A> is a <I>singleton</I> object that holds 455 information that is relevant to the current IMAP session.</P> 456 457 <P>Currently, the <A HREF="#Session">Session</A> contains information about:</P> 458 459 <UL> 460 <LI>Global configuration (administrator settings)</LI> 461 <LI>Local configuration (user settings)</LI> 462 <LI>Command line arguments</LI> 463 <LI>Folder subscription list</LI> 464 </UL> 465 </BLOCKQUOTE> 466 467 <HR> 468 469 <P>Last updated on <B>2003-07-31</B>.</P> 470 471 <P>Please direct comments on this document to the <A 472 HREF="/#mailinglist">Binc IMAP mailing list</A>. Remember to <I>search 473 the archives</I> first.</P> 474 475 </BLOCKQUOTE> 476 477 <TABLE WIDTH="99%" ALIGN="CENTER" CELLSPACING="0" CELLPADDING="4"> 478 <TR> 479 <TD CLASS="bodytext" BGCOLOR="#FFFFFF"></TD> 480 </TR> 481 <TR> 482 <TD CLASS="headtext" BGCOLOR="#226666"> 483 <A HREF="http://validator.w3.org/check/referer"> 484 <IMG BORDER="0" SRC="http://www.w3.org/Icons/valid-html401" 485 ALT="Valid HTML 4.01!" HEIGHT="31" WIDTH="88"> 486 </A> 487 <A HREF="http://cr.yp.to/djbdns.html"><IMG BORDER="0" WIDTH="88" 488 HEIGHT="31" SRC="djbdns.jpg" ALT="Powered by djbdns!"></A> 489 <IMG BORDER="0" WIDTH="88" HEIGHT="30" SRC="binclogo.gif" 490 ALT="Powered by Binc IMAP"> 491 </TD> 492 </TR> 493 </TABLE> 494 495 </DIV> 496 </TD> 497 </TR> 498 </TABLE> 499 <BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> 500 <BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> 501 502 </BODY> 503 </HTML>