bincimap

Log | Files | Refs | LICENSE

bincimap-up.cc (5637B)


      1 /* -*- Mode: c++; -*- */
      2 /*  --------------------------------------------------------------------
      3  *  Filename:
      4  *    bincimap-up.cc
      5  *  
      6  *  Description:
      7  *    Implementation of the preauthenticated bincimap stub
      8  *
      9  *  Authors:
     10  *    Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
     11  *
     12  *  Bugs:
     13  *
     14  *  ChangeLog:
     15  *
     16  *  --------------------------------------------------------------------
     17  *  Copyright 2002-2005 Andreas Aardal Hanssen
     18  *
     19  *  This program is free software; you can redistribute it and/or modify
     20  *  it under the terms of the GNU General Public License as published by
     21  *  the Free Software Foundation; either version 2 of the License, or
     22  *  (at your option) any later version.
     23  *
     24  *  This program is distributed in the hope that it will be useful,
     25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     27  *  GNU General Public License for more details.
     28  *
     29  *  You should have received a copy of the GNU General Public License
     30  *  along with this program; if not, write to the Free Software
     31  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
     32  *  --------------------------------------------------------------------
     33  */
     34 #ifdef HAVE_CONFIG_H
     35 #include <config.h>
     36 #endif
     37 
     38 #include <string>
     39 
     40 #include "broker.h"
     41 #include "recursivedescent.h"
     42 #include "io.h"
     43 #ifdef WITH_SSL
     44 #include "io-ssl.h"
     45 #endif
     46 #include "operators.h"
     47 #include "session.h"
     48 
     49 using namespace ::std;
     50 using namespace Binc;
     51 
     52 namespace Binc {
     53   bool showGreeting(void);
     54 }
     55 
     56 //------------------------------------------------------------------------
     57 int main(int argc, char *argv[]) 
     58 {
     59   Session &session = Session::getInstance();
     60   if (!session.initialize(argc, argv)) {
     61     if (session.getLastError() != "") {
     62       IO &logger = IOFactory::getInstance().get(2);
     63       logger << "error initializing Binc IMAP: " << session.getLastError()
     64 	     << endl;
     65       logger.flushContent();
     66     }
     67     return 111;
     68   }
     69 
     70   IO &com = IOFactory::getInstance().get(1);
     71   IO &logger = IOFactory::getInstance().get(2);
     72 
     73   logger << "connection from " << session.getIP() << endl;
     74 
     75   // Show standard greeting
     76   showGreeting();
     77   bool recovery = false;
     78   bool timedout = false;
     79   bool disconnect = false;
     80   bool abrt = false;
     81 
     82   // Read commands and run functions
     83   do {
     84     com.enableInputLimit();
     85 
     86     // recover from syntax error. There will be trash in the input
     87     // buffer. We need to flush everything until we see an LF.
     88     if (recovery) {
     89       for (;;) {
     90 	int c = com.readChar(session.timeout());
     91 	if (c == '\n') break;
     92 	if (c == -1) {
     93 	  disconnect = true;
     94 	  abrt = true;
     95 	  break;
     96 	} else if (c == -2) {
     97 	  com << "* BYE Timeout after " << session.timeout()
     98 	      << " seconds of inactivity." << endl;
     99 	  timedout = true;
    100 	  abrt = true;
    101 	  break;
    102 	}
    103       }
    104       
    105       if (abrt)
    106 	break;
    107     }
    108 
    109     Request request;
    110     recovery = false;
    111 
    112     BrokerFactory &brokerFactory = BrokerFactory::getInstance();
    113     Broker *broker = brokerFactory.getBroker(session.getState());
    114     if (!broker) {
    115       // will never happen
    116     }
    117 
    118     com.flushContent();
    119     com.noFlushOnEndl();
    120 
    121     switch (broker->parseStub(request)) {
    122     case Operator::TIMEOUT:
    123       com << "* BYE Timeout after " << session.timeout()
    124 	  << " seconds of inactivity." << endl;
    125       timedout = true;
    126       abrt = true;
    127       break;
    128     case Operator::REJECT:
    129       com << "* NO " << session.getLastError() << endl;
    130       recovery = true;
    131       continue;
    132     case Operator::ERROR:
    133       com << "* BAD " << session.getLastError() << endl;
    134       recovery = true;
    135       continue;
    136     default:
    137       break;
    138     }
    139 
    140     if (abrt)
    141       break;
    142 
    143     Operator *o = broker->get(request.getName());
    144     if (!o) {
    145       com << request.getTag() << " NO The command \"" 
    146 	  << (request.getUidMode() ? "UID " : "")
    147 	  << request.getName()
    148 	  << "\" is unsupported in this state. "
    149 	  << "Please authenticate." << endl;
    150       recovery = true;
    151       continue;
    152     }
    153 
    154     switch (o->parse(request)) {
    155     case Operator::TIMEOUT:
    156       com << "* BYE Timeout after " << session.timeout()
    157 	  << " seconds of inactivity." << endl;
    158       timedout = true;
    159       abrt = true;
    160       break;
    161     case Operator::REJECT:
    162       com << "* NO " << session.getLastError() << endl;
    163       recovery = true;
    164       continue;
    165     case Operator::ERROR:
    166       com << "* BAD " << session.getLastError() << endl;
    167       recovery = true;
    168       continue;
    169     default:
    170       break;
    171     }
    172 
    173     switch (o->process(*session.getDepot(), request)) {
    174     case Operator::OK:
    175       com << request.getTag() << " OK " << request.getName()
    176 	  << " completed" << endl;
    177       break;
    178     case Operator::NO:
    179       com << request.getTag() << " NO " << session.getResponseCode()
    180           << request.getName() << " failed: " << session.getLastError() << endl;
    181       session.clearResponseCode();
    182       break;
    183     case Operator::BAD:
    184       com << request.getTag() << " BAD " << request.getName() 
    185 	  << " failed: " << session.getLastError() << endl;
    186       recovery = true;
    187       break;
    188     case Operator::NOTHING:
    189       break;
    190     case Operator::ABORT:
    191       session.setState(Session::LOGOUT);
    192       abrt = true;
    193       break;
    194     }
    195 
    196     if (abrt)
    197       break;
    198   } while (session.getState() != Session::LOGOUT);
    199 
    200   logger << "shutting down ";
    201   if (timedout)
    202     logger << "(timeout " + toString(session.timeout()) + "s) ";
    203   else if (disconnect)
    204     logger << "(" << com.getLastError() << ") ";
    205   
    206   logger << "- read:"
    207 	 << session.getReadBytes() 
    208 	 << " bytes, wrote:" << session.getWriteBytes() 
    209 	 << " bytes." << endl;
    210   
    211   com.flushContent();
    212 }