- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gpopserverprotocol.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
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.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gpopserverprotocol.cpp
19 //
20
21 #include "gdef.h"
22 #include "gpop.h"
23 #include "gpopserverprotocol.h"
24 #include "gstr.h"
25 #include "gmemory.h"
26 #include "gbase64.h"
27 #include "gassert.h"
28 #include "glog.h"
29 #include <sstream>
30
31 GPop::ServerProtocol::ServerProtocol( Sender & sender , Security & security , Store & store , const Secrets & secrets ,
32 const Text & text , GNet::Address peer_address , Config ) :
33 m_text(text) ,
34 m_sender(sender) ,
35 m_security(security) ,
36 m_store(store) ,
37 m_store_lock(m_store) ,
38 m_secrets(secrets) ,
39 m_auth(m_secrets) ,
40 m_peer_address(peer_address) ,
41 m_fsm(sStart,sEnd,s_Same,s_Any) ,
42 m_body_limit(-1L) ,
43 m_in_body(false) ,
44 m_secure(false)
45 {
46 // (dont send anything to the peer from this ctor -- the Sender object is not fuly constructed)
47
48 m_fsm.addTransition( eStat , sActive , sActive , &GPop::ServerProtocol::doStat ) ;
49 m_fsm.addTransition( eList , sActive , sActive , &GPop::ServerProtocol::doList ) ;
50 m_fsm.addTransition( eRetr , sActive , sData , &GPop::ServerProtocol::doRetr , sActive ) ;
51 m_fsm.addTransition( eTop , sActive , sData , &GPop::ServerProtocol::doTop , sActive ) ;
52 m_fsm.addTransition( eDele , sActive , sActive , &GPop::ServerProtocol::doDele ) ;
53 m_fsm.addTransition( eNoop , sActive , sActive , &GPop::ServerProtocol::doNoop ) ;
54 m_fsm.addTransition( eRset , sActive , sActive , &GPop::ServerProtocol::doRset ) ;
55 m_fsm.addTransition( eUidl , sActive , sActive , &GPop::ServerProtocol::doUidl ) ;
56 m_fsm.addTransition( eSent , sData , sActive , &GPop::ServerProtocol::doNothing ) ;
57 m_fsm.addTransition( eUser , sStart , sStart , &GPop::ServerProtocol::doUser ) ;
58 m_fsm.addTransition( ePass , sStart , sActive , &GPop::ServerProtocol::doPass , sStart ) ;
59 m_fsm.addTransition( eApop , sStart , sActive , &GPop::ServerProtocol::doApop , sStart ) ;
60 m_fsm.addTransition( eQuit , sStart , sEnd , &GPop::ServerProtocol::doQuitEarly ) ;
61 m_fsm.addTransition( eCapa , sStart , sStart , &GPop::ServerProtocol::doCapa ) ;
62 m_fsm.addTransition( eCapa , sActive , sActive , &GPop::ServerProtocol::doCapa ) ;
63 if( m_security.securityEnabled() )
64 m_fsm.addTransition( eStls , sStart , sStart , &GPop::ServerProtocol::doStls , sStart ) ;
65 m_fsm.addTransition( eAuth , sStart , sAuth , &GPop::ServerProtocol::doAuth , sStart ) ;
66 m_fsm.addTransition( eAuthData , sAuth , sActive , &GPop::ServerProtocol::doAuthData , sStart ) ;
67 m_fsm.addTransition( eCapa , sActive , sActive , &GPop::ServerProtocol::doCapa ) ;
68 m_fsm.addTransition( eQuit , sActive , sEnd , &GPop::ServerProtocol::doQuit ) ;
69 }
70
71 void GPop::ServerProtocol::init()
72 {
73 sendInit() ;
74 }
75
76 GPop::ServerProtocol::~ServerProtocol()
77 {
78 }
79
80 void GPop::ServerProtocol::sendInit()
81 {
82 std::string greeting = std::string() + "+OK " + m_text.greeting() ;
83 std::string apop_challenge = m_auth.challenge() ;
84 if( ! apop_challenge.empty() )
85 {
86 greeting.append( " " ) ;
87 greeting.append( apop_challenge ) ;
88 }
89 send( greeting ) ;
90 }
91
92 void GPop::ServerProtocol::sendOk()
93 {
94 send( "+OK" ) ;
95 }
96
97 void GPop::ServerProtocol::sendError( const std::string & more )
98 {
99 if( more.empty() )
100 sendError() ;
101 else
102 send( std::string() + "-ERR " + more ) ;
103 }
104
105 void GPop::ServerProtocol::sendError()
106 {
107 send( "-ERR" ) ;
108 }
109
110 void GPop::ServerProtocol::apply( const std::string & line )
111 {
112 // decode the event
113 Event event = m_fsm.state() == sAuth ? eAuthData : commandEvent(commandWord(line)) ;
114
115 // log the input
116 std::string log_text = G::Str::printable(line) ;
117 if( event == ePass )
118 log_text = (commandPart(line,0U)+" [password not logged]") ;
119 if( event == eAuthData )
120 log_text = ("[password not logged]") ;
121 if( event == eAuth && !commandPart(line,1U).empty() )
122 log_text = (commandPart(line,0U)+" "+commandPart(line,1U) + " [password not logged]") ;
123 G_LOG( "GPop::ServerProtocol: rx<<: \"" << log_text << "\"" ) ;
124
125 // apply the event to the state machine
126 State new_state = m_fsm.apply( *this , event , line ) ;
127 const bool protocol_error = new_state == s_Any ;
128 if( protocol_error )
129 sendError() ;
130
131 // squirt data down the pipe if appropriate
132 if( new_state == sData )
133 sendContent() ;
134 }
135
136 void GPop::ServerProtocol::sendContent()
137 {
138 // send until no more content or until blocked by flow-control
139 std::string line( 200 , '.' ) ;
140 size_t n = 0 ;
141 bool end_of_content = false ;
142 while( sendContentLine(line,end_of_content) )
143 n++ ;
144
145 G_LOG( "GPop::ServerProtocol: tx>>: [" << n << " line(s) of content]" ) ;
146
147 if( end_of_content )
148 {
149 G_LOG( "GPop::ServerProtocol: tx>>: ." ) ;
150 m_content <<= 0 ; // free up resources
151 m_fsm.apply( *this , eSent , "" ) ; // sData -> sActive
152 }
153 }
154
155 void GPop::ServerProtocol::resume()
156 {
157 G_DEBUG( "GPop::ServerProtocol::resume: flow control released" ) ;
158 if( m_fsm.state() == sData )
159 sendContent() ;
160 }
161
162 bool GPop::ServerProtocol::sendContentLine( std::string & line , bool & stop )
163 {
164 G_ASSERT( m_content.get() != NULL ) ;
165
166 // maintain the line limit
167 bool limited = m_in_body && m_body_limit == 0L ;
168 if( m_body_limit > 0L && m_in_body )
169 m_body_limit-- ;
170
171 // read the line of text
172 line.erase( 1U ) ; // leave "."
173 G::Str::readLineFrom( *(m_content.get()) , crlf() , line , false ) ;
174
175 // add crlf and choose an offset
176 bool eof = m_content->fail() || m_content->bad() ;
177 size_t offset = 0U ;
178 if( eof || limited )
179 {
180 line.erase( 1U ) ;
181 line.append( crlf() ) ;
182 }
183 else
184 {
185 line.append( crlf() ) ;
186 offset = line.at(1U) == '.' ? 0U : 1U ;
187 }
188
189 // maintain the in-body flag
190 if( !m_in_body && line.length() == (offset+2U) )
191 m_in_body = true ;
192
193 // send it
194 bool line_fully_sent = m_sender.protocolSend( line , offset ) ;
195
196 // continue to send while not finished or blocked by flow-control
197 stop = ( limited || eof ) && line_fully_sent ;
198 const bool pause = limited || eof || ! line_fully_sent ;
199 return !pause ;
200 }
201
202 int GPop::ServerProtocol::commandNumber( const std::string & line , int default_ , size_t index ) const
203 {
204 int number = default_ ;
205 try
206 {
207 number = G::Str::toInt( commandParameter(line,index) ) ;
208 }
209 catch( G::Str::Overflow & ) // defaulted
210 {
211 }
212 catch( G::Str::InvalidFormat & ) // defaulted
213 {
214 }
215 return number ;
216 }
217
218 std::string GPop::ServerProtocol::commandWord( const std::string & line ) const
219 {
220 return G::Str::upper(commandPart(line,0U)) ;
221 }
222
223 std::string GPop::ServerProtocol::commandPart( const std::string & line , size_t index ) const
224 {
225 G::Strings part ;
226 G::Str::splitIntoTokens( line , part , " \t\r\n" ) ;
227 if( index >= part.size() ) return std::string() ;
228 G::Strings::iterator p = part.begin() ;
229 for( ; index > 0 ; ++p , index-- ) ;
230 return *p ;
231 }
232
233 std::string GPop::ServerProtocol::commandParameter( const std::string & line_in , size_t index ) const
234 {
235 return commandPart( line_in , index ) ;
236 }
237
238 GPop::ServerProtocol::Event GPop::ServerProtocol::commandEvent( const std::string & command ) const
239 {
240 if( command == "QUIT" ) return eQuit ;
241 if( command == "STAT" ) return eStat ;
242 if( command == "LIST" ) return eList ;
243 if( command == "RETR" ) return eRetr ;
244 if( command == "DELE" ) return eDele ;
245 if( command == "NOOP" ) return eNoop ;
246 if( command == "RSET" ) return eRset ;
247 //
248 if( command == "TOP" ) return eTop ;
249 if( command == "UIDL" ) return eUidl ;
250 if( command == "USER" ) return eUser ;
251 if( command == "PASS" ) return ePass ;
252 if( command == "APOP" ) return eApop ;
253 if( command == "AUTH" ) return eAuth ;
254 if( command == "CAPA" ) return eCapa ;
255 if( command == "STLS" ) return eStls ;
256
257 return eUnknown ;
258 }
259
260 void GPop::ServerProtocol::doQuitEarly( const std::string & , bool & )
261 {
262 send( std::string() + "+OK " + m_text.quit() ) ;
263 throw ProtocolDone() ;
264 }
265
266 void GPop::ServerProtocol::doQuit( const std::string & , bool & )
267 {
268 m_store_lock.commit() ;
269 send( std::string() + "+OK " + m_text.quit() ) ;
270 throw ProtocolDone() ;
271 }
272
273 void GPop::ServerProtocol::doStat( const std::string & , bool & )
274 {
275 std::ostringstream ss ;
276 ss << "+OK " << m_store_lock.messageCount() << " " << m_store_lock.totalByteCount() ;
277 send( ss.str() ) ;
278 }
279
280 void GPop::ServerProtocol::doUidl( const std::string & line , bool & )
281 {
282 sendList( line , true ) ;
283 }
284
285 void GPop::ServerProtocol::doList( const std::string & line , bool & )
286 {
287 sendList( line , false ) ;
288 }
289
290 void GPop::ServerProtocol::sendList( const std::string & line , bool uidl )
291 {
292 std::string id_string = commandParameter( line ) ;
293
294 // parse and check the id if supplied
295 int id = -1 ;
296 if( ! id_string.empty() )
297 {
298 id = commandNumber( line , -1 ) ;
299 if( !m_store_lock.valid(id) )
300 {
301 sendError( "invalid id" ) ;
302 return ;
303 }
304 }
305
306 // send back the list with sizes or uidls
307 bool multi_line = id == -1 ;
308 GPop::StoreLock::List list = m_store_lock.list( id ) ;
309 std::ostringstream ss ;
310 ss << "+OK " ;
311 if( multi_line ) ss << list.size() << " message(s)" << crlf() ;
312 for( GPop::StoreLock::List::iterator p = list.begin() ; p != list.end() ; ++p )
313 {
314 ss << (*p).id << " " ;
315 if( uidl ) ss << (*p).uidl ;
316 if( !uidl ) ss << (*p).size ;
317 if( multi_line ) ss << crlf() ;
318 }
319 if( multi_line ) ss << "." ;
320 send( ss.str() ) ;
321 }
322
323 void GPop::ServerProtocol::doRetr( const std::string & line , bool & more )
324 {
325 int id = commandNumber( line , -1 ) ;
326 if( id == -1 || ! m_store_lock.valid(id) )
327 {
328 more = false ; // stay in the same state
329 sendError() ;
330 }
331 else
332 {
333 std::auto_ptr<std::istream> content( m_store_lock.get(id) ) ; // for gcc2.95
334 m_content <<= content.release() ;
335 m_body_limit = -1L ;
336
337 std::ostringstream ss ;
338 ss << "+OK " << m_store_lock.byteCount(id) << " octets" ;
339 send( ss.str() ) ;
340 }
341 }
342
343 void GPop::ServerProtocol::doTop( const std::string & line , bool & more )
344 {
345 int id = commandNumber( line , -1 , 1U ) ;
346 int n = commandNumber( line , -1 , 2U ) ;
347 G_DEBUG( "ServerProtocol::doTop: " << id << ", " << n ) ;
348 if( id == -1 || ! m_store_lock.valid(id) || n < 0 )
349 {
350 more = false ; // stay in the same state
351 sendError() ;
352 }
353 else
354 {
355 std::auto_ptr<std::istream> content( m_store_lock.get(id) ) ; // for gcc2.95
356 m_content <<= content.release() ;
357 m_body_limit = n ;
358 m_in_body = false ;
359 sendOk() ;
360 }
361 }
362
363 void GPop::ServerProtocol::doDele( const std::string & line , bool & )
364 {
365 int id = commandNumber( line , -1 ) ;
366 if( id == -1 || ! m_store_lock.valid(id) )
367 {
368 sendError() ;
369 }
370 else
371 {
372 m_store_lock.remove( id ) ;
373 sendOk() ;
374 }
375 }
376
377 void GPop::ServerProtocol::doRset( const std::string & , bool & )
378 {
379 m_store_lock.rollback() ;
380 sendOk() ;
381 }
382
383 void GPop::ServerProtocol::doNoop( const std::string & , bool & )
384 {
385 sendOk() ;
386 }
387
388 void GPop::ServerProtocol::doNothing( const std::string & , bool & )
389 {
390 }
391
392 void GPop::ServerProtocol::doAuth( const std::string & line , bool & ok )
393 {
394 std::string mechanism = G::Str::upper( commandParameter(line) ) ;
395
396 if( mechanism.empty() )
397 {
398 // completely non-standard behaviour, but required by some clients
399 ok = false ; // dont change state
400 std::string list = m_auth.mechanisms() ;
401 G::Str::replaceAll(list," ",crlf()) ;
402 send( "+OK" ) ;
403 send( list ) ;
404 send( "." ) ;
405 }
406 else if( m_auth.sensitive() && ! m_secure )
407 {
408 // reject authentication over an unencrypted transport
409 // if authentication is sensitive
410 ok = false ;
411 sendError( "must use STLS before authentication" ) ;
412 }
413 else
414 {
415 std::string initial_response = commandParameter(line,2) ;
416 if( initial_response == "=" )
417 initial_response = std::string() ; // RFC 5034
418
419 // reject the LOGIN mechanism here since we did not avertise it
420 // and we only want a one-step challenge-response dialogue
421
422 bool supported = mechanism != "LOGIN" && m_auth.init( mechanism ) ;
423 if( !supported )
424 {
425 ok = false ;
426 sendError( "invalid mechanism" ) ;
427 }
428 else if( m_auth.mustChallenge() && !initial_response.empty() )
429 {
430 ok = false ;
431 sendError( "invalid initial response" ) ;
432 }
433 else if( !initial_response.empty() )
434 {
435 m_fsm.apply( *this , eAuthData , initial_response ) ;
436 }
437 else
438 {
439 std::string initial_challenge = m_auth.challenge() ;
440 send( std::string() + "+ " + G::Base64::encode(initial_challenge) ) ;
441 }
442 }
443 }
444
445 void GPop::ServerProtocol::doAuthData( const std::string & line , bool & ok )
446 {
447 // (only one-step sasl authentication supported for now)
448 ok = m_auth.authenticated( G::Base64::decode(line) , std::string() ) ;
449 if( ok )
450 {
451 sendOk() ;
452 m_user = m_auth.id() ;
453 lockStore() ;
454 }
455 else
456 {
457 sendError() ;
458 }
459 }
460
461 void GPop::ServerProtocol::lockStore()
462 {
463 m_store_lock.lock( m_user ) ;
464 G_LOG_S( "GPop::ServerProtocol: pop authentication of " << m_user
465 << " connected from " << m_peer_address.displayString() ) ;
466 }
467
468 void GPop::ServerProtocol::doStls( const std::string & , bool & )
469 {
470 G_ASSERT( m_security.securityEnabled() ) ;
471 sendOk() ; // "please start tls"
472 m_security.securityStart() ;
473 }
474
475 void GPop::ServerProtocol::secure()
476 {
477 m_secure = true ;
478 sendOk() ; // "hello (again)"
479 }
480
481 bool GPop::ServerProtocol::mechanismsIncludePlain() const
482 {
483 return m_auth.valid() && m_auth.mechanisms().find("PLAIN") != std::string::npos ;
484 }
485
486 std::string GPop::ServerProtocol::mechanismsWithoutLogin() const
487 {
488 std::string result ;
489 if( m_auth.valid() )
490 {
491 result = m_auth.mechanisms() ;
492 G::Str::replace( result , "LOGIN" , "" ) ; // could do better
493 G::Str::replace( result , " " , " " ) ;
494 }
495 return result ;
496 }
497
498 void GPop::ServerProtocol::doCapa( const std::string & , bool & )
499 {
500 send( std::string() + "+OK " + m_text.capa() ) ;
501
502 // USER/PASS POP3 authentication uses the PLAIN SASL mechanism
503 // so only advertise it if it is available
504 if( mechanismsIncludePlain() )
505 send( "USER" ) ;
506
507 send( "CAPA" ) ;
508 send( "TOP" ) ;
509 send( "UIDL" ) ;
510
511 if( m_security.securityEnabled() )
512 send( "STLS" ) ;
513
514 // don't advertise LOGIN since we cannot do multi-challenge
515 // mechanisms and USER/PASS provides the same functionality
516 //
517 std::string mechanisms = std::string(1U,' ') + mechanismsWithoutLogin() ;
518 if( mechanisms.length() > 1U )
519 send( std::string() + "SASL" + mechanisms ) ;
520
521 send( "." ) ;
522 }
523
524 void GPop::ServerProtocol::doUser( const std::string & line , bool & )
525 {
526 if( mechanismsIncludePlain() )
527 {
528 m_user = commandParameter(line) ;
529 send( std::string() + "+OK " + m_text.user(commandParameter(line)) ) ;
530 }
531 else
532 {
533 sendError( "no SASL PLAIN mechanism to do USER/PASS authentication" ) ;
534 }
535 }
536
537 void GPop::ServerProtocol::doPass( const std::string & line , bool & ok )
538 {
539 // note that USER/PASS POP3 authentication uses the PLAIN SASL mechanism
540 std::string rsp = m_user + std::string(1U,'\0') + m_user + std::string(1U,'\0') + commandParameter(line) ;
541 ok = !m_user.empty() && m_auth.valid() && m_auth.init("PLAIN") &&
542 m_auth.authenticated( rsp , std::string() ) ;
543 if( ok )
544 {
545 lockStore() ;
546 sendOk() ;
547 }
548 else
549 {
550 sendError() ;
551 }
552 }
553
554 void GPop::ServerProtocol::doApop( const std::string & line , bool & ok )
555 {
556 m_user = commandParameter(line,1) ;
557 std::string rsp = m_user + " " + commandParameter(line,2) ;
558 ok = m_auth.valid() && m_auth.init("APOP") && m_auth.authenticated(rsp,std::string()) ;
559 if( ok )
560 {
561 lockStore() ;
562 sendOk() ;
563 }
564 else
565 {
566 m_user = std::string() ;
567 sendError() ;
568 }
569 }
570
571 void GPop::ServerProtocol::send( std::string line )
572 {
573 G_LOG( "GPop::ServerProtocol: tx>>: \"" << G::Str::printable(line) << "\"" ) ;
574 line.append( crlf() ) ;
575 m_sender.protocolSend( line , 0U ) ;
576 }
577
578 const std::string & GPop::ServerProtocol::crlf()
579 {
580 static const std::string s( "\015\012" ) ;
581 return s ;
582 }
583
584 // ===
585
586 GPop::ServerProtocolText::ServerProtocolText( GNet::Address )
587 {
588 }
589
590 std::string GPop::ServerProtocolText::greeting() const
591 {
592 return "POP3 server ready" ;
593 }
594
595 std::string GPop::ServerProtocolText::quit() const
596 {
597 return "signing off" ;
598 }
599
600 std::string GPop::ServerProtocolText::capa() const
601 {
602 return "capability list follows" ;
603 }
604
605 std::string GPop::ServerProtocolText::user( const std::string & id ) const
606 {
607 return std::string() + "user: " + id ;
608 }
609
610 // ===
611
612 GPop::ServerProtocol::Text::~Text()
613 {
614 }
615
616 // ===
617
618 GPop::ServerProtocol::Sender::~Sender()
619 {
620 }
621
622 // ===
623
624 GPop::ServerProtocol::Config::Config()
625 {
626 }
627
628 // ===
629
630 GPop::ServerProtocol::Security::~Security()
631 {
632 }
633
G_LOG_S
#define G_LOG_S(expr)
Definition: glog.h:103
G::Str::printable
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
Definition: gstr.cpp:507
GPop::ServerProtocol::Security::securityEnabled
virtual bool securityEnabled() const =0
GPop::Secrets
A simple interface to a store of secrets as used in authentication.
Definition: gpopsecrets.h:44
glog.h
GPop::ServerProtocolText::quit
virtual std::string quit() const
Final override from GPop::ServerProtocol::Text.
Definition: gpopserverprotocol.cpp:595
G::Str::toInt
static int toInt(const std::string &s)
Converts string 's' to an int.
Definition: gstr.cpp:310
G::Strings
std::list< std::string > Strings
A std::list of std::strings.
Definition: gstrings.h:39
GPop::ServerProtocolText::greeting
virtual std::string greeting() const
Final override from GPop::ServerProtocol::Text.
Definition: gpopserverprotocol.cpp:590
GNet::Address
The Address class encapsulates an IP transport address.
Definition: gaddress.h:48
GPop::ServerProtocolText::capa
virtual std::string capa() const
Final override from GPop::ServerProtocol::Text.
Definition: gpopserverprotocol.cpp:600
GPop::ServerProtocol::Security::~Security
virtual ~Security()
Definition: gpopserverprotocol.cpp:630
G::Str::splitIntoTokens
static void splitIntoTokens(const std::string &in, Strings &out, const std::string &ws)
Splits the string into 'ws'-delimited tokens.
Definition: gstr.cpp:714
GPop::ServerProtocol::init
void init()
Starts the protocol.
Definition: gpopserverprotocol.cpp:71
GPop::ServerProtocol::~ServerProtocol
virtual ~ServerProtocol()
Destructor.
Definition: gpopserverprotocol.cpp:76
GPop::ServerProtocol::Sender
An interface used by ServerProtocol to send protocol replies.
Definition: gpopserverprotocol.h:55
GPop::Store
A message store.
Definition: gpopstore.h:46
GPop::ServerProtocol::Security
An interface used by ServerProtocol to enable TLS.
Definition: gpopserverprotocol.h:78
GPop::ServerProtocolText::ServerProtocolText
ServerProtocolText(GNet::Address peer)
Constructor.
Definition: gpopserverprotocol.cpp:586
G_ASSERT
#define G_ASSERT(test)
Definition: gassert.h:30
gstr.h
G::Str::replace
static bool replace(std::string &s, const std::string &from, const std::string &to, size_type *pos_p=NULL)
Replaces 'from' with 'to', starting at offset '*pos_p'.
Definition: gstr.cpp:55
gassert.h
G::Str::replaceAll
static unsigned int replaceAll(std::string &s, const std::string &from, const std::string &to)
Does a global replace on string 's', replacing all occurences of sub-string 'from' with 'to'...
Definition: gstr.cpp:78
GPop::ServerProtocol::Text
An interface used by ServerProtocol to provide response text strings.
Definition: gpopserverprotocol.h:62
GPop::ServerProtocolText::user
virtual std::string user(const std::string &id) const
Final override from GPop::ServerProtocol::Text.
Definition: gpopserverprotocol.cpp:605
G_LOG
#define G_LOG(expr)
Definition: glog.h:98
gpopserverprotocol.h
G::Str::upper
static std::string upper(const std::string &s)
Returns a copy of 's' in which all lowercase characters have been replaced by uppercase characters...
Definition: gstr.cpp:426
G::Str::readLineFrom
static std::string readLineFrom(std::istream &stream, const std::string &eol=std::string())
Reads a line from the stream using the given line terminator.
Definition: gstr.cpp:536
G_DEBUG
#define G_DEBUG(expr)
Definition: glog.h:95
gpop.h
GPop::StoreLock::List
std::list< Entry > List
Definition: gpopstore.h:106
GPop::ServerProtocol::ServerProtocol
ServerProtocol(Sender &sender, Security &security, Store &store, const Secrets &secrets, const Text &text, GNet::Address peer_address, Config config)
Constructor.
Definition: gpopserverprotocol.cpp:31
GPop::ServerProtocol::Config
A structure containing configuration parameters for ServerProtocol. NOT USED.
Definition: gpopserverprotocol.h:72
gbase64.h
G::StateMachine::addTransition
void addTransition(Event event, State from, State to, Action action)
Adds a transition.
Definition: gstatemachine.h:179
GPop::ServerProtocol::secure
void secure()
Called when the server connection becomes secure.
Definition: gpopserverprotocol.cpp:475
G::Base64::decode
static std::string decode(const std::string &)
Decodes the given string.
Definition: gbase64.cpp:131
gmemory.h
GPop::ServerProtocol::apply
void apply(const std::string &line)
Called on receipt of a string from the client.
Definition: gpopserverprotocol.cpp:110
G::Base64::encode
static std::string encode(const std::string &s, const std::string &line_break)
Encodes the given string.
Definition: gbase64.cpp:68
GPop::ServerProtocol::resume
void resume()
Called when the Sender can send again.
Definition: gpopserverprotocol.cpp:155
GPop::ServerProtocol::Config::Config
Config()
Definition: gpopserverprotocol.cpp:624
GPop::ServerProtocol::Text::~Text
virtual ~Text()
Definition: gpopserverprotocol.cpp:612
GPop::ServerProtocol::Sender::~Sender
virtual ~Sender()
Definition: gpopserverprotocol.cpp:618